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 )
: 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 {
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,

View File

@ -11,6 +11,8 @@ class SDLPPSCOPE CircleColider : public CollisionPolygon {
public:
CircleColider( double x, double y, 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 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;

View File

@ -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() );
}
}

View File

@ -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 ) {

View File

@ -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,

View File

@ -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() {

View File

@ -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,

View File

@ -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;

View File

@ -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() {

View File

@ -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();
}

View File

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

View File

@ -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();

View File

@ -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 > > &

View File

@ -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);
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() {

View File

@ -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 );

View File

@ -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