// TODO render function like in rectangle #include "sdlpp_circlecolider.hpp" namespace SDLPP { CircleColider::CircleColider( double x, double y, double rad ) : CollisionPolygon( x, y ) { original_rad = rad; } bool CircleColider::colidesWith( const SDLPP::CollisionPolygon &other ) const { if ( other.isCircle() ) { int otherRad = ( other.rightmost() - other.leftmost() ) / 2; int thisRad = getRadius(); int totalDist = otherRad + thisRad; int xdiff = other.leftmost() + otherRad - ( leftmost() + thisRad ); int ydiff = other.topmost() + otherRad - ( topmost() + thisRad ); 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(); } 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; } bool CircleColider::isCircle() const { return true; } int CircleColider::topmost() const { return getY() - rad_; } int CircleColider::bottommost() const { return getY() + rad_; } int CircleColider::leftmost() const { return getX() - rad_; } int CircleColider::rightmost() const { return getX() + rad_; } void CircleColider::updateCollision( int x, int y, int w, int h ) { position_x = original_x * w + x; position_y = original_y * h + y; rad_ = original_rad * w; } void CircleColider::render( Renderer &renderer, const std::tuple< int, int, int, int > &color ) { 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(), std::get< 0 >( color ), std::get< 1 >( color ), std::get< 2 >( color ), 0x40 ); 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_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 ); } 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 ) { 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 ); } } int CircleColider::getRadius() const { return rad_; } std::shared_ptr< CollisionPolygon > CircleColider::copySelf() { return std::make_shared< CircleColider >( *this ); } } // namespace SDLPP