Working, terrible code, but working
This commit is contained in:
commit
3f61cd59ba
156
main.cpp
Normal file
156
main.cpp
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include "sdlpp.hpp"
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <SDL2/SDL2_framerate.h>
|
||||||
|
|
||||||
|
#define PLAYER_ID 0x00000001
|
||||||
|
#define FINALLY_ID 0x00000002
|
||||||
|
|
||||||
|
std::shared_ptr<SDLPP::RenderObject> player;
|
||||||
|
std::vector<std::shared_ptr<SDLPP::Texture>> bgtextures;
|
||||||
|
bool quit = false;
|
||||||
|
|
||||||
|
void addStuff(SDLPP::Scene &scene, std::shared_ptr<SDLPP::Renderer> &r) {
|
||||||
|
auto y = std::make_shared<SDLPP::RectangleRender>(0.4,0.2,0.25,0.4, r);
|
||||||
|
y->addCollision(SDLPP::Rect(0,0,1,1));
|
||||||
|
y->setTexture("6.png");
|
||||||
|
y->setId(FINALLY_ID);
|
||||||
|
scene.addObject(y);
|
||||||
|
auto x = std::make_shared<SDLPP::RectangleRender>(0,0,0.2,0.2, r);
|
||||||
|
x->addCollision(SDLPP::Rect(0,0,1,1));
|
||||||
|
x->setTexture("5.png");
|
||||||
|
x->setId(PLAYER_ID);
|
||||||
|
scene.addObject(x);
|
||||||
|
player = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void quitGame() {
|
||||||
|
std::cout << "Quitting!" << std::endl;
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleKeyDown(SDL_Keycode key, SDLPP::Scene &scene) {
|
||||||
|
switch(key) {
|
||||||
|
case SDLK_UP:
|
||||||
|
scene.setBackground(bgtextures[0]);
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
scene.setBackground(bgtextures[1]);
|
||||||
|
break;
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
scene.setBackground(bgtextures[2]);
|
||||||
|
break;
|
||||||
|
case SDLK_LEFT:
|
||||||
|
scene.setBackground(bgtextures[3]);
|
||||||
|
break;
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
quitGame();
|
||||||
|
break;
|
||||||
|
case SDLK_a:
|
||||||
|
player->addMovement(-1,0);
|
||||||
|
break;
|
||||||
|
case SDLK_d:
|
||||||
|
player->addMovement(1,0);
|
||||||
|
break;
|
||||||
|
case SDLK_w:
|
||||||
|
player->addMovement(0,-1);
|
||||||
|
break;
|
||||||
|
case SDLK_s:
|
||||||
|
player->addMovement(0,1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scene.setBackground(bgtextures[4]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleKeyUp(SDL_Keycode key) {
|
||||||
|
switch(key) {
|
||||||
|
case SDLK_a:
|
||||||
|
player->addMovement(1,0);
|
||||||
|
break;
|
||||||
|
case SDLK_d:
|
||||||
|
player->addMovement(-1,0);
|
||||||
|
break;
|
||||||
|
case SDLK_w:
|
||||||
|
player->addMovement(0,1);
|
||||||
|
break;
|
||||||
|
case SDLK_s:
|
||||||
|
player->addMovement(0,-1);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pollEvents(SDLPP::Scene &scene) {
|
||||||
|
SDL_Event event;
|
||||||
|
while( SDL_PollEvent( &event ) != 0 ) {
|
||||||
|
switch(event.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
quitGame();
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if( !event.key.repeat )
|
||||||
|
handleKeyDown(event.key.keysym.sym, scene);
|
||||||
|
break;
|
||||||
|
case SDL_KEYUP:
|
||||||
|
handleKeyUp(event.key.keysym.sym);
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
if(event.window.event == SDL_WINDOWEVENT_RESIZED)
|
||||||
|
scene.updateSizeAndPosition();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doInput(std::shared_ptr<SDLPP::Scene> scene) {
|
||||||
|
FPSmanager gFPS;
|
||||||
|
SDL_initFramerate(&gFPS);
|
||||||
|
SDL_setFramerate(&gFPS, 200);
|
||||||
|
int base = SDL_GetTicks();
|
||||||
|
int frames = 0;
|
||||||
|
while(!quit) {
|
||||||
|
SDL_framerateDelay(&gFPS);
|
||||||
|
pollEvents(*scene);
|
||||||
|
scene->movement();
|
||||||
|
for( auto &x : scene->getCollisions(*player) ) {
|
||||||
|
if( x->getId() == FINALLY_ID ) {
|
||||||
|
std::cout << "Finally!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frames++;
|
||||||
|
if(SDL_GetTicks() - base >= 1000) {
|
||||||
|
base = SDL_GetTicks();
|
||||||
|
printf("FPS: %d\n", frames);
|
||||||
|
frames = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
SDLPP::init();
|
||||||
|
SDLPP::Window w("Oh yeah, boi!");
|
||||||
|
auto renderer = std::make_shared<SDLPP::Renderer>(w);
|
||||||
|
auto main_scene = std::make_shared<SDLPP::Scene>(renderer);
|
||||||
|
bgtextures.push_back(std::make_shared<SDLPP::Texture>(renderer, "1.bmp"));
|
||||||
|
bgtextures.push_back(std::make_shared<SDLPP::Texture>(renderer, "2.bmp"));
|
||||||
|
bgtextures.push_back(std::make_shared<SDLPP::Texture>(renderer, "3.png"));
|
||||||
|
bgtextures.push_back(std::make_shared<SDLPP::Texture>(renderer, "4.png"));
|
||||||
|
bgtextures.push_back(std::make_shared<SDLPP::Texture>(renderer, "test.bmp"));
|
||||||
|
main_scene->setBackground(bgtextures[0]);
|
||||||
|
addStuff(*main_scene, renderer);
|
||||||
|
player->setMovementSpeed(0.3);
|
||||||
|
|
||||||
|
FPSmanager gFPS;
|
||||||
|
SDL_initFramerate(&gFPS);
|
||||||
|
SDL_setFramerate(&gFPS, 60);
|
||||||
|
std::thread inputThread(doInput, main_scene);
|
||||||
|
while( !quit ) {
|
||||||
|
SDL_framerateDelay(&gFPS);
|
||||||
|
main_scene->renderScene();
|
||||||
|
main_scene->presentScene();
|
||||||
|
}
|
||||||
|
inputThread.join();
|
||||||
|
}
|
107
sdlpp.cpp
Normal file
107
sdlpp.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "sdlpp.hpp"
|
||||||
|
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
bool SDLPP::init() {
|
||||||
|
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
|
||||||
|
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( IMG_Init( IMG_INIT_PNG ) != IMG_INIT_PNG ) {
|
||||||
|
std::cerr << "SDL_image could not initialize! SDL_image Error: " << IMG_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLPP::init(uint32_t SDL_OPTIONS) {
|
||||||
|
if( SDL_Init(SDL_OPTIONS) < 0 ) {
|
||||||
|
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( IMG_Init( IMG_INIT_PNG ) != IMG_INIT_PNG ) {
|
||||||
|
std::cerr << "SDL_image could not initialize! SDL_image Error: " << IMG_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLPP::init(uint32_t SDL_OPTIONS, int IMAGE_OPTIONS) {
|
||||||
|
if( SDL_Init(SDL_OPTIONS) < 0 ) {
|
||||||
|
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( IMG_Init( IMAGE_OPTIONS ) != IMAGE_OPTIONS ) {
|
||||||
|
std::cerr << "SDL_image could not initialize! SDL_image Error: " << IMG_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLPP::CircleRender::render() {
|
||||||
|
std::cout << "I'm a circle, look at me go!" << std::endl << "My dimensions are: [" << x_ << ", " << y_ << "], radius: " << rad_ << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only rectangles for now
|
||||||
|
bool intersects(const SDLPP::CollisionPolygon &p1, const SDLPP::CollisionPolygon &p2) {
|
||||||
|
return !(p1.rightmost() < p2.leftmost() || p2.rightmost() < p1.leftmost() ||
|
||||||
|
p1.topmost() > p2.bottommost() || p2.topmost() > p1.bottommost());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool infinityIntersection(const SDLPP::CollisionPolygon &infinite, const SDLPP::CollisionPolygon &other) {
|
||||||
|
int ileft = infinite.leftmost();
|
||||||
|
int iright = infinite.rightmost();
|
||||||
|
int itop = infinite.topmost();
|
||||||
|
int ibottom = infinite.bottommost();
|
||||||
|
bool ret = ileft != -1 && ileft <= other.rightmost();
|
||||||
|
ret |= iright != -1 && iright >= other.leftmost();
|
||||||
|
ret |= itop != -1 && itop <= other.bottommost();
|
||||||
|
ret |= ibottom != -1 && ibottom >= other.topmost();
|
||||||
|
ret |= ileft == -1 && iright == -1 && itop == -1 && ibottom == -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLPP::Rect::colidesWith(const SDLPP::CollisionPolygon &other) const {
|
||||||
|
if(other.isCircle()) {
|
||||||
|
return other.colidesWith(*this);
|
||||||
|
}
|
||||||
|
if(other.isInfinite()) {
|
||||||
|
return infinityIntersection(other, *this);
|
||||||
|
}
|
||||||
|
return intersects(*this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLPP::Circle::colidesWith(const SDLPP::CollisionPolygon &other) const {
|
||||||
|
if(other.isCircle()) {
|
||||||
|
int otherRad = (other.rightmost() - other.leftmost())/2;
|
||||||
|
int thisRad = getRadius();
|
||||||
|
int totalDist = otherRad + thisRad;
|
||||||
|
int xdiff = other.leftmost() + otherRad - (leftmost() + thisRad);
|
||||||
|
int ydiff = other.topmost() + otherRad - (topmost() + thisRad);
|
||||||
|
return (xdiff*xdiff + ydiff*ydiff) <= totalDist * totalDist;
|
||||||
|
} else if (other.isInfinite()) {
|
||||||
|
return infinityIntersection(other, *this);
|
||||||
|
}
|
||||||
|
int rad = rad_;
|
||||||
|
int centerx = getX();
|
||||||
|
int centery = getY();
|
||||||
|
if(other.topmost() <= centery && other.bottommost() >= centery) {
|
||||||
|
return other.leftmost() <= rightmost() && other.rightmost() >= leftmost();
|
||||||
|
} else if (other.leftmost() <= centerx && other.rightmost() >= centerx) {
|
||||||
|
return other.topmost() <= bottommost() && other.bottommost() >= topmost();
|
||||||
|
}
|
||||||
|
int pointx=0, pointy=0;
|
||||||
|
if(centerx > other.rightmost()) {
|
||||||
|
pointx = other.rightmost();
|
||||||
|
} else {
|
||||||
|
pointx = other.leftmost();
|
||||||
|
}
|
||||||
|
if(centery < other.topmost()) {
|
||||||
|
pointy = other.topmost();
|
||||||
|
} else {
|
||||||
|
pointy = other.bottommost();
|
||||||
|
}
|
||||||
|
int distancesquared = (pointx - centerx)*(pointx - centerx) + (pointy - centery)*(pointy-centery);
|
||||||
|
return distancesquared <= rad*rad;
|
||||||
|
}
|
461
sdlpp.hpp
Normal file
461
sdlpp.hpp
Normal file
@ -0,0 +1,461 @@
|
|||||||
|
#ifndef SDLPP_HPP
|
||||||
|
#define SDLPP_HPP
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace SDLPP {
|
||||||
|
|
||||||
|
class Window {
|
||||||
|
public:
|
||||||
|
Window() : Window("SDL Window", 640, 480, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED) {
|
||||||
|
}
|
||||||
|
Window(const std::string &window_name) : Window(window_name, 640, 480, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED) {
|
||||||
|
}
|
||||||
|
Window(const std::string &window_name, uint32_t width, uint32_t height) : Window(window_name, width, height, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED) {}
|
||||||
|
Window(const std::string &window_name, uint32_t width, uint32_t height,
|
||||||
|
uint32_t posx, uint32_t posy) {
|
||||||
|
window = SDL_CreateWindow(window_name.c_str(), posx, posy, width, height, SDL_WINDOW_SHOWN);
|
||||||
|
if( window == NULL ) {
|
||||||
|
std::cerr << "SDL could not create a window! SDL_Error: " << SDL_GetError() << std::endl;
|
||||||
|
throw "Couldn't create window";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~Window() {
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
}
|
||||||
|
SDL_Window *getWindowPtr() {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SDL_Window *window = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Renderer {
|
||||||
|
public:
|
||||||
|
Renderer() = delete;
|
||||||
|
Renderer(Window &window) {
|
||||||
|
renderer = SDL_CreateRenderer(window.getWindowPtr(), -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
if(renderer == NULL ) {
|
||||||
|
std::cerr << "SDL could not create a renderer! SDL_Error: " << SDL_GetError();
|
||||||
|
throw "Couldn't create renderer";
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||||
|
}
|
||||||
|
~Renderer() {
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
}
|
||||||
|
SDL_Renderer *getRendererPtr() {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
std::pair<int, int> getDimensions() {
|
||||||
|
int width = 0, height = 0;
|
||||||
|
SDL_GetRendererOutputSize(renderer, &width, &height);
|
||||||
|
return {width, height};
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SDL_Renderer *renderer = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
public:
|
||||||
|
Texture() = delete;
|
||||||
|
Texture(std::shared_ptr<Renderer> &renderer, const std::string &img_path) : Texture(renderer, img_path, "") {}
|
||||||
|
Texture(std::shared_ptr<Renderer> &renderer, const std::string &img_path, const std::string &color_key) {
|
||||||
|
SDL_Surface *surface = IMG_Load(img_path.c_str());
|
||||||
|
if( surface == NULL ) {
|
||||||
|
std::cerr << "Unable to load image '" << img_path << "': IMG Error: " << IMG_GetError() << std::endl;
|
||||||
|
throw "IMG_Load error";
|
||||||
|
}
|
||||||
|
if( !color_key.empty() ) {
|
||||||
|
auto colors = getColorsHEX(color_key);
|
||||||
|
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, std::get<0>(colors), std::get<1>(colors), std::get<2>(colors)));
|
||||||
|
}
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer->getRendererPtr(), surface);
|
||||||
|
if( texture == NULL ) {
|
||||||
|
std::cerr << "Unable to create texture from '" << img_path << "'! SDL Error: " << SDL_GetError() << std::endl;
|
||||||
|
throw "Texture error";
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
}
|
||||||
|
~Texture() {
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
}
|
||||||
|
SDL_Texture *getTexturePtr() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int hex2num(char c) {
|
||||||
|
if(c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
switch(c) {
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
return 10;
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
return 11;
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
return 12;
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
return 13;
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
return 14;
|
||||||
|
default:
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<int, int, int> getColorsHEX(const std::string &color) {
|
||||||
|
int red = 0, green = 0, blue = 0;
|
||||||
|
const char *color_ptr = color.c_str();
|
||||||
|
if(color_ptr[0] == '#')
|
||||||
|
color_ptr++;
|
||||||
|
red = hex2num(color_ptr[0])*16 + hex2num(color_ptr[1]);
|
||||||
|
green = hex2num(color_ptr[2])*16 + hex2num(color_ptr[3]);
|
||||||
|
blue = hex2num(color_ptr[4])*16 + hex2num(color_ptr[5]);
|
||||||
|
return {red, green, blue};
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *texture = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CollisionPolygon {
|
||||||
|
public:
|
||||||
|
CollisionPolygon(double x, double y) {
|
||||||
|
original_x = x;
|
||||||
|
original_y = y;
|
||||||
|
position_x = 0;
|
||||||
|
position_y = 0;
|
||||||
|
}
|
||||||
|
virtual ~CollisionPolygon() {}
|
||||||
|
virtual bool colidesWith(const CollisionPolygon &other) const = 0;
|
||||||
|
virtual bool isCircle() const = 0;
|
||||||
|
virtual bool isInfinite() const = 0;
|
||||||
|
virtual int topmost() const = 0;
|
||||||
|
virtual int bottommost() const = 0;
|
||||||
|
virtual int leftmost() const = 0;
|
||||||
|
virtual int rightmost() const = 0;
|
||||||
|
virtual void updateCollision(int x, int y, int w, int h) {
|
||||||
|
position_x = original_x * w + x;
|
||||||
|
position_y = original_y * h + y;
|
||||||
|
}
|
||||||
|
int getX() const {
|
||||||
|
return position_x;
|
||||||
|
}
|
||||||
|
int getY() const {
|
||||||
|
return position_y;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
double original_x;
|
||||||
|
double original_y;
|
||||||
|
int position_x;
|
||||||
|
int position_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RenderObject {
|
||||||
|
public:
|
||||||
|
RenderObject(std::shared_ptr<Renderer> &r) : renderer(r) {}
|
||||||
|
virtual ~RenderObject() {}
|
||||||
|
virtual void render() = 0;
|
||||||
|
virtual int leftmost() = 0;
|
||||||
|
virtual int topmost() = 0;
|
||||||
|
virtual int collisionPushX() = 0;
|
||||||
|
virtual int collisionPushY() = 0;
|
||||||
|
virtual int collisionWidth() = 0;
|
||||||
|
virtual int collisionHeight() = 0;
|
||||||
|
bool colidesWith(const RenderObject &other) const {
|
||||||
|
if(!hasCollisions() || !other.hasCollisions()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for( const auto &x : collisions ) {
|
||||||
|
for( const auto &y : other.getCollisions() ) {
|
||||||
|
if(x->colidesWith(*y))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
void addCollision(const T &p) {
|
||||||
|
collisions.push_back(std::make_shared<T>(p));
|
||||||
|
collisions.back()->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
||||||
|
}
|
||||||
|
bool hasCollisions() const {
|
||||||
|
return !collisions.empty();
|
||||||
|
}
|
||||||
|
const std::vector<std::shared_ptr<CollisionPolygon>> &getCollisions() const {
|
||||||
|
return collisions;
|
||||||
|
}
|
||||||
|
void setTexture(std::shared_ptr<Texture> &t) {
|
||||||
|
texture = t;
|
||||||
|
}
|
||||||
|
void setTexture(const std::string &img_path) {
|
||||||
|
texture = std::make_shared<Texture>(renderer, img_path);
|
||||||
|
}
|
||||||
|
// per second, relative to window width
|
||||||
|
void setMovementSpeed(double speed) {
|
||||||
|
movementSpeed = speed;
|
||||||
|
}
|
||||||
|
void addMovement(int x, int y) {
|
||||||
|
movementDirection.first += x;
|
||||||
|
movementDirection.second += y;
|
||||||
|
}
|
||||||
|
void clearColided() {
|
||||||
|
colidedWith.clear();
|
||||||
|
}
|
||||||
|
void addColided(std::shared_ptr<RenderObject> &obj) {
|
||||||
|
colidedWith.push_back(obj);
|
||||||
|
}
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> &getColidedWith() {
|
||||||
|
return colidedWith;
|
||||||
|
}
|
||||||
|
void setId(uint64_t input_id) {
|
||||||
|
id = input_id;
|
||||||
|
}
|
||||||
|
uint64_t getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
virtual void move(int ticks) = 0;
|
||||||
|
virtual void updateSizeAndPosition() = 0;
|
||||||
|
protected:
|
||||||
|
std::vector<std::shared_ptr<CollisionPolygon>> collisions;
|
||||||
|
std::shared_ptr<Texture> texture;
|
||||||
|
std::shared_ptr<Renderer> renderer;
|
||||||
|
double movementSpeed;
|
||||||
|
std::pair<int,int> movementDirection;
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> colidedWith;
|
||||||
|
uint64_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Scene {
|
||||||
|
public:
|
||||||
|
Scene(std::shared_ptr<Renderer> &r) : renderer(r) {
|
||||||
|
SDL_SetRenderDrawColor(renderer->getRendererPtr(), 0xFF, 0xFF, 0xFF, 0xFF);
|
||||||
|
prev_ticks = SDL_GetTicks();
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
void addObject(std::shared_ptr<T> &obj) {
|
||||||
|
renderObjects.push_back(obj);
|
||||||
|
if(obj->hasCollisions()) {
|
||||||
|
collisionObjects.push_back(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::shared_ptr<RenderObject> getObject(int index) {
|
||||||
|
return renderObjects[index];
|
||||||
|
}
|
||||||
|
void movement() {
|
||||||
|
int now_ticks = SDL_GetTicks();
|
||||||
|
for( const auto &x : renderObjects ) {
|
||||||
|
x->move(now_ticks - prev_ticks);
|
||||||
|
}
|
||||||
|
prev_ticks = now_ticks;
|
||||||
|
}
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> getCollisions(RenderObject &r) {
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> ret{};
|
||||||
|
for(const auto &x : collisionObjects) {
|
||||||
|
if(x->colidesWith(r)) {
|
||||||
|
ret.push_back(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void renderScene() {
|
||||||
|
SDL_RenderClear(renderer->getRendererPtr());
|
||||||
|
SDL_RenderCopy(renderer->getRendererPtr(), background->getTexturePtr(), NULL, NULL);
|
||||||
|
for( const auto &x : renderObjects ) {
|
||||||
|
x->render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void presentScene() {
|
||||||
|
SDL_RenderPresent(renderer->getRendererPtr());
|
||||||
|
}
|
||||||
|
void setBackground(std::shared_ptr<Texture> bg) {
|
||||||
|
background = bg;
|
||||||
|
}
|
||||||
|
void setBackground(const std::string &img_path) {
|
||||||
|
background = std::make_shared<Texture>(renderer, img_path);
|
||||||
|
}
|
||||||
|
void updateSizeAndPosition() {
|
||||||
|
for( auto &x : renderObjects ) {
|
||||||
|
x->updateSizeAndPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> renderObjects;
|
||||||
|
std::vector<std::shared_ptr<RenderObject>> collisionObjects;
|
||||||
|
std::shared_ptr<Renderer> renderer;
|
||||||
|
std::shared_ptr<Texture> background;
|
||||||
|
int prev_ticks = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RectangleRender : public RenderObject {
|
||||||
|
public:
|
||||||
|
RectangleRender() = delete;
|
||||||
|
virtual ~RectangleRender() {};
|
||||||
|
RectangleRender(double x, double y, double w, double h, std::shared_ptr<Renderer> &r) : RenderObject(r) {
|
||||||
|
auto dimensions = renderer->getDimensions();
|
||||||
|
auto smaller_dimension = dimensions.first < dimensions.second ? dimensions.first : dimensions.second;
|
||||||
|
rect.x = x * dimensions.first;
|
||||||
|
rect.y = y * dimensions.second;
|
||||||
|
rect.w = w * smaller_dimension;
|
||||||
|
rect.h = h * smaller_dimension;
|
||||||
|
x_ = x;
|
||||||
|
y_ = y;
|
||||||
|
w_ = w;
|
||||||
|
h_ = h;
|
||||||
|
}
|
||||||
|
RectangleRender(int x, int y, int w, int h, std::shared_ptr<Renderer> &r, std::shared_ptr<Texture> &t) : RectangleRender(x, y, w, h, r) {
|
||||||
|
setTexture(t);
|
||||||
|
}
|
||||||
|
RectangleRender(int x, int y, int w, int h, std::shared_ptr<Renderer> &r, const std::string &img_path) : RectangleRender(x,y,w,h,r) {
|
||||||
|
auto texture = std::make_shared<Texture>(r, img_path);
|
||||||
|
setTexture(texture);
|
||||||
|
}
|
||||||
|
virtual void render() {
|
||||||
|
SDL_RenderCopy(renderer->getRendererPtr(), texture->getTexturePtr(), NULL, &rect);
|
||||||
|
}
|
||||||
|
virtual void move(int ticks) {
|
||||||
|
auto dimensions = renderer->getDimensions();
|
||||||
|
auto addx = static_cast<double>(movementSpeed * movementDirection.first)*(static_cast<double>(ticks)/1000);
|
||||||
|
auto addy = static_cast<double>(movementSpeed * movementDirection.second)*(static_cast<double>(ticks)/1000);
|
||||||
|
x_ += addx;
|
||||||
|
y_ += addy;
|
||||||
|
rect.x = x_ * dimensions.first;
|
||||||
|
rect.y = y_ * dimensions.second;
|
||||||
|
for( auto &x : collisions ) {
|
||||||
|
x->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual int leftmost() {
|
||||||
|
return rect.x;
|
||||||
|
}
|
||||||
|
virtual int topmost() {
|
||||||
|
return rect.y;
|
||||||
|
}
|
||||||
|
virtual int collisionPushX() {
|
||||||
|
return rect.x;
|
||||||
|
}
|
||||||
|
virtual int collisionPushY() {
|
||||||
|
return rect.y;
|
||||||
|
}
|
||||||
|
virtual int collisionWidth() {
|
||||||
|
return rect.w;
|
||||||
|
}
|
||||||
|
virtual int collisionHeight() {
|
||||||
|
return rect.h;
|
||||||
|
}
|
||||||
|
virtual void updateSizeAndPosition() {
|
||||||
|
auto dimensions = renderer->getDimensions();
|
||||||
|
auto smaller_dimension = dimensions.first < dimensions.second ? dimensions.first : dimensions.second;
|
||||||
|
rect.x = x_ * dimensions.first;
|
||||||
|
rect.y = y_ * dimensions.second;
|
||||||
|
rect.w = w_ * smaller_dimension;
|
||||||
|
rect.h = h_ * smaller_dimension;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
double x_;
|
||||||
|
double y_;
|
||||||
|
double w_;
|
||||||
|
double h_;
|
||||||
|
SDL_Rect rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CircleRender : public RenderObject {
|
||||||
|
public:
|
||||||
|
CircleRender() = delete;
|
||||||
|
virtual ~CircleRender() {};
|
||||||
|
CircleRender(int x, int y, int rad, std::shared_ptr<Renderer> &r) : RenderObject(r) {
|
||||||
|
x_ = x;
|
||||||
|
y_ = y;
|
||||||
|
rad_ = rad;
|
||||||
|
}
|
||||||
|
CircleRender(int x, int y, int rad, std::shared_ptr<Renderer> &r, std::shared_ptr<Texture> &t) : CircleRender(x,y,rad,r) {
|
||||||
|
setTexture(t);
|
||||||
|
}
|
||||||
|
CircleRender(int x, int y, int rad, std::shared_ptr<Renderer> &r, const std::string &img_path) : CircleRender(x,y,rad,r) {
|
||||||
|
auto texture = std::make_shared<Texture>(r, img_path);
|
||||||
|
setTexture(texture);
|
||||||
|
}
|
||||||
|
virtual void render();
|
||||||
|
virtual int leftmost() {
|
||||||
|
return x_-rad_;
|
||||||
|
}
|
||||||
|
virtual int topmost() {
|
||||||
|
return y_-rad_;
|
||||||
|
}
|
||||||
|
virtual int collisionPushX() {
|
||||||
|
return x_;
|
||||||
|
}
|
||||||
|
virtual int collisionPushY() {
|
||||||
|
return y_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int x_;
|
||||||
|
int y_;
|
||||||
|
int rad_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Rect : public CollisionPolygon {
|
||||||
|
public:
|
||||||
|
Rect(int x, int y, int w, int h) : CollisionPolygon(x, y) {
|
||||||
|
w_ = w;
|
||||||
|
h_ = h;
|
||||||
|
}
|
||||||
|
virtual ~Rect() {}
|
||||||
|
virtual bool colidesWith(const CollisionPolygon &other) const override;
|
||||||
|
virtual bool isCircle() const override { return false; }
|
||||||
|
virtual bool isInfinite() const override { return false; }
|
||||||
|
virtual int topmost() const override { return getY(); }
|
||||||
|
virtual int bottommost() const override { return getY() + pixel_h; };
|
||||||
|
virtual int leftmost() const override { return getX(); }
|
||||||
|
virtual int rightmost() const override { return getX() + pixel_w; }
|
||||||
|
virtual void updateCollision(int x, int y, int w, int h) override {
|
||||||
|
position_x = original_x * w + x;
|
||||||
|
position_y = original_y * h + y;
|
||||||
|
pixel_w = w_ * w;
|
||||||
|
pixel_h = h_ * h;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
double w_;
|
||||||
|
double h_;
|
||||||
|
int pixel_w;
|
||||||
|
int pixel_h;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circle : public CollisionPolygon {
|
||||||
|
public:
|
||||||
|
Circle(int x, int y, int rad) : CollisionPolygon(x, y) {
|
||||||
|
rad_ = rad;
|
||||||
|
}
|
||||||
|
virtual ~Circle() {}
|
||||||
|
virtual bool colidesWith(const CollisionPolygon &other) const;
|
||||||
|
virtual bool isCircle() const { return true; }
|
||||||
|
virtual bool isInfinite() const { return false; }
|
||||||
|
virtual int topmost() const { return getY() - rad_; }
|
||||||
|
virtual int bottommost() const { return getY() + rad_; };
|
||||||
|
virtual int leftmost() const { return getX() - rad_; }
|
||||||
|
virtual int rightmost() const { return getX() + rad_; }
|
||||||
|
private:
|
||||||
|
int getRadius() const {
|
||||||
|
return rad_;
|
||||||
|
}
|
||||||
|
int rad_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
bool init(uint32_t SDL_OPTIONS);
|
||||||
|
bool init(uint32_t SDL_OPTIONS, int IMAGE_OPTIONS);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void testPolymorphism(T &obj);
|
||||||
|
|
||||||
|
} // end of namespace SDLPP
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user