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
Diff: Engine/Engine.cpp
- Revision:
- 12:2af7b4868033
- Parent:
- 5:3c9407e2fe55
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Engine/Engine.cpp Wed May 27 07:00:37 2020 +0000
@@ -0,0 +1,546 @@
+#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);
+ }
+ }
+}
\ No newline at end of file