2020-07-26 20:37:20 +00:00
|
|
|
#ifndef SDLPP_HPP
|
|
|
|
#define SDLPP_HPP
|
|
|
|
|
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
#include <SDL2/SDL_image.h>
|
2020-08-22 11:17:56 +00:00
|
|
|
#include <SDL2/SDL_ttf.h>
|
2020-08-21 19:40:15 +00:00
|
|
|
#include <algorithm>
|
2020-08-21 18:53:21 +00:00
|
|
|
#include <cmath>
|
2020-07-26 20:37:20 +00:00
|
|
|
#include <iostream>
|
2020-07-28 17:35:31 +00:00
|
|
|
#include <limits>
|
2020-07-26 20:37:20 +00:00
|
|
|
#include <memory>
|
2020-08-21 19:40:15 +00:00
|
|
|
#include <mutex>
|
2020-08-22 23:08:10 +00:00
|
|
|
#include <unordered_set>
|
2020-07-26 20:37:20 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace SDLPP {
|
|
|
|
|
2020-08-21 16:32:15 +00:00
|
|
|
int hex2num(char c);
|
|
|
|
|
2020-08-22 11:17:56 +00:00
|
|
|
std::tuple<int, int, int, int> getColorsHEX(const std::string &color);
|
|
|
|
SDL_Color getSDLColorHEX(const std::string &color);
|
|
|
|
std::tuple<int, int, int, int> getColorsSDLColor(const SDL_Color &color);
|
|
|
|
SDL_Color getSDLColorTuple(const std::tuple<int, int, int, int> &tuple);
|
2020-08-21 16:32:15 +00:00
|
|
|
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
std::pair<int, int> getDimensions() const {
|
2020-07-26 20:37:20 +00:00
|
|
|
int width = 0, height = 0;
|
|
|
|
SDL_GetRendererOutputSize(renderer, &width, &height);
|
|
|
|
return {width, height};
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
int getWidth() const {
|
2020-07-28 12:46:48 +00:00
|
|
|
return getDimensions().first;
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
int getHeight() const {
|
2020-07-28 12:46:48 +00:00
|
|
|
return getDimensions().second;
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
int getSmallerSide() const {
|
2020-07-28 12:46:48 +00:00
|
|
|
auto dimensions = getDimensions();
|
|
|
|
return dimensions.first < dimensions.second ? dimensions.first : dimensions.second;
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
int getLargerSide() const {
|
2020-07-28 12:46:48 +00:00
|
|
|
auto dimensions = getDimensions();
|
|
|
|
return dimensions.first > dimensions.second ? dimensions.first : dimensions.second;
|
|
|
|
}
|
2020-08-21 16:32:15 +00:00
|
|
|
void setBlendMode(SDL_BlendMode blendMode) {
|
|
|
|
SDL_SetRenderDrawBlendMode(renderer, blendMode);
|
|
|
|
}
|
|
|
|
void setRenderColiders(bool render) {
|
|
|
|
render_coliders = render;
|
|
|
|
}
|
|
|
|
bool getRenderColiders() {
|
|
|
|
return render_coliders;
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
private:
|
|
|
|
SDL_Renderer *renderer = NULL;
|
2020-08-21 16:32:15 +00:00
|
|
|
bool render_coliders = false;
|
2020-07-26 20:37:20 +00:00
|
|
|
};
|
|
|
|
|
2020-08-22 11:17:56 +00:00
|
|
|
class Font {
|
|
|
|
public:
|
|
|
|
Font() = delete;
|
|
|
|
Font(const std::string &font, int size) {
|
|
|
|
font_ptr = TTF_OpenFont(font.c_str(), size);
|
2020-08-22 23:14:59 +00:00
|
|
|
if(font_ptr == NULL) {
|
|
|
|
std::cerr << "Unable to load font '" << font << "': TTF Error: " << TTF_GetError() << std::endl;
|
|
|
|
throw "TTF_OpenFont error";
|
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
}
|
|
|
|
~Font() {
|
|
|
|
TTF_CloseFont( font_ptr );
|
|
|
|
}
|
|
|
|
const TTF_Font *getFont() const {
|
|
|
|
return font_ptr;
|
|
|
|
}
|
|
|
|
TTF_Font *getFont() {
|
|
|
|
return font_ptr;
|
|
|
|
}
|
|
|
|
void setOutline(int size) {
|
|
|
|
TTF_SetFontOutline(font_ptr, size);
|
|
|
|
}
|
|
|
|
int getOutline() {
|
|
|
|
return TTF_GetFontOutline(font_ptr);
|
|
|
|
}
|
|
|
|
void setStyle(int style) {
|
|
|
|
TTF_SetFontStyle(font_ptr, style);
|
|
|
|
}
|
|
|
|
void setHinting(int hinting) {
|
|
|
|
TTF_SetFontHinting(font_ptr, hinting);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
TTF_Font *font_ptr;
|
|
|
|
};
|
|
|
|
|
2020-07-26 20:37:20 +00:00
|
|
|
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)));
|
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
setTextureFromSurface(renderer, surface);
|
|
|
|
}
|
|
|
|
Texture(std::shared_ptr<Renderer> &renderer, Font &font, const std::string &text, const std::string &color = "FFFFFF", const std::string &outline_color = "000000", const int outline_size = -1) {
|
|
|
|
if(outline_size != -1) {
|
|
|
|
font.setOutline(outline_size);
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
int og_outline = 0;
|
|
|
|
SDL_Surface *bg_surface = NULL;
|
|
|
|
if((og_outline = font.getOutline()) != 0) {
|
|
|
|
bg_surface = TTF_RenderUTF8_Blended( font.getFont(), text.c_str(), getSDLColorHEX(outline_color) );
|
|
|
|
if( bg_surface == NULL ) {
|
|
|
|
std::cerr << "Unable to render text '" << text << "': TTF Error: " << TTF_GetError() << std::endl;
|
|
|
|
throw "TTF_RenderUTF8_Shaded error";
|
|
|
|
}
|
|
|
|
font.setOutline(0);
|
|
|
|
}
|
|
|
|
SDL_Surface *surface = TTF_RenderUTF8_Blended( font.getFont(), text.c_str(), getSDLColorHEX(color) );
|
|
|
|
if( surface == NULL ) {
|
|
|
|
std::cerr << "Unable to render text '" << text << "': TTF Error: " << TTF_GetError() << std::endl;
|
|
|
|
throw "TTF_RenderUTF8_Shaded error";
|
|
|
|
}
|
|
|
|
if(og_outline != 0) {
|
|
|
|
SDL_Rect rect = {og_outline, og_outline, surface->w, surface->h};
|
|
|
|
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
|
|
|
|
SDL_BlitSurface(surface, NULL, bg_surface, &rect);
|
|
|
|
SDL_FreeSurface(surface);
|
|
|
|
surface = bg_surface;
|
|
|
|
bg_surface = NULL;
|
|
|
|
font.setOutline(og_outline);
|
|
|
|
}
|
|
|
|
setTextureFromSurface(renderer, surface);
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
|
|
|
~Texture() {
|
|
|
|
SDL_DestroyTexture(texture);
|
|
|
|
}
|
|
|
|
SDL_Texture *getTexturePtr() {
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
private:
|
2020-08-22 11:17:56 +00:00
|
|
|
void setTextureFromSurface(std::shared_ptr<Renderer> &renderer, SDL_Surface *surface) {
|
|
|
|
texture = SDL_CreateTextureFromSurface(renderer->getRendererPtr(), surface);
|
|
|
|
if( texture == NULL ) {
|
|
|
|
std::cerr << "Unable to create texture from surface! SDL Error: " << SDL_GetError() << std::endl;
|
|
|
|
throw "Texture error";
|
|
|
|
}
|
|
|
|
SDL_FreeSurface(surface);
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
2020-07-28 17:35:31 +00:00
|
|
|
virtual bool isInfinite() const { return infinite; }
|
|
|
|
virtual void setInfinite() { infinite = true; }
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
virtual void render(Renderer &renderer, const std::tuple<int,int,int,int> &color) = 0;
|
|
|
|
virtual void render(Renderer &renderer) = 0;
|
2020-07-26 20:37:20 +00:00
|
|
|
int getX() const {
|
|
|
|
return position_x;
|
|
|
|
}
|
|
|
|
int getY() const {
|
|
|
|
return position_y;
|
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
void setColor(const std::string &color) {
|
|
|
|
sdl_color = getSDLColorHEX(color);
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
void setOutlineColor(const std::string &color) {
|
|
|
|
sdl_outline = getSDLColorHEX(color);
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
protected:
|
|
|
|
double original_x;
|
|
|
|
double original_y;
|
|
|
|
int position_x;
|
|
|
|
int position_y;
|
2020-07-28 17:35:31 +00:00
|
|
|
bool infinite = false;
|
2020-08-22 23:08:10 +00:00
|
|
|
SDL_Color sdl_color = {0,0,0,0};
|
|
|
|
SDL_Color sdl_outline = {0,0,0,0};
|
2020-07-26 20:37:20 +00:00
|
|
|
};
|
|
|
|
|
2020-08-21 19:40:15 +00:00
|
|
|
class Scene;
|
|
|
|
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
2020-07-28 17:35:31 +00:00
|
|
|
virtual int rightmost() = 0;
|
|
|
|
virtual int bottommost() = 0;
|
2020-07-26 20:37:20 +00:00
|
|
|
virtual int collisionPushX() = 0;
|
|
|
|
virtual int collisionPushY() = 0;
|
|
|
|
virtual int collisionWidth() = 0;
|
|
|
|
virtual int collisionHeight() = 0;
|
2020-08-21 19:40:15 +00:00
|
|
|
virtual void specialAction(int code) = 0;
|
2020-07-27 18:05:59 +00:00
|
|
|
virtual std::pair<std::pair<double,double>,std::pair<double,double>> getDoubleRect() = 0;
|
|
|
|
virtual void setPos(double x, double y) = 0;
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual std::pair<double, double> getPos() = 0;
|
2020-07-26 20:37:20 +00:00
|
|
|
bool colidesWith(const RenderObject &other) const {
|
2020-08-21 16:54:42 +00:00
|
|
|
if(!hasCollisions() || !other.hasCollisions() || getHidden() || other.getHidden()) {
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setTexture(std::shared_ptr<Texture> &t) {
|
2020-07-26 20:37:20 +00:00
|
|
|
texture = t;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setTexture(const std::string &img_path) {
|
2020-07-26 20:37:20 +00:00
|
|
|
texture = std::make_shared<Texture>(renderer, img_path);
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setTexture(Font &font, const std::string &text, const std::string &color = "FFFFFF", const std::string &outline_color = "000000", int outline_size = -1) {
|
2020-08-22 11:17:56 +00:00
|
|
|
texture = std::make_shared<Texture>(renderer, font, text, color, outline_color, outline_size);
|
|
|
|
}
|
2020-08-22 12:29:39 +00:00
|
|
|
virtual void setColor(const std::string &color) = 0;
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setOutlineColor(const std::string &color) = 0;
|
2020-08-22 12:29:39 +00:00
|
|
|
virtual void unsetTexture() {
|
|
|
|
texture.reset();
|
|
|
|
}
|
|
|
|
virtual void unsetColor() {
|
|
|
|
polygon.reset();
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
// per second, relative to window width
|
|
|
|
void setMovementSpeed(double speed) {
|
|
|
|
movementSpeed = speed;
|
|
|
|
}
|
|
|
|
void addMovement(int x, int y) {
|
|
|
|
movementDirection.first += x;
|
|
|
|
movementDirection.second += y;
|
|
|
|
}
|
2020-08-22 12:13:28 +00:00
|
|
|
void resetMovementX() {
|
|
|
|
movementDirection.first = 0;
|
|
|
|
}
|
|
|
|
void resetMovementY() {
|
|
|
|
movementDirection.second = 0;
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-08-21 16:32:15 +00:00
|
|
|
void setHidden(bool hid) {
|
|
|
|
hidden = hid;
|
|
|
|
}
|
2020-08-21 16:54:42 +00:00
|
|
|
bool getHidden() const {
|
2020-08-21 16:32:15 +00:00
|
|
|
return hidden;
|
|
|
|
}
|
2020-08-21 19:40:15 +00:00
|
|
|
void destroy() {
|
|
|
|
setHidden(true);
|
|
|
|
kill = true;
|
|
|
|
}
|
|
|
|
bool getKilled() {
|
|
|
|
return kill;
|
|
|
|
}
|
2020-08-21 16:32:15 +00:00
|
|
|
void setColiderColor(const std::string &color) {
|
|
|
|
colider_color = getColorsHEX(color);
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
virtual void move(int ticks) = 0;
|
2020-08-22 12:13:28 +00:00
|
|
|
virtual void custom_move(int ticks) = 0;
|
2020-07-26 20:37:20 +00:00
|
|
|
virtual void updateSizeAndPosition() = 0;
|
2020-07-28 17:35:31 +00:00
|
|
|
virtual SDL_Rect getRect() = 0;
|
2020-08-22 11:17:56 +00:00
|
|
|
void setPermanent(bool perm) {
|
|
|
|
permanent = perm;
|
|
|
|
}
|
|
|
|
bool getPermanent() const {
|
|
|
|
return permanent;
|
|
|
|
}
|
2020-08-22 12:13:28 +00:00
|
|
|
virtual void centerX() = 0;
|
2020-07-26 20:37:20 +00:00
|
|
|
protected:
|
|
|
|
std::vector<std::shared_ptr<CollisionPolygon>> collisions;
|
|
|
|
std::shared_ptr<Texture> texture;
|
|
|
|
std::shared_ptr<Renderer> renderer;
|
2020-08-22 11:17:56 +00:00
|
|
|
std::shared_ptr<CollisionPolygon> polygon;
|
2020-07-26 20:37:20 +00:00
|
|
|
double movementSpeed;
|
|
|
|
std::pair<int,int> movementDirection;
|
|
|
|
std::vector<std::shared_ptr<RenderObject>> colidedWith;
|
|
|
|
uint64_t id;
|
2020-08-21 16:32:15 +00:00
|
|
|
bool hidden = false;
|
2020-08-21 19:40:15 +00:00
|
|
|
bool kill = false;
|
2020-08-22 11:17:56 +00:00
|
|
|
std::tuple<int,int,int,int> colider_color = {0x00, 0xFF, 0xFF, 0xFF};
|
2020-08-21 19:40:15 +00:00
|
|
|
uint64_t scene_id;
|
2020-08-22 11:17:56 +00:00
|
|
|
bool permanent = false;
|
2020-08-21 19:40:15 +00:00
|
|
|
private:
|
|
|
|
void setSceneID(int id) {
|
|
|
|
scene_id = id;
|
|
|
|
}
|
|
|
|
friend Scene;
|
2020-07-26 20:37:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Scene {
|
|
|
|
public:
|
|
|
|
Scene(std::shared_ptr<Renderer> &r) : renderer(r) {
|
|
|
|
SDL_SetRenderDrawColor(renderer->getRendererPtr(), 0xFF, 0xFF, 0xFF, 0xFF);
|
|
|
|
prev_ticks = SDL_GetTicks();
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
void addObject(const std::shared_ptr<RenderObject> &obj) {
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.lock();
|
2020-07-26 20:37:20 +00:00
|
|
|
renderObjects.push_back(obj);
|
2020-08-21 19:40:15 +00:00
|
|
|
obj->setSceneID(++max_object_id);
|
2020-07-26 20:37:20 +00:00
|
|
|
if(obj->hasCollisions()) {
|
|
|
|
collisionObjects.push_back(obj);
|
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
|
|
|
|
if(renderObjects.size() == 1) {
|
|
|
|
leftmost_obj = obj;
|
|
|
|
rightmost_obj = obj;
|
|
|
|
} else {
|
|
|
|
auto rect = obj->getDoubleRect();
|
|
|
|
auto leftmost_rect = leftmost_obj->getDoubleRect();
|
|
|
|
if(rect.first.first < leftmost_rect.first.first)
|
|
|
|
leftmost_obj = obj;
|
|
|
|
auto rightmost_rect = rightmost_obj->getDoubleRect();
|
|
|
|
if(rect.first.first + rect.second.first > rightmost_rect.first.first + rightmost_rect.second.first)
|
|
|
|
rightmost_obj = obj;
|
|
|
|
}
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.unlock();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
|
|
|
std::shared_ptr<RenderObject> getObject(int index) {
|
|
|
|
return renderObjects[index];
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
std::vector<std::shared_ptr<RenderObject>> getObjects() {
|
|
|
|
return renderObjects;
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
void movement() {
|
2020-08-21 19:40:15 +00:00
|
|
|
checkKilled();
|
|
|
|
render_mutex.lock();
|
2020-07-26 20:37:20 +00:00
|
|
|
int now_ticks = SDL_GetTicks();
|
|
|
|
for( const auto &x : renderObjects ) {
|
|
|
|
x->move(now_ticks - prev_ticks);
|
|
|
|
}
|
|
|
|
prev_ticks = now_ticks;
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.unlock();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
|
|
|
std::vector<std::shared_ptr<RenderObject>> getCollisions(RenderObject &r) {
|
2020-08-21 16:54:42 +00:00
|
|
|
if(r.getHidden())
|
|
|
|
return {};
|
2020-07-26 20:37:20 +00:00
|
|
|
std::vector<std::shared_ptr<RenderObject>> ret{};
|
|
|
|
for(const auto &x : collisionObjects) {
|
|
|
|
if(x->colidesWith(r)) {
|
|
|
|
ret.push_back(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
std::vector<std::shared_ptr<RenderObject>> getCollisions( RenderObject &r, const std::unordered_set<int> &objectIDs ) {
|
|
|
|
if(r.getHidden())
|
|
|
|
return {};
|
|
|
|
std::vector<std::shared_ptr<RenderObject>> ret{};
|
|
|
|
for(const auto &x : collisionObjects) {
|
|
|
|
if(objectIDs.find(x->getId()) != objectIDs.end() && x->colidesWith(r)) {
|
|
|
|
ret.push_back(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2020-08-22 12:13:28 +00:00
|
|
|
void renderScene(bool clear_scene = true) {
|
2020-08-21 19:40:15 +00:00
|
|
|
checkKilled();
|
|
|
|
render_mutex.lock();
|
2020-08-22 12:13:28 +00:00
|
|
|
if(clear_scene)
|
|
|
|
SDL_RenderClear(renderer->getRendererPtr());
|
2020-08-22 11:17:56 +00:00
|
|
|
if(background && background->getTexturePtr())
|
|
|
|
SDL_RenderCopy(renderer->getRendererPtr(), background->getTexturePtr(), NULL, NULL);
|
2020-07-26 20:37:20 +00:00
|
|
|
for( const auto &x : renderObjects ) {
|
|
|
|
x->render();
|
|
|
|
}
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.unlock();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
|
|
|
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() {
|
2020-08-21 19:40:15 +00:00
|
|
|
checkKilled();
|
|
|
|
render_mutex.lock();
|
2020-07-26 20:37:20 +00:00
|
|
|
for( auto &x : renderObjects ) {
|
|
|
|
x->updateSizeAndPosition();
|
2020-08-21 17:49:42 +00:00
|
|
|
for( auto &col : x->getCollisions() ) {
|
|
|
|
col->updateCollision(x->collisionPushX(), x->collisionPushY(), x->collisionWidth(), x->collisionHeight());
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.unlock();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-07-28 17:35:31 +00:00
|
|
|
void moveEverything(double x, double y) {
|
2020-08-21 19:40:15 +00:00
|
|
|
checkKilled();
|
|
|
|
render_mutex.lock();
|
2020-07-28 17:35:31 +00:00
|
|
|
for( auto &obj : renderObjects ) {
|
2020-08-22 23:08:10 +00:00
|
|
|
if(obj->getPermanent())
|
|
|
|
continue;
|
2020-07-28 17:35:31 +00:00
|
|
|
auto curPos = obj->getDoubleRect();
|
|
|
|
obj->setPos( curPos.first.first + x, curPos.first.second + y );
|
|
|
|
}
|
2020-08-21 19:40:15 +00:00
|
|
|
render_mutex.unlock();
|
2020-07-28 17:35:31 +00:00
|
|
|
}
|
|
|
|
const std::shared_ptr<RenderObject> &leftmost() {
|
|
|
|
return leftmost_obj;
|
|
|
|
}
|
|
|
|
const std::shared_ptr<RenderObject> &rightmost() {
|
|
|
|
return rightmost_obj;
|
|
|
|
}
|
|
|
|
std::pair<int, int> getDimensions() const {
|
|
|
|
return renderer->getDimensions();
|
|
|
|
}
|
|
|
|
int getWidth() const {
|
|
|
|
return renderer->getWidth();
|
|
|
|
}
|
|
|
|
int getHeight() const {
|
|
|
|
return renderer->getHeight();
|
|
|
|
}
|
2020-08-21 16:32:15 +00:00
|
|
|
Renderer &getRenderer() {
|
|
|
|
return *renderer;
|
|
|
|
}
|
2020-08-21 16:54:42 +00:00
|
|
|
void setPrevTicks(int ticks) {
|
|
|
|
prev_ticks = ticks;
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
private:
|
2020-08-21 19:40:15 +00:00
|
|
|
void checkKilled() {
|
|
|
|
render_mutex.lock();
|
|
|
|
std::vector<int> killed;
|
|
|
|
for( long unsigned int i = 0; i < renderObjects.size(); i++ ) {
|
|
|
|
if(renderObjects[i]->getKilled())
|
|
|
|
killed.push_back(i);
|
|
|
|
}
|
|
|
|
std::reverse(killed.begin(), killed.end());
|
|
|
|
for(auto &index : killed) {
|
|
|
|
renderObjects.erase(renderObjects.begin() + index);
|
|
|
|
}
|
|
|
|
render_mutex.unlock();
|
|
|
|
}
|
|
|
|
|
2020-07-26 20:37:20 +00:00
|
|
|
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;
|
2020-07-28 17:35:31 +00:00
|
|
|
std::shared_ptr<RenderObject> leftmost_obj;
|
|
|
|
std::shared_ptr<RenderObject> rightmost_obj;
|
2020-08-21 19:40:15 +00:00
|
|
|
uint64_t max_object_id = 0;
|
|
|
|
std::mutex render_mutex;
|
2020-07-26 20:37:20 +00:00
|
|
|
};
|
|
|
|
|
2020-08-22 11:17:56 +00:00
|
|
|
class Rect : public CollisionPolygon {
|
|
|
|
public:
|
|
|
|
Rect(double x, double y, double w, double 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 int topmost() const override {
|
|
|
|
return (!isInfinite() || original_y != -1) * getY() + isInfinite() * -1;
|
|
|
|
}
|
|
|
|
virtual int bottommost() const override {
|
|
|
|
return (!isInfinite() || h_ != -1) * (getY() + pixel_h) + isInfinite() * -1;
|
|
|
|
};
|
|
|
|
virtual int leftmost() const override {
|
|
|
|
return (!isInfinite() || original_x != -1) * getX() + isInfinite() * -1;
|
|
|
|
}
|
|
|
|
virtual int rightmost() const override {
|
|
|
|
return (!isInfinite() || w_ != -1) * (getX() + pixel_w) + isInfinite() * -1;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
virtual void render(Renderer &renderer, const std::tuple<int,int,int,int> &color) override {
|
|
|
|
auto rect = getRect();
|
|
|
|
// outline with desired color at 50% opacity
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), std::get<0>(color), std::get<1>(color), std::get<2>(color), 0x80);
|
|
|
|
SDL_RenderDrawRect(renderer.getRendererPtr(), &rect);
|
|
|
|
// fill with desired color at 25% opacity
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), std::get<0>(color), std::get<1>(color), std::get<2>(color), 0x40);
|
|
|
|
SDL_RenderFillRect(renderer.getRendererPtr(), &rect);
|
|
|
|
}
|
|
|
|
virtual void render(Renderer &renderer) override {
|
|
|
|
auto rect = getRect();
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a);
|
|
|
|
SDL_RenderFillRect(renderer.getRendererPtr(), &rect);
|
2020-08-22 23:08:10 +00:00
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), sdl_outline.r, sdl_outline.g, sdl_outline.b, sdl_outline.a);
|
|
|
|
SDL_RenderDrawRect(renderer.getRendererPtr(), &rect);
|
2020-08-22 11:17:56 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
SDL_Rect getRect() {
|
|
|
|
if( !isInfinite() )
|
|
|
|
return {leftmost(), topmost(), pixel_w, pixel_h};
|
|
|
|
|
|
|
|
SDL_Rect r = {0,0,0,0};
|
|
|
|
if((r.x = leftmost()) == -1)
|
|
|
|
r.x = 0;
|
|
|
|
if((r.y = topmost()) == -1)
|
|
|
|
r.y = 0;
|
|
|
|
if(rightmost() == -1)
|
|
|
|
r.w = std::numeric_limits<int>::max();
|
|
|
|
else
|
|
|
|
r.w = pixel_w;
|
|
|
|
if(bottommost() == -1)
|
|
|
|
r.h = std::numeric_limits<int>::max();
|
|
|
|
else
|
|
|
|
r.h = pixel_h;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
double w_;
|
|
|
|
double h_;
|
|
|
|
int pixel_w;
|
|
|
|
int pixel_h;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Circle : public CollisionPolygon {
|
|
|
|
public:
|
|
|
|
Circle(double x, double y, double rad) : CollisionPolygon(x, y) {
|
|
|
|
original_rad = rad;
|
|
|
|
}
|
|
|
|
virtual ~Circle() {}
|
|
|
|
virtual bool colidesWith(const CollisionPolygon &other) const override;
|
|
|
|
virtual bool isCircle() const override { return true; }
|
|
|
|
virtual int topmost() const override { return getY() - rad_; }
|
|
|
|
virtual int bottommost() const override { return getY() + rad_; };
|
|
|
|
virtual int leftmost() const override { return getX() - rad_; }
|
|
|
|
virtual int rightmost() const override { return getX() + rad_; }
|
|
|
|
virtual void updateCollision(int x, int y, int w, int h) override {
|
|
|
|
position_x = original_x * w + x;
|
|
|
|
position_y = original_y * h + y;
|
|
|
|
rad_ = original_rad * w;
|
|
|
|
}
|
|
|
|
virtual void render(Renderer &renderer, const std::tuple<int,int,int,int> &color) override {
|
|
|
|
std::vector<int> rect = {leftmost(), topmost(), rightmost(), bottommost()};
|
|
|
|
auto center_x = getX();
|
|
|
|
auto center_y = getY();
|
|
|
|
auto radsq = rad_ * rad_;
|
|
|
|
for(int i = rect[0]; i <= rect[2]; i++) {
|
|
|
|
auto xdiff = center_x - i;
|
|
|
|
auto xdist = xdiff * xdiff;
|
|
|
|
auto allowed_rad = sqrt(radsq - xdist);
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), std::get<0>(color), std::get<1>(color), std::get<2>(color), 0x40);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y - allowed_rad, i, center_y + allowed_rad);
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), std::get<0>(color), std::get<1>(color), std::get<2>(color), 0x80);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y - allowed_rad, i, center_y - allowed_rad + 2);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y + allowed_rad, i, center_y + allowed_rad - 2);
|
|
|
|
}
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), 0xFF, 0, 0, 0xFF);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), center_x, center_y, center_x + rad_, center_y);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), center_x, center_y, center_x, center_y + rad_);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), center_x, center_y, center_x - rad_, center_y);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), center_x, center_y, center_x, center_y - rad_);
|
|
|
|
}
|
|
|
|
virtual void render(Renderer &renderer) override {
|
|
|
|
std::vector<int> rect = {leftmost(), topmost(), rightmost(), bottommost()};
|
|
|
|
auto center_x = getX();
|
|
|
|
auto center_y = getY();
|
|
|
|
auto radsq = rad_ * rad_;
|
|
|
|
for(int i = rect[0]; i <= rect[2]; i++) {
|
|
|
|
auto xdiff = center_x - i;
|
|
|
|
auto xdist = xdiff * xdiff;
|
|
|
|
auto allowed_rad = sqrt(radsq - xdist);
|
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y - allowed_rad, i, center_y + allowed_rad);
|
2020-08-22 23:08:10 +00:00
|
|
|
SDL_SetRenderDrawColor(renderer.getRendererPtr(), sdl_outline.r, sdl_outline.g, sdl_outline.b, sdl_outline.a);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y - allowed_rad, i, center_y - allowed_rad + 2);
|
|
|
|
SDL_RenderDrawLine(renderer.getRendererPtr(), i, center_y + allowed_rad, i, center_y + allowed_rad - 2);
|
2020-08-22 11:17:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
int getRadius() const {
|
|
|
|
return rad_;
|
|
|
|
}
|
|
|
|
double original_rad;
|
|
|
|
int rad_;
|
|
|
|
};
|
|
|
|
|
2020-07-26 20:37:20 +00:00
|
|
|
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) {
|
2020-08-22 12:13:28 +00:00
|
|
|
og_x = x_ = x;
|
|
|
|
og_y = y_ = y;
|
|
|
|
og_w = w_ = w;
|
|
|
|
og_h = h_ = h;
|
2020-08-22 23:08:10 +00:00
|
|
|
updateSizeAndPosition();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
RectangleRender(double x, double y, double w, double h, std::shared_ptr<Renderer> &r, std::shared_ptr<Texture> &t) : RectangleRender(x, y, w, h, r) {
|
2020-07-26 20:37:20 +00:00
|
|
|
setTexture(t);
|
|
|
|
}
|
2020-08-22 11:17:56 +00:00
|
|
|
RectangleRender(double x, double y, double w, double h, std::shared_ptr<Renderer> &r, const std::string &img_or_color, bool is_polygon = false) : RectangleRender(x,y,w,h,r) {
|
|
|
|
if(!is_polygon) {
|
2020-08-22 12:13:28 +00:00
|
|
|
setTexture(img_or_color);
|
2020-08-22 11:17:56 +00:00
|
|
|
} else {
|
2020-08-22 12:13:28 +00:00
|
|
|
setColor(img_or_color);
|
2020-08-22 11:17:56 +00:00
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setColor(const std::string &color) override {
|
|
|
|
if(!polygon) {
|
|
|
|
polygon = std::make_shared<Rect>(0,0,1,1);
|
|
|
|
polygon->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
|
|
|
}
|
2020-08-22 12:13:28 +00:00
|
|
|
polygon->setColor(color);
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setOutlineColor(const std::string &color) override {
|
|
|
|
if(!polygon) {
|
|
|
|
polygon = std::make_shared<Rect>(0,0,1,1);
|
|
|
|
polygon->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
|
|
|
}
|
|
|
|
polygon->setOutlineColor(color);
|
|
|
|
}
|
|
|
|
virtual void specialAction(int /*UNUSED*/) override {};
|
|
|
|
virtual void render() override {
|
|
|
|
if(!getHidden()) {
|
|
|
|
if(polygon)
|
|
|
|
polygon->render(*renderer);
|
|
|
|
if(texture != NULL)
|
|
|
|
SDL_RenderCopy(renderer->getRendererPtr(), texture->getTexturePtr(), NULL, &rect);
|
2020-08-22 12:15:12 +00:00
|
|
|
}
|
2020-08-21 16:54:42 +00:00
|
|
|
if(hasCollisions() && renderer->getRenderColiders() && !getHidden()) {
|
2020-08-21 16:32:15 +00:00
|
|
|
for(const auto &col : getCollisions())
|
|
|
|
col->render(*renderer, colider_color);
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void move(int ticks) override {
|
2020-08-22 11:17:56 +00:00
|
|
|
if(permanent)
|
|
|
|
return;
|
2020-07-26 20:37:20 +00:00
|
|
|
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);
|
2020-08-22 23:08:10 +00:00
|
|
|
if(std::isnan(addx) || std::isnan(addy))
|
|
|
|
return;
|
|
|
|
|
|
|
|
og_x += addx;
|
|
|
|
og_y += addy;
|
2020-08-22 12:13:28 +00:00
|
|
|
|
|
|
|
custom_move(ticks);
|
|
|
|
|
2020-08-22 23:08:10 +00:00
|
|
|
updateSizeAndPosition();
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void custom_move(int /*UNUSED*/) override {}
|
|
|
|
virtual std::pair<std::pair<double,double>,std::pair<double,double>> getDoubleRect() override {
|
|
|
|
return {{og_x,og_y}, {og_w,og_h}};
|
2020-07-27 18:05:59 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void setPos(double x, double y) override {
|
|
|
|
og_x = x;
|
|
|
|
og_y = y;
|
|
|
|
updateSizeAndPosition();
|
2020-07-27 18:05:59 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual std::pair<double, double> getPos() override {
|
|
|
|
return {og_x, og_y};
|
|
|
|
}
|
|
|
|
virtual int leftmost() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.x;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int topmost() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.y;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int rightmost() override {
|
2020-07-28 17:35:31 +00:00
|
|
|
return rect.x + rect.w;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int bottommost() override {
|
2020-07-28 17:35:31 +00:00
|
|
|
return rect.y + rect.h;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int collisionPushX() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.x;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int collisionPushY() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.y;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int collisionWidth() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.w;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual int collisionHeight() override {
|
2020-07-26 20:37:20 +00:00
|
|
|
return rect.h;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void updateSizeAndPosition() override {
|
|
|
|
updateXY();
|
2020-07-28 12:46:48 +00:00
|
|
|
auto dimension = renderer->getSmallerSide();
|
|
|
|
rect.x = x_ * dimension;
|
|
|
|
rect.y = y_ * dimension;
|
|
|
|
rect.w = w_ * dimension;
|
|
|
|
rect.h = h_ * dimension;
|
2020-08-22 11:17:56 +00:00
|
|
|
if(polygon)
|
|
|
|
polygon->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
2020-08-22 23:08:10 +00:00
|
|
|
for( auto &x : collisions ) {
|
|
|
|
x->updateCollision(collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight());
|
|
|
|
}
|
2020-07-26 20:37:20 +00:00
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual SDL_Rect getRect() override {
|
2020-07-28 17:35:31 +00:00
|
|
|
return rect;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
virtual void centerX() override {
|
2020-08-22 12:13:28 +00:00
|
|
|
centerx = true;
|
|
|
|
updateSizeAndPosition();
|
|
|
|
}
|
2020-07-27 18:05:59 +00:00
|
|
|
protected:
|
2020-08-22 23:08:10 +00:00
|
|
|
void updateXY() {
|
|
|
|
if(!centerx) {
|
|
|
|
x_ = og_x;
|
|
|
|
y_ = og_y;
|
|
|
|
return;
|
|
|
|
}
|
2020-08-22 12:13:28 +00:00
|
|
|
auto width = renderer->getWidth();
|
|
|
|
auto height = renderer->getHeight();
|
|
|
|
if(width > height) {
|
|
|
|
auto multiplier = static_cast<double>(width)/static_cast<double>(height);
|
2020-08-22 23:08:10 +00:00
|
|
|
x_ = og_x + static_cast<double>(multiplier - 1)/2;
|
2020-08-22 12:13:28 +00:00
|
|
|
} else {
|
|
|
|
x_ = og_x;
|
|
|
|
}
|
2020-08-22 23:08:10 +00:00
|
|
|
y_ = og_y;
|
2020-08-22 12:13:28 +00:00
|
|
|
}
|
|
|
|
double og_x;
|
|
|
|
double og_y;
|
|
|
|
double og_w;
|
|
|
|
double og_h;
|
2020-07-26 20:37:20 +00:00
|
|
|
double x_;
|
|
|
|
double y_;
|
|
|
|
double w_;
|
|
|
|
double h_;
|
2020-08-22 12:13:28 +00:00
|
|
|
bool centerx = false;
|
2020-07-26 20:37:20 +00:00
|
|
|
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_;
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|