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
Engine/Engine.cpp
- Committer:
- Mousky
- Date:
- 2020-05-27
- Revision:
- 13:76bac89c447b
- Parent:
- 12:2af7b4868033
File content as of revision 13:76bac89c447b:
#include "Engine.h"
Engine::Engine()
{
}
Engine::~Engine()
{
}
void Engine::init(int paddle_width,int paddle_height,int ball_size,int ball2_size,int speed,int thing_size, int repaddle_size)
{
// initialise the game parameters
_paddle_width = paddle_width;
_paddle_height = paddle_height;
_ball_size = ball_size;
_ball2_size = ball2_size; // add another ball when score reaches 5
_thing_size = thing_size;
_repaddle_size = repaddle_size;
_speed = speed;
// x position on screen - WIDTH is defined in N5110.h
_p1y = HEIGHT - GAP;
// puts paddles and ball in middle
_p1.init(HEIGHT/2,_p1y,_paddle_width);
_ball.init(_ball_size,_speed);
_ball2.init(_ball2_size,_speed);
_thing.init(_thing_size);
}
void Engine::read_input(Gamepad &pad)
{
_d = pad.get_direction();
_mag = pad.get_mag();
}
/////////////////////// Draw the graph ///////////////////////////////////////
void Engine::draw(N5110 &lcd)
{
// draw the elements in the LCD buffer
// pitch
lcd.drawRect(0,0,WIDTH,HEIGHT,FILL_TRANSPARENT);
lcd.drawLine(20,30,70,30,FILL_BLACK); //the first reflection board.
lcd.drawLine(25,22,45,22,FILL_BLACK); // the second reflection board.
lcd.drawLine(55,25,75,25,FILL_BLACK); // the third reflection board.
//score
print_scores(lcd);
//draw paddles
_p1.draw(lcd);
// draw ball1, thing and repaddle
_ball.draw(lcd);
_ball2.draw(lcd);
_thing.draw(lcd);
/// _repaddle.draw(lcd);
}
//////////////////////////////UPDATE/////////////////////////////////////////////
void Engine::update(N5110 &lcd,Gamepad &pad)
{
check_goal(pad);
check_ball2_goal(pad);
// important to update paddles and ball before checking collisions so can
// correct for it before updating the display
_p1.update(_d,_mag);
_ball.update();
/////// check ball///////////////
check_wall_collision(pad);
check_paddle_collisions(pad);
check_thing_collisions(pad);
check_reflection(pad);
///////////////Ball2///////////////
_ball2.update();
// get the scores
int p_score = _p1.get_score();
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
Vector2D thing_pos = _thing.get_pos();
// if the score is bigger than 5, than add another ball
if (p_score < 5) {
ball2_pos.x = thing_pos.x;
ball2_pos.y = thing_pos.y;
ball2_velocity.x = 0;
ball2_velocity.y = 0;
_ball2.set_velocity(ball2_velocity);
_ball2.set_pos(ball2_pos);
}
// the another ball will begin to move in a random direction
else if (p_score == 5) {
ball2_velocity.x = _speed * (2*(rand() % 2) - 1);
ball2_velocity.y = _speed * (2*(rand() % 2) - 1);
_ball2.set_velocity(ball2_velocity);
while (_p1.get_score() == 5) {
read_input(pad);
check_goal(pad);
check_ball2_goal(pad);
_p1.update(_d,_mag);
_ball.update();
check_wall_collision(pad);
check_paddle_collisions(pad);
check_thing_collisions(pad);
check_reflection(pad);
_ball2.update();
check_ball2(pad);
lcd.clear();
draw(lcd);
lcd.refresh();
wait(1.0f/8);
}
}
check_ball2(pad); // check the states of ball2 for updating
}
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////CHECK BALL1////////////////////////////////////////
// set the refrection of the board and speed up the ball
// two ways of refrection: x-direction and y-direction
void Engine::check_reflection(Gamepad &pad)
{
Vector2D ball_pos = _ball.get_pos();
Vector2D ball_velocity = _ball.get_velocity();
if ((ball_pos.x >= 20) && (ball_pos.x <= 70) && (ball_pos.y <= 31) && (ball_pos.y >= 29)) {
ball_velocity.x = ball_velocity.x*2;
// audio feedback
pad.tone(750.0,0.1);
}
else if ((ball_pos.x >=25) && (ball_pos.x <= 45) && (ball_pos.y >= 21) && (ball_pos.y <= 23)){
ball_velocity.y = ball_velocity.y*2;
// audio feedback
pad.tone(750.0,0.1);
}
else if ((ball_pos.x >=55) && (ball_pos.x <= 75) && (ball_pos.y >= 24) && (ball_pos.y <= 26)){
ball_velocity.y = ball_velocity.y*2;
// audio feedback
pad.tone(750.0,0.1);
}
_ball.set_velocity(ball_velocity);
_ball.set_pos(ball_pos);
}
void Engine::check_wall_collision(Gamepad &pad)
{
// read current ball attributes
Vector2D ball_pos = _ball.get_pos();
Vector2D ball_velocity = _ball.get_velocity();
//adjust to the original speed
if (abs(ball_velocity.x) > _speed) {
ball_velocity.x = ball_velocity.x / abs(ball_velocity.x) * 2;
}
if (abs(ball_velocity.y) > _speed) {
ball_velocity.y = ball_velocity.y / abs(ball_velocity.y) * 2;
}
// check if hit top wall
if (ball_pos.y <= 1) { // 1 due to 1 pixel boundary
ball_pos.y = 1; // bounce off ceiling without going off screen
ball_velocity.y = -ball_velocity.y;
// audio feedback
pad.tone(750.0,0.1);
}
// check if hit bottom wall
else if (ball_pos.x <= 1) { // 1 due to 1 pixel boundary
ball_pos.x = 1; // bounce off ceiling without going off screen
ball_velocity.x = -ball_velocity.x;
// audio feedback
pad.tone(750.0,0.1);
}
else if (ball_pos.x >= 84) { // 1 due to 1 pixel boundary
ball_pos.x = 84; // bounce off ceiling without going off screen
ball_velocity.x = -ball_velocity.x;
// audio feedback
pad.tone(750.0,0.1);
}
// update ball parameters
_ball.set_velocity(ball_velocity);
_ball.set_pos(ball_pos);
}
void Engine::check_paddle_collisions(Gamepad &pad)
{
// read current ball attributes
Vector2D ball_pos = _ball.get_pos();
Vector2D ball_velocity = _ball.get_velocity();
Vector2D p1_pos = _p1.get_pos();
//adjust to the original speed
if (abs(ball_velocity.x) > _speed) {
ball_velocity.x = ball_velocity.x / abs(ball_velocity.x) * 2;
}
if (abs(ball_velocity.y) > _speed) {
ball_velocity.y = ball_velocity.y / abs(ball_velocity.y) * 2;
}
// see if ball has hit the paddle by checking for overlaps
if (
(ball_pos.y >= p1_pos.y) && //top
(ball_pos.y <= p1_pos.y + 2) && //bottom
(ball_pos.x >= p1_pos.x-4) && //left
(ball_pos.x <= p1_pos.x + 10) //right
) {
// if it has, fix position and reflect x velocity
ball_pos.x = p1_pos.x ;
ball_velocity.y = -ball_velocity.y;
// audio feedback
pad.tone(1000.0,0.1);
}
// write new attributes
_ball.set_velocity(ball_velocity);
_ball.set_pos(ball_pos);
}
void Engine::check_thing_collisions(Gamepad &pad)
{
// read current ball attributes
Vector2D ball_pos = _ball.get_pos();
Vector2D ball_velocity = _ball.get_velocity();
// read current thing position
Vector2D thing_pos = _thing.get_pos();
//adjust to the original speed
if (abs(ball_velocity.x) > _speed) {
ball_velocity.x = ball_velocity.x / abs(ball_velocity.x) * 2;
}
if (abs(ball_velocity.y) > _speed) {
ball_velocity.y = ball_velocity.y / abs(ball_velocity.y) * 2;
}
// see if ball has hit the thing by checking for overlaps
if (
(ball_pos.y >= thing_pos.y - 1) && //top
(ball_pos.y <= thing_pos.y + 1) && //bottom
(ball_pos.x >= thing_pos.x - 3) && //left
(ball_pos.x <= thing_pos.x + 10) //right
) {
// if it has, fix position and reflect x velocity
ball_pos.x = thing_pos.x ;
ball_velocity.y = -ball_velocity.y;
// audio feedback
pad.tone(1000.0,0.1);
}
// write new attributes
_ball.set_velocity(ball_velocity);
_ball.set_pos(ball_pos);
}
void Engine::check_goal(Gamepad &pad)
{
Vector2D ball_pos = _ball.get_pos();
Vector2D thing_pos = _thing.get_pos();
if (
(ball_pos.y >= thing_pos.y - 1) && //top
(ball_pos.y <= thing_pos.y + 1) && //bottom
(ball_pos.x >= thing_pos.x - 3) && //left
(ball_pos.x <= thing_pos.x + 10) //right
) {
_p1.add_score();
_thing.init(_thing_size);
pad.tone(1500.0,0.5);
pad.leds_on();
wait(0.5);
pad.leds_off();
}
if (ball_pos.y >= HEIGHT) {
_ball.init(_ball_size,_speed);
pad.tone(1500.0,0.5);
pad.leds_on();
wait(0.5);
pad.leds_off();
}
}
void Engine::print_scores(N5110 &lcd)
{
// get scores from paddles
int p1_score = _p1.get_score();
// print to LCD i
char buffer1[14];
sprintf(buffer1,"%2d",p1_score);
lcd.printString(buffer1,60,1); // print at top-right corner
}
/////////////////////////////////////////////////////////////////////////////////
//////////////////// Check Ball2 ////////////////////////////////////
void Engine::check_ball2(Gamepad &pad)
{
check_ball2_wall_collision(pad);
check_ball2_paddle_collisions(pad);
check_ball2_thing_collisions(pad);
check_ball2_reflection(pad);
}
////////////// Check the states of the second ball /////////////////////////////
void Engine::check_ball2_reflection(Gamepad &pad)
{
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
if ((ball2_pos.x >= 20) && (ball2_pos.x <= 70) && (ball2_pos.y >= 29)&& (ball2_pos.y <= 31)) {
ball2_velocity.x = ball2_velocity.x*2;
// audio feedback
pad.tone(750.0,0.1);
}
else if ((ball2_pos.x >=25) && (ball2_pos.x <= 45) && (ball2_pos.y >= 21) && (ball2_pos.y <= 23)) {
ball2_velocity.y = ball2_velocity.y*2;
// audio feedback
pad.tone(750.0,0.1);
}
else if ((ball2_pos.x >=55) && (ball2_pos.x <= 75) && (ball2_pos.y >= 24) && (ball2_pos.y <= 26)) {
ball2_velocity.y = ball2_velocity.y*2;
// audio feedback
pad.tone(750.0,0.1);
}
_ball2.set_velocity(ball2_velocity);
_ball2.set_pos(ball2_pos);
}
void Engine::check_ball2_wall_collision(Gamepad &pad)
{
// read current ball attributes
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
//adjust to the original speed
if (abs(ball2_velocity.x) > _speed) {
ball2_velocity.x = ball2_velocity.x / abs(ball2_velocity.x) * 2;
}
if (abs(ball2_velocity.y) > _speed) {
ball2_velocity.y = ball2_velocity.y / abs(ball2_velocity.y) * 2;
}
// check if hit top wall
if (ball2_pos.y <= 1) { // 1 due to 1 pixel boundary
ball2_pos.y = 1; // bounce off ceiling without going off screen
ball2_velocity.y = -ball2_velocity.y;
// audio feedback
pad.tone(750.0,0.1);
}
// check if hit bottom wall
else if (ball2_pos.x <= 1) { // 1 due to 1 pixel boundary
ball2_pos.x = 1; // bounce off ceiling without going off screen
ball2_velocity.x = -ball2_velocity.x;
// audio feedback
pad.tone(750.0,0.1);
}
else if (ball2_pos.x >= 84) { // 1 due to 1 pixel boundary
ball2_pos.x = 84; // bounce off ceiling without going off screen
ball2_velocity.x = -ball2_velocity.x;
// audio feedback
pad.tone(750.0,0.1);
}
// update ball parameters
_ball2.set_velocity(ball2_velocity);
_ball2.set_pos(ball2_pos);
}
void Engine::check_ball2_paddle_collisions(Gamepad &pad)
{
// read current ball attributes
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
Vector2D p1_pos = _p1.get_pos();
//adjust to the original speed
if (abs(ball2_velocity.x) > _speed) {
ball2_velocity.x = ball2_velocity.x / abs(ball2_velocity.x) * 2;
}
if (abs(ball2_velocity.y) > _speed) {
ball2_velocity.y = ball2_velocity.y / abs(ball2_velocity.y) * 2;
}
// see if ball has hit the paddle by checking for overlaps
if (
(ball2_pos.y >= p1_pos.y) && //top
(ball2_pos.y <= p1_pos.y + 2) && //bottom
(ball2_pos.x >= p1_pos.x-4) && //left
(ball2_pos.x <= p1_pos.x + 10) //right
) {
// if it has, fix position and reflect x velocity
ball2_pos.x = p1_pos.x ;
ball2_velocity.y = -ball2_velocity.y;
// audio feedback
pad.tone(1000.0,0.1);
}
// write new attributes
_ball2.set_velocity(ball2_velocity);
_ball2.set_pos(ball2_pos);
}
void Engine::check_ball2_thing_collisions(Gamepad &pad)
{
// read current ball attributes
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
// read current thing position
Vector2D thing_pos = _thing.get_pos();
//adjust to the original speed
if (abs(ball2_velocity.x) > _speed) {
ball2_velocity.x = ball2_velocity.x / abs(ball2_velocity.x) * _speed;
}
if (abs(ball2_velocity.y) > _speed) {
ball2_velocity.y = ball2_velocity.y / abs(ball2_velocity.y) * _speed;
}
// see if ball has hit the thing by checking for overlaps
if (
(ball2_pos.y >= thing_pos.y - 1) && //top
(ball2_pos.y <= thing_pos.y + 1) && //bottom
(ball2_pos.x >= thing_pos.x - 3) && //left
(ball2_pos.x <= thing_pos.x + 10) //right
) {
// if it has, fix position and reflect x velocity
ball2_pos.x = thing_pos.x ;
ball2_velocity.y = -ball2_velocity.y;
// audio feedback
pad.tone(1000.0,0.1);
}
// write new attributes
_ball2.set_velocity(ball2_velocity);
_ball2.set_pos(ball2_pos);
}
void Engine::check_ball2_goal(Gamepad &pad)
{
Vector2D ball2_pos = _ball2.get_pos();
Vector2D thing_pos = _thing.get_pos();
if (
(ball2_pos.y >= thing_pos.y - 1) && //top
(ball2_pos.y <= thing_pos.y + 1) && //bottom
(ball2_pos.x >= thing_pos.x - 3) && //left
(ball2_pos.x <= thing_pos.x + 10) //right
) {
_p1.add_score();
_thing.init(_thing_size);
pad.tone(1500.0,0.5);
pad.leds_on();
wait(0.5);
pad.leds_off();
}
if (ball2_pos.y >= HEIGHT) {
_ball2.init(_ball2_size,_speed);
pad.tone(1500.0,0.5);
pad.leds_on();
wait(0.5);
pad.leds_off();
}
}
////////////////////// The World //////////////////////////////////
/* Every time we get 6 socres , the stand power of the world is triggered
* The function of the world is used to pause the first ball for a while
*/
void Engine::The_world(N5110 &lcd, Gamepad &pad){
Vector2D ball_pos = _ball.get_pos();
Vector2D ball_velocity = _ball.get_velocity();
// check the score whether reach the goal
while ((_p1.get_score() % 6 == 0) && (_p1.get_score() != 0)){
//set the sound of the world
pad.tone(500.0,0.2);
wait(0.2);
pad.tone(800.0,0.2);
pad.tone(1300.0,0.3);
pad.tone(1600.0,0.3);
// get the state of ball 1 before begin the world
// make the ball 2 keep moving
while((_p1.get_score() % 6 == 0) && (_p1.get_score() != 0)){
read_input(pad);
check_ball2_goal(pad);
_p1.update(_d,_mag);
_ball2.update();
check_ball2(pad);
// reflesh the lcd and make pause
lcd.clear();
draw(lcd);
lcd.refresh();
wait(1.0f/8);
}
// restore the state of ball 1 after the world
_ball.set_velocity(ball_velocity);
}
}
////////////////////// Bite the Dust /////////////////////////////////
/* When the socre we get reaches 8, the stand power of bite the dust is triggered
* The function of bite the dust is time backing tracking
*/// The second ball will go back to the initial state
void Engine::bite_dust(N5110 &lcd, Gamepad &pad){
// check the score whether reach the goal
while ((_p1.get_score() % 8 == 0) && (_p1.get_score() != 0)){
//set the sound of the world
pad.tone(1000.0,0.2);
wait(0.1);
pad.tone(1000.0,0.2);
wait(0.1);
pad.tone(600.0,0.3);
// get the state of ball 2
Vector2D ball2_pos = _ball2.get_pos();
Vector2D ball2_velocity = _ball2.get_velocity();
Vector2D thing_pos = _thing.get_pos();
int distance_x = floor((ball2_pos.x - thing_pos.x)/3.0);
int distance_y = floor((ball2_pos.y - thing_pos.y)/3.0);
for (int i = 1; i <= 3; i ++){
ball2_pos.x = ball2_pos.x - distance_x;
ball2_pos.y = ball2_pos.y - distance_y;
_ball2.set_pos(ball2_pos);
// reflesh the lcd and make pause
lcd.clear();
draw(lcd);
lcd.refresh();
wait(0.5);
}
while((_p1.get_score() % 8 == 0) && (_p1.get_score() != 0)){
int p_score_b = _p1.get_score();
read_input(pad);
update(lcd,pad);
lcd.clear();
draw(lcd);
lcd.refresh();
wait(1.0f/8);
}
}
}