SDLPP: add collider IDs

This commit is contained in:
zvon 2021-04-26 21:57:31 +02:00
parent 19e66bf34a
commit dd6f37264c
16 changed files with 112 additions and 41 deletions

View File

@ -7,6 +7,13 @@ CircleColider::CircleColider( double x, double y, double rad )
CircleColider::CircleColider( const Vec2D< double > &center, double rad ) CircleColider::CircleColider( const Vec2D< double > &center, double rad )
: CollisionPolygon( center ), original_rad( 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 > &center, double rad,
uint64_t id )
: CircleColider( center, rad ) {
_id = id;
}
bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const {
if ( other.isCircle() ) { if ( other.isCircle() ) {
@ -47,9 +54,11 @@ int CircleColider::rightmost() const {
return getX() + rad_; 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 ); position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y );
rad_ = original_rad * w; rad_ = original_rad * w;
if ( _id == static_cast< uint64_t >( -1 ) )
_id = id;
} }
void CircleColider::render( Renderer &renderer, const SDL_Color &color, void CircleColider::render( Renderer &renderer, const SDL_Color &color,

View File

@ -11,6 +11,8 @@ class SDLPPSCOPE CircleColider : public CollisionPolygon {
public: public:
CircleColider( double x, double y, double rad ); CircleColider( double x, double y, double rad );
CircleColider( const Vec2D< double > &center, double rad ); CircleColider( const Vec2D< double > &center, double rad );
CircleColider( double x, double y, double rad, uint64_t id );
CircleColider( const Vec2D< double > &center, double rad, uint64_t id );
virtual ~CircleColider() {} virtual ~CircleColider() {}
virtual bool colidesWith( const CollisionPolygon &other ) const override; virtual bool colidesWith( const CollisionPolygon &other ) const override;
@ -20,7 +22,8 @@ public:
virtual int leftmost() const override; virtual int leftmost() const override;
virtual int rightmost() 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, virtual void render( Renderer &renderer, const SDL_Color &color,
const SDL_Color &outline_color ) override; const SDL_Color &outline_color ) override;
virtual void render( Renderer &renderer, const SDL_Color &color ) override; virtual void render( Renderer &renderer, const SDL_Color &color ) override;

View File

@ -49,7 +49,8 @@ void CircleRender::setColor( const std::string &color ) {
if ( !polygon ) { if ( !polygon ) {
polygon = std::make_shared< CircleColider >( 0, 0, 1 ); polygon = std::make_shared< CircleColider >( 0, 0, 1 );
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
} }
polygon->setColor( color ); polygon->setColor( color );
} }
@ -58,7 +59,8 @@ void CircleRender::setOutlineColor( const std::string &color ) {
if ( !polygon ) { if ( !polygon ) {
polygon = std::make_shared< CircleColider >( 0, 0, 1 ); polygon = std::make_shared< CircleColider >( 0, 0, 1 );
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
} }
polygon->setOutlineColor( color ); polygon->setOutlineColor( color );
} }
@ -110,10 +112,11 @@ void CircleRender::updateSizeAndPosition() {
rect.h = std::round( ( current.getY() + r_ ) * dimension ) - rect.y; rect.h = std::round( ( current.getY() + r_ ) * dimension ) - rect.y;
if ( polygon ) if ( polygon )
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
for ( auto &x : collisions ) { for ( auto &x : collisions ) {
x->updateCollision( collisionPushX(), collisionPushY(), x->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(), getId() );
} }
} }

View File

@ -9,6 +9,12 @@ CollisionPolygon::CollisionPolygon( const Vec2D< double > &input ) {
original = input; original = input;
position = { 0, 0 }; 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 { bool CollisionPolygon::isInfinite() const {
return infinite; return infinite;
@ -17,7 +23,10 @@ void CollisionPolygon::setInfinite() {
infinite = true; 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 ); 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 ) { void CollisionPolygon::setOutlineColor( const std::string &color ) {
sdl_outline = getSDLColorHEX( 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, bool infinityIntersection( const SDLPP::CollisionPolygon &infinite,
const SDLPP::CollisionPolygon &other ) { const SDLPP::CollisionPolygon &other ) {

View File

@ -13,6 +13,8 @@ class SDLPPSCOPE CollisionPolygon {
public: public:
CollisionPolygon( double x, double y ); CollisionPolygon( double x, double y );
CollisionPolygon( const Vec2D< double > &input ); CollisionPolygon( const Vec2D< double > &input );
CollisionPolygon( double x, double y, uint64_t id );
CollisionPolygon( const Vec2D< double > &input, uint64_t id );
virtual ~CollisionPolygon() {} virtual ~CollisionPolygon() {}
virtual bool colidesWith( const CollisionPolygon &other ) const = 0; virtual bool colidesWith( const CollisionPolygon &other ) const = 0;
virtual bool isCircle() const = 0; virtual bool isCircle() const = 0;
@ -22,7 +24,8 @@ public:
virtual int bottommost() const = 0; virtual int bottommost() const = 0;
virtual int leftmost() const = 0; virtual int leftmost() const = 0;
virtual int rightmost() 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, virtual void render( Renderer &renderer, const SDL_Color &color,
const SDL_Color &outline_color ) = 0; const SDL_Color &outline_color ) = 0;
virtual void render( Renderer &renderer, const SDL_Color &color ) = 0; virtual void render( Renderer &renderer, const SDL_Color &color ) = 0;
@ -33,6 +36,8 @@ public:
void setOutlineColor( const std::string &color ); void setOutlineColor( const std::string &color );
virtual std::shared_ptr< CollisionPolygon > copySelf() = 0; virtual std::shared_ptr< CollisionPolygon > copySelf() = 0;
virtual std::vector< Line< int > > getLines() const = 0; virtual std::vector< Line< int > > getLines() const = 0;
uint64_t getId();
void setId( uint64_t id );
protected: protected:
Vec2D< double > original; Vec2D< double > original;
@ -40,6 +45,7 @@ protected:
bool infinite = false; bool infinite = false;
SDL_Color sdl_color = { 0, 0, 0, 0 }; SDL_Color sdl_color = { 0, 0, 0, 0 };
SDL_Color sdl_outline = { 0, 0, 0, 0 }; SDL_Color sdl_outline = { 0, 0, 0, 0 };
uint64_t _id = -1;
}; };
SDLPPSCOPE bool infinityIntersection( const SDLPP::CollisionPolygon &infinite, SDLPPSCOPE bool infinityIntersection( const SDLPP::CollisionPolygon &infinite,

View File

@ -94,7 +94,7 @@ void LineRenderer::updateSizeAndPosition() {
std::round( current.getEnd().getY() * dimension ) ) ); std::round( current.getEnd().getY() * dimension ) ) );
for ( auto &x : collisions ) { for ( auto &x : collisions ) {
x->updateCollision( collisionPushX(), collisionPushY(), x->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(), getId() );
} }
} }
void LineRenderer::centerX() { void LineRenderer::centerX() {

View File

@ -25,6 +25,15 @@ RectColider::RectColider( const Vec2D< double > &top_left,
const Vec2D< double > &size ) const Vec2D< double > &size )
: CollisionPolygon( top_left ), _size( 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 { bool RectColider::colidesWith( const SDLPP::CollisionPolygon &other ) const {
if ( other.isCircle() ) { if ( other.isCircle() ) {
return other.colidesWith( *this ); return other.colidesWith( *this );
@ -57,9 +66,11 @@ int RectColider::rightmost() const {
isInfinite() * -1; 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 ); position = Vec2D< int >( original.getX() * w + x, original.getY() * h + y );
_size_pixel = Vec2D< int >( width() * w, height() * h ); _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, void RectColider::render( Renderer &renderer, const SDL_Color &color,

View File

@ -14,6 +14,9 @@ class SDLPPSCOPE RectColider : public CollisionPolygon {
public: public:
RectColider( double x, double y, double w, double h ); RectColider( double x, double y, double w, double h );
RectColider( const Vec2D< double > &top_left, const Vec2D< double > &size ); 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 ~RectColider() {}
virtual bool colidesWith( const CollisionPolygon &other ) const override; virtual bool colidesWith( const CollisionPolygon &other ) const override;
virtual bool isCircle() const override; virtual bool isCircle() const override;
@ -21,7 +24,8 @@ public:
virtual int bottommost() const override; virtual int bottommost() const override;
virtual int leftmost() const override; virtual int leftmost() const override;
virtual int rightmost() 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, virtual void render( Renderer &renderer, const SDL_Color &color,
const SDL_Color &outline_color ) override; const SDL_Color &outline_color ) override;
virtual void render( Renderer &renderer, const SDL_Color &color ) override; virtual void render( Renderer &renderer, const SDL_Color &color ) override;

View File

@ -93,7 +93,8 @@ void RectangleRender::setColor( const std::string &color ) {
if ( !polygon ) { if ( !polygon ) {
polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); polygon = std::make_shared< RectColider >( 0, 0, 1, 1 );
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
} }
polygon->setColor( color ); polygon->setColor( color );
} }
@ -101,7 +102,8 @@ void RectangleRender::setOutlineColor( const std::string &color ) {
if ( !polygon ) { if ( !polygon ) {
polygon = std::make_shared< RectColider >( 0, 0, 1, 1 ); polygon = std::make_shared< RectColider >( 0, 0, 1, 1 );
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
} }
polygon->setOutlineColor( color ); polygon->setOutlineColor( color );
} }
@ -146,10 +148,11 @@ void RectangleRender::updateSizeAndPosition() {
rect.y; rect.y;
if ( polygon ) if ( polygon )
polygon->updateCollision( collisionPushX(), collisionPushY(), polygon->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(),
getId() );
for ( auto &x : collisions ) { for ( auto &x : collisions ) {
x->updateCollision( collisionPushX(), collisionPushY(), x->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionHeight() ); collisionWidth(), collisionHeight(), getId() );
} }
} }
SDL_Rect RectangleRender::getRect() { SDL_Rect RectangleRender::getRect() {

View File

@ -22,6 +22,13 @@ Vec2D< int > Renderer::getDimensions() const {
SDL_GetRendererOutputSize( renderer, &width, &height ); SDL_GetRendererOutputSize( renderer, &width, &height );
return { 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 { int Renderer::getWidth() const {
return getDimensions().getX(); return getDimensions().getX();
} }

View File

@ -24,6 +24,7 @@ public:
bool getRenderColiders(); bool getRenderColiders();
void clearRenderer(); void clearRenderer();
void presentRenderer(); void presentRenderer();
Vec2D< double > getDoubleDimensions() const;
private: private:
SDL_Renderer *renderer = NULL; SDL_Renderer *renderer = NULL;

View File

@ -41,18 +41,20 @@ void RenderObject::setPos( const Vec2D< double > &vec ) {
Vec2D< double > RenderObject::getPos() const { Vec2D< double > RenderObject::getPos() const {
return original; return original;
} }
bool RenderObject::colidesWith( const RenderObject &other ) const { std::vector< uint64_t >
RenderObject::colidesWith( const RenderObject &other ) const {
if ( !hasCollisions() || !other.hasCollisions() || getHidden() || if ( !hasCollisions() || !other.hasCollisions() || getHidden() ||
other.getHidden() ) { other.getHidden() ) {
return false; return {};
} }
std::vector< uint64_t > ret = {};
for ( const auto &x : collisions ) { for ( const auto &x : collisions ) {
for ( const auto &y : other.getCollisions() ) { for ( const auto &y : other.getCollisions() ) {
if ( x->colidesWith( *y ) ) if ( x->colidesWith( *y ) )
return true; ret.push_back( x->getId() );
} }
} }
return false; return ret;
} }
bool RenderObject::hasCollisions() const { bool RenderObject::hasCollisions() const {
return !collisions.empty(); return !collisions.empty();

View File

@ -34,12 +34,12 @@ public:
virtual void setPos( const std::pair< double, double > &pos ); virtual void setPos( const std::pair< double, double > &pos );
virtual void setPos( const Vec2D< double > &vec ); virtual void setPos( const Vec2D< double > &vec );
virtual Vec2D< double > getPos() const; 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 ) { template < class T > void addCollision( const T &p ) {
collisions.push_back( std::make_shared< T >( p ) ); collisions.push_back( std::make_shared< T >( p ) );
collisions.back()->updateCollision( collisionPushX(), collisionPushY(), collisions.back()->updateCollision( collisionPushX(), collisionPushY(),
collisionWidth(), collisionWidth(), collisionHeight(),
collisionHeight() ); getId() );
} }
bool hasCollisions() const; bool hasCollisions() const;
const std::vector< std::shared_ptr< CollisionPolygon > > & const std::vector< std::shared_ptr< CollisionPolygon > > &

View File

@ -20,11 +20,15 @@ void Scene::addObject( const std::shared_ptr< RenderObject > &obj ) {
} else { } else {
auto rect = obj->getDoubleRect(); auto rect = obj->getDoubleRect();
auto leftmost_rect = leftmost_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; leftmost_obj = obj;
auto rightmost_rect = rightmost_obj->getDoubleRect(); auto rightmost_rect = rightmost_obj->getDoubleRect();
if ( rect.first.getX() + rect.second.getX() > if ( ( rect.first.getX() + rect.second.getX() >
rightmost_rect.first.getX() + rightmost_rect.second.getX() ) rightmost_rect.first.getX() + rightmost_rect.second.getX() &&
!obj->getPermanent() ) ||
( rightmost_obj->getPermanent() && !obj->getPermanent() ) )
rightmost_obj = obj; rightmost_obj = obj;
} }
} }
@ -95,33 +99,35 @@ void Scene::updateScene() {
} }
prev_ticks = now_ticks; prev_ticks = now_ticks;
} }
std::vector< std::shared_ptr< RenderObject > > std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > >
Scene::getCollisions( RenderObject &r ) { Scene::getCollisions( RenderObject &r ) {
if ( r.getHidden() ) if ( r.getHidden() )
return {}; 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 ) { for ( const auto &x : collision_objects ) {
if ( x->colidesWith( r ) ) { for ( auto id : r.colidesWith( *x ) ) {
ret.push_back( x ); ret.emplace_back( id, x );
} }
} }
return ret; return ret;
} }
void Scene::visitCollisions( RenderObject &r, Visitor &v ) { void Scene::visitCollisions( RenderObject &r, Visitor &v ) {
for ( auto &collision : getCollisions( r ) ) { for ( auto &collision : getCollisions( r ) ) {
collision->visit(v); 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, Scene::getCollisions( RenderObject &r,
const std::unordered_set< int > &objectIDs ) { const std::unordered_set< int > &objectIDs ) {
if ( r.getHidden() ) if ( r.getHidden() )
return {}; 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 ) { for ( const auto &x : collision_objects ) {
if ( objectIDs.find( x->getId() ) != objectIDs.end() && if ( objectIDs.find( x->getId() ) != objectIDs.end() ) {
x->colidesWith( r ) ) { for ( auto id : r.colidesWith( *x ) ) {
ret.push_back( x ); ret.push_back( { id, x } );
}
} }
} }
return ret; return ret;
@ -154,7 +160,8 @@ void Scene::updateSizeAndPosition() {
x->updateSizeAndPosition(); x->updateSizeAndPosition();
for ( auto &col : x->getCollisions() ) { for ( auto &col : x->getCollisions() ) {
col->updateCollision( x->collisionPushX(), x->collisionPushY(), 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 ) { for ( auto &obj : render_objects ) {
if ( obj->getPermanent() ) if ( obj->getPermanent() )
continue; continue;
auto curPos = obj->getDoubleRect(); obj->setPos( obj->getDoubleRect().first + Vec2D< double >( x, y ) );
obj->setPos( curPos.first.getX() + x, curPos.first.getY() + y );
} }
} }
const std::shared_ptr< RenderObject > &Scene::leftmost() { const std::shared_ptr< RenderObject > &Scene::leftmost() {

View File

@ -27,10 +27,10 @@ public:
std::vector< std::shared_ptr< RenderObject > > std::vector< std::shared_ptr< RenderObject > >
getObjects( const std::unordered_set< int > &objectIDs ); getObjects( const std::unordered_set< int > &objectIDs );
void updateScene(); void updateScene();
std::vector< std::shared_ptr< RenderObject > > std::vector< std::pair< uint64_t, std::shared_ptr< RenderObject > > >
getCollisions( RenderObject &r ); getCollisions( RenderObject &r );
void visitCollisions( RenderObject &r, Visitor &v ); 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, getCollisions( RenderObject &r,
const std::unordered_set< int > &objectIDs ); const std::unordered_set< int > &objectIDs );
void renderScene( bool clear_renderer = true ); void renderScene( bool clear_renderer = true );

View File

@ -11,6 +11,7 @@ class SDLPPSCOPE Visitor {
public: public:
Visitor() {} Visitor() {}
virtual void visit( const RenderObject &obj ) = 0; virtual void visit( const RenderObject &obj ) = 0;
virtual void fromId( uint64_t id ) = 0;
}; };
} // namespace SDLPP } // namespace SDLPP