From 258ce51cfe599843fcb9fe3cf1df34bdc6adaf48 Mon Sep 17 00:00:00 2001 From: zv0n Date: Fri, 12 Mar 2021 22:33:46 +0100 Subject: [PATCH] Trying to switch to more object-oriented --- Makefile | 72 ++++++++++++++++++----- main.cpp | 26 ++++---- sdlpp/Makefile | 2 +- sdlpp/sdlpp.hpp | 4 ++ sdlpp/sdlpp_circlecolider.cpp | 10 ++-- sdlpp/sdlpp_circlecolider.hpp | 1 + sdlpp/sdlpp_circlerenderer.cpp | 68 ++++++++++++--------- sdlpp/sdlpp_circlerenderer.hpp | 9 ++- sdlpp/sdlpp_collision.cpp | 18 +++--- sdlpp/sdlpp_collision.hpp | 10 ++-- sdlpp/sdlpp_geometry.hpp | 7 +++ sdlpp/sdlpp_geometry_line.hpp | 30 ++++++++++ sdlpp/sdlpp_geometry_vector.hpp | 31 ++++++++++ sdlpp/sdlpp_line.hpp | 52 ++++++++++++++++ sdlpp/sdlpp_linerenderer.cpp | 101 ++++++++++++++++++-------------- sdlpp/sdlpp_linerenderer.hpp | 28 ++++----- sdlpp/sdlpp_rectcolider.cpp | 59 ++++++++++++++----- sdlpp/sdlpp_rectcolider.hpp | 16 +++-- sdlpp/sdlpp_rectrenderer.cpp | 97 +++++++++++++++++++++--------- sdlpp/sdlpp_rectrenderer.hpp | 31 +++++++--- sdlpp/sdlpp_renderobject.cpp | 13 ++-- sdlpp/sdlpp_renderobject.hpp | 13 ++-- sdlpp/sdlpp_scene.cpp | 11 ++-- sdlpp/sdlpp_vector.hpp | 56 ++++++++++++++++++ test.cpp | 32 ++++++++++ tests/Makefile | 18 ++++++ tests/test.cpp | 52 +++++++++++++++- tetris/Makefile | 2 +- tetris/custom_classes.cpp | 50 ++++++++-------- tetris/custom_classes.hpp | 5 +- tetris/functions.cpp | 12 ++-- tetris/scenes.cpp | 6 +- 32 files changed, 693 insertions(+), 249 deletions(-) create mode 100644 sdlpp/sdlpp_geometry.hpp create mode 100644 sdlpp/sdlpp_geometry_line.hpp create mode 100644 sdlpp/sdlpp_geometry_vector.hpp create mode 100644 sdlpp/sdlpp_line.hpp create mode 100644 sdlpp/sdlpp_vector.hpp create mode 100644 test.cpp create mode 100644 tests/Makefile diff --git a/Makefile b/Makefile index 64c198b..4496f61 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,65 @@ -CXX ?= g++ -CFLAGS ?= -O2 -Wall -Wextra -g PREFIX ?= /usr/local/bin + +ifeq ($(OS),Windows_NT) +UNAME_S := Windows +CXX = cl +CXXFLAGS = -MD -EHsc +OBJEXT = obj +LDFLAGS = +OUTPUTFLAG = -Fo +else +UNAME_S := $(shell uname -s) +CXX ?= g++ +CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic -O2 -DDEBUG -DFEATURE # -g -fsanitize=address +OBJEXT = o LDFLAGS ?= -lSDL2 -lSDL2_image -lSDL2_gfx -lSDL2_ttf -pthread +OUTPUTFLAG = -o +endif + +TEST_OBJECTS = test.${OBJEXT} + +ifeq ($(UNAME_S),Linux) +TEST_OBJECTS += libsdlpp.so +endif +ifeq ($(UNAME_S),Darwin) +TEST_OBJECTS += libsdlpp.dylib +endif +ifeq ($(UNAME_S),Windows) +TEST_OBJECTS += sdlpp/SDL2/SDL2_framerate.c sdlpp/SDL2/SDL2_gfxPrimitives.c sdlpp/SDL2/SDL2_imageFilter.c sdlpp/SDL2/SDL2_rotozoom.c +SDLLIB = libsdlpp.dll +endif .PHONY: default -default: demo +default: test -demo: main.o sdlpp.o - $(CXX) $(CFLAGS) -o $@ $^ ${LDFLAGS} -test: test.o sdlpp.o - $(CXX) $(CFLAGS) -o $@ $^ ${LDFLAGS} +ifeq ($(UNAME_S),Windows) +test: ${TEST_OBJECTS} ${SDLLIB} + $(CXX) $(CXXFLAGS) -Fe"$@" ${TEST_OBJECTS} /link sdlpp\SDL2.lib sdlpp\SDL2_ttf.lib sdlpp\SDL2_image.lib libsdlpp.lib -main.o: main.cpp sdlpp.hpp - $(CXX) $(CFLAGS) -c -o $@ $< -sdlpp.o: sdlpp.cpp sdlpp.hpp - $(CXX) $(CFLAGS) -c -o $@ $< -test.o: tests/test.cpp sdlpp.hpp tests/catch.hpp - $(CXX) $(CFLAGS) -c -o $@ $< +else +test: ${TEST_OBJECTS} + $(CXX) $(CXXFLAGS) -o $@ $^ ${LDFLAGS} -L $(shell pwd) -lsdlpp +endif -windows_tetris: sdlpp.hpp sdlpp.cpp tetris/tetris.cpp tetris/config.cpp tetris/global_vars.cpp tetris/scenes.cpp tetris/functions.cpp tetris/config.hpp tetris/global_vars.hpp tetris/scenes.hpp tetris/functions.hpp - cl -MD -EHsc -Fe"Tetris" sdlpp.cpp tetris/tetris.cpp tetris/config.cpp tetris/global_vars.cpp tetris/scenes.cpp tetris/functions.cpp SDL2/SDL2_framerate.c SDL2/SDL2_gfxPrimitives.c SDL2/SDL2_imageFilter.c SDL2/SDL2_rotozoom.c /link SDL2.lib SDL2_ttf.lib SDL2_image.lib +test.${OBJEXT}: test.cpp + $(CXX) $(CXXFLAGS) -c ${OUTPUTFLAG}$@ $< +libsdlpp.so: sdlpp + $(MAKE) clean -C sdlpp + $(MAKE) -C sdlpp + cp sdlpp/libsdlpp.so . + ln -sf libsdlpp.so libsdlpp.so.1 +libsdlpp.dylib: sdlpp + $(MAKE) clean -C sdlpp + $(MAKE) -C sdlpp + cp sdlpp/libsdlpp.dylib . +libsdlpp.dll: ../sdlpp + $(MAKE) clean -C sdlpp + $(MAKE) -C sdlpp + cp sdlpp/libsdlpp.dll . + cp sdlpp/libsdlpp.lib . + +start: + LD_LIBRARY_PATH=$$(pwd) ./test clean: - rm -Rf *.o test demo + rm -Rf *.${OBJEXT} test diff --git a/main.cpp b/main.cpp index 77dfe2b..26b6f89 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,4 @@ -#include "sdlpp.hpp" +#include "sdlpp/sdlpp.hpp" #include #include #include @@ -78,8 +78,8 @@ public: } if ( jump_ < 0 || jump_ > jump_speed ) jump_ = 0; - og_y += grav * time_portion; - og_y -= jump_ * time_portion; + double addition = grav * time_portion - jump_ * time_portion; + original += {0, addition}; } private: @@ -135,7 +135,7 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { while ( posx < 3 ) { stone = std::make_shared< Destroyable >( posx, 0.5, 0.15, 0.1, r, 1000 ); - stone->addCollision( SDLPP::Rect( 0, 0, 1, 1 ) ); + stone->addCollision( SDLPP::RectColider( 0, 0, 1, 1 ) ); stone->setColor( "#222222FF" ); stone->setId( STONE_ID ); stone->setColiderColor( "FF0000" ); @@ -143,24 +143,24 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { posx += 0.45; } auto x = std::make_shared< Player >( 0, 0, 0.2, 0.2, r ); - x->addCollision( SDLPP::Rect( 0.3, 0.7, 0.05, 0.31 ) ); - x->addCollision( SDLPP::Rect( 0.65, 0.7, 0.05, 0.31 ) ); - x->addCollision( SDLPP::Rect( 0.2, 0.3, 0.6, 0.45 ) ); - x->addCollision( SDLPP::Circle( 0.5, 0.15, 0.3 ) ); + x->addCollision( SDLPP::RectColider( 0.3, 0.7, 0.05, 0.31 ) ); + x->addCollision( SDLPP::RectColider( 0.65, 0.7, 0.05, 0.31 ) ); + x->addCollision( SDLPP::RectColider( 0.2, 0.3, 0.6, 0.45 ) ); + x->addCollision( SDLPP::CircleColider( 0.5, 0.15, 0.3 ) ); x->setColor( "E164B7" ); x->setId( PLAYER_ID ); x->setColiderColor( "00FF00" ); scene.addObject( x ); player = x; auto z = std::make_shared< SDLPP::RectangleRender >( 0, 2.5, 0, 0, r ); - auto z_col = SDLPP::Rect( -1, 0, -1, -1 ); + auto z_col = SDLPP::RectColider( -1, 0, -1, -1 ); z_col.setInfinite(); z->addCollision( z_col ); z->setId( DEATH ); z->setColiderColor( "FF00FF" ); scene.addObject( z ); auto y = std::make_shared< SDLPP::TextRenderer >( 0, 0, 0.2, 0.1, r ); - y->setText( *font, "DEMO", "#FFFFFF", "#000000", 5 ); + y->setText( font, "DEMO", "#FFFFFF", "#000000", 5 ); y->setPermanent( true ); y->setId( 123 ); scene.addObject( y ); @@ -173,20 +173,20 @@ void addPause( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { bg->setPermanent( true ); scene.addObject( bg ); auto y = std::make_shared< SDLPP::TextRenderer >( 0.25, 0.1, 0.5, 0.3, r ); - y->setText( *font, "PAUSED", "#FFFFFF", "#000000", 5 ); + y->setText( font, "PAUSED", "#FFFFFF", "#000000", 5 ); y->setId( 0 ); y->centerX(); scene.addObject( y ); auto resume = std::make_shared< SDLPP::TextRenderer >( 0.4, 0.5, 0.2, 0.1, r ); - resume->setText( *font, "Resume", "#FFFFFF", "#000000", 5 ); + resume->setText( font, "Resume", "#FFFFFF", "#000000", 5 ); resume->setColor( "#FFFFFF40" ); resume->centerX(); scene.addObject( resume ); pause_options.push_back( resume ); auto quit = std::make_shared< SDLPP::TextRenderer >( 0.4, 0.7, 0.2, 0.1, r ); - quit->setText( *font, "Quit Game", "#FFFFFF", "#000000", 5 ); + quit->setText( font, "Quit Game", "#FFFFFF", "#000000", 5 ); quit->centerX(); scene.addObject( quit ); pause_options.push_back( quit ); diff --git a/sdlpp/Makefile b/sdlpp/Makefile index 786133f..a2779c0 100644 --- a/sdlpp/Makefile +++ b/sdlpp/Makefile @@ -11,7 +11,7 @@ RM = del else UNAME_S := $(shell uname -s) CXX ?= g++ -CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic +CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic -g OBJEXT = o endif diff --git a/sdlpp/sdlpp.hpp b/sdlpp/sdlpp.hpp index b6a32c1..11c5b63 100644 --- a/sdlpp/sdlpp.hpp +++ b/sdlpp/sdlpp.hpp @@ -17,4 +17,8 @@ #include "sdlpp_texture.hpp" #include "sdlpp_window.hpp" +#include "sdlpp_line.hpp" +#include "sdlpp_vector.hpp" +#include "sdlpp_geometry.hpp" + #endif diff --git a/sdlpp/sdlpp_circlecolider.cpp b/sdlpp/sdlpp_circlecolider.cpp index fd92310..078ff2a 100644 --- a/sdlpp/sdlpp_circlecolider.cpp +++ b/sdlpp/sdlpp_circlecolider.cpp @@ -2,9 +2,10 @@ namespace SDLPP { CircleColider::CircleColider( double x, double y, double rad ) - : CollisionPolygon( x, y ) { - original_rad = rad; -} + : CircleColider( {x, y}, rad ) {}; + +CircleColider::CircleColider( const Vec2D< double > ¢er, double rad ) + : CollisionPolygon( center ), original_rad( rad ) {} bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { if ( other.isCircle() ) { @@ -60,8 +61,7 @@ int CircleColider::rightmost() const { } void CircleColider::updateCollision( int x, int y, int w, int h ) { - position_x = original_x * w + x; - position_y = original_y * h + y; + position = Vec2D ( original.getX() * w + x, original.getY() * h + y ); rad_ = original_rad * w; } diff --git a/sdlpp/sdlpp_circlecolider.hpp b/sdlpp/sdlpp_circlecolider.hpp index 551677c..62ca485 100644 --- a/sdlpp/sdlpp_circlecolider.hpp +++ b/sdlpp/sdlpp_circlecolider.hpp @@ -10,6 +10,7 @@ namespace SDLPP { class SDLPPSCOPE CircleColider : public CollisionPolygon { public: CircleColider( double x, double y, double rad ); + CircleColider( const Vec2D ¢er, double rad ); virtual ~CircleColider() {} virtual bool colidesWith( const CollisionPolygon &other ) const override; diff --git a/sdlpp/sdlpp_circlerenderer.cpp b/sdlpp/sdlpp_circlerenderer.cpp index b3cd6ea..d2432f9 100644 --- a/sdlpp/sdlpp_circlerenderer.cpp +++ b/sdlpp/sdlpp_circlerenderer.cpp @@ -6,28 +6,41 @@ namespace SDLPP { CircleRender::CircleRender( double x, double y, double rad, std::shared_ptr< Renderer > &r ) - : RenderObject( r ) { - og_x = x_ = x; - og_y = y_ = y; - og_r = r_ = rad; -} + : CircleRender( { x, y }, rad, r ) {} CircleRender::CircleRender( double x, double y, double rad, std::shared_ptr< Renderer > &r, std::shared_ptr< Texture > &t ) - : CircleRender( x, y, rad, r ) { - throw "I don't support textures yet!!!"; -} + : CircleRender( { x, y }, rad, r, t ) {} CircleRender::CircleRender( double x, double y, double rad, std::shared_ptr< Renderer > &r, - const std::string &img_or_color, - bool is_polygon ) - : CircleRender( x, y, rad, r ) { - if(!is_polygon) { + const std::string &img_or_color, bool is_polygon ) + : CircleRender( { x, y }, rad, r, img_or_color, is_polygon ) {} + +CircleRender::CircleRender( Vec2D< double > center, double rad, + std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + original = center; + current = center; + og_r = r_ = rad; +} + +CircleRender::CircleRender( Vec2D< double > center, double rad, + std::shared_ptr< Renderer > &r, + std::shared_ptr< Texture > &t ) + : CircleRender( center, rad, r ) { + throw "I don't support textures yet!!!"; +} + +CircleRender::CircleRender( Vec2D< double > center, double rad, + std::shared_ptr< Renderer > &r, + const std::string &img_or_color, bool is_polygon ) + : CircleRender( center, rad, r ) { + if ( !is_polygon ) { throw "I don't support textures yet!!!"; } else { - setColor(img_or_color); + setColor( img_or_color ); color = img_or_color; } } @@ -50,9 +63,9 @@ void CircleRender::setOutlineColor( const std::string &color ) { polygon->setOutlineColor( color ); } -std::pair< std::pair< double, double >, std::pair< double, double > > +std::pair< Vec2D, Vec2D > CircleRender::getDoubleRect() const { - return { { og_x - og_r, og_y - og_r }, { 2 * og_r, 2 * og_r } }; + return { { original.getX() - og_r, original.getY() - og_r }, { 2 * og_r, 2 * og_r } }; } int CircleRender::leftmost() { @@ -90,10 +103,10 @@ int CircleRender::collisionHeight() { void CircleRender::updateSizeAndPosition() { updateXY(); auto dimension = renderer->getSmallerSide(); - rect.x = std::round( (x_ - r_) * dimension ); - rect.y = std::round( (y_ - r_) * dimension ); - rect.w = std::round( ( x_ + r_ ) * dimension ) - rect.x; - rect.h = std::round( ( y_ + r_ ) * dimension ) - rect.y; + rect.x = std::round( ( current.getX() - r_ ) * dimension ); + rect.y = std::round( ( current.getY() - r_ ) * dimension ); + rect.w = std::round( ( current.getX() + r_ ) * dimension ) - rect.x; + rect.h = std::round( ( current.getY() + r_ ) * dimension ) - rect.y; if ( polygon ) polygon->updateCollision( collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight() ); @@ -114,12 +127,12 @@ void CircleRender::centerX() { std::shared_ptr< RenderObject > CircleRender::copySelf() { auto ret = std::make_shared< CircleRender >( *this ); - copyTo(ret); + copyTo( ret ); return ret; } -void CircleRender::copyTo(std::shared_ptr other) { - RenderObject::copyTo(other); +void CircleRender::copyTo( std::shared_ptr< RenderObject > other ) { + RenderObject::copyTo( other ); } std::string CircleRender::getColor() const { @@ -128,19 +141,20 @@ std::string CircleRender::getColor() const { void CircleRender::updateXY() { if ( !centerx ) { - x_ = og_x; - y_ = og_y; + current = original; return; } auto width = renderer->getWidth(); auto height = renderer->getHeight(); + double x_, y_; if ( width > height ) { auto multiplier = static_cast< double >( width ) / static_cast< double >( height ); - x_ = og_x + static_cast< double >( multiplier - 1 ) / 2; + x_ = original.getX() + static_cast< double >( multiplier - 1 ) / 2; } else { - x_ = og_x; + x_ = original.getX(); } - y_ = og_y; + y_ = original.getY(); + current = { x_, y_ }; } } // namespace SDLPP diff --git a/sdlpp/sdlpp_circlerenderer.hpp b/sdlpp/sdlpp_circlerenderer.hpp index aa13e8f..bc872dc 100644 --- a/sdlpp/sdlpp_circlerenderer.hpp +++ b/sdlpp/sdlpp_circlerenderer.hpp @@ -16,12 +16,17 @@ public: std::shared_ptr< Texture > &t ); CircleRender( double x, double y, double rad, std::shared_ptr< Renderer > &r, const std::string &img_or_color, bool is_polygon = false ); + + CircleRender( Vec2D center, double rad, std::shared_ptr< Renderer > &r ); + CircleRender( Vec2D center, double rad, std::shared_ptr< Renderer > &r, + std::shared_ptr< Texture > &t ); + CircleRender( Vec2D center, double rad, 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 custom_move( int /*UNUSED*/ ) override{} - virtual std::pair< std::pair< double, double >, - std::pair< double, double > > + virtual std::pair< Vec2D, Vec2D > getDoubleRect() const override; virtual int leftmost() override; virtual int topmost() override; diff --git a/sdlpp/sdlpp_collision.cpp b/sdlpp/sdlpp_collision.cpp index 62f5cd4..f0901de 100644 --- a/sdlpp/sdlpp_collision.cpp +++ b/sdlpp/sdlpp_collision.cpp @@ -1,11 +1,12 @@ #include "sdlpp_collision.hpp" namespace SDLPP { -CollisionPolygon::CollisionPolygon( double x, double y ) { - original_x = x; - original_y = y; - position_x = 0; - position_y = 0; +CollisionPolygon::CollisionPolygon( double x, double y ) + : CollisionPolygon( Vec2D( x, y ) ) {} + +CollisionPolygon::CollisionPolygon( const Vec2D< double > &input ) { + original = input; + position = { 0, 0 }; } bool CollisionPolygon::isInfinite() const { @@ -16,15 +17,14 @@ void CollisionPolygon::setInfinite() { } void CollisionPolygon::updateCollision( int x, int y, int w, int h ) { - position_x = original_x * w + x; - position_y = original_y * h + y; + position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y ); } int CollisionPolygon::getX() const { - return position_x; + return position.getX(); } int CollisionPolygon::getY() const { - return position_y; + return position.getY(); } void CollisionPolygon::setColor( const std::string &color ) { diff --git a/sdlpp/sdlpp_collision.hpp b/sdlpp/sdlpp_collision.hpp index 375d693..347f9e8 100644 --- a/sdlpp/sdlpp_collision.hpp +++ b/sdlpp/sdlpp_collision.hpp @@ -3,12 +3,14 @@ #include "sdlpp_common.hpp" #include "sdlpp_renderer.hpp" +#include "sdlpp_vector.hpp" #include namespace SDLPP { class SDLPPSCOPE CollisionPolygon { public: CollisionPolygon( double x, double y ); + CollisionPolygon( const Vec2D &input ); virtual ~CollisionPolygon() {} virtual bool colidesWith( const CollisionPolygon &other ) const = 0; virtual bool isCircle() const = 0; @@ -26,13 +28,11 @@ public: int getY() const; void setColor( const std::string &color ); void setOutlineColor( const std::string &color ); - virtual std::shared_ptr copySelf() = 0; + virtual std::shared_ptr< CollisionPolygon > copySelf() = 0; protected: - double original_x; - double original_y; - int position_x; - int position_y; + Vec2D original; + Vec2D position; bool infinite = false; SDL_Color sdl_color = { 0, 0, 0, 0 }; SDL_Color sdl_outline = { 0, 0, 0, 0 }; diff --git a/sdlpp/sdlpp_geometry.hpp b/sdlpp/sdlpp_geometry.hpp new file mode 100644 index 0000000..af6447d --- /dev/null +++ b/sdlpp/sdlpp_geometry.hpp @@ -0,0 +1,7 @@ +#ifndef SDLPP_HPP_GEOMETRY +#define SDLPP_HPP_GEOMETRY + +#include "sdlpp_geometry_vector.hpp" +#include "sdlpp_geometry_line.hpp" + +#endif diff --git a/sdlpp/sdlpp_geometry_line.hpp b/sdlpp/sdlpp_geometry_line.hpp new file mode 100644 index 0000000..b0e21ad --- /dev/null +++ b/sdlpp/sdlpp_geometry_line.hpp @@ -0,0 +1,30 @@ +#ifndef SDLPP_HPP_GEOMETRY_LINE +#define SDLPP_HPP_GEOMETRY_LINE + +#include "sdlpp_common.hpp" +#include "sdlpp_vector.hpp" +#include "sdlpp_line.hpp" +#include + +namespace SDLPP { +template +Vec2D pointProjectionOnLine( const Vec2D &point, const Line &line ) { + /* from here - + * https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment + */ + auto length_squared = line.lengthSquared(); + if ( length_squared == 0.0 ) + return point; + auto t = + std::max( 0.0, std::min( 1.0, ( ( point - line.getStart() ) * + ( line.getEnd() - line.getStart() ) ) / + length_squared ) ); + return line.getStart() + t * ( line.getEnd() - line.getStart() ); +} +template +double pointLineDistance( const Vec2D &point, const Line &line ) { + return vecDistance( point, pointProjectionOnLine( point, line ) ); +} +} // namespace SDLPP + +#endif diff --git a/sdlpp/sdlpp_geometry_vector.hpp b/sdlpp/sdlpp_geometry_vector.hpp new file mode 100644 index 0000000..e1405fe --- /dev/null +++ b/sdlpp/sdlpp_geometry_vector.hpp @@ -0,0 +1,31 @@ +#ifndef SDLPP_HPP_GEOMETRY_VECTOR +#define SDLPP_HPP_GEOMETRY_VECTOR + +#include "sdlpp_common.hpp" +#include "sdlpp_vector.hpp" +#include + +namespace SDLPP { +template +double vecDotProduct( const Vec2D &a, const Vec2D &b ) { + return a * b; +} +template +double vecLengthSquared( const Vec2D &vec ) { + return vecDotProduct( vec, vec ); +} +template +double vecLength( const Vec2D &vec ) { + return std::sqrt( vecLengthSquared( vec ) ); +} +template +double vecDistanceSquared( const Vec2D &a, const Vec2D &b ) { + return vecLengthSquared( a - b ); +} +template +double vecDistance( const Vec2D &a, const Vec2D &b ) { + return vecLength( a - b ); +} +} // namespace SDLPP + +#endif diff --git a/sdlpp/sdlpp_line.hpp b/sdlpp/sdlpp_line.hpp new file mode 100644 index 0000000..687ac36 --- /dev/null +++ b/sdlpp/sdlpp_line.hpp @@ -0,0 +1,52 @@ +#ifndef SDLPP_HPP_LINE +#define SDLPP_HPP_LINE + +#include "sdlpp_common.hpp" +#include "sdlpp_vector.hpp" + +namespace SDLPP { +template +class SDLPPSCOPE Line { +public: + Line() = delete; + ~Line() = default; + Line( const Vec2D &start, const Vec2D &end ) + : _start( start ), _end( end ) {} + Line( T x_1, T y_1, T x_2, T y_2 ) + : _start( { x_1, y_1 } ), _end( { x_2, y_2 } ) {} + Line( const Vec2D &start, const Vec2D &end, bool infinite ) + : _start( start ), _end( end ), _infinite( infinite ) {} + Line( T x_1, T y_1, T x_2, T y_2, bool infinite ) + : _start( { x_1, y_1 } ), _end( { x_2, y_2 } ), + _infinite( infinite ) {} + const Vec2D &getStart() const { + return _start; + } + const Vec2D &getEnd() const { + return _end; + } + double length() const { + return vecDistance( _start, _end ); + } + double lengthSquared() const { + return vecDistanceSquared( _start, _end ); + } + void setInfinite( bool infinite ) { + _infinite = infinite; + } + bool isInfinite() { + return _infinite; + } + void add(const Vec2D &vec) { + _start += vec; + _end += vec; + } + +private: + Vec2D _start; + Vec2D _end; + bool _infinite = false; +}; +} // namespace SDLPP + +#endif diff --git a/sdlpp/sdlpp_linerenderer.cpp b/sdlpp/sdlpp_linerenderer.cpp index 4c9f53e..9943e05 100644 --- a/sdlpp/sdlpp_linerenderer.cpp +++ b/sdlpp/sdlpp_linerenderer.cpp @@ -4,17 +4,21 @@ 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( { { x1, y1 }, { x2, y2 } }, r ) {} 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 ) { + : LineRenderer( { { x1, y1 }, { x2, y2 } }, r, color ) {} +LineRenderer::LineRenderer( const Line< double > &line, + const std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + original = current = line; + updateSizeAndPosition(); +} +LineRenderer::LineRenderer( const Line< double > &line, + const std::shared_ptr< Renderer > &r, + const std::string &color ) + : LineRenderer( line, r ) { setColor( color ); } void LineRenderer::setColor( const std::string &color ) { @@ -26,8 +30,10 @@ void LineRenderer::render() { 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 ); + SDL_RenderDrawLine( + renderer->getRendererPtr(), pixel_line.getStart().getX(), + pixel_line.getStart().getY(), pixel_line.getEnd().getX(), + pixel_line.getEnd().getY() ); } if ( hasCollisions() && renderer->getRenderColiders() && !getHidden() ) { for ( const auto &col : getCollisions() ) @@ -46,41 +52,46 @@ void LineRenderer::move( int ticks ) { if ( std::isnan( addx ) || std::isnan( addy ) ) return; - og_x1 += addx; - og_x2 += addx; - og_y1 += addy; - og_y2 += addy; + original.add( { addx, 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; + auto diffx = original.getEnd().getX() - original.getStart().getX(); + auto diffy = original.getEnd().getY() - original.getStart().getY(); + original = { { x, y }, { x + diffx, y + 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 }; +void LineRenderer::setPos( const Vec2D &vec ) { + setPos( vec.getX(), vec.getY() ); +} +Vec2D< double > LineRenderer::getPos() const { + return original.getStart(); } int LineRenderer::leftmost() { - return pixel_x1 < pixel_x2 ? pixel_x1 : pixel_x2; + return pixel_line.getStart().getX() < pixel_line.getEnd().getX() + ? pixel_line.getStart().getX() + : pixel_line.getEnd().getX(); } int LineRenderer::topmost() { - return pixel_y1 < pixel_y2 ? pixel_y1 : pixel_y2; + return pixel_line.getStart().getY() < pixel_line.getEnd().getY() + ? pixel_line.getStart().getY() + : pixel_line.getEnd().getY(); } int LineRenderer::rightmost() { - return pixel_x1 > pixel_x2 ? pixel_x1 : pixel_x2; + return pixel_line.getStart().getX() > pixel_line.getEnd().getX() + ? pixel_line.getStart().getX() + : pixel_line.getEnd().getX(); } int LineRenderer::bottommost() { - return pixel_y1 > pixel_y2 ? pixel_y1 : pixel_y2; + return pixel_line.getStart().getY() > pixel_line.getEnd().getY() + ? pixel_line.getStart().getY() + : pixel_line.getEnd().getY(); } int LineRenderer::collisionPushX() { return leftmost(); @@ -97,10 +108,11 @@ int LineRenderer::collisionHeight() { 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 ); + pixel_line = Line< int >( + Vec2D< int >( std::round( current.getStart().getX() * dimension ), + std::round( current.getStart().getY() * dimension ) ), + Vec2D< int >( std::round( current.getEnd().getX() * dimension ), + std::round( current.getEnd().getY() * dimension ) ) ); for ( auto &x : collisions ) { x->updateCollision( collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight() ); @@ -112,42 +124,41 @@ void LineRenderer::centerX() { } std::shared_ptr< RenderObject > LineRenderer::copySelf() { auto ret = std::make_shared< LineRenderer >( *this ); - copyTo(ret); + copyTo( ret ); return ret; } -void LineRenderer::copyTo(std::shared_ptr other) { - RenderObject::copyTo(other); +void LineRenderer::copyTo( std::shared_ptr< RenderObject > other ) { + RenderObject::copyTo( other ); } SDL_Rect LineRenderer::getRect() { return { leftmost(), topmost(), rightmost() - leftmost(), bottommost() - topmost() }; } -std::pair< std::pair< double, double >, std::pair< double, double > > +std::pair< Vec2D, Vec2D > LineRenderer::getDoubleRect() const { - return { { og_x1, og_y1 }, { og_x2 - og_x1, og_y2 - og_y1 } }; + return { original.getStart(), original.getEnd() - original.getStart() }; } void LineRenderer::updateXY() { if ( !centerx ) { - x1_ = og_x1; - y1_ = og_y1; - x2_ = og_x2; - y2_ = og_y2; + current = original; return; } auto width = renderer->getWidth(); auto height = renderer->getHeight(); + double x1_, x2_, y1_, y2_; 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; + x1_ = original.getStart().getX() + static_cast< double >( multiplier - 1 ) / 2; + x2_ = original.getEnd().getX() + static_cast< double >( multiplier - 1 ) / 2; } else { - x1_ = og_x1; - x2_ = og_x2; + x1_ = original.getStart().getX(); + x2_ = original.getEnd().getX(); } - y1_ = og_y1; - y2_ = og_y2; + y1_ = original.getStart().getY(); + y2_ = original.getEnd().getY(); + current = {{x1_, y1_}, {x2_, y2_}}; } } // namespace SDLPP diff --git a/sdlpp/sdlpp_linerenderer.hpp b/sdlpp/sdlpp_linerenderer.hpp index 4f92e31..c852296 100644 --- a/sdlpp/sdlpp_linerenderer.hpp +++ b/sdlpp/sdlpp_linerenderer.hpp @@ -2,7 +2,9 @@ #define SDLPP_HPP_LINE_RENDERER #include "sdlpp_common.hpp" +#include "sdlpp_line.hpp" #include "sdlpp_renderobject.hpp" +#include "sdlpp_vector.hpp" namespace SDLPP { class SDLPPSCOPE LineRenderer : public RenderObject { @@ -14,6 +16,11 @@ public: LineRenderer( double x1, double y1, double x2, double y2, const std::shared_ptr< Renderer > &r, const std::string &color ); + LineRenderer( const Line &line, + const std::shared_ptr< Renderer > &r ); + LineRenderer( const Line &line, + 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; @@ -21,7 +28,8 @@ public: 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 void setPos( const Vec2D &vec ) override; + virtual Vec2D getPos() const override; virtual int leftmost() override; virtual int topmost() override; virtual int rightmost() override; @@ -35,26 +43,16 @@ public: virtual std::shared_ptr< RenderObject > copySelf() override; virtual SDL_Rect getRect() override; - virtual std::pair< std::pair< double, double >, - std::pair< double, double > > + virtual std::pair< Vec2D, Vec2D> getDoubleRect() const override; void setOutlineColor( const std::string & /*UNUSED*/ ) override {} protected: virtual void copyTo(std::shared_ptr other) override; 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{}; + Line original = {{0, 0}, {0, 0}}; + Line current = {{0, 0}, {0, 0}}; + Line pixel_line = {{0, 0}, {0, 0}}; bool centerx = false; std::tuple< int, int, int, int > _color; }; diff --git a/sdlpp/sdlpp_rectcolider.cpp b/sdlpp/sdlpp_rectcolider.cpp index 1507291..e41d8f7 100644 --- a/sdlpp/sdlpp_rectcolider.cpp +++ b/sdlpp/sdlpp_rectcolider.cpp @@ -1,12 +1,30 @@ #include "sdlpp_rectcolider.hpp" namespace SDLPP { -RectColider::RectColider( double x, double y, double w, double h ) - : CollisionPolygon( x, y ) { - w_ = w; - h_ = h; + +double RectColider::width() const { + return _size.getX(); } +double RectColider::height() const { + return _size.getY(); +} + +int RectColider::pixel_width() const { + return _size_pixel.getX(); +} + +int RectColider::pixel_height() const { + return _size_pixel.getY(); +} + +RectColider::RectColider( double x, double y, double w, double h ) + : RectColider( { x, y }, { w, h } ) {} + +RectColider::RectColider( const Vec2D< double > &top_left, + const Vec2D< double > &size ) + : CollisionPolygon( top_left ), _size( size ) {} + bool RectColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { if ( other.isCircle() ) { return other.colidesWith( *this ); @@ -23,25 +41,25 @@ bool RectColider::isCircle() const { return false; } int RectColider::topmost() const { - return ( !isInfinite() || original_y != -1 ) * getY() + isInfinite() * -1; + return ( !isInfinite() || original.getY() != -1 ) * getY() + + isInfinite() * -1; } int RectColider::bottommost() const { - return ( !isInfinite() || h_ != -1 ) * ( getY() + pixel_h ) + + return ( !isInfinite() || height() != -1 ) * ( getY() + pixel_height() ) + isInfinite() * -1; } int RectColider::leftmost() const { - return ( !isInfinite() || original_x != -1 ) * getX() + isInfinite() * -1; + return ( !isInfinite() || original.getX() != -1 ) * getX() + + isInfinite() * -1; } int RectColider::rightmost() const { - return ( !isInfinite() || w_ != -1 ) * ( getX() + pixel_w ) + + return ( !isInfinite() || width() != -1 ) * ( getX() + pixel_width() ) + 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; + position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y ); + _size_pixel = Vec2D< int >( width() * w, height() * h ); } void RectColider::render( Renderer &renderer, @@ -71,7 +89,7 @@ void RectColider::render( Renderer &renderer ) { SDL_Rect RectColider::getRect() { if ( !isInfinite() ) - return { leftmost(), topmost(), pixel_w, pixel_h }; + return { leftmost(), topmost(), pixel_width(), pixel_height() }; SDL_Rect r = { 0, 0, 0, 0 }; if ( ( r.x = leftmost() ) == -1 ) @@ -81,11 +99,11 @@ SDL_Rect RectColider::getRect() { if ( rightmost() == -1 ) r.w = std::numeric_limits< int >::max(); else - r.w = pixel_w; + r.w = pixel_width(); if ( bottommost() == -1 ) r.h = std::numeric_limits< int >::max(); else - r.h = pixel_h; + r.h = pixel_height(); return r; } @@ -93,4 +111,15 @@ std::shared_ptr< CollisionPolygon > RectColider::copySelf() { return std::make_shared< RectColider >( *this ); } +std::vector< Line< double > > RectColider::getLines() { + std::vector< Line< double > > ret{}; + ret.emplace_back( original, original + Vec2D< double >( width(), 0 ) ); + ret.emplace_back( original + Vec2D< double >( width(), 0 ), + original + _size ); + ret.emplace_back( original, original + Vec2D< double >( 0, height() ) ); + ret.emplace_back( original + Vec2D< double >( 0, height() ), + original + _size ); + return ret; +} + } // namespace SDLPP diff --git a/sdlpp/sdlpp_rectcolider.hpp b/sdlpp/sdlpp_rectcolider.hpp index 75d0918..e302816 100644 --- a/sdlpp/sdlpp_rectcolider.hpp +++ b/sdlpp/sdlpp_rectcolider.hpp @@ -3,13 +3,17 @@ #include "sdlpp_common.hpp" #include "sdlpp_collision.hpp" +#include "sdlpp_vector.hpp" +#include "sdlpp_line.hpp" #include +#include namespace SDLPP { class SDLPPSCOPE RectColider : public CollisionPolygon { public: RectColider( double x, double y, double w, double h ); + RectColider( const Vec2D &top_left, const Vec2D &size ); virtual ~RectColider() {} virtual bool colidesWith( const CollisionPolygon &other ) const override; virtual bool isCircle() const override; @@ -23,14 +27,18 @@ public: const std::tuple< int, int, int, int > &color ) override; virtual void render( Renderer &renderer ) override; virtual std::shared_ptr copySelf() override; + virtual std::vector> getLines(); private: SDL_Rect getRect(); - double w_; - double h_; - int pixel_w; - int pixel_h; + double width() const; + double height() const; + int pixel_width() const; + int pixel_height() const; + + Vec2D _size; + Vec2D _size_pixel; }; } // end of namespace SDLPP #endif diff --git a/sdlpp/sdlpp_rectrenderer.cpp b/sdlpp/sdlpp_rectrenderer.cpp index 397781f..34a414d 100644 --- a/sdlpp/sdlpp_rectrenderer.cpp +++ b/sdlpp/sdlpp_rectrenderer.cpp @@ -4,33 +4,67 @@ 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( { x, y }, { w, h }, r ) {} RectangleRender::RectangleRender( double x, double y, double w, double h, const std::shared_ptr< Renderer > &r, const std::shared_ptr< Texture > &t, int source_x, int source_y, int source_width, int source_height ) - : RectangleRender( x, y, w, h, r ) { - setTexture( t, source_x, source_y, source_width, source_height ); -} + : RectangleRender( { x, y }, { w, h }, r, t, source_x, source_y, + source_width, source_height ) {} RectangleRender::RectangleRender( double x, double y, double w, double h, const std::shared_ptr< Renderer > &r, const std::shared_ptr< Texture > &t, const SDL_Rect &source_rect ) - : RectangleRender( x, y, w, h, r ) { - setTexture( t, source_rect ); -} + : RectangleRender( { x, y }, { w, h }, r, t, source_rect ) {} 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 ) { + : RectangleRender( { x, y }, { w, h }, r, img_or_color, is_polygon ) {} +RectangleRender::RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::string &img, int source_x, + int source_y, int source_width, + int source_height ) + : RectangleRender( { x, y }, { w, h }, r, img, source_x, source_y, + source_width, source_height ) {} +RectangleRender::RectangleRender( double x, double y, double w, double h, + const std::shared_ptr< Renderer > &r, + const std::string &img, + const SDL_Rect &source_rect ) + : RectangleRender( { x, y }, { w, h }, r, img, source_rect ) {} +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, + const std::shared_ptr< Renderer > &r ) + : RenderObject( r ) { + original = top_left; + original_size = size; + updateSizeAndPosition(); +} +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t, + int source_x, int source_y, int source_width, + int source_height ) + : RectangleRender( top_left, size, r ) { + setTexture( t, source_x, source_y, source_width, source_height ); +} +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t, + const SDL_Rect &source_rect ) + : RectangleRender( top_left, size, r ) { + setTexture( t, source_rect ); +} +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, + const std::shared_ptr< Renderer > &r, + const std::string &img_or_color, + bool is_polygon ) + : RectangleRender( top_left, size, r ) { if ( !is_polygon ) { setTexture( img_or_color ); } else { @@ -38,19 +72,21 @@ RectangleRender::RectangleRender( double x, double y, double w, double h, color = img_or_color; } } -RectangleRender::RectangleRender( double x, double y, double w, double h, +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, const std::shared_ptr< Renderer > &r, const std::string &img, int source_x, int source_y, int source_width, int source_height ) - : RectangleRender( x, y, w, h, r ) { + : RectangleRender( top_left, size, r ) { setTexture( img, source_x, source_y, source_width, source_height ); } -RectangleRender::RectangleRender( double x, double y, double w, double h, +RectangleRender::RectangleRender( const Vec2D< double > &top_left, + const Vec2D< double > &size, const std::shared_ptr< Renderer > &r, const std::string &img, const SDL_Rect &source_rect ) - : RectangleRender( x, y, w, h, r ) { + : RectangleRender( top_left, size, r ) { setTexture( img, source_rect ); } void RectangleRender::setColor( const std::string &color ) { @@ -69,9 +105,9 @@ void RectangleRender::setOutlineColor( const std::string &color ) { } polygon->setOutlineColor( color ); } -std::pair< std::pair< double, double >, std::pair< double, double > > +std::pair< Vec2D< double >, Vec2D< double > > RectangleRender::getDoubleRect() const { - return { { og_x, og_y }, { og_w, og_h } }; + return { original, original_size }; } int RectangleRender::leftmost() { return rect.x; @@ -100,10 +136,12 @@ int RectangleRender::collisionHeight() { 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; + rect.x = std::round( current.getX() * dimension ); + rect.y = std::round( current.getY() * dimension ); + rect.w = + std::round( ( current.getX() + original_size.getX() ) * dimension ) - rect.x; + rect.h = + std::round( ( current.getY() + original_size.getY() ) * dimension ) - rect.y; if ( polygon ) polygon->updateCollision( collisionPushX(), collisionPushY(), collisionWidth(), collisionHeight() ); @@ -133,19 +171,20 @@ std::string RectangleRender::getColor() const { void RectangleRender::updateXY() { if ( !centerx ) { - x_ = og_x; - y_ = og_y; + current = original; return; } auto width = renderer->getWidth(); auto height = renderer->getHeight(); + double x_, y_; if ( width > height ) { auto multiplier = static_cast< double >( width ) / static_cast< double >( height ); - x_ = og_x + static_cast< double >( multiplier - 1 ) / 2; + x_ = original.getX() + static_cast< double >( multiplier - 1 ) / 2; } else { - x_ = og_x; + x_ = original.getX(); } - y_ = og_y; + y_ = original.getY(); + current = { x_, y_ }; } } // namespace SDLPP diff --git a/sdlpp/sdlpp_rectrenderer.hpp b/sdlpp/sdlpp_rectrenderer.hpp index aa9d934..aa73f3f 100644 --- a/sdlpp/sdlpp_rectrenderer.hpp +++ b/sdlpp/sdlpp_rectrenderer.hpp @@ -31,13 +31,32 @@ public: RectangleRender( double x, double y, double w, double h, const std::shared_ptr< Renderer > &r, const std::string &img, const SDL_Rect &source_rect ); + + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r ); + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t, int source_x, + int source_y, int source_width, int source_height ); + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r, + const std::shared_ptr< Texture > &t, + const SDL_Rect &source_rect = { -1, -1, -1, -1 } ); + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r, + const std::string &img_or_color, bool is_polygon = false ); + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r, + const std::string &img, int source_x, int source_y, + int source_width, int source_height ); + RectangleRender( const Vec2D &top_left, const Vec2D &size, + const std::shared_ptr< Renderer > &r, + const std::string &img, const SDL_Rect &source_rect ); virtual void setColor( const std::string &color ) override; virtual void setOutlineColor( const std::string &color ) override; virtual void specialAction( int /*UNUSED*/ ) override {} virtual void custom_move( int /*UNUSED*/ ) override {} - virtual std::pair< std::pair< double, double >, - std::pair< double, double > > - getDoubleRect() const override; + virtual std::pair< Vec2D, Vec2D > getDoubleRect() const override; virtual int leftmost() override; virtual int topmost() override; virtual int rightmost() override; @@ -55,10 +74,8 @@ public: protected: virtual void copyTo( std::shared_ptr< RenderObject > other ) override; void updateXY(); - double og_w; - double og_h; - double w_; - double h_; + Vec2D original_size; + Vec2D size; std::string color = ""; }; } // end of namespace SDLPP diff --git a/sdlpp/sdlpp_renderobject.cpp b/sdlpp/sdlpp_renderobject.cpp index 5beec94..c35da6c 100644 --- a/sdlpp/sdlpp_renderobject.cpp +++ b/sdlpp/sdlpp_renderobject.cpp @@ -28,15 +28,17 @@ void RenderObject::render() { } } void RenderObject::setPos( double x, double y ) { - og_x = x; - og_y = y; + original = { x, y }; updateSizeAndPosition(); } void RenderObject::setPos( const std::pair< double, double > &pos ) { setPos( pos.first, pos.second ); } -std::pair< double, double > RenderObject::getPos() const { - return { og_x, og_y }; +void RenderObject::setPos( const Vec2D &vec ) { + setPos( vec.getX(), vec.getY() ); +} +Vec2D< double > RenderObject::getPos() const { + return original; } bool RenderObject::colidesWith( const RenderObject &other ) const { if ( !hasCollisions() || !other.hasCollisions() || getHidden() || @@ -161,8 +163,7 @@ void RenderObject::move( int ticks ) { if ( std::isnan( addx ) || std::isnan( addy ) ) return; - og_x += addx; - og_y += addy; + original += { addx, addy }; custom_move( ticks ); diff --git a/sdlpp/sdlpp_renderobject.hpp b/sdlpp/sdlpp_renderobject.hpp index 155962a..bd60f05 100644 --- a/sdlpp/sdlpp_renderobject.hpp +++ b/sdlpp/sdlpp_renderobject.hpp @@ -5,6 +5,7 @@ #include "sdlpp_collision.hpp" #include "sdlpp_renderer.hpp" #include "sdlpp_texture.hpp" +#include "sdlpp_vector.hpp" #include #include @@ -26,12 +27,12 @@ public: 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 > > + virtual std::pair< Vec2D< double >, Vec2D< double > > getDoubleRect() const = 0; virtual void setPos( double x, double y ); virtual void setPos( const std::pair< double, double > &pos ); - virtual std::pair< double, double > getPos() const; + virtual void setPos( const Vec2D &vec ); + virtual Vec2D< double > getPos() const; bool colidesWith( const RenderObject &other ) const; template < class T > void addCollision( const T &p ) { collisions.push_back( std::make_shared< T >( p ) ); @@ -131,10 +132,8 @@ private: friend Scene; protected: - double og_x; - double og_y; - double x_; - double y_; + Vec2D< double > original; + Vec2D< double > current; }; } // end of namespace SDLPP diff --git a/sdlpp/sdlpp_scene.cpp b/sdlpp/sdlpp_scene.cpp index a3df905..495b95e 100644 --- a/sdlpp/sdlpp_scene.cpp +++ b/sdlpp/sdlpp_scene.cpp @@ -20,11 +20,11 @@ void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) { } else { auto rect = obj->getDoubleRect(); auto leftmost_rect = leftmost_obj->getDoubleRect(); - if ( rect.first.first < leftmost_rect.first.first ) + if ( rect.first.getX() < leftmost_rect.first.getX() ) leftmost_obj = obj; auto rightmost_rect = rightmost_obj->getDoubleRect(); - if ( rect.first.first + rect.second.first > - rightmost_rect.first.first + rightmost_rect.second.first ) + if ( rect.first.getX() + rect.second.getX() > + rightmost_rect.first.getX() + rightmost_rect.second.getX() ) rightmost_obj = obj; } } @@ -123,8 +123,9 @@ void Scene::renderScene( bool clear_renderer ) { if ( background && background->getTexturePtr() ) SDL_RenderCopy( renderer->getRendererPtr(), background->getTexturePtr(), NULL, NULL ); - for ( const auto &x : render_objects ) + for ( const auto &x : render_objects ) { x->render(); + } } void Scene::presentScene() { SDL_RenderPresent( renderer->getRendererPtr() ); @@ -153,7 +154,7 @@ void Scene::moveEverything( double x, double y ) { if ( obj->getPermanent() ) continue; auto curPos = obj->getDoubleRect(); - obj->setPos( curPos.first.first + x, curPos.first.second + y ); + obj->setPos( curPos.first.getX() + x, curPos.first.getY() + y ); } } const std::shared_ptr< RenderObject > &Scene::leftmost() { diff --git a/sdlpp/sdlpp_vector.hpp b/sdlpp/sdlpp_vector.hpp new file mode 100644 index 0000000..4644c9e --- /dev/null +++ b/sdlpp/sdlpp_vector.hpp @@ -0,0 +1,56 @@ +#ifndef SDLPP_HPP_VECTOR +#define SDLPP_HPP_VECTOR + +#include "sdlpp_common.hpp" + +namespace SDLPP { +template +class SDLPPSCOPE Vec2D { +public: + Vec2D() = default; + ~Vec2D() = default; + Vec2D(T x, T y) : _x(x), _y(y) {} + T getX() const { + return _x; + } + T getY() const { + return _y; + } + Vec2D operator-(const Vec2D &other) const { + return Vec2D( getX() - other.getX(), getY() - other.getY() ); + } + Vec2D operator+(const Vec2D &other) const { + return Vec2D( getX() + other.getX(), getY() + other.getY() ); + } + Vec2D operator*(double multiplier) const { + return Vec2D( getX() * multiplier, getY() * multiplier ); + } + Vec2D operator/(double divisor) const { + return *this * ( 1.0 / divisor ); + } + T operator*(const Vec2D &other) const { + return getX() * other.getX() + getY() * other.getY(); + } + Vec2D &operator+=(const Vec2D &other) { + *this = *this + other; + return *this; + } + Vec2D &operator-=(const Vec2D &other) { + *this = *this - other; + return *this; + } +private: + T _x = 0.0; + T _y = 0.0; +}; +template +Vec2D operator*(double multiplier, const Vec2D &vec) { + return vec * multiplier; +} +template +Vec2D operator/(double divisor, const Vec2D &vec) { + return vec / divisor; +} +} + +#endif diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..5410314 --- /dev/null +++ b/test.cpp @@ -0,0 +1,32 @@ +#include "sdlpp/sdlpp.hpp" +#include + +int main() { + SDLPP::init(); + SDLPP::Window w("Test"); + w.setResizable( true ); + auto renderer = std::make_shared< SDLPP::Renderer >( w ); + renderer->setBlendMode( SDL_BLENDMODE_BLEND ); + auto main_scene = std::make_shared< SDLPP::Scene >( renderer ); + auto bg = std::make_shared(0, 0, 10, 10, renderer, "#FF0000", true); + bg->setId(123); + bg->setPermanent(true); + main_scene->addObject(bg); + FPSmanager gFPS; + SDL_initFramerate( &gFPS ); + SDL_setFramerate( &gFPS, 60 ); + + int base = SDL_GetTicks(); + int frames = 0; + while(true) { + SDL_PumpEvents(); + main_scene->renderScene(); + main_scene->presentScene(); + frames++; + if ( SDL_GetTicks() - base >= 1000 ) { + base = SDL_GetTicks(); + printf( "FPS: %d\n", frames ); + frames = 0; + } + } +} diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..2d54c4d --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,18 @@ +PREFIX ?= /usr/local/bin +CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic +OBJEXT=o +LDFLAGS ?= -lSDL2 -lSDL2_image -lSDL2_gfx -lSDL2_ttf -pthread + +.PHONY: default +default: test + +OBJECTFILES = sdlpp_circlecolider.${OBJEXT} sdlpp_circlerenderer.${OBJEXT} sdlpp_collision.${OBJEXT} sdlpp_common.${OBJEXT} sdlpp_font.${OBJEXT} sdlpp_linerenderer.${OBJEXT} sdlpp_rectcolider.${OBJEXT} sdlpp_rectrenderer.${OBJEXT} sdlpp_renderer.${OBJEXT} sdlpp_renderobject.${OBJEXT} sdlpp_scene.${OBJEXT} sdlpp_textrenderer.${OBJEXT} sdlpp_texture.${OBJEXT} sdlpp_window.${OBJEXT} sdlpp_vector.${OBJEXT} sdlpp_line.${OBJEXT} sdlpp_geometry.${OBJEXT} + +%.${OBJEXT}: ../sdlpp/%.cpp + ${CXX} ${CXXFLAGS} ${LIBRARYFLAGS} -c $< -o $@ + +test: test.cpp ${OBJECTFILES} + $(CXX) $(CXXFLAGS) -o $@ $^ ${LDFLAGS} + +clean: + rm -Rf *.${OBJEXT} test diff --git a/tests/test.cpp b/tests/test.cpp index 6c25ba7..e73edc6 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1,11 +1,12 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include "../sdlpp.hpp" +#include "../sdlpp/sdlpp.hpp" +#include // sdlpp.hpp -TEST_CASE( "Rect collisions" ) { +/*TEST_CASE( "Rect collisions" ) { SDLPP::Rect r(0,0,10,10); REQUIRE(r.colidesWith(r)); SDLPP::Rect r2(100,100,10,10); @@ -40,5 +41,52 @@ TEST_CASE( "Multiple collisions" ) { REQUIRE(r.colidesWith(r1)); REQUIRE(r.colidesWith(r2)); REQUIRE_FALSE(r.colidesWith(r3)); +}*/ + +TEST_CASE( "Point distances" ) { + SDLPP::Vec2D p1(0,0); + SDLPP::Vec2D p2(1,0); + auto dist = vecDistance(p1, p2); + REQUIRE( dist > 0.99 ); + REQUIRE( dist < 1.01 ); + dist = vecDistance(p2, p1); + REQUIRE( dist > 0.99 ); + REQUIRE( dist < 1.01 ); + p2 = SDLPP::Vec2D(0,1); + dist = vecDistance(p1, p2); + REQUIRE( dist > 0.99 ); + REQUIRE( dist < 1.01 ); + dist = vecDistance(p2, p1); + REQUIRE( dist > 0.99 ); + REQUIRE( dist < 1.01 ); + p2 = SDLPP::Vec2D(1,1); + dist = vecDistance(p1, p2); + REQUIRE( dist > 1.4142 ); + REQUIRE( dist < 1.41422 ); +} + +TEST_CASE( "Point line distances" ) { + SDLPP::Vec2D p1(0,0); + SDLPP::Line line({-1,-1}, {1, -1}); + auto dist = pointLineDistance(p1, line); + REQUIRE( dist > 0.99 ); + REQUIRE( dist < 1.01 ); + line = SDLPP::Line({-3,-1}, {-1,-1}); + dist = pointLineDistance(p1, line); + REQUIRE( dist > 1.4142 ); + REQUIRE( dist < 1.41422 ); + line = SDLPP::Line({-3,-2}, {-2,-2}); + dist = pointLineDistance(p1, line); + REQUIRE( dist > 2.8284 ); + REQUIRE( dist < 2.82843 ); + line = SDLPP::Line({-3,-1}, {-2,-2}); + dist = pointLineDistance(p1, line); + std::cout << dist << std::endl; + line = SDLPP::Line({-3,-1}, {-2,-180}); + dist = pointLineDistance(p1, line); + std::cout << dist << std::endl; + SDLPP::Vec2D p2(-3, -1); + dist = vecDistance(p1, p2); + std::cout << dist << std::endl; } diff --git a/tetris/Makefile b/tetris/Makefile index c171338..409b2f0 100644 --- a/tetris/Makefile +++ b/tetris/Makefile @@ -10,7 +10,7 @@ OUTPUTFLAG = -Fo else UNAME_S := $(shell uname -s) CXX ?= g++ -CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic -O2 # -DDEBUG -DFEATURE # -g -fsanitize=address +CXXFLAGS = -std=c++14 -Wall -Wextra -pedantic -O2 -DDEBUG -DFEATURE -g -fsanitize=address OBJEXT = o LDFLAGS ?= -lSDL2 -lSDL2_image -lSDL2_gfx -lSDL2_ttf -pthread OUTPUTFLAG = -o diff --git a/tetris/custom_classes.cpp b/tetris/custom_classes.cpp index 2c5fc5a..305d588 100644 --- a/tetris/custom_classes.cpp +++ b/tetris/custom_classes.cpp @@ -32,10 +32,10 @@ TetrisBlock::TetrisBlock( double x, double y, double w, double h, } TetrisBlock::TetrisBlock( const TetrisBlock &other ) - : TetrisBlock( other.getDoubleRect().first.first, - other.getDoubleRect().first.second, - other.getDoubleRect().second.first, - other.getDoubleRect().second.second, other.getRenderer(), + : TetrisBlock( other.getDoubleRect().first.getX(), + other.getDoubleRect().first.getY(), + other.getDoubleRect().second.getX(), + other.getDoubleRect().second.getY(), other.getRenderer(), other.getColor(), true, other._index, other._scene, other.pieces_bag ) {} @@ -63,9 +63,9 @@ std::shared_ptr< TetrisBlock > TetrisBlock::copyInScene() { bool TetrisBlock::isSamePos( const SDLPP::RenderObject &other ) const { auto mypos = getPos(); auto otherpos = other.getPos(); - auto diff1 = mypos.first - otherpos.first; + auto diff1 = mypos.getX() - otherpos.getX(); diff1 = ( diff1 < 0 ) * ( -1 ) * diff1 + ( diff1 > 0 ) * diff1; - auto diff2 = mypos.second - otherpos.second; + auto diff2 = mypos.getY() - otherpos.getY(); diff2 = ( diff2 < 0 ) * ( -1 ) * diff2 + ( diff2 > 0 ) * diff2; return diff1 < 0.0001 && diff2 < 0.0001; } @@ -152,23 +152,23 @@ void TetrisPiece::rotate() { for ( unsigned long i = 0; i < pieces.size(); i++ ) { auto &piece = pieces[i]; auto &positions = pieces_rel_position[i]; - auto position = piece->getPos(); - original_pos[i] = position; - position.first += positions[0] * BLOCK_SIZE; - position.first -= positions[1] * BLOCK_SIZE; - position.second += positions[2] * BLOCK_SIZE; - position.second -= positions[3] * BLOCK_SIZE; + auto piece_position = piece->getPos(); + original_pos[i] = piece_position; + piece_position += { positions[0] * BLOCK_SIZE - + positions[1] * BLOCK_SIZE, + positions[2] * BLOCK_SIZE - + positions[3] * BLOCK_SIZE }; auto bottom = positions[3]; auto top = positions[2]; positions[3] = positions[1]; positions[2] = positions[0]; positions[1] = top; positions[0] = bottom; - position.first -= positions[0] * BLOCK_SIZE; - position.first += positions[1] * BLOCK_SIZE; - position.second -= positions[2] * BLOCK_SIZE; - position.second += positions[3] * BLOCK_SIZE; - piece->setPos( position.first, position.second ); + piece_position += { positions[1] * BLOCK_SIZE - + positions[0] * BLOCK_SIZE, + positions[3] * BLOCK_SIZE - + positions[2] * BLOCK_SIZE }; + piece->setPos( piece_position ); } } @@ -176,7 +176,7 @@ void TetrisPiece::revert() { for ( unsigned long i = 0; i < pieces.size(); i++ ) { auto &piece = pieces[i]; auto &positions = pieces_rel_position[i]; - piece->setPos( original_pos[i].first, original_pos[i].second ); + piece->setPos( original_pos[i] ); auto top = positions[1]; auto bottom = positions[0]; positions[1] = positions[3]; @@ -207,14 +207,16 @@ void TetrisPiece::setPos( const std::pair< double, double > &pos ) { setPos( pos.first, pos.second ); } -std::pair< double, double > TetrisPiece::getPos() { +void TetrisPiece::setPos( const SDLPP::Vec2D &vec ) { + setPos( vec.getX(), vec.getY() ); +} + +SDLPP::Vec2D TetrisPiece::getPos() { auto &piece = pieces[0]; auto &relpositions = pieces_rel_position[0]; auto pos = piece->getPos(); - pos.first += relpositions[0] * BLOCK_SIZE; - pos.first -= relpositions[1] * BLOCK_SIZE; - pos.second += relpositions[2] * BLOCK_SIZE; - pos.second -= relpositions[3] * BLOCK_SIZE; + pos += { relpositions[0] * BLOCK_SIZE - relpositions[1] * BLOCK_SIZE, + relpositions[2] * BLOCK_SIZE - relpositions[3] * BLOCK_SIZE }; return pos; } @@ -258,7 +260,7 @@ bool TetrisPiece::isRight( const SDLPP::RenderObject &block ) const { void TetrisPiece::movePiece( double x, double y ) { for ( auto &block : getObjects() ) { auto pos = block->getPos(); - block->setPos( pos.first + x, pos.second + y ); + block->setPos( pos + SDLPP::Vec2D( x, y ) ); } } diff --git a/tetris/custom_classes.hpp b/tetris/custom_classes.hpp index 28acd32..1e29a2d 100644 --- a/tetris/custom_classes.hpp +++ b/tetris/custom_classes.hpp @@ -40,7 +40,8 @@ public: std::vector< std::shared_ptr< TetrisBlock > > &getObjects(); void setPos( double x, double y ); void setPos( const std::pair< double, double > &pos ); - std::pair< double, double > getPos(); + void setPos( const SDLPP::Vec2D &vec ); + SDLPP::Vec2D getPos(); void clear(); void startDescend(); void stopDescend(); @@ -69,7 +70,7 @@ private: std::vector< std::vector< int > > pieces_rel_position; std::vector< std::shared_ptr< TetrisBlock > > pieces; - std::vector< std::pair< double, double > > original_pos; + std::vector< SDLPP::Vec2D > original_pos; bool descend = false; int userMovement = 0; bool rotate_allowed = true; diff --git a/tetris/functions.cpp b/tetris/functions.cpp index 37f1913..dcded52 100644 --- a/tetris/functions.cpp +++ b/tetris/functions.cpp @@ -27,19 +27,19 @@ void updateShadow( SDLPP::Scene &scene ) { auto &invalid_objects = g_cur_object->getObjects(); for ( auto &x : g_cur_shadow->getObjects() ) { auto block_pos = x->getPos(); - if ( BOTTOM_BORDER - block_pos.second < shadow_drop ) - shadow_drop = BOTTOM_BORDER - block_pos.second; + if ( BOTTOM_BORDER - block_pos.getY() < shadow_drop ) + shadow_drop = BOTTOM_BORDER - block_pos.getY(); // set colider column's position to current block's X position - g_shadow_colider->setPos( block_pos.first, TOP_BORDER ); + g_shadow_colider->setPos( block_pos.getX(), TOP_BORDER ); auto collisions = scene.getCollisions( *g_shadow_colider, { BRICK_ID } ); - auto curY = block_pos.second; + auto curY = block_pos.getY(); for ( auto &col : collisions ) { // if collision with g_cur_object, ignore if ( std::find( invalid_objects.begin(), invalid_objects.end(), col ) != invalid_objects.end() ) continue; - auto possible_drop = col->getPos().second - curY; + auto possible_drop = col->getPos().getY() - curY; if ( possible_drop < shadow_drop && possible_drop >= 0 ) shadow_drop = possible_drop; } @@ -47,7 +47,7 @@ void updateShadow( SDLPP::Scene &scene ) { // we want the shadow to rest on top of the nearest floor shadow_drop -= BLOCK_SIZE; auto shadow_pos = g_cur_shadow->getPos(); - g_cur_shadow->setPos( shadow_pos.first, shadow_pos.second + shadow_drop ); + g_cur_shadow->setPos( shadow_pos.getX(), shadow_pos.getY() + shadow_drop ); } void moveThem( std::shared_ptr< SDLPP::Scene > scene, int ticks ) { diff --git a/tetris/scenes.cpp b/tetris/scenes.cpp index 7146fba..ff5f8fc 100644 --- a/tetris/scenes.cpp +++ b/tetris/scenes.cpp @@ -457,11 +457,11 @@ void mainSceneInput( for ( auto &col : collisions ) { col->destroy(); } - auto colider_y = colider->getPos().second; + auto colider_y = colider->getPos().getY(); for ( auto &elem : scene->getObjects( { BRICK_ID } ) ) { auto pos = elem->getPos(); - if ( pos.second < colider_y && pos.first <= RIGHT_BORDER ) { - elem->setPos( pos.first, pos.second + BLOCK_SIZE ); + if ( pos.getY() < colider_y && pos.getX() <= RIGHT_BORDER ) { + elem->setPos( pos.getX(), pos.getY() + BLOCK_SIZE ); } } using namespace std::chrono_literals;