compGraph: flying object
This commit is contained in:
parent
f9a5e49d29
commit
c880ad658d
14
compGraph/flying_object/Makefile
Normal file
14
compGraph/flying_object/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
CC = g++
|
||||
SDL_ROOT = lib/i686-w64-mingw32
|
||||
|
||||
build/phys.exe: build/main.o
|
||||
$(CC) -o $@ $^ -L$(SDL_ROOT)/lib -lmingw32 -lSDL2main -lSDL2 -lSDL2_ttf -mwindows
|
||||
build/main.o: main.cpp
|
||||
$(CC) -c -o $@ $^ -I$(SDL_ROOT)/include/SDL2
|
||||
|
||||
run: build/phys.exe
|
||||
cd ./build && ./$(notdir $<); cd ..
|
||||
|
||||
clear:
|
||||
-rm ./build/*.o
|
||||
-rm ./build/*.exe
|
BIN
compGraph/flying_object/build/FreeSans.ttf
Normal file
BIN
compGraph/flying_object/build/FreeSans.ttf
Normal file
Binary file not shown.
BIN
compGraph/flying_object/build/SDL2.dll
Normal file
BIN
compGraph/flying_object/build/SDL2.dll
Normal file
Binary file not shown.
BIN
compGraph/flying_object/build/SDL2_ttf.dll
Normal file
BIN
compGraph/flying_object/build/SDL2_ttf.dll
Normal file
Binary file not shown.
BIN
compGraph/flying_object/build/libfreetype-6.dll
Normal file
BIN
compGraph/flying_object/build/libfreetype-6.dll
Normal file
Binary file not shown.
317
compGraph/flying_object/main.cpp
Normal file
317
compGraph/flying_object/main.cpp
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
Copyright 2020 KoroLion (github.com/KoroLion)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_TTF.h"
|
||||
|
||||
const int WIN_WIDTH = 1280;
|
||||
const int WIN_HEIGHT = 800;
|
||||
|
||||
const char* WIN_TITLE = "Fall Simulator";
|
||||
const int FPS = 60;
|
||||
|
||||
#define PI 3.1415
|
||||
|
||||
// configurate here
|
||||
#define HEIGHT 200
|
||||
#define SPEED 100
|
||||
#define ANGLE -90
|
||||
// endconf
|
||||
|
||||
template <typename T>
|
||||
float sqr(T a) {
|
||||
return a * a;
|
||||
}
|
||||
|
||||
std::string floatToStr(float v, int p) {
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(p) << v;
|
||||
std::string s = stream.str();
|
||||
return s;
|
||||
}
|
||||
|
||||
void renderText(SDL_Renderer *renderer, const char *s,
|
||||
float x, float y, float size) {
|
||||
SDL_Texture *texture;
|
||||
TTF_Font *font = TTF_OpenFont("FreeSans.ttf", size);
|
||||
SDL_Surface *surface;
|
||||
SDL_Color textColor = {128, 128, 128, 0};
|
||||
|
||||
surface = TTF_RenderText_Solid(font, s, textColor);
|
||||
texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_Rect rect{(int)round(x), (int)round(y), surface->w, surface->h};
|
||||
SDL_RenderCopy(renderer, texture, NULL, &rect);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
|
||||
class Object {
|
||||
protected:
|
||||
float x, y;
|
||||
int width, height;
|
||||
public:
|
||||
Object(float x, float y, int width, int height): x(x), y(y), width(width), height(height) {};
|
||||
|
||||
float getX() const { return x; }
|
||||
float getY() const { return y; }
|
||||
void setX(float x) { this->x = x; }
|
||||
void setY(float y) { this->y = y; }
|
||||
|
||||
virtual void update(int fps) {};
|
||||
virtual void render(SDL_Renderer *renderer) {
|
||||
SDL_SetRenderDrawColor(renderer, 64, 80, 64, 0);
|
||||
|
||||
SDL_Rect r{(int)x, (int)y, width, height};
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class PhysObject: public Object {
|
||||
protected:
|
||||
float speedX, speedY, aX, aY;
|
||||
float m = 1;
|
||||
public:
|
||||
PhysObject(): Object(0, 0, 1, 1), speedX(0), speedY(0), aX(0), aY(0) {}
|
||||
PhysObject(float x, float y, float speed, float angle): Object(x, y, 15, 15) {
|
||||
speedX = speed * cos(angle * PI / 180);
|
||||
speedY = speed * sin(angle * PI / 180);
|
||||
aX = 0;
|
||||
aY = 9.8;
|
||||
}
|
||||
|
||||
float getSpeedX() const { return speedX; }
|
||||
float getSpeedY() const { return speedY; }
|
||||
float getWidth() const { return width; }
|
||||
float getHeight() const { return height; }
|
||||
|
||||
float getSpeed() {
|
||||
return sqrt(sqr(speedX) + sqr(speedY));
|
||||
}
|
||||
float getEKin() {
|
||||
return sqr(getSpeed()) * m / 2.0;
|
||||
}
|
||||
float getEPot(float height) {
|
||||
return m * aY * height;
|
||||
}
|
||||
|
||||
void setSpeedX(float speedX) { this->speedX = speedX; }
|
||||
void setSpeedY(float speedY) { this->speedY = speedY; }
|
||||
|
||||
void update(int fps) {
|
||||
x += speedX / fps;
|
||||
y -= speedY / fps;
|
||||
speedX += aX / fps;
|
||||
speedY -= aY / fps; // y axes is reversed
|
||||
}
|
||||
|
||||
void render(SDL_Renderer *renderer) {
|
||||
SDL_SetRenderDrawColor(renderer, 32, 200, 32, 0);
|
||||
|
||||
SDL_Rect r{(int)x, (int)y, width, height};
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
}
|
||||
};
|
||||
|
||||
class Simulation {
|
||||
private:
|
||||
int width, height, floorHeight = 10;
|
||||
float t = 0;
|
||||
PhysObject *physObject;
|
||||
std::vector<Object*> objects;
|
||||
|
||||
void renderFloor(SDL_Renderer *renderer) {
|
||||
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 0);
|
||||
|
||||
SDL_Rect r{0, height - floorHeight, width, floorHeight};
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
}
|
||||
|
||||
float yToHeight(float y, int objHeight) {
|
||||
return height - y - floorHeight - objHeight;
|
||||
}
|
||||
|
||||
void renderInfo(SDL_Renderer *renderer) {
|
||||
float h = yToHeight(physObject->getY(), physObject->getHeight());
|
||||
|
||||
std::string st = floatToStr(t, 2);
|
||||
std::string sh = floatToStr(h, 2);
|
||||
std::string sv = floatToStr(physObject->getSpeed(), 2);
|
||||
|
||||
renderText(renderer, ("t = " + st + " s").c_str(), 10, 10, 16);
|
||||
renderText(renderer, ("h = " + sh + " m").c_str(), 10, 30, 16);
|
||||
renderText(renderer, ("V = " + sv + " m/s").c_str(), 10, 50, 16);
|
||||
}
|
||||
|
||||
void renderEInfoAndGraphs(SDL_Renderer *renderer, int x, int y) {
|
||||
float h = yToHeight(physObject->getY(), physObject->getHeight());
|
||||
float ep = physObject->getEPot(h);
|
||||
float ek = physObject->getEKin();
|
||||
float e = ep + ek;
|
||||
|
||||
std::string sek = floatToStr(ek, 2);
|
||||
std::string sep = floatToStr(ep, 2);
|
||||
std::string se = floatToStr(e, 2);
|
||||
|
||||
const int maxWidth = 300;
|
||||
SDL_Rect r{x, 200, maxWidth, 30};
|
||||
|
||||
renderText(renderer, ("Ep = " + sek + " J").c_str(), x, y, 16);
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64, 0);
|
||||
r.y = y + 20;
|
||||
r.w = maxWidth;
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
r.w = maxWidth * (ep / e);
|
||||
SDL_SetRenderDrawColor(renderer, 32, 128, 32, 0);
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
|
||||
renderText(renderer, ("Ek = " + sek + " J").c_str(), x, y + 70, 16);
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64, 0);
|
||||
r.y = y + 90;
|
||||
r.w = maxWidth;
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
r.w = maxWidth * (ek / e);
|
||||
SDL_SetRenderDrawColor(renderer, 32, 128, 128, 0);
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
|
||||
renderText(renderer, ("E = " + se + " J").c_str(), x, y + 140, 16);
|
||||
}
|
||||
public:
|
||||
Simulation(int width, int height): width(width), height(height) {
|
||||
float h = HEIGHT;
|
||||
physObject = new PhysObject(50, 0, SPEED, ANGLE);
|
||||
physObject->setY(height - h - floorHeight - physObject->getWidth());
|
||||
objects.push_back(physObject);
|
||||
}
|
||||
|
||||
~Simulation() {
|
||||
std::for_each(
|
||||
objects.begin(),
|
||||
objects.end(),
|
||||
[](Object *obj) {
|
||||
delete obj;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void update(int fps) {
|
||||
t += 1.0 / fps;
|
||||
|
||||
std::for_each(
|
||||
objects.begin(),
|
||||
objects.end(),
|
||||
[fps](Object* obj) {
|
||||
obj->update(60);
|
||||
}
|
||||
);
|
||||
|
||||
if (physObject->getSpeed() > 0.1) {
|
||||
float x = physObject->getX() + physObject->getWidth() / 2;
|
||||
float y = physObject->getY() + physObject->getHeight() / 2;
|
||||
objects.push_back(new Object(x, y, 5, 5));
|
||||
}
|
||||
|
||||
float collisionY = height - floorHeight - physObject->getHeight();
|
||||
if (physObject->getY() > collisionY) {
|
||||
physObject->setY(collisionY);
|
||||
physObject->setSpeedY(floor(abs(physObject->getSpeedY() / 2)));
|
||||
}
|
||||
}
|
||||
|
||||
void render(SDL_Renderer *renderer) {
|
||||
std::for_each(
|
||||
objects.rbegin(),
|
||||
objects.rend(),
|
||||
[renderer](Object* obj) {
|
||||
obj->render(renderer);
|
||||
}
|
||||
);
|
||||
|
||||
renderFloor(renderer);
|
||||
renderEInfoAndGraphs(renderer, 150, 10);
|
||||
renderInfo(renderer);
|
||||
}
|
||||
};
|
||||
|
||||
class App {
|
||||
private:
|
||||
int width, height, fps;
|
||||
bool isRunning;
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
|
||||
Simulation *matPlot;
|
||||
|
||||
void handleEvents() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
bool esc_or_quit = event.type == SDL_QUIT ||
|
||||
event.key.keysym.sym == SDLK_ESCAPE;
|
||||
bool win_close = event.type == SDL_WINDOWEVENT &&
|
||||
event.window.event == SDL_WINDOWEVENT_CLOSE;
|
||||
if (esc_or_quit || win_close) {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleKeyboard() {
|
||||
const Uint8 *keys = SDL_GetKeyboardState(0);
|
||||
}
|
||||
|
||||
public:
|
||||
App(const char* title, int width, int height, int initX, int initY,
|
||||
int fps):
|
||||
width(width), height(height), fps(fps), isRunning(true) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
TTF_Init();
|
||||
|
||||
window = SDL_CreateWindow(title, initX, initY, width, height,
|
||||
SDL_WINDOW_OPENGL);
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |
|
||||
SDL_RENDERER_PRESENTVSYNC);
|
||||
matPlot = new Simulation(width, height);
|
||||
}
|
||||
~App() {
|
||||
delete matPlot;
|
||||
TTF_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void start() {
|
||||
while (isRunning) {
|
||||
handleEvents();
|
||||
handleKeyboard();
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
matPlot->update(fps);
|
||||
matPlot->render(renderer);
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
SDL_Delay(1000 / fps);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::stringstream ss;
|
||||
ss << WIN_TITLE << " (H = " << HEIGHT << " m, V = " << SPEED << " m/s, angle = " << ANGLE << " deg)";
|
||||
App app(ss.str().c_str(), WIN_WIDTH, WIN_HEIGHT, 100, 100, FPS);
|
||||
app.start();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user