New collision detection

This commit is contained in:
2021-03-13 15:05:16 +01:00
parent 258ce51cfe
commit d2cf54556e
12 changed files with 186 additions and 125 deletions
+36 -67
View File
@@ -1,47 +1,34 @@
#include "sdlpp_circlecolider.hpp"
#include "sdlpp_geometry.hpp"
namespace SDLPP {
CircleColider::CircleColider( double x, double y, double rad )
: CircleColider( {x, y}, rad ) {};
: CircleColider( { x, y }, rad ){};
CircleColider::CircleColider( const Vec2D< double > &center, double rad )
: CollisionPolygon( center ), original_rad( rad ) {}
bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const {
if ( other.isCircle() ) {
int otherRad = ( other.rightmost() - other.leftmost() ) / 2;
/* check if distance of centers is lower than radiuses added together */
int otherRad =
dynamic_cast< const SDLPP::CircleColider & >( other ).getRadius();
int thisRad = getRadius();
int totalDist = otherRad + thisRad;
int xdiff = other.leftmost() + otherRad - ( leftmost() + thisRad );
int ydiff = other.topmost() + otherRad - ( topmost() + thisRad );
int xdiff = other.getX() - getX();
int ydiff = other.getY() - getY();
return ( xdiff * xdiff + ydiff * ydiff ) <= totalDist * totalDist;
} else if ( other.isInfinite() ) {
return infinityIntersection( other, *this );
}
int rad = rad_;
int centerx = getX();
int centery = getY();
if ( other.topmost() <= centery && other.bottommost() >= centery ) {
return other.leftmost() <= rightmost() &&
other.rightmost() >= leftmost();
} else if ( other.leftmost() <= centerx && other.rightmost() >= centerx ) {
return other.topmost() <= bottommost() &&
other.bottommost() >= topmost();
/* other is not a circle */
int rad = getRadius();
for ( auto &line : other.getLines() ) {
auto distance = pointLineDistance( position, line );
if ( distance * distance <= rad * rad )
return true;
}
int pointx = 0, pointy = 0;
if ( centerx > other.rightmost() ) {
pointx = other.rightmost();
} else {
pointx = other.leftmost();
}
if ( centery < other.topmost() ) {
pointy = other.topmost();
} else {
pointy = other.bottommost();
}
int distancesquared = ( pointx - centerx ) * ( pointx - centerx ) +
( pointy - centery ) * ( pointy - centery );
return distancesquared <= rad * rad;
return false;
}
bool CircleColider::isCircle() const {
@@ -61,12 +48,12 @@ int CircleColider::rightmost() const {
}
void CircleColider::updateCollision( int x, int y, int w, int h ) {
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;
}
void CircleColider::render( Renderer &renderer,
const std::tuple< int, int, int, int > &color ) {
void CircleColider::render( Renderer &renderer, const SDL_Color &color,
const SDL_Color &outline_color ) {
std::vector< int > rect = { leftmost(), topmost(), rightmost(),
bottommost() };
auto center_x = getX();
@@ -76,14 +63,13 @@ void CircleColider::render( Renderer &renderer,
auto xdiff = center_x - i;
auto xdist = xdiff * xdiff;
auto allowed_rad = sqrt( radsq - xdist );
SDL_SetRenderDrawColor( renderer.getRendererPtr(),
std::get< 0 >( color ), std::get< 1 >( color ),
std::get< 2 >( color ), 0x40 );
SDL_SetRenderDrawColor( renderer.getRendererPtr(), color.r, color.g,
color.b, color.a );
SDL_RenderDrawLine( renderer.getRendererPtr(), i,
center_y - allowed_rad, i, center_y + allowed_rad );
SDL_SetRenderDrawColor( renderer.getRendererPtr(),
std::get< 0 >( color ), std::get< 1 >( color ),
std::get< 2 >( color ), 0x80 );
SDL_SetRenderDrawColor( renderer.getRendererPtr(), outline_color.r,
outline_color.g, outline_color.b,
outline_color.a );
SDL_RenderDrawLine( renderer.getRendererPtr(), i,
center_y - allowed_rad, i,
center_y - allowed_rad + 2 );
@@ -91,39 +77,18 @@ void CircleColider::render( Renderer &renderer,
center_y + allowed_rad, i,
center_y + allowed_rad - 2 );
}
SDL_SetRenderDrawColor( renderer.getRendererPtr(), 0xFF, 0, 0, 0xFF );
SDL_RenderDrawLine( renderer.getRendererPtr(), center_x, center_y,
center_x + rad_, center_y );
SDL_RenderDrawLine( renderer.getRendererPtr(), center_x, center_y, center_x,
center_y + rad_ );
SDL_RenderDrawLine( renderer.getRendererPtr(), center_x, center_y,
center_x - rad_, center_y );
SDL_RenderDrawLine( renderer.getRendererPtr(), center_x, center_y, center_x,
center_y - rad_ );
}
void CircleColider::render( Renderer &renderer, const SDL_Color &color ) {
auto input_color = color;
auto outline_color = color;
input_color.a = 0x40;
outline_color.a = 0x80;
render( renderer, input_color, outline_color );
}
void CircleColider::render( Renderer &renderer ) {
std::vector< int > rect = { leftmost(), topmost(), rightmost(),
bottommost() };
auto center_x = getX();
auto center_y = getY();
auto radsq = rad_ * rad_;
for ( int i = rect[0]; i <= rect[2]; i++ ) {
auto xdiff = center_x - i;
auto xdist = xdiff * xdiff;
auto allowed_rad = sqrt( radsq - xdist );
SDL_SetRenderDrawColor( renderer.getRendererPtr(), sdl_color.r,
sdl_color.g, sdl_color.b, sdl_color.a );
SDL_RenderDrawLine( renderer.getRendererPtr(), i,
center_y - allowed_rad, i, center_y + allowed_rad );
SDL_SetRenderDrawColor( renderer.getRendererPtr(), sdl_outline.r,
sdl_outline.g, sdl_outline.b, sdl_outline.a );
SDL_RenderDrawLine( renderer.getRendererPtr(), i,
center_y - allowed_rad, i,
center_y - allowed_rad + 2 );
SDL_RenderDrawLine( renderer.getRendererPtr(), i,
center_y + allowed_rad, i,
center_y + allowed_rad - 2 );
}
render( renderer, sdl_color, sdl_outline );
}
int CircleColider::getRadius() const {
@@ -133,4 +98,8 @@ int CircleColider::getRadius() const {
std::shared_ptr< CollisionPolygon > CircleColider::copySelf() {
return std::make_shared< CircleColider >( *this );
}
std::vector< Line< int > > CircleColider::getLines() const {
return {};
}
} // namespace SDLPP