diff --git a/sdlpp/sdlpp_circlecolider.cpp b/sdlpp/sdlpp_circlecolider.cpp index 6693f31..5c24915 100644 --- a/sdlpp/sdlpp_circlecolider.cpp +++ b/sdlpp/sdlpp_circlecolider.cpp @@ -7,6 +7,13 @@ CircleColider::CircleColider( double x, double y, double rad ) CircleColider::CircleColider( const Vec2D< double > ¢er, double rad ) : CollisionPolygon( center ), original_rad( rad ) {} +CircleColider::CircleColider( double x, double y, double rad, uint64_t id ) + : CircleColider( { x, y }, rad, id ) {} +CircleColider::CircleColider( const Vec2D< double > ¢er, double rad, + uint64_t id ) + : CircleColider( center, rad ) { + _id = id; +} bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { if ( other.isCircle() ) { @@ -47,9 +54,11 @@ int CircleColider::rightmost() const { return getX() + rad_; } -void CircleColider::updateCollision( int x, int y, int w, int h ) { +void CircleColider::updateCollision( int x, int y, int w, int h, uint64_t id ) { position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y ); rad_ = original_rad * w; + if ( _id == static_cast< uint64_t >( -1 ) ) + _id = id; } void CircleColider::render( Renderer &renderer, const SDL_Color &color, diff --git a/sdlpp/sdlpp_circlecolider.hpp b/sdlpp/sdlpp_circlecolider.hpp index ec9364d..a2f0ee5 100644 --- a/sdlpp/sdlpp_circlecolider.hpp +++ b/sdlpp/sdlpp_circlecolider.hpp @@ -11,6 +11,8 @@ class SDLPPSCOPE CircleColider : public CollisionPolygon { public: CircleColider( double x, double y, double rad ); CircleColider( const Vec2D< double > ¢er, double rad ); + CircleColider( double x, double y, double rad, uint64_t id ); + CircleColider( const Vec2D< double > ¢er, double rad, uint64_t id ); virtual ~CircleColider() {} virtual bool colidesWith( const CollisionPolygon &other ) const override; @@ -20,7 +22,8 @@ public: virtual int leftmost() const override; virtual int rightmost() const override; - virtual void updateCollision( int x, int y, int w, int h ) override; + virtual void updateCollision( int x, int y, int w, int h, + uint64_t id ) override; virtual void render( Renderer &renderer, const SDL_Color &color, const SDL_Color &outline_color ) override; virtual void render( Renderer &renderer, const SDL_Color &color ) override; diff --git a/sdlpp/sdlpp_circlerenderer.cpp b/sdlpp/sdlpp_circlerenderer.cpp index 10f61a9..c2ea5e8 100644 --- a/sdlpp/sdlpp_circlerenderer.cpp +++ b/sdlpp/sdlpp_circlerenderer.cpp @@ -49,7 +49,8 @@ void CircleRender::setColor( const std::string &color ) { if ( !polygon ) { polygon = std::make_shared< CircleColider >( 0, 0, 1 ); polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); } polygon->setColor( color ); } @@ -58,7 +59,8 @@ void CircleRender::setOutlineColor( const std::string &color ) { if ( !polygon ) { polygon = std::make_shared< CircleColider >( 0, 0, 1 ); polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); } polygon->setOutlineColor( color ); } @@ -110,10 +112,11 @@ void CircleRender::updateSizeAndPosition() { rect.h = std::round( ( current.getY() + r_ ) * dimension ) - rect.y; if ( polygon ) polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); for ( auto &x : collisions ) { x->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), getId() ); } } diff --git a/sdlpp/sdlpp_collision.cpp b/sdlpp/sdlpp_collision.cpp index 187554a..63ad7e1 100644 --- a/sdlpp/sdlpp_collision.cpp +++ b/sdlpp/sdlpp_collision.cpp @@ -9,6 +9,12 @@ CollisionPolygon::CollisionPolygon( const Vec2D< double > &input ) { original = input; position = { 0, 0 }; } +CollisionPolygon::CollisionPolygon( double x, double y, uint64_t id ) + : CollisionPolygon( Vec2D< double >( x, y ), id ) {} +CollisionPolygon::CollisionPolygon( const Vec2D< double > &input, uint64_t id ) + : CollisionPolygon( input ) { + _id = id; +} bool CollisionPolygon::isInfinite() const { return infinite; @@ -17,7 +23,10 @@ void CollisionPolygon::setInfinite() { infinite = true; } -void CollisionPolygon::updateCollision( int x, int y, int w, int h ) { +void CollisionPolygon::updateCollision( int x, int y, int w, int h, + uint64_t id ) { + if ( _id == static_cast< uint64_t >( -1 ) ) + _id = id; position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y ); } @@ -34,6 +43,12 @@ void CollisionPolygon::setColor( const std::string &color ) { void CollisionPolygon::setOutlineColor( const std::string &color ) { sdl_outline = getSDLColorHEX( color ); } +void CollisionPolygon::setId( uint64_t id ) { + _id = id; +} +uint64_t CollisionPolygon::getId() { + return _id; +} bool infinityIntersection( const SDLPP::CollisionPolygon &infinite, const SDLPP::CollisionPolygon &other ) { diff --git a/sdlpp/sdlpp_collision.hpp b/sdlpp/sdlpp_collision.hpp index 2193443..c330a04 100644 --- a/sdlpp/sdlpp_collision.hpp +++ b/sdlpp/sdlpp_collision.hpp @@ -13,6 +13,8 @@ class SDLPPSCOPE CollisionPolygon { public: CollisionPolygon( double x, double y ); CollisionPolygon( const Vec2D< double > &input ); + CollisionPolygon( double x, double y, uint64_t id ); + CollisionPolygon( const Vec2D< double > &input, uint64_t id ); virtual ~CollisionPolygon() {} virtual bool colidesWith( const CollisionPolygon &other ) const = 0; virtual bool isCircle() const = 0; @@ -22,7 +24,8 @@ public: 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 updateCollision( int x, int y, int w, int h, + uint64_t objectId ); virtual void render( Renderer &renderer, const SDL_Color &color, const SDL_Color &outline_color ) = 0; virtual void render( Renderer &renderer, const SDL_Color &color ) = 0; @@ -33,6 +36,8 @@ public: void setOutlineColor( const std::string &color ); virtual std::shared_ptr< CollisionPolygon > copySelf() = 0; virtual std::vector< Line< int > > getLines() const = 0; + uint64_t getId(); + void setId( uint64_t id ); protected: Vec2D< double > original; @@ -40,6 +45,7 @@ protected: bool infinite = false; SDL_Color sdl_color = { 0, 0, 0, 0 }; SDL_Color sdl_outline = { 0, 0, 0, 0 }; + uint64_t _id = -1; }; SDLPPSCOPE bool infinityIntersection( const SDLPP::CollisionPolygon &infinite, diff --git a/sdlpp/sdlpp_linerenderer.cpp b/sdlpp/sdlpp_linerenderer.cpp index 06c184b..3f1a3ae 100644 --- a/sdlpp/sdlpp_linerenderer.cpp +++ b/sdlpp/sdlpp_linerenderer.cpp @@ -94,7 +94,7 @@ void LineRenderer::updateSizeAndPosition() { std::round( current.getEnd().getY() * dimension ) ) ); for ( auto &x : collisions ) { x->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), getId() ); } } void LineRenderer::centerX() { diff --git a/sdlpp/sdlpp_rectcolider.cpp b/sdlpp/sdlpp_rectcolider.cpp index 658046b..06b2cd3 100644 --- a/sdlpp/sdlpp_rectcolider.cpp +++ b/sdlpp/sdlpp_rectcolider.cpp @@ -25,6 +25,15 @@ RectColider::RectColider( const Vec2D< double > &top_left, const Vec2D< double > &size ) : CollisionPolygon( top_left ), _size( size ) {} +RectColider::RectColider( double x, double y, double w, double h, uint64_t id ) + : RectColider( { x, y }, { w, h }, id ) {} + +RectColider::RectColider( const Vec2D< double > &top_left, + const Vec2D< double > &size, uint64_t id ) + : RectColider( top_left, size ) { + _id = id; +} + bool RectColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { if ( other.isCircle() ) { return other.colidesWith( *this ); @@ -57,9 +66,11 @@ int RectColider::rightmost() const { isInfinite() * -1; } -void RectColider::updateCollision( int x, int y, int w, int h ) { +void RectColider::updateCollision( int x, int y, int w, int h, uint64_t id ) { position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y ); _size_pixel = Vec2D< int >( width() * w, height() * h ); + if ( _id == static_cast< uint64_t >( -1 ) ) + _id = id; } void RectColider::render( Renderer &renderer, const SDL_Color &color, diff --git a/sdlpp/sdlpp_rectcolider.hpp b/sdlpp/sdlpp_rectcolider.hpp index 1784d0a..89cfb0c 100644 --- a/sdlpp/sdlpp_rectcolider.hpp +++ b/sdlpp/sdlpp_rectcolider.hpp @@ -14,6 +14,9 @@ class SDLPPSCOPE RectColider : public CollisionPolygon { public: RectColider( double x, double y, double w, double h ); RectColider( const Vec2D< double > &top_left, const Vec2D< double > &size ); + RectColider( double x, double y, double w, double h, uint64_t id ); + RectColider( const Vec2D< double > &top_left, const Vec2D< double > &size, + uint64_t id ); virtual ~RectColider() {} virtual bool colidesWith( const CollisionPolygon &other ) const override; virtual bool isCircle() const override; @@ -21,7 +24,8 @@ public: 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 updateCollision( int x, int y, int w, int h, + uint64_t id ) override; virtual void render( Renderer &renderer, const SDL_Color &color, const SDL_Color &outline_color ) override; virtual void render( Renderer &renderer, const SDL_Color &color ) override; diff --git a/sdlpp/sdlpp_rectrenderer.cpp b/sdlpp/sdlpp_rectrenderer.cpp index f747279..c2ba730 100644 --- a/sdlpp/sdlpp_rectrenderer.cpp +++ b/sdlpp/sdlpp_rectrenderer.cpp @@ -93,7 +93,8 @@ void RectangleRender::setColor( const std::string &color ) { if ( !polygon ) { polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); } polygon->setColor( color ); } @@ -101,7 +102,8 @@ void RectangleRender::setOutlineColor( const std::string &color ) { if ( !polygon ) { polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); } polygon->setOutlineColor( color ); } @@ -146,10 +148,11 @@ void RectangleRender::updateSizeAndPosition() { rect.y; if ( polygon ) polygon->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), + getId() ); for ( auto &x : collisions ) { x->updateCollision( collisionPushX(), collisionPushY(), - collisionWidth(), collisionHeight() ); + collisionWidth(), collisionHeight(), getId() ); } } SDL_Rect RectangleRender::getRect() { diff --git a/sdlpp/sdlpp_renderer.cpp b/sdlpp/sdlpp_renderer.cpp index 24abb52..3f22e03 100644 --- a/sdlpp/sdlpp_renderer.cpp +++ b/sdlpp/sdlpp_renderer.cpp @@ -22,6 +22,13 @@ Vec2D< int > Renderer::getDimensions() const { SDL_GetRendererOutputSize( renderer, &width, &height ); return { width, height }; } +Vec2D< double > Renderer::getDoubleDimensions() const { + auto dimensions = getDimensions(); + double smaller = dimensions.getX() < dimensions.getY() ? dimensions.getX() + : dimensions.getY(); + return { static_cast< double >( dimensions.getX() ) / smaller, + static_cast< double >( dimensions.getY() ) / smaller }; +} int Renderer::getWidth() const { return getDimensions().getX(); } diff --git a/sdlpp/sdlpp_renderer.hpp b/sdlpp/sdlpp_renderer.hpp index b5a3186..4c61541 100644 --- a/sdlpp/sdlpp_renderer.hpp +++ b/sdlpp/sdlpp_renderer.hpp @@ -24,6 +24,7 @@ public: bool getRenderColiders(); void clearRenderer(); void presentRenderer(); + Vec2D< double > getDoubleDimensions() const; private: SDL_Renderer *renderer = NULL; diff --git a/sdlpp/sdlpp_renderobject.cpp b/sdlpp/sdlpp_renderobject.cpp index 142122c..1e43945 100644 --- a/sdlpp/sdlpp_renderobject.cpp +++ b/sdlpp/sdlpp_renderobject.cpp @@ -41,18 +41,20 @@ void RenderObject::setPos( const Vec2D< double > &vec ) { Vec2D< double > RenderObject::getPos() const { return original; } -bool RenderObject::colidesWith( const RenderObject &other ) const { +std::vector< uint64_t > +RenderObject::colidesWith( const RenderObject &other ) const { if ( !hasCollisions() || !other.hasCollisions() || getHidden() || other.getHidden() ) { - return false; + return {}; } + std::vector< uint64_t > ret = {}; for ( const auto &x : collisions ) { for ( const auto &y : other.getCollisions() ) { if ( x->colidesWith( *y ) ) - return true; + ret.push_back( x->getId() ); } } - return false; + return ret; } bool RenderObject::hasCollisions() const { return !collisions.empty(); diff --git a/sdlpp/sdlpp_renderobject.hpp b/sdlpp/sdlpp_renderobject.hpp index d975301..cb8b77a 100644 --- a/sdlpp/sdlpp_renderobject.hpp +++ b/sdlpp/sdlpp_renderobject.hpp @@ -34,12 +34,12 @@ public: virtual void setPos( const std::pair< double, double > &pos ); virtual void setPos( const Vec2D< double > &vec ); virtual Vec2D< double > getPos() const; - bool colidesWith( const RenderObject &other ) const; + std::vector< uint64_t > 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() ); + collisionWidth(), collisionHeight(), + getId() ); } bool hasCollisions() const; const std::vector< std::shared_ptr< CollisionPolygon > > & diff --git a/sdlpp/sdlpp_scene.cpp b/sdlpp/sdlpp_scene.cpp index d57df2c..946918e 100644 --- a/sdlpp/sdlpp_scene.cpp +++ b/sdlpp/sdlpp_scene.cpp @@ -20,11 +20,15 @@ void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) { } else { auto rect = obj->getDoubleRect(); auto leftmost_rect = leftmost_obj->getDoubleRect(); - if ( rect.first.getX() < leftmost_rect.first.getX() ) + if ( ( rect.first.getX() < leftmost_rect.first.getX() && + !obj->getPermanent() ) || + ( leftmost_obj->getPermanent() && !obj->getPermanent() ) ) leftmost_obj = obj; auto rightmost_rect = rightmost_obj->getDoubleRect(); - if ( rect.first.getX() + rect.second.getX() > - rightmost_rect.first.getX() + rightmost_rect.second.getX() ) + if ( ( rect.first.getX() + rect.second.getX() > + rightmost_rect.first.getX() + rightmost_rect.second.getX() && + !obj->getPermanent() ) || + ( rightmost_obj->getPermanent() && !obj->getPermanent() ) ) rightmost_obj = obj; } } @@ -95,33 +99,35 @@ void Scene::updateScene() { } prev_ticks = now_ticks; } -std::vector< std::shared_ptr< RenderObject > > +std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > Scene::getCollisions( RenderObject &r ) { if ( r.getHidden() ) return {}; - std::vector< std::shared_ptr< RenderObject > > ret{}; + std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > ret{}; for ( const auto &x : collision_objects ) { - if ( x->colidesWith( r ) ) { - ret.push_back( x ); + for ( auto id : r.colidesWith( *x ) ) { + ret.emplace_back( id, x ); } } return ret; } void Scene::visitCollisions( RenderObject &r, Visitor &v ) { - for(auto &collision : getCollisions(r)) { - collision->visit(v); + for ( auto &collision : getCollisions( r ) ) { + v.fromId( collision.first ); + collision.second->visit( v ); } } -std::vector< std::shared_ptr< RenderObject > > +std::vector< std::pair< uint64_t, 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{}; + std::vector< std::pair< uint64_t, 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 ); + if ( objectIDs.find( x->getId() ) != objectIDs.end() ) { + for ( auto id : r.colidesWith( *x ) ) { + ret.push_back( { id, x } ); + } } } return ret; @@ -154,7 +160,8 @@ void Scene::updateSizeAndPosition() { x->updateSizeAndPosition(); for ( auto &col : x->getCollisions() ) { col->updateCollision( x->collisionPushX(), x->collisionPushY(), - x->collisionWidth(), x->collisionHeight() ); + x->collisionWidth(), x->collisionHeight(), + x->getId() ); } } } @@ -164,8 +171,7 @@ void Scene::moveEverything( double x, double y ) { for ( auto &obj : render_objects ) { if ( obj->getPermanent() ) continue; - auto curPos = obj->getDoubleRect(); - obj->setPos( curPos.first.getX() + x, curPos.first.getY() + y ); + obj->setPos( obj->getDoubleRect().first + Vec2D< double >( x, y ) ); } } const std::shared_ptr< RenderObject > &Scene::leftmost() { diff --git a/sdlpp/sdlpp_scene.hpp b/sdlpp/sdlpp_scene.hpp index 035b881..096e482 100644 --- a/sdlpp/sdlpp_scene.hpp +++ b/sdlpp/sdlpp_scene.hpp @@ -27,10 +27,10 @@ public: std::vector< std::shared_ptr< RenderObject > > getObjects( const std::unordered_set< int > &objectIDs ); void updateScene(); - std::vector< std::shared_ptr< RenderObject > > + std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > getCollisions( RenderObject &r ); void visitCollisions( RenderObject &r, Visitor &v ); - std::vector< std::shared_ptr< RenderObject > > + std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > > getCollisions( RenderObject &r, const std::unordered_set< int > &objectIDs ); void renderScene( bool clear_renderer = true ); diff --git a/sdlpp/sdlpp_visitor.hpp b/sdlpp/sdlpp_visitor.hpp index b88885e..8acb887 100644 --- a/sdlpp/sdlpp_visitor.hpp +++ b/sdlpp/sdlpp_visitor.hpp @@ -11,6 +11,7 @@ class SDLPPSCOPE Visitor { public: Visitor() {} virtual void visit( const RenderObject &obj ) = 0; + virtual void fromId( uint64_t id ) = 0; }; } // namespace SDLPP