diff --git a/sdlpp/Makefile b/sdlpp/Makefile new file mode 100644 index 0000000..1f7ca37 --- /dev/null +++ b/sdlpp/Makefile @@ -0,0 +1,27 @@ +CXX ?= g++ +CPPFLAGS = -std=c++14 -Wall -Wextra -pedantic +LIBRARYFLAGS = -fPIC + +MAJOR ?= 1 +MINOR ?= 0 +RELEASE ?= 0 + +SDLPPLIBRARY = libsdlpp.so.${MAJOR}.${MINOR}.${RELEASE} + +OBJECTFILES = sdlpp_circlecolider.o sdlpp_circlerenderer.o sdlpp_collision.o sdlpp_common.o sdlpp_font.o sdlpp_linerenderer.o sdlpp_rectcolider.o sdlpp_rectrenderer.o sdlpp_renderer.o sdlpp_renderobject.o sdlpp_scene.o sdlpp_textrenderer.o sdlpp_texture.o sdlpp_window.o + +all: ${SDLPPLIBRARY} + +%.o: %.cpp + ${CXX} ${CPPFLAGS} ${LIBRARYFLAGS} -c $< -o $@ + +${SDLPPLIBRARY}: ${OBJECTFILES} + ${CXX} ${CPPFLAGS} -shared -Wl,-soname,libsdlpp.so.${MAJOR}\ + -o ${SDLPPLIBRARY} $^ + ln -sf ${SDLPPLIBRARY} libsdlpp.so + ln -sf ${SDLPPLIBRARY} libsdlpp.so.${MAJOR} + +clean: + ${RM} *.so* *.o + +.PHONY: all clean test diff --git a/sdlpp/sdlpp.hpp b/sdlpp/sdlpp.hpp new file mode 100644 index 0000000..b6a32c1 --- /dev/null +++ b/sdlpp/sdlpp.hpp @@ -0,0 +1,20 @@ +#ifndef SDLPP_HPP +#define SDLPP_HPP + +#include "sdlpp_common.hpp" + +#include "sdlpp_collision.hpp" +#include "sdlpp_circlecolider.hpp" +#include "sdlpp_circlerenderer.hpp" +#include "sdlpp_font.hpp" +#include "sdlpp_linerenderer.hpp" +#include "sdlpp_scene.hpp" +#include "sdlpp_rectcolider.hpp" +#include "sdlpp_rectrenderer.hpp" +#include "sdlpp_renderer.hpp" +#include "sdlpp_renderobject.hpp" +#include "sdlpp_textrenderer.hpp" +#include "sdlpp_texture.hpp" +#include "sdlpp_window.hpp" + +#endif diff --git a/sdlpp/sdlpp_circlecolider.cpp b/sdlpp/sdlpp_circlecolider.cpp new file mode 100644 index 0000000..e26eed7 --- /dev/null +++ b/sdlpp/sdlpp_circlecolider.cpp @@ -0,0 +1,133 @@ +// TODO render function like in rectangle +#include "sdlpp_circlecolider.hpp" + +namespace SDLPP { +CircleColider::CircleColider( double x, double y, double rad ) + : CollisionPolygon( x, y ) { + original_rad = rad; +} + +bool CircleColider::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; +} + +bool CircleColider::isCircle() const { + return true; +} +int CircleColider::topmost() const { + return getY() - rad_; +} +int CircleColider::bottommost() const { + return getY() + rad_; +} +int CircleColider::leftmost() const { + return getX() - rad_; +} +int CircleColider::rightmost() const { + return getX() + rad_; +} + +void CircleColider::updateCollision( int x, int y, int w, int h ) { + position_x = original_x * w + x; + position_y = original_y * h + y; + rad_ = original_rad * w; +} + +void CircleColider::render( Renderer &renderer, + const std::tuple< int, int, int, int > &color ) { + 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_ ); +} +void CircleColider::render( Renderer &renderer ) { + 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 ); + 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 ); + } +} + +int CircleColider::getRadius() const { + return rad_; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_circlecolider.hpp b/sdlpp/sdlpp_circlecolider.hpp new file mode 100644 index 0000000..64019d7 --- /dev/null +++ b/sdlpp/sdlpp_circlecolider.hpp @@ -0,0 +1,34 @@ +#ifndef SDLPP_HPP_CIRCLE +#define SDLPP_HPP_CIRCLE + +#include + +#include "sdlpp_common.hpp" +#include "sdlpp_collision.hpp" + +namespace SDLPP { +class CircleColider : public CollisionPolygon { +public: + CircleColider( double x, double y, double rad ); + virtual ~CircleColider() {} + + virtual bool colidesWith( const CollisionPolygon &other ) const override; + virtual bool isCircle() const override; + virtual int topmost() const override; + virtual int bottommost() const override; + virtual int leftmost() const override; + virtual int rightmost() const override; + + virtual void updateCollision( int x, int y, int w, int h ) override; + virtual void + render( Renderer &renderer, + const std::tuple< int, int, int, int > &color ) override; + virtual void render( Renderer &renderer ) override; + +private: + int getRadius() const; + double original_rad; + int rad_; +}; +} // namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_circlerenderer.cpp b/sdlpp/sdlpp_circlerenderer.cpp new file mode 100644 index 0000000..1e2f292 --- /dev/null +++ b/sdlpp/sdlpp_circlerenderer.cpp @@ -0,0 +1,48 @@ +#include "sdlpp_circlerenderer.hpp" + +namespace SDLPP { +CircleRender::CircleRender( int x, int y, int rad, + std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + x_ = x; + y_ = y; + rad_ = rad; +} + +CircleRender::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::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 ); +} + +void CircleRender::render() { + std::cout << "I'm a circle, look at me go!" << std::endl + << "My dimensions are: [" << x_ << ", " << y_ + << "], radius: " << rad_ << std::endl; +} + +int CircleRender::leftmost() { + return x_ - rad_; +} + +int CircleRender::topmost() { + return y_ - rad_; +} + +int CircleRender::collisionPushX() { + return x_; +} + +int CircleRender::collisionPushY() { + return y_; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_circlerenderer.hpp b/sdlpp/sdlpp_circlerenderer.hpp new file mode 100644 index 0000000..de1d51b --- /dev/null +++ b/sdlpp/sdlpp_circlerenderer.hpp @@ -0,0 +1,31 @@ +#ifndef SDLPP_HPP_CIRCLE_RENDERER +#define SDLPP_HPP_CIRCLE_RENDERER + +#include "sdlpp_common.hpp" +#include "sdlpp_renderobject.hpp" + +#include + +namespace SDLPP { +class CircleRender : public RenderObject { +public: + CircleRender() = delete; + virtual ~CircleRender(){}; + CircleRender( int x, int y, int rad, std::shared_ptr< Renderer > &r ); + CircleRender( int x, int y, int rad, std::shared_ptr< Renderer > &r, + std::shared_ptr< Texture > &t ); + CircleRender( int x, int y, int rad, std::shared_ptr< Renderer > &r, + const std::string &img_path ); + virtual void render(); + virtual int leftmost(); + virtual int topmost(); + virtual int collisionPushX(); + virtual int collisionPushY(); + +private: + int x_; + int y_; + int rad_; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_collision.cpp b/sdlpp/sdlpp_collision.cpp new file mode 100644 index 0000000..62f5cd4 --- /dev/null +++ b/sdlpp/sdlpp_collision.cpp @@ -0,0 +1,60 @@ +#include "sdlpp_collision.hpp" + +namespace SDLPP { +CollisionPolygon::CollisionPolygon( double x, double y ) { + original_x = x; + original_y = y; + position_x = 0; + position_y = 0; +} + +bool CollisionPolygon::isInfinite() const { + return infinite; +} +void CollisionPolygon::setInfinite() { + infinite = true; +} + +void CollisionPolygon::updateCollision( int x, int y, int w, int h ) { + position_x = original_x * w + x; + position_y = original_y * h + y; +} + +int CollisionPolygon::getX() const { + return position_x; +} +int CollisionPolygon::getY() const { + return position_y; +} + +void CollisionPolygon::setColor( const std::string &color ) { + sdl_color = getSDLColorHEX( color ); +} +void CollisionPolygon::setOutlineColor( const std::string &color ) { + sdl_outline = getSDLColorHEX( color ); +} + +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() && ileft >= other.leftmost(); + ret |= iright != -1 && iright >= other.leftmost() && + iright <= other.rightmost(); + ret |= itop != -1 && itop <= other.bottommost() && itop >= other.topmost(); + ret |= ibottom != -1 && ibottom >= other.topmost() && + ibottom <= other.bottommost(); + ret |= ileft == -1 && iright == -1 && itop == -1 && ibottom == -1; + return ret; +} + +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() ); +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_collision.hpp b/sdlpp/sdlpp_collision.hpp new file mode 100644 index 0000000..1b1fe48 --- /dev/null +++ b/sdlpp/sdlpp_collision.hpp @@ -0,0 +1,44 @@ +#ifndef SDLPP_HPP_COLLISION +#define SDLPP_HPP_COLLISION + +#include "sdlpp_common.hpp" +#include "sdlpp_renderer.hpp" + +namespace SDLPP { +class CollisionPolygon { +public: + CollisionPolygon( double x, double y ); + virtual ~CollisionPolygon() {} + virtual bool colidesWith( const CollisionPolygon &other ) const = 0; + virtual bool isCircle() const = 0; + virtual bool isInfinite() const; + virtual void setInfinite(); + 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 ); + virtual void render( Renderer &renderer, + const std::tuple< int, int, int, int > &color ) = 0; + virtual void render( Renderer &renderer ) = 0; + int getX() const; + int getY() const; + void setColor( const std::string &color ); + void setOutlineColor( const std::string &color ); + +protected: + double original_x; + double original_y; + int position_x; + int position_y; + bool infinite = false; + SDL_Color sdl_color = { 0, 0, 0, 0 }; + SDL_Color sdl_outline = { 0, 0, 0, 0 }; +}; + +bool infinityIntersection( const SDLPP::CollisionPolygon &infinite, + const SDLPP::CollisionPolygon &other ); +bool intersects( const SDLPP::CollisionPolygon &p1, + const SDLPP::CollisionPolygon &p2 ); +} // namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_common.cpp b/sdlpp/sdlpp_common.cpp new file mode 100644 index 0000000..c84a49d --- /dev/null +++ b/sdlpp/sdlpp_common.cpp @@ -0,0 +1,122 @@ +#include "sdlpp_common.hpp" + +#ifdef _WIN32 +#include "SDL2/SDL_image.h" +#else +#include +#endif +#include + +int SDLPP::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; + } +} + +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; + } + if ( TTF_Init() == -1 ) { + std::cerr << "SDL_ttf could not initialize! SDL_ttf Error: " + << TTF_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; +} + +std::tuple< int, int, int, int > +SDLPP::getColorsHEX( const std::string &color ) { + int red = 0, green = 0, blue = 0, alpha = 255; + 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] ); + if ( color_ptr[6] != '\0' ) + alpha = hex2num( color_ptr[6] ) * 16 + hex2num( color_ptr[7] ); + return { red, green, blue, alpha }; +} + +SDL_Color +SDLPP::getSDLColorTuple( const std::tuple< int, int, int, int > &tuple ) { + SDL_Color ret_color{}; + ret_color.r = std::get< 0 >( tuple ); + ret_color.g = std::get< 1 >( tuple ); + ret_color.b = std::get< 2 >( tuple ); + ret_color.a = std::get< 3 >( tuple ); + return ret_color; +} + +SDL_Color SDLPP::getSDLColorHEX( const std::string &color ) { + auto color_tuple = SDLPP::getColorsHEX( color ); + return getSDLColorTuple( color_tuple ); +} + +std::tuple< int, int, int, int > +SDLPP::getColorsSDLColor( const SDL_Color &color ) { + return { color.r, color.g, color.b, color.a }; +} + +bool SDLPP::getSDLEvent( SDL_Event &e ) { + if ( SDL_PeepEvents( &e, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, + SDL_LASTEVENT ) == 1 ) { + SDL_PeepEvents( &e, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT ); + return true; + } + return false; +} diff --git a/sdlpp/sdlpp_common.hpp b/sdlpp/sdlpp_common.hpp new file mode 100644 index 0000000..0deb4c1 --- /dev/null +++ b/sdlpp/sdlpp_common.hpp @@ -0,0 +1,38 @@ +#ifndef SDLPP_HPP_COMMON +#define SDLPP_HPP_COMMON + +#ifdef _WIN32 +#include "SDL2/SDL.h" +#include "SDL2/SDL_image.h" +#include "SDL2/SDL_ttf.h" +#else +#include +#include +#include +#endif // UNIX +#include +#include +#include + +#define SDLPP_TEXT_LEFT 0x0001 +#define SDLPP_TEXT_RIGHT 0x0002 +#define SDLPP_TEXT_CENTER 0x0004 +#define SDLPP_TEXT_TOP 0x0008 +#define SDLPP_TEXT_BOTTOM 0x0010 + +namespace SDLPP { + +int hex2num( char c ); + +bool init(); +bool init( uint32_t SDL_OPTIONS ); +bool init( uint32_t SDL_OPTIONS, int IMAGE_OPTIONS ); + +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 ); + +bool getSDLEvent( SDL_Event &e ); +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_font.cpp b/sdlpp/sdlpp_font.cpp new file mode 100644 index 0000000..81b6996 --- /dev/null +++ b/sdlpp/sdlpp_font.cpp @@ -0,0 +1,33 @@ +#include "sdlpp_font.hpp" + +namespace SDLPP { +Font::Font( const std::string &font, int size ) { + font_ptr = TTF_OpenFont( font.c_str(), size ); + if ( font_ptr == NULL ) { + std::cerr << "Unable to load font '" << font + << "': TTF Error: " << TTF_GetError() << std::endl; + throw "TTF_OpenFont error"; + } +} +Font::~Font() { + TTF_CloseFont( font_ptr ); +} +const TTF_Font *Font::getFont() const { + return font_ptr; +} +TTF_Font *Font::getFont() { + return font_ptr; +} +void Font::setOutline( int size ) { + TTF_SetFontOutline( font_ptr, size ); +} +int Font::getOutline() { + return TTF_GetFontOutline( font_ptr ); +} +void Font::setStyle( int style ) { + TTF_SetFontStyle( font_ptr, style ); +} +void Font::setHinting( int hinting ) { + TTF_SetFontHinting( font_ptr, hinting ); +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_font.hpp b/sdlpp/sdlpp_font.hpp new file mode 100644 index 0000000..aef386a --- /dev/null +++ b/sdlpp/sdlpp_font.hpp @@ -0,0 +1,25 @@ +#ifndef SDLPP_HPP_FONT +#define SDLPP_HPP_FONT + +#include "sdlpp_common.hpp" + +#include + +namespace SDLPP { +class Font { +public: + Font() = delete; + Font( const std::string &font, int size ); + virtual ~Font(); + const TTF_Font *getFont() const; + TTF_Font *getFont(); + void setOutline( int size ); + int getOutline(); + void setStyle( int style ); + void setHinting( int hinting ); + +private: + TTF_Font *font_ptr; +}; +} // namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_linerenderer.cpp b/sdlpp/sdlpp_linerenderer.cpp new file mode 100644 index 0000000..db9f717 --- /dev/null +++ b/sdlpp/sdlpp_linerenderer.cpp @@ -0,0 +1,149 @@ +#include "sdlpp_linerenderer.hpp" + +namespace SDLPP { +LineRenderer::LineRenderer( double x1, double y1, double x2, double y2, + const std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + og_x1 = x1_ = x1; + og_y1 = y1_ = y1; + og_x2 = x2_ = x2; + og_y2 = y2_ = y2; + updateSizeAndPosition(); +} +LineRenderer::LineRenderer( double x1, double y1, double x2, double y2, + const std::shared_ptr< Renderer > &r, + const std::string &color ) + : LineRenderer( x1, y1, x2, y2, r ) { + setColor( color ); +} +void LineRenderer::setColor( const std::string &color ) { + _color = getColorsHEX( color ); +} +void LineRenderer::render() { + if ( !getHidden() ) { + SDL_SetRenderDrawColor( + renderer->getRendererPtr(), std::get< 0 >( _color ), + std::get< 1 >( _color ), std::get< 2 >( _color ), + std::get< 3 >( _color ) ); + SDL_RenderDrawLine( renderer->getRendererPtr(), pixel_x1, pixel_y1, + pixel_x2, pixel_y2 ); + } + if ( hasCollisions() && renderer->getRenderColiders() && !getHidden() ) { + for ( const auto &col : getCollisions() ) + col->render( *renderer, colider_color ); + } +} +void LineRenderer::move( int ticks ) { + if ( permanent ) + return; + 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 ); + if ( std::isnan( addx ) || std::isnan( addy ) ) + return; + + og_x1 += addx; + og_x2 += addx; + og_y1 += addy; + og_y2 += addy; + + custom_move( ticks ); + + updateSizeAndPosition(); +} +void LineRenderer::setPos( double x, double y ) { + auto diffx = og_x2 - og_x1; + auto diffy = og_y2 - og_y1; + og_x1 = x; + og_y1 = y; + og_x2 = og_x1 + diffx; + og_y2 = og_y1 + diffy; + updateSizeAndPosition(); +} +void LineRenderer::setPos( const std::pair< double, double > &pos ) { + setPos( pos.first, pos.second ); +} +std::pair< double, double > LineRenderer::getPos() const { + return { og_x1, og_y1 }; +} +int LineRenderer::leftmost() { + return pixel_x1 < pixel_x2 ? pixel_x1 : pixel_x2; +} +int LineRenderer::topmost() { + return pixel_y1 < pixel_y2 ? pixel_y1 : pixel_y2; +} +int LineRenderer::rightmost() { + return pixel_x1 > pixel_x2 ? pixel_x1 : pixel_x2; +} +int LineRenderer::bottommost() { + return pixel_y1 > pixel_y2 ? pixel_y1 : pixel_y2; +} +int LineRenderer::collisionPushX() { + return leftmost(); +} +int LineRenderer::collisionPushY() { + return topmost(); +} +int LineRenderer::collisionWidth() { + return rightmost() - leftmost(); +} +int LineRenderer::collisionHeight() { + return bottommost() - topmost(); +} +void LineRenderer::updateSizeAndPosition() { + updateXY(); + auto dimension = renderer->getSmallerSide(); + pixel_x1 = std::round( x1_ * dimension ); + pixel_x2 = std::round( x2_ * dimension ); + pixel_y1 = std::round( y1_ * dimension ); + pixel_y2 = std::round( y2_ * dimension ); + for ( auto &x : collisions ) { + x->updateCollision( collisionPushX(), collisionPushY(), + collisionWidth(), collisionHeight() ); + } +} +void LineRenderer::centerX() { + centerx = true; + updateSizeAndPosition(); +} +std::shared_ptr< RenderObject > LineRenderer::copySelf() { + // TODO ACTUALLY copy, don't just copy pointers to textures and whatnot, + // create new textures!!! + return std::make_shared< LineRenderer >( *this ); +} + +SDL_Rect LineRenderer::getRect() { + return { leftmost(), topmost(), rightmost() - leftmost(), + bottommost() - topmost() }; +} +std::pair< std::pair< double, double >, std::pair< double, double > > +LineRenderer::getDoubleRect() const { + return { { og_x1, og_y1 }, { og_x2 - og_x1, og_y2 - og_y1 } }; +} + +void LineRenderer::updateXY() { + if ( !centerx ) { + x1_ = og_x1; + y1_ = og_y1; + x2_ = og_x2; + y2_ = og_y2; + return; + } + auto width = renderer->getWidth(); + auto height = renderer->getHeight(); + if ( width > height ) { + auto multiplier = + static_cast< double >( width ) / static_cast< double >( height ); + x1_ = og_x1 + static_cast< double >( multiplier - 1 ) / 2; + x2_ = og_x2 + static_cast< double >( multiplier - 1 ) / 2; + } else { + x1_ = og_x1; + x2_ = og_x2; + } + y1_ = og_y1; + y2_ = og_y2; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_linerenderer.hpp b/sdlpp/sdlpp_linerenderer.hpp new file mode 100644 index 0000000..64f74e3 --- /dev/null +++ b/sdlpp/sdlpp_linerenderer.hpp @@ -0,0 +1,61 @@ +#ifndef SDLPP_HPP_LINE_RENDERER +#define SDLPP_HPP_LINE_RENDERER + +#include "sdlpp_common.hpp" +#include "sdlpp_renderobject.hpp" + +namespace SDLPP { +class LineRenderer : public RenderObject { +public: + LineRenderer() = delete; + virtual ~LineRenderer(){}; + LineRenderer( double x1, double y1, double x2, double y2, + const std::shared_ptr< Renderer > &r ); + LineRenderer( double x1, double y1, double x2, double y2, + const std::shared_ptr< Renderer > &r, + const std::string &color ); + virtual void setColor( const std::string &color ) override; + virtual void specialAction( int /*UNUSED*/ ) override{}; + virtual void render() override; + virtual void move( int ticks ) override; + virtual void custom_move( int /*UNUSED*/ ) override {} + virtual void setPos( double x, double y ) override; + virtual void setPos( const std::pair< double, double > &pos ) override; + virtual std::pair< double, double > getPos() const override; + virtual int leftmost() override; + virtual int topmost() override; + virtual int rightmost() override; + virtual int bottommost() override; + virtual int collisionPushX() override; + virtual int collisionPushY() override; + virtual int collisionWidth() override; + virtual int collisionHeight() override; + virtual void updateSizeAndPosition() override; + virtual void centerX() override; + virtual std::shared_ptr< RenderObject > copySelf() override; + + virtual SDL_Rect getRect() override; + virtual std::pair< std::pair< double, double >, + std::pair< double, double > > + getDoubleRect() const override; + void setOutlineColor( const std::string & /*UNUSED*/ ) override {} + +protected: + void updateXY(); + double og_x1; + double og_y1; + double x1_; + double y1_; + double og_x2; + double og_y2; + double x2_; + double y2_; + int pixel_x1{}; + int pixel_y1{}; + int pixel_x2{}; + int pixel_y2{}; + bool centerx = false; + std::tuple< int, int, int, int > _color; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_rectcolider.cpp b/sdlpp/sdlpp_rectcolider.cpp new file mode 100644 index 0000000..4c7f273 --- /dev/null +++ b/sdlpp/sdlpp_rectcolider.cpp @@ -0,0 +1,91 @@ +#include "sdlpp_rectcolider.hpp" + +namespace SDLPP { +RectColider::RectColider( double x, double y, double w, double h ) + : CollisionPolygon( x, y ) { + w_ = w; + h_ = h; +} + +bool RectColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { + if ( other.isCircle() ) { + return other.colidesWith( *this ); + } + if ( other.isInfinite() ) { + return infinityIntersection( other, *this ); + } + if ( isInfinite() ) + return infinityIntersection( *this, other ); + return intersects( *this, other ); +} + +bool RectColider::isCircle() const { + return false; +} +int RectColider::topmost() const { + return ( !isInfinite() || original_y != -1 ) * getY() + isInfinite() * -1; +} +int RectColider::bottommost() const { + return ( !isInfinite() || h_ != -1 ) * ( getY() + pixel_h ) + + isInfinite() * -1; +} +int RectColider::leftmost() const { + return ( !isInfinite() || original_x != -1 ) * getX() + isInfinite() * -1; +} +int RectColider::rightmost() const { + return ( !isInfinite() || w_ != -1 ) * ( getX() + pixel_w ) + + isInfinite() * -1; +} + +void RectColider::updateCollision( int x, int y, int w, int h ) { + position_x = original_x * w + x; + position_y = original_y * h + y; + pixel_w = w_ * w; + pixel_h = h_ * h; +} + +void RectColider::render( Renderer &renderer, + const std::tuple< int, int, int, int > &color ) { + 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 ); +} + +void RectColider::render( Renderer &renderer ) { + auto rect = getRect(); + SDL_SetRenderDrawColor( renderer.getRendererPtr(), sdl_color.r, sdl_color.g, + sdl_color.b, sdl_color.a ); + SDL_RenderFillRect( renderer.getRendererPtr(), &rect ); + SDL_SetRenderDrawColor( renderer.getRendererPtr(), sdl_outline.r, + sdl_outline.g, sdl_outline.b, sdl_outline.a ); + SDL_RenderDrawRect( renderer.getRendererPtr(), &rect ); +} + +SDL_Rect RectColider::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; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_rectcolider.hpp b/sdlpp/sdlpp_rectcolider.hpp new file mode 100644 index 0000000..c965897 --- /dev/null +++ b/sdlpp/sdlpp_rectcolider.hpp @@ -0,0 +1,35 @@ +#ifndef SDLPP_HPP_RECT_COLIDER +#define SDLPP_HPP_RECT_COLIDER + +#include "sdlpp_common.hpp" +#include "sdlpp_collision.hpp" + +#include + +namespace SDLPP { +class RectColider : public CollisionPolygon { +public: + RectColider( double x, double y, double w, double h ); + virtual ~RectColider() {} + virtual bool colidesWith( const CollisionPolygon &other ) const override; + virtual bool isCircle() const override; + virtual int topmost() const override; + virtual int bottommost() const override; + virtual int leftmost() const override; + virtual int rightmost() const override; + virtual void updateCollision( int x, int y, int w, int h ) override; + virtual void + render( Renderer &renderer, + const std::tuple< int, int, int, int > &color ) override; + virtual void render( Renderer &renderer ) override; + +private: + SDL_Rect getRect(); + + double w_; + double h_; + int pixel_w; + int pixel_h; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_rectrenderer.cpp b/sdlpp/sdlpp_rectrenderer.cpp new file mode 100644 index 0000000..8d4c8bf --- /dev/null +++ b/sdlpp/sdlpp_rectrenderer.cpp @@ -0,0 +1,166 @@ +#include "sdlpp_rectrenderer.hpp" + +namespace SDLPP { +RectangleRender::RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + og_x = x_ = x; + og_y = y_ = y; + og_w = w_ = w; + og_h = h_ = h; + updateSizeAndPosition(); +} +RectangleRender::RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t ) + : RectangleRender( x, y, w, h, r ) { + setTexture( t ); +} +RectangleRender::RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::string &img_or_color, + bool is_polygon ) + : RectangleRender( x, y, w, h, r ) { + if ( !is_polygon ) { + setTexture( img_or_color ); + } else { + setColor( img_or_color ); + color = img_or_color; + } +} +void RectangleRender::setColor( const std::string &color ) { + if ( !polygon ) { + polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); + polygon->updateCollision( collisionPushX(), collisionPushY(), + collisionWidth(), collisionHeight() ); + } + polygon->setColor( color ); +} +void RectangleRender::setOutlineColor( const std::string &color ) { + if ( !polygon ) { + polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); + polygon->updateCollision( collisionPushX(), collisionPushY(), + collisionWidth(), collisionHeight() ); + } + polygon->setOutlineColor( color ); +} +void RectangleRender::render() { + if ( !getHidden() ) { + if ( polygon ) + polygon->render( *renderer ); + if ( texture != NULL ) + SDL_RenderCopy( renderer->getRendererPtr(), + texture->getTexturePtr(), NULL, &rect ); + } + if ( hasCollisions() && renderer->getRenderColiders() && !getHidden() ) { + for ( const auto &col : getCollisions() ) + col->render( *renderer, colider_color ); + } +} +void RectangleRender::move( int ticks ) { + if ( permanent ) + return; + 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 ); + if ( std::isnan( addx ) || std::isnan( addy ) ) + return; + + og_x += addx; + og_y += addy; + + custom_move( ticks ); + + updateSizeAndPosition(); +} +std::pair< std::pair< double, double >, std::pair< double, double > > +RectangleRender::getDoubleRect() const { + return { { og_x, og_y }, { og_w, og_h } }; +} +void RectangleRender::setPos( double x, double y ) { + og_x = x; + og_y = y; + updateSizeAndPosition(); +} +void RectangleRender::setPos( const std::pair< double, double > &pos ) { + setPos( pos.first, pos.second ); +} +std::pair< double, double > RectangleRender::getPos() const { + return { og_x, og_y }; +} +int RectangleRender::leftmost() { + return rect.x; +} +int RectangleRender::topmost() { + return rect.y; +} +int RectangleRender::rightmost() { + return rect.x + rect.w; +} +int RectangleRender::bottommost() { + return rect.y + rect.h; +} +int RectangleRender::collisionPushX() { + return rect.x; +} +int RectangleRender::collisionPushY() { + return rect.y; +} +int RectangleRender::collisionWidth() { + return rect.w; +} +int RectangleRender::collisionHeight() { + return rect.h; +} +void RectangleRender::updateSizeAndPosition() { + updateXY(); + auto dimension = renderer->getSmallerSide(); + rect.x = std::round( x_ * dimension ); + rect.y = std::round( y_ * dimension ); + rect.w = std::round( ( x_ + w_ ) * dimension ) - rect.x; + rect.h = std::round( ( y_ + h_ ) * dimension ) - rect.y; + if ( polygon ) + polygon->updateCollision( collisionPushX(), collisionPushY(), + collisionWidth(), collisionHeight() ); + for ( auto &x : collisions ) { + x->updateCollision( collisionPushX(), collisionPushY(), + collisionWidth(), collisionHeight() ); + } +} +SDL_Rect RectangleRender::getRect() { + return rect; +} +void RectangleRender::centerX() { + centerx = true; + updateSizeAndPosition(); +} +std::shared_ptr< RenderObject > RectangleRender::copySelf() { + // TODO ACTUALLY copy, don't just copy pointers to textures and whatnot, + // create new textures!!! + return std::make_shared< RectangleRender >( *this ); +} +std::string RectangleRender::getColor() const { + return color; +} + +void RectangleRender::updateXY() { + if ( !centerx ) { + x_ = og_x; + y_ = og_y; + return; + } + auto width = renderer->getWidth(); + auto height = renderer->getHeight(); + if ( width > height ) { + auto multiplier = + static_cast< double >( width ) / static_cast< double >( height ); + x_ = og_x + static_cast< double >( multiplier - 1 ) / 2; + } else { + x_ = og_x; + } + y_ = og_y; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_rectrenderer.hpp b/sdlpp/sdlpp_rectrenderer.hpp new file mode 100644 index 0000000..6002249 --- /dev/null +++ b/sdlpp/sdlpp_rectrenderer.hpp @@ -0,0 +1,62 @@ +#ifndef SDLPP_HPP_RECT_RENDERER +#define SDLPP_HPP_RECT_RENDERER + +#include "sdlpp_common.hpp" +#include "sdlpp_renderobject.hpp" +#include "sdlpp_rectcolider.hpp" + +namespace SDLPP { +class RectangleRender : public RenderObject { +public: + RectangleRender() = delete; + virtual ~RectangleRender(){}; + RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r ); + RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t ); + RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::string &img_or_color, bool is_polygon = false ); + virtual void setColor( const std::string &color ) override; + virtual void setOutlineColor( const std::string &color ) override; + virtual void specialAction( int /*UNUSED*/ ) override{}; + virtual void render() override; + virtual void move( int ticks ) override; + virtual void custom_move( int /*UNUSED*/ ) override {} + virtual std::pair< std::pair< double, double >, + std::pair< double, double > > + getDoubleRect() const override; + virtual void setPos( double x, double y ) override; + virtual void setPos( const std::pair< double, double > &pos ) override; + virtual std::pair< double, double > getPos() const override; + virtual int leftmost() override; + virtual int topmost() override; + virtual int rightmost() override; + virtual int bottommost() override; + virtual int collisionPushX() override; + virtual int collisionPushY() override; + virtual int collisionWidth() override; + virtual int collisionHeight() override; + virtual void updateSizeAndPosition() override; + virtual SDL_Rect getRect() override; + virtual void centerX() override; + virtual std::shared_ptr< RenderObject > copySelf() override; + std::string getColor() const; + +protected: + void updateXY(); + double og_x; + double og_y; + double og_w; + double og_h; + double x_; + double y_; + double w_; + double h_; + bool centerx = false; + SDL_Rect rect; + std::string color = ""; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_renderer.cpp b/sdlpp/sdlpp_renderer.cpp new file mode 100644 index 0000000..612b8a9 --- /dev/null +++ b/sdlpp/sdlpp_renderer.cpp @@ -0,0 +1,56 @@ +#include "sdlpp_renderer.hpp" + +namespace SDLPP { +Renderer::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::~Renderer() { + SDL_DestroyRenderer( renderer ); +} +SDL_Renderer *Renderer::getRendererPtr() { + return renderer; +} +std::pair< int, int > Renderer::getDimensions() const { + int width = 0, height = 0; + SDL_GetRendererOutputSize( renderer, &width, &height ); + return { width, height }; +} +int Renderer::getWidth() const { + return getDimensions().first; +} +int Renderer::getHeight() const { + return getDimensions().second; +} +int Renderer::getSmallerSide() const { + auto dimensions = getDimensions(); + return dimensions.first < dimensions.second ? dimensions.first + : dimensions.second; +} +int Renderer::getLargerSide() const { + auto dimensions = getDimensions(); + return dimensions.first > dimensions.second ? dimensions.first + : dimensions.second; +} +void Renderer::setBlendMode( SDL_BlendMode blendMode ) { + SDL_SetRenderDrawBlendMode( renderer, blendMode ); +} +void Renderer::setRenderColiders( bool render ) { + render_coliders = render; +} +bool Renderer::getRenderColiders() { + return render_coliders; +} +void Renderer::clearRenderer() { + SDL_RenderClear( getRendererPtr() ); +} +void Renderer::presentRenderer() { + SDL_RenderPresent( getRendererPtr() ); +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_renderer.hpp b/sdlpp/sdlpp_renderer.hpp new file mode 100644 index 0000000..5aaf62e --- /dev/null +++ b/sdlpp/sdlpp_renderer.hpp @@ -0,0 +1,32 @@ +#ifndef SDLPP_HPP_RENDERER +#define SDLPP_HPP_RENDERER + +#include "sdlpp_common.hpp" +#include "sdlpp_window.hpp" + +#include + +namespace SDLPP { +class Renderer { +public: + Renderer() = delete; + Renderer( Window &window ); + virtual ~Renderer(); + SDL_Renderer *getRendererPtr(); + std::pair< int, int > getDimensions() const; + int getWidth() const; + int getHeight() const; + int getSmallerSide() const; + int getLargerSide() const; + void setBlendMode( SDL_BlendMode blendMode ); + void setRenderColiders( bool render ); + bool getRenderColiders(); + void clearRenderer(); + void presentRenderer(); + +private: + SDL_Renderer *renderer = NULL; + bool render_coliders = false; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_renderobject.cpp b/sdlpp/sdlpp_renderobject.cpp new file mode 100644 index 0000000..a7a8477 --- /dev/null +++ b/sdlpp/sdlpp_renderobject.cpp @@ -0,0 +1,107 @@ +#include "sdlpp_renderobject.hpp" + +namespace SDLPP { +bool RenderObject::colidesWith( const RenderObject &other ) const { + if ( !hasCollisions() || !other.hasCollisions() || getHidden() || + other.getHidden() ) { + return false; + } + for ( const auto &x : collisions ) { + for ( const auto &y : other.getCollisions() ) { + if ( x->colidesWith( *y ) ) + return true; + } + } + return false; +} +bool RenderObject::hasCollisions() const { + return !collisions.empty(); +} +const std::vector< std::shared_ptr< CollisionPolygon > > & +RenderObject::getCollisions() const { + return collisions; +} +void RenderObject::setTexture( const std::shared_ptr< Texture > &t ) { + texture = t; +} +void RenderObject::setTexture( const std::string &img_path ) { + texture = std::make_shared< Texture >( renderer, img_path ); +} +void RenderObject::setTexture( Font &font, const std::string &text, + const std::string &color, + const std::string &outline_color, + int outline_size ) { + texture = std::make_shared< Texture >( renderer, font, text, color, + outline_color, outline_size ); +} +void RenderObject::unsetTexture() { + texture.reset(); +} +void RenderObject::unsetColor() { + polygon.reset(); +} +// per second, relative to window width +void RenderObject::setMovementSpeed( double speed ) { + movementSpeed = speed; +} +void RenderObject::addMovement( int x, int y ) { + movementDirection.first += x; + movementDirection.second += y; +} +void RenderObject::resetMovementX() { + movementDirection.first = 0; +} +void RenderObject::resetMovementY() { + movementDirection.second = 0; +} +void RenderObject::clearColided() { + colidedWith.clear(); +} +void RenderObject::addColided( std::shared_ptr< RenderObject > &obj ) { + colidedWith.push_back( obj ); +} +std::vector< std::shared_ptr< RenderObject > > &RenderObject::getColidedWith() { + return colidedWith; +} +void RenderObject::setId( uint64_t input_id ) { + id = input_id; +} +uint64_t RenderObject::getId() { + return id; +} +void RenderObject::setHidden( bool hid ) { + hidden = hid; +} +bool RenderObject::getHidden() const { + return hidden; +} +void RenderObject::destroy() { + setHidden( true ); + kill = true; +} +bool RenderObject::getKilled() { + return kill; +} +void RenderObject::setColiderColor( const std::string &color ) { + colider_color = getColorsHEX( color ); +} +void RenderObject::setPermanent( bool perm ) { + permanent = perm; + setStatic( perm ); +} +bool RenderObject::getPermanent() const { + return permanent; +} +bool RenderObject::isStatic() { + return is_static; +} +void RenderObject::setStatic( bool stat ) { + is_static = stat; +} +std::shared_ptr< Renderer > RenderObject::getRenderer() const { + return renderer; +} +void RenderObject::setSceneID( int id ) { + scene_id = id; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_renderobject.hpp b/sdlpp/sdlpp_renderobject.hpp new file mode 100644 index 0000000..f6deda8 --- /dev/null +++ b/sdlpp/sdlpp_renderobject.hpp @@ -0,0 +1,104 @@ +#ifndef SDLPP_HPP_RENDER_OBJECT +#define SDLPP_HPP_RENDER_OBJECT + +#include "sdlpp_common.hpp" +#include "sdlpp_collision.hpp" +#include "sdlpp_renderer.hpp" +#include "sdlpp_texture.hpp" + +#include +#include + +namespace SDLPP { +class Scene; + +class RenderObject { +public: + RenderObject( const std::shared_ptr< Renderer > &r ) : renderer( r ) {} + virtual ~RenderObject() {} + virtual void render() = 0; + virtual int leftmost() = 0; + virtual int topmost() = 0; + virtual int rightmost() = 0; + virtual int bottommost() = 0; + virtual int collisionPushX() = 0; + virtual int collisionPushY() = 0; + virtual int collisionWidth() = 0; + virtual int collisionHeight() = 0; + virtual void specialAction( int code ) = 0; + virtual std::pair< std::pair< double, double >, + std::pair< double, double > > + getDoubleRect() const = 0; + virtual void setPos( double x, double y ) = 0; + virtual void setPos( const std::pair< double, double > &pos ) = 0; + virtual std::pair< double, double > getPos() const = 0; + bool colidesWith( const RenderObject &other ) const; + 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; + const std::vector< std::shared_ptr< CollisionPolygon > > & + getCollisions() const; + virtual void setTexture( const std::shared_ptr< Texture > &t ); + virtual void setTexture( const std::string &img_path ); + virtual void setTexture( Font &font, const std::string &text, + const std::string &color = "FFFFFF", + const std::string &outline_color = "000000", + int outline_size = -1 ); + virtual void setColor( const std::string &color ) = 0; + virtual void setOutlineColor( const std::string &color ) = 0; + virtual void unsetTexture(); + virtual void unsetColor(); + // per second, relative to window width + void setMovementSpeed( double speed ); + void addMovement( int x, int y ); + void resetMovementX(); + void resetMovementY(); + void clearColided(); + void addColided( std::shared_ptr< RenderObject > &obj ); + std::vector< std::shared_ptr< RenderObject > > &getColidedWith(); + void setId( uint64_t input_id ); + uint64_t getId(); + void setHidden( bool hid ); + bool getHidden() const; + void destroy(); + bool getKilled(); + void setColiderColor( const std::string &color ); + virtual void move( int ticks ) = 0; + virtual void custom_move( int ticks ) = 0; + virtual void updateSizeAndPosition() = 0; + virtual SDL_Rect getRect() = 0; + void setPermanent( bool perm = true ); + bool getPermanent() const; + virtual void centerX() = 0; + virtual std::shared_ptr< RenderObject > copySelf() = 0; + bool isStatic(); + void setStatic( bool stat = true ); + std::shared_ptr< Renderer > getRenderer() const; + +protected: + std::vector< std::shared_ptr< CollisionPolygon > > collisions; + std::shared_ptr< Texture > texture; + std::shared_ptr< Renderer > renderer; + std::shared_ptr< CollisionPolygon > polygon; + double movementSpeed = 0; + std::pair< int, int > movementDirection = { 0, 0 }; + std::vector< std::shared_ptr< RenderObject > > colidedWith; + uint64_t id = -1; + bool hidden = false; + bool kill = false; + std::tuple< int, int, int, int > colider_color = { 0x00, 0xFF, 0xFF, 0xFF }; + uint64_t scene_id = -1; + bool permanent = false; + bool is_static = true; + +private: + void setSceneID( int id ); + friend Scene; +}; +} // end of namespace SDLPP + +#endif diff --git a/sdlpp/sdlpp_scene.cpp b/sdlpp/sdlpp_scene.cpp new file mode 100644 index 0000000..bf17db5 --- /dev/null +++ b/sdlpp/sdlpp_scene.cpp @@ -0,0 +1,235 @@ +#include "sdlpp_scene.hpp" + +namespace SDLPP { +Scene::Scene( std::shared_ptr< Renderer > &r ) : renderer( r ) { + SDL_SetRenderDrawColor( renderer->getRendererPtr(), 0xFF, 0xFF, 0xFF, + 0xFF ); + prev_ticks = SDL_GetTicks(); +} +void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) { + std::lock_guard< std::mutex > lock( render_mutex ); + render_objects.push_back( obj ); + obj->setSceneID( ++max_object_id ); + if ( obj->hasCollisions() ) { + collision_objects.push_back( obj ); + } + + if ( render_objects.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; + } +} +void Scene::setZIndex( const std::shared_ptr< RenderObject > &obj, int index ) { + std::lock_guard< std::mutex > guard( render_mutex ); + int original_index = 0; + for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { + if ( render_objects[i] == obj ) { + original_index = i; + } + } + if ( original_index == index ) + return; + if ( original_index > index ) + original_index++; + render_objects.insert( render_objects.begin() + index, obj ); + render_objects.erase( render_objects.begin() + original_index ); +} +void Scene::moveDownZ( const std::shared_ptr< RenderObject > &obj ) { + moveZ( obj, -1 ); +} +void Scene::moveUpZ( const std::shared_ptr< RenderObject > &obj ) { + moveZ( obj, 1 ); +} +void Scene::moveZ( const std::shared_ptr< RenderObject > &obj, int addition ) { + int original_index = 0; + for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { + if ( render_objects[i] == obj ) { + original_index = i; + } + } + std::iter_swap( render_objects.begin() + original_index, + render_objects.begin() + original_index + addition ); +} +// TODO addCollision +std::shared_ptr< RenderObject > Scene::getObject( int index ) { + return render_objects[index]; +} +std::vector< std::shared_ptr< RenderObject > > Scene::getObjects() { + return render_objects; +} +std::vector< std::shared_ptr< RenderObject > > +Scene::getObjects( const std::unordered_set< int > &objectIDs ) { + std::vector< std::shared_ptr< RenderObject > > ret{}; + for ( const auto &x : render_objects ) { + // check if object exists because of possible race condition + if ( x && objectIDs.find( x->getId() ) != objectIDs.end() ) { + ret.push_back( x ); + } + } + return ret; +} +void Scene::movement() { + checkKilled(); + std::lock_guard< std::mutex > lock( render_mutex ); + int now_ticks = SDL_GetTicks(); + for ( const auto &x : render_objects ) { + x->move( now_ticks - prev_ticks ); + } + prev_ticks = now_ticks; +} +std::vector< std::shared_ptr< RenderObject > > +Scene::getCollisions( RenderObject &r ) { + if ( r.getHidden() ) + return {}; + std::vector< std::shared_ptr< RenderObject > > ret{}; + for ( const auto &x : collision_objects ) { + if ( x->colidesWith( r ) ) { + ret.push_back( x ); + } + } + return ret; +} +std::vector< std::shared_ptr< RenderObject > > +Scene::getCollisions( RenderObject &r, + const std::unordered_set< int > &objectIDs ) { + if ( r.getHidden() ) + return {}; + std::vector< std::shared_ptr< RenderObject > > ret{}; + for ( const auto &x : collision_objects ) { + if ( objectIDs.find( x->getId() ) != objectIDs.end() && + x->colidesWith( r ) ) { + ret.push_back( x ); + } + } + return ret; +} +void Scene::renderScene( bool clear_renderer ) { + checkKilled(); + std::lock_guard< std::mutex > lock( render_mutex ); + if ( clear_renderer ) + SDL_RenderClear( renderer->getRendererPtr() ); + if ( background && background->getTexturePtr() ) + SDL_RenderCopy( renderer->getRendererPtr(), background->getTexturePtr(), + NULL, NULL ); + for ( const auto &x : render_objects ) { + x->render(); + } +} +void Scene::presentScene() { + SDL_RenderPresent( renderer->getRendererPtr() ); +} +void Scene::setBackground( std::shared_ptr< Texture > bg ) { + background = bg; +} +void Scene::setBackground( const std::string &img_path ) { + background = std::make_shared< Texture >( renderer, img_path ); +} +void Scene::updateSizeAndPosition() { + checkKilled(); + std::lock_guard< std::mutex > lock( render_mutex ); + for ( auto &x : render_objects ) { + x->updateSizeAndPosition(); + for ( auto &col : x->getCollisions() ) { + col->updateCollision( x->collisionPushX(), x->collisionPushY(), + x->collisionWidth(), x->collisionHeight() ); + } + } +} +void Scene::moveEverything( double x, double y ) { + checkKilled(); + std::lock_guard< std::mutex > lock( render_mutex ); + for ( auto &obj : render_objects ) { + if ( obj->getPermanent() ) + continue; + auto curPos = obj->getDoubleRect(); + obj->setPos( curPos.first.first + x, curPos.first.second + y ); + } +} +const std::shared_ptr< RenderObject > &Scene::leftmost() { + return leftmost_obj; +} +const std::shared_ptr< RenderObject > &Scene::rightmost() { + return rightmost_obj; +} +std::pair< int, int > Scene::getDimensions() const { + return renderer->getDimensions(); +} +int Scene::getWidth() const { + return renderer->getWidth(); +} +int Scene::getHeight() const { + return renderer->getHeight(); +} +Renderer &Scene::getRenderer() { + return *renderer; +} +std::shared_ptr< Renderer > Scene::getRendererShared() { + return renderer; +} +void Scene::setPrevTicks( int ticks ) { + prev_ticks = ticks; +} +void Scene::saveScene() { + saved_render_objects.clear(); + saved_collision_objects.clear(); + for ( auto &obj : render_objects ) { + if ( !obj->isStatic() ) + saved_render_objects.push_back( obj->copySelf() ); + else + saved_render_objects.push_back( obj ); + } + for ( auto &obj : collision_objects ) { + if ( !obj->isStatic() ) + saved_collision_objects.push_back( obj->copySelf() ); + else + saved_collision_objects.push_back( obj ); + } +} +void Scene::resetScene() { + render_objects.clear(); + collision_objects.clear(); + for ( auto &obj : saved_render_objects ) { + if ( !obj->isStatic() ) + render_objects.push_back( obj->copySelf() ); + else + render_objects.push_back( obj ); + } + for ( auto &obj : saved_collision_objects ) { + if ( !obj->isStatic() ) + collision_objects.push_back( obj->copySelf() ); + else + collision_objects.push_back( obj ); + } +} + +void Scene::checkKilled() { + std::lock_guard< std::mutex > lock( render_mutex ); + std::vector< int > killed; + std::vector< int > killed_collisions; + for ( long unsigned int i = 0; i < render_objects.size(); i++ ) { + if ( render_objects[i]->getKilled() ) + killed.push_back( i ); + if ( i < collision_objects.size() && collision_objects[i]->getKilled() ) + killed_collisions.push_back( i ); + } + // reverse so we don't screw up indexing while going thorugh the kill + // indices + std::reverse( killed.begin(), killed.end() ); + std::reverse( killed_collisions.begin(), killed_collisions.end() ); + for ( auto &index : killed ) { + render_objects.erase( render_objects.begin() + index ); + } + for ( auto &index : killed_collisions ) { + collision_objects.erase( collision_objects.begin() + index ); + } +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_scene.hpp b/sdlpp/sdlpp_scene.hpp new file mode 100644 index 0000000..85e5037 --- /dev/null +++ b/sdlpp/sdlpp_scene.hpp @@ -0,0 +1,66 @@ +#ifndef SDLPP_HPP_SCENE +#define SDLPP_HPP_SCENE + +#include +#include +#include +#include + +#include "sdlpp_common.hpp" +#include "sdlpp_renderer.hpp" +#include "sdlpp_renderobject.hpp" + +namespace SDLPP { +class Scene { +public: + Scene( std::shared_ptr< Renderer > &r ); + void addObject( const std::shared_ptr< RenderObject > &obj ); + void setZIndex( const std::shared_ptr< RenderObject > &obj, int index ); + void moveDownZ( const std::shared_ptr< RenderObject > &obj ); + void moveUpZ( const std::shared_ptr< RenderObject > &obj ); + void moveZ( const std::shared_ptr< RenderObject > &obj, int addition ); + // TODO addCollision + std::shared_ptr< RenderObject > getObject( int index ); + std::vector< std::shared_ptr< RenderObject > > getObjects(); + std::vector< std::shared_ptr< RenderObject > > + getObjects( const std::unordered_set< int > &objectIDs ); + void movement(); + std::vector< std::shared_ptr< RenderObject > > + getCollisions( RenderObject &r ); + std::vector< std::shared_ptr< RenderObject > > + getCollisions( RenderObject &r, + const std::unordered_set< int > &objectIDs ); + void renderScene( bool clear_renderer = true ); + void presentScene(); + void setBackground( std::shared_ptr< Texture > bg ); + void setBackground( const std::string &img_path ); + void updateSizeAndPosition(); + void moveEverything( double x, double y ); + const std::shared_ptr< RenderObject > &leftmost(); + const std::shared_ptr< RenderObject > &rightmost(); + std::pair< int, int > getDimensions() const; + int getWidth() const; + int getHeight() const; + Renderer &getRenderer(); + std::shared_ptr< Renderer > getRendererShared(); + void setPrevTicks( int ticks ); + void saveScene(); + void resetScene(); + +private: + void checkKilled(); + + std::vector< std::shared_ptr< RenderObject > > render_objects; + std::vector< std::shared_ptr< RenderObject > > collision_objects; + std::vector< std::shared_ptr< RenderObject > > saved_render_objects; + std::vector< std::shared_ptr< RenderObject > > saved_collision_objects; + std::shared_ptr< Renderer > renderer; + std::shared_ptr< Texture > background; + int prev_ticks = 0; + std::shared_ptr< RenderObject > leftmost_obj; + std::shared_ptr< RenderObject > rightmost_obj; + uint64_t max_object_id = 0; + std::mutex render_mutex; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_textrenderer.cpp b/sdlpp/sdlpp_textrenderer.cpp new file mode 100644 index 0000000..101d881 --- /dev/null +++ b/sdlpp/sdlpp_textrenderer.cpp @@ -0,0 +1,98 @@ +#include "sdlpp_textrenderer.hpp" + +namespace SDLPP { +TextRenderer::TextRenderer( double x, double y, double w, double h, + std::shared_ptr< Renderer > &r ) + : RectangleRender( x, y, w, h, r ) {} +TextRenderer::TextRenderer( double x, double y, double w, double h, + std::shared_ptr< Renderer > &r, Font &font, + const std::string &text, const std::string &color, + const std::string &outline_color, int outline_size, + int flags ) + : RectangleRender( x, y, w, h, r ) { + position_flags = flags; + setText( font, text, color, outline_color, outline_size ); +} +void TextRenderer::setText( Font &font, const std::string &text, + const std::string &color, + const std::string &outline_color, + int outline_size ) { + _text = text; + setTextColor( font, color, outline_color, outline_size ); +} +void TextRenderer::setTextColor( Font &font, const std::string &color, + const std::string &outline_color, + int outline_size ) { + setTexture( font, _text, color, outline_color, outline_size ); + updateDstRect(); +} +void TextRenderer::changeText( const std::string &text ) { + _text = text; +} +void TextRenderer::setFlags( int flags ) { + position_flags = flags; + updateDstRect(); +} +void TextRenderer::render() { + if ( !getHidden() ) { + if ( polygon ) + polygon->render( *renderer ); + if ( texture != NULL ) + SDL_RenderCopy( renderer->getRendererPtr(), + texture->getTexturePtr(), NULL, &dst_rect ); + } + if ( hasCollisions() && renderer->getRenderColiders() && !getHidden() ) { + for ( const auto &col : getCollisions() ) + col->render( *renderer, colider_color ); + } +} +void TextRenderer::updateSizeAndPosition() { + RectangleRender::updateSizeAndPosition(); + updateDstRect(); +} +std::shared_ptr< RenderObject > TextRenderer::copySelf() { + // TODO ACTUALLY copy, don't just copy pointers to textures and whatnot, + // create new textures!!! + return std::make_shared< TextRenderer >( *this ); +} + +void TextRenderer::updateDstRect() { + if ( !texture ) + return; + int text_width{}, text_height{}; + SDL_QueryTexture( texture->getTexturePtr(), NULL, NULL, &text_width, + &text_height ); + if ( text_width < rect.w && text_height < rect.h ) { + dst_rect.w = text_width; + dst_rect.h = text_height; + } else { + double x_div = static_cast< double >( text_width ) / + static_cast< double >( rect.w ); + double y_div = static_cast< double >( text_height ) / + static_cast< double >( rect.h ); + if ( x_div > y_div ) { + dst_rect.w = text_width / x_div; + dst_rect.h = text_height / x_div; + } else { + dst_rect.w = text_width / y_div; + dst_rect.h = text_height / y_div; + } + } + if ( !( position_flags & SDLPP_TEXT_LEFT || + position_flags & SDLPP_TEXT_RIGHT ) ) { + dst_rect.x = rect.x + ( rect.w - dst_rect.w ) / 2; + } else if ( position_flags & SDLPP_TEXT_LEFT ) { + dst_rect.x = rect.x; + } else if ( position_flags & SDLPP_TEXT_RIGHT ) { + dst_rect.x = rect.x + rect.w - dst_rect.w; + } + if ( !( position_flags & SDLPP_TEXT_TOP || + position_flags & SDLPP_TEXT_BOTTOM ) ) { + dst_rect.y = rect.y + ( rect.h - dst_rect.h ) / 2; + } else if ( position_flags & SDLPP_TEXT_TOP ) { + dst_rect.y = rect.y; + } else if ( position_flags & SDLPP_TEXT_BOTTOM ) { + dst_rect.y = rect.y + rect.h - dst_rect.h; + } +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_textrenderer.hpp b/sdlpp/sdlpp_textrenderer.hpp new file mode 100644 index 0000000..a83fc41 --- /dev/null +++ b/sdlpp/sdlpp_textrenderer.hpp @@ -0,0 +1,41 @@ +#ifndef SDLPP_HPP_TEXT_RENDERER +#define SDLPP_HPP_TEXT_RENDERER + +#include "sdlpp_common.hpp" +#include "sdlpp_rectrenderer.hpp" + +#include +#include + +namespace SDLPP { +class TextRenderer : public RectangleRender { +public: + TextRenderer() = delete; + TextRenderer( double x, double y, double w, double h, + std::shared_ptr< Renderer > &r ); + TextRenderer( double x, double y, double w, double h, + std::shared_ptr< Renderer > &r, Font &font, + const std::string &text, const std::string &color = "FFFFFF", + const std::string &outline_color = "000000", + int outline_size = -1, int flags = SDLPP_TEXT_CENTER ); + void setText( Font &font, const std::string &text, + const std::string &color = "FFFFFF", + const std::string &outline_color = "000000", + int outline_size = -1 ); + void setTextColor( Font &font, const std::string &color = "FFFFFF", + const std::string &outline_color = "000000", + int outline_size = -1 ); + void changeText( const std::string &text ); + void setFlags( int flags ); + virtual void render() override; + virtual void updateSizeAndPosition() override; + virtual std::shared_ptr< RenderObject > copySelf() override; + +private: + void updateDstRect(); + std::string _text{}; + int position_flags = 0; + SDL_Rect dst_rect{}; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_texture.cpp b/sdlpp/sdlpp_texture.cpp new file mode 100644 index 0000000..09f80f6 --- /dev/null +++ b/sdlpp/sdlpp_texture.cpp @@ -0,0 +1,75 @@ +#include "sdlpp_texture.hpp" + +namespace SDLPP { +Texture::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 ) ) ); + } + setTextureFromSurface( renderer, surface ); +} +Texture::Texture( std::shared_ptr< Renderer > &renderer, Font &font, + const std::string &text, const std::string &color, + const std::string &outline_color, const int outline_size ) { + if ( outline_size != -1 ) { + font.setOutline( outline_size ); + } + 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 ); +} +Texture::~Texture() { + SDL_DestroyTexture( texture ); +} +SDL_Texture *Texture::getTexturePtr() { + return texture; +} + +void Texture::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 ); +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_texture.hpp b/sdlpp/sdlpp_texture.hpp new file mode 100644 index 0000000..fb1eab6 --- /dev/null +++ b/sdlpp/sdlpp_texture.hpp @@ -0,0 +1,32 @@ +#ifndef SDLPP_HPP_TEXTURE +#define SDLPP_HPP_TEXTURE + +#include + +#include "sdlpp_common.hpp" +#include "sdlpp_font.hpp" +#include "sdlpp_renderer.hpp" + +namespace SDLPP { +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 ); + 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 ); + virtual ~Texture(); + SDL_Texture *getTexturePtr(); + +private: + void setTextureFromSurface( std::shared_ptr< Renderer > &renderer, + SDL_Surface *surface ); + SDL_Texture *texture = NULL; +}; +} // end of namespace SDLPP +#endif diff --git a/sdlpp/sdlpp_window.cpp b/sdlpp/sdlpp_window.cpp new file mode 100644 index 0000000..d21b626 --- /dev/null +++ b/sdlpp/sdlpp_window.cpp @@ -0,0 +1,33 @@ +#include "sdlpp_window.hpp" + +namespace SDLPP { +Window::Window() + : Window( "SDL Window", 640, 480, SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED ) {} +Window::Window( const std::string &window_name ) + : Window( window_name, 640, 480, SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED ) {} +Window::Window( const std::string &window_name, uint32_t width, + uint32_t height ) + : Window( window_name, width, height, SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED ) {} +Window::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"; + } +} +void Window::setResizable( bool resizable ) { + SDL_SetWindowResizable( window, resizable ? SDL_TRUE : SDL_FALSE ); +} +Window::~Window() { + SDL_DestroyWindow( window ); +} +SDL_Window *Window::getWindowPtr() { + return window; +} +} // namespace SDLPP diff --git a/sdlpp/sdlpp_window.hpp b/sdlpp/sdlpp_window.hpp new file mode 100644 index 0000000..fdb81ad --- /dev/null +++ b/sdlpp/sdlpp_window.hpp @@ -0,0 +1,24 @@ +#ifndef SDLPP_HPP_WINDOW +#define SDLPP_HPP_WINDOW + +#include "sdlpp_common.hpp" + +#include + +namespace SDLPP { +class Window { +public: + Window(); + Window( const std::string &window_name ); + Window( const std::string &window_name, uint32_t width, uint32_t height ); + Window( const std::string &window_name, uint32_t width, uint32_t height, + uint32_t posx, uint32_t posy ); + void setResizable( bool resizable ); + virtual ~Window(); + SDL_Window *getWindowPtr(); + +private: + SDL_Window *window = NULL; +}; +} // namespace SDLPP +#endif