Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FATFileSystem
Ball/Ball.cpp
- Committer:
- ellisbhastroud
- Date:
- 2019-05-08
- Revision:
- 15:d855e8c666e7
- Parent:
- 14:08ac9aaa34c3
- Child:
- 16:c8d68cbd1ae2
File content as of revision 15:d855e8c666e7:
#include "Ball.h"
//constructor
Ball::Ball()
{
}
//deconstructor
Ball::~Ball()
{
}
//public methods
void Ball::init(Coord start_pos) //ball starts new level stationary in x and y positions given
{
_x_pos = start_pos.x; //moves ball position to coordinates given
_y_pos = start_pos.y;
_x_vel = 0.0f; //makes ball stationary
_y_vel = 0.0f;
_total_shot_count = _total_shot_count + _shot_count; //totals shot count from previous levels
_shot_count = 0; //resets in level shot count for the next level
}
void Ball::drawBall(N5110 &lcd) //draws ball into lcd buffer
{
lcd.drawRect(_x_pos,_y_pos,2,2,FILL_BLACK); //draws ball
}
void Ball::printShotCount(N5110 &lcd) //this is tallied for each level to give user an end score
{
char buffer[14];
sprintf(buffer,"Shot %i",_shot_count);
lcd.printString(buffer,40,0);
}
void Ball::drawPower(N5110 &lcd, float mag) //draws power bar in top left of screen to indicate how hard a shot is hit
{
lcd.drawRect(0,1,36,6,FILL_TRANSPARENT);
lcd.drawRect(0,1,36*mag,6,FILL_BLACK);
}
void Ball::drawAim(N5110 &lcd, Vector2D joy_coord, float angle) //draws aim help for ball
{ //aim indicates path of ball if shot
if(angle != -1.0f && abs(_x_vel) < TOL && abs(_y_vel) < TOL) { //if joystick off centre and ball stationary draw shot direction indicator
lcd.drawLine(_x_pos,_y_pos,_x_pos-12*joy_coord.x,_y_pos+12*joy_coord.y,2);
}
}
void Ball::move_ball() //controls using
{
_x_pos = _x_pos + _x_vel*10.0f/_frame_rate; //move ball position at rate proportional to velocity in each direction
_y_pos = _y_pos + _y_vel*10.0f/_frame_rate;
_x_vel = _x_vel*(1.0f-(0.6f/_frame_rate)); //velocity decreases as ball moves
_y_vel = _y_vel*(1.0f-(0.6f/_frame_rate)); //inversely proportional to frame rate to ensure ball movement is the same at all frame rates
if(_x_vel != 0 && _y_vel != 0 && abs(_x_vel) < 0.15f && abs(_y_vel) < 0.15f) { //to make ball come to complete stop when velocity is small enough
_x_vel = 0;
_y_vel = 0;
}
}
void Ball::check_shoot_ball(Gamepad &pad, Vector2D _joy_coord) //checks if shoot coniditons met and A pressed then ball is shot using joystick input
{ //direction of shot is in opposite direction of joystick direction
if(pad.check_event(Gamepad::A_PRESSED) == true && abs(_x_vel) < TOL && abs(_y_vel) < TOL && pad.get_mag() > 0.05f){ //If ball stationary and A pressed then shoot
_x_vel = 6.0f * -_joy_coord.x; //scale x velocity by joystick direction and magnitude
_y_vel = 6.0f * _joy_coord.y; //scale y velocity by joystick direction and magnitude
_shot_count ++; //increment shot count
pad.tone(392.00 , 0.25); //play note when ball shot (G4)
}
}
void Ball::set_total_shot_count(int total_shot_count) //used to initialise value to 0
{
_total_shot_count = total_shot_count;
}
int Ball::get_total_shot_count() //used at end to add tally to highscore - the lowest shot count is the best score
{
int total_shot_count = _total_shot_count;
return total_shot_count;
}
bool Ball::check_hole(Coord hole) //returns true when ball is hit in hole and next level begins
{
if(_x_pos > hole.x - 1 && _x_pos < hole.x + 2 && _y_pos > hole.y - 1 && _y_pos < hole.y + 2) {
_x_vel = 0; //stop ball moving
_y_vel = 0;
_x_pos = hole.x;
_y_pos = hole.y;
return true; //causes next level process to begin
}
else {
return false;
}
}
void Ball::check_wall_bounce(WallMap map[], int size) //uses information from WallMap array for each level to check for bounces
{
for(int i = 0; i < size; i ++) { //runs through each element in array of wall types to check if bounce condition is met by ball
if(map[i].wall == LEFT) {
left_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == RIGHT) {
right_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == TOP) {
top_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == BOTTOM) {
bottom_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == BOTTOMLEFT) {
bottom_left_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == BOTTOMRIGHT) {
bottom_right_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == TOPLEFT) {
top_left_bounce(map[i].start,map[i].end);
}
else if(map[i].wall == TOPRIGHT) {
top_right_bounce(map[i].start,map[i].end);
}
}
}
void Ball::set_frame_rate(int frame_rate)
{
_frame_rate = frame_rate;
}
bool Ball::get_bounce_flag()
{
return _bounce_flag;
}
void Ball::reset_bounce_flag()
{
_bounce_flag = false;
}
//private methods
void Ball::left_bounce(Coord start, Coord end) //check for left wall collision
{
if(_x_pos + _x_vel*10.0f/_frame_rate - 1 < start.x && _x_pos + _x_vel*10.0f/_frame_rate > start.x - 5 && _y_pos >= start.y && _y_pos + 1 <= end.y && _x_vel < 0){
_x_pos = start.x + 1;
_x_vel = -_x_vel;
_bounce_flag = true;
}
}
void Ball::right_bounce(Coord start, Coord end) //check for right wall collision
{
if(_x_pos + _x_vel*10.0f/_frame_rate + 2 > start.x && _x_pos + _x_vel*10.0f/_frame_rate < start.x + 5 && _y_pos >= start.y && _y_pos + 1 <= end.y && _x_vel > 0){ //right wall x + 1
_x_pos = start.x - 1;
_x_vel = -_x_vel;
_bounce_flag = true;
}
}
void Ball::top_bounce(Coord start, Coord end) //check for top wall collision
{
if(_y_pos + _y_vel*10.0f/_frame_rate - 1 < start.y && _y_pos + _y_vel*10.0f/_frame_rate > start.y - 5 && _x_pos >= start.x && _x_pos + 1 <= end.x && _y_vel < 0){ //top wall y -1
_y_pos = start.y + 1;
_y_vel = -_y_vel;
_bounce_flag = true;
}
}
void Ball::bottom_bounce(Coord start, Coord end) //check for bottom wall collision
{
if(_y_pos + _y_vel*10.0f/_frame_rate + 2 > start.y && _y_pos + _y_vel*10.0f/_frame_rate < start.y + 5 && _x_pos >= start.x && _x_pos + 1 <= end.x && _y_vel > 0){ //bottom wall
_y_pos = start.y - 1;
_y_vel = -_y_vel;
_bounce_flag = true;
}
}
void Ball::bottom_left_bounce(Coord start, Coord end) //check for bottom left wall collision
{
if((_y_pos + _y_vel*10.0f/_frame_rate + 1) > (_x_pos + _x_vel*10.0f/_frame_rate - 1) + (start.y-start.x) && //bottom left bounce conditions
(_x_pos + _x_vel*10.0f/_frame_rate - 1) >= start.x && (_x_pos + _x_vel*10.0f/_frame_rate - 1) <= end.x &&
(_y_pos + _y_vel*10.0f/_frame_rate + 1) >= start.y && (_y_pos + _y_vel*10.0f/_frame_rate + 1) <= end.y ) {
swap(_x_vel, _y_vel); //reflects from wall with velocity directions swapped
_bounce_flag = true;
}
}
void Ball::bottom_right_bounce(Coord start, Coord end) //check for bottom right wall collision
{
if((_x_pos + _x_vel*10.0f/_frame_rate + 1) > -(_y_pos + _y_vel*10.0f/_frame_rate + 1) + (start.x+start.y) //bottom right bounce conditions
&& (_x_pos + _x_vel*10.0f/_frame_rate + 1) >= start.x && (_x_pos + _x_vel*10.0f/_frame_rate + 1) <= end.x
&& (_y_pos + _y_vel*10.0f/_frame_rate + 1) >= end.y && (_y_pos + _y_vel*10.0f/_frame_rate + 1) <= start.y) {
_x_vel = -_x_vel; //negative wall
_y_vel = -_y_vel;
swap(_x_vel, _y_vel); //reflects from wall with velocity directions swapped
_bounce_flag = true;
}
}
void Ball::top_left_bounce(Coord start, Coord end) //check for top left wall collision
{
if((_x_pos + _x_vel*10.0f/_frame_rate - 1) < -(_y_pos + _y_vel*10.0f/_frame_rate + 1) + (start.x+start.y) //top left bounce conditions
&& (_x_pos + _x_vel*10.0f/_frame_rate - 1) >= start.x && (_x_pos + _x_vel*10.0f/_frame_rate - 1) <= end.x
&& (_y_pos + _y_vel*10.0f/_frame_rate + 1) >= end.y && (_y_pos + _y_vel*10.0f/_frame_rate + 1) <= start.y) {
_x_vel = -_x_vel; //negative wall
_y_vel = -_y_vel;
swap(_x_vel, _y_vel); //reflects from wall with velocity directions swapped
_bounce_flag = true;
}
}
void Ball::top_right_bounce(Coord start, Coord end) //check for top right wall collision
{
if((_y_pos + _y_vel*10.0f/_frame_rate - 1) < (_x_pos + _x_vel*10.0f/_frame_rate + 1) + (start.y-start.x) //top right bounce conditions
&& (_x_pos + _x_vel*10.0f/_frame_rate + 1) >= start.x && (_x_pos + _x_vel*10.0f/_frame_rate + 1) <= end.x
&& (_y_pos + _y_vel*10.0f/_frame_rate - 1) >= start.y && (_y_pos + _y_vel*10.0f/_frame_rate - 1) <= end.y) {
swap(_x_vel, _y_vel); //reflects from wall with velocity directions swapped
_bounce_flag = true;
}
}