00001 #include "BreakoutBall.h"
00002 #include "AABB.h"
00003 #include "Vector2.h"
00004 #include <math.h>
00005
00006 #include "BreakoutBox.h"
00007 #include "BreakoutPaddle.h"
00008 #include "BreakoutWorldBoundaries.h"
00009
00010 #include "GameConfig.h"
00011
00012 #include "GameException.h"
00013
00014 BreakoutBall::BreakoutBall(const int &radius, const ColourRGB &innerColour, const ColourRGB &outerColour)
00015 : m_radius(radius), m_spriteID(0)
00016 {
00017 m_spriteID = Visualisation::getSingleton()->CreateSpriteBall((int)radius, innerColour, outerColour);
00018 }
00019
00020 BreakoutBall::~BreakoutBall()
00021 {
00022 }
00023
00024 void BreakoutBall::Draw()
00025 {
00026 int halfRadius = m_radius / 2;
00027 Visualisation::getSingleton()->DrawSprite(m_spriteID, m_position.x - halfRadius, m_position.y - halfRadius);
00028 }
00029
00030 void BreakoutBall::Update()
00031 {
00032 if(m_velocity.x > BALL_MAX_SPEED_X)
00033 m_velocity.x = BALL_MAX_SPEED_X;
00034 if(m_velocity.y > BALL_MAX_SPEED_Y)
00035 m_velocity.y = BALL_MAX_SPEED_Y;
00036
00037 m_previousPosition = m_position;
00038 m_position += m_velocity;
00039 }
00040
00041 bool BreakoutBall::HandleCollisionWithBox(BreakoutBox* pBox)
00042 {
00043 if(!pBox)
00044 {
00045 throw GameException(eMinorError, "BreakoutBall: HandleCollisionWithBox() failed due to non-existant box passed to it.");
00046 return false;
00047 }
00048
00049 AABBi bbox = pBox->GetAABB();
00050 Vector2i closestPoint;
00051 if(AABBi::AABBvsCircleCollisionTest(bbox, m_position, m_radius, closestPoint))
00052 {
00053 eAABBSideQueryResult boxSide = AABBi::GetSideFromClosestPoint(bbox, closestPoint);
00054 if(boxSide == eInsideAABB)
00055 {
00056 AABBi::AABBvsCircleCollisionTest(bbox, m_previousPosition, m_radius, closestPoint);
00057 boxSide = AABBi::GetSideFromClosestPoint(bbox, closestPoint);
00058 }
00059
00060 switch(boxSide)
00061 {
00062 case eTopSide:
00063 m_position.y = bbox.Top + m_radius;
00064 m_velocity.y = -m_velocity.y;
00065 break;
00066 case eBottomSide:
00067 m_position.y = bbox.Bottom - m_radius;
00068 m_velocity.y = -m_velocity.y;
00069 break;
00070 case eLeftSide:
00071 m_position.x = bbox.Left - m_radius;
00072 m_velocity.x = -m_velocity.x;
00073 break;
00074 case eRightSide:
00075 m_position.x = bbox.Right + m_radius;
00076 m_velocity.x = -m_velocity.x;
00077 break;
00078 }
00079
00080 return true;
00081 }
00082
00083 return false;
00084 }
00085
00086 bool BreakoutBall::HandleCollisionWithPaddle(BreakoutPaddle* pPaddle)
00087 {
00088 if(!pPaddle)
00089 {
00090 throw GameException(eMinorError, "BreakoutBall: HandleCollisionWithPaddle() failed due to non-existant paddle passed to it.");
00091 return false;
00092 }
00093
00094
00095 AABBi paddleBox = pPaddle->GetAABB();
00096
00097 int minCircleX = m_position.x - m_radius;
00098 int maxCircleX = m_position.x + m_radius;
00099
00100 if(minCircleX > paddleBox.Right)
00101 return false;
00102 else if(maxCircleX < paddleBox.Left)
00103 return false;
00104
00105 int minCircleY = m_position.y - m_radius;
00106 int maxCircleY = m_position.y + m_radius;
00107 if(minCircleY > paddleBox.Top)
00108 return false;
00109 if(maxCircleY < paddleBox.Bottom)
00110 return false;
00111
00112 int yDiff = paddleBox.Top - minCircleY;
00113 m_position.y -= yDiff;
00114 m_velocity.y = -m_velocity.y;
00115
00116 int xDiff = m_position.x - (paddleBox.Left + ((paddleBox.Right - paddleBox.Left) / 2));
00117
00118
00119 m_velocity.x += xDiff / PADDLE_SPIN_PRECISION;
00120
00121
00122
00123
00124
00125 return true;
00126 }
00127
00128 bool BreakoutBall::HandleCollisionWithWorldBoundaries(BreakoutWorldBoundaries* pBounds)
00129 {
00130 if(!pBounds)
00131 {
00132 throw GameException(eMinorError, "BreakoutBall: HandleCollisionWithWorldBoundaries() failed due to non-existant world boundaries passed to it.");
00133 return false;
00134 }
00135
00136 bool bCollides = false;
00137
00138 Vector2i min = pBounds->GetMinBounds(), max = pBounds->GetMaxBounds();
00139
00140 int posDiff = (m_position.x - m_radius) - min.x;
00141 if(posDiff < 0)
00142 {
00143 bCollides = true;
00144 m_position.x -= posDiff;
00145 m_velocity.x = -m_velocity.x;
00146 }
00147
00148 posDiff = (m_position.x + m_radius) - max.x;
00149 if(posDiff > 0)
00150 {
00151 bCollides = true;
00152 m_position.x -= posDiff;
00153 m_velocity.x = -m_velocity.x;
00154 }
00155
00156 posDiff = (m_position.y - m_radius) - min.y;
00157 if(posDiff < 0)
00158 {
00159 bCollides = true;
00160 m_position.y -= posDiff;
00161 m_velocity.y = -m_velocity.y;
00162 }
00163
00164 posDiff = (m_position.y + m_radius) - max.y;
00165 if(posDiff > 0)
00166 {
00167 bCollides = true;
00168 m_position.y -= posDiff;
00169 m_velocity.y = -m_velocity.y;
00170 }
00171
00172 return bCollides;
00173 }