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.
Fork of 2645_Physics_Engine_Example by
Revision 1:6632d8423c65, committed 2016-05-05
- Comitter:
- HarryPetrovic1
- Date:
- Thu May 05 14:18:21 2016 +0000
- Parent:
- 0:6a561e8d6713
- Commit message:
- Pong
Changed in this revision
--- a/N5110.lib Fri Mar 11 09:52:11 2016 +0000 +++ b/N5110.lib Thu May 05 14:18:21 2016 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/eencae/code/N5110/#ba8addc061ea +http://developer.mbed.org/users/eencae/code/N5110/#ba8addc061ea
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data.h Thu May 05 14:18:21 2016 +0000 @@ -0,0 +1,50 @@ +#include "mbed.h" +#include "N5110.h" +#define BALLRADIUS 2 + + + +// VCC, SCE, RST, D/C, MOSI, SCLK, LED +N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3); +AnalogIn yin(PTB3); /*!< sets y position of user paddle*/ +DigitalIn select(PTB11); + + +Ticker game_timer; + + + +/*!< struct used to store 2D vectors*/ +typedef struct vector_t vector_t; /*!< struct used to store 2D vectors*/ +struct vector_t { + float x; + float y; +}; +/** + +@file data.h +@brief A file containing variables and constants +@brief These variables and constants are then called to be used within the game +@author Harry Petrovic +@date May 2016 +*/ + +vector_t pos; /*!< Position of the ball*/ +vector_t vel; /*!< Velocity of the ball*/ +vector_t acc; /*!< acceleration of the ball*/ + +float refresh_rate = 200.0; /*!< how often to update display (Hz)*/ +float g_dt = 20.0F/refresh_rate; /*!< global to store time step (F makes it a float, gets rid of compiler warning)*/ +volatile int g_timer_flag = 0; + +int yp = 0; /*!< y position of user controlled paddle*/ +int yc = 0;/*!< y position of computer controlled paddle*/ +char score1[80]; /*!< Score 1, used for human score*/ +char score2[80]; /*!< Score 2, used for computer score*/ +int playerScore = 0;/*!< Set innitially to 0 at start of game*/ +int computerScore = 0;/*!< Set innitially to 0 at start of game*/ +int Array [84][48]; /*!< Array of Nokia LCD Screen pixels [x][y]*/ +int nx = 84; /*!< integer value of number of pixels on x axis, used for lcd.Clearpixels*/ +int ny = 48; /*!< integer value of number of pixels on y axis, used for lcd.Clearpixels*/ +unsigned char next[84][48]; /*!< used to set buffer for the screen*/ +int difficulty =1; /*!< used in initial menu screen to select difficuly*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/functions.h Thu May 05 14:18:21 2016 +0000 @@ -0,0 +1,492 @@ +#include "mbed.h" +#include "N5110.h" +#include "data.h" + +/**@file functions.h +@brief File containing functions and actions within the game +@author Harry Petrovic +@date May 2016 +*/ + + + +/**initialises display so that you can view images upon LCD screen*/ + +void init_display(); + +/** sets the initial position, velocity and acceleration when the game starts and when the computer scores + + @param pos.x - initial x position + + @param pos.y - initial y position + + @param vel.x - initial x direction velocity + + @param vel.y -initial y direction velocity + + @param acc.x - initial x direction acceleration, starts it off moving towards the right + + @param acc.y -initial y direction acceleration, starts it off moving towards ground + */ + + +void init_ball(); + + +/** sets the initial position, velocity and acceleration when the player scores + + @param pos.x - initial x position + + @param pos.y - initial y position + + @param vel.x - initial x direction velocity + + @param vel.y -initial y direction velocity + + @param acc.x - initial x direction acceleration, starts it off moving towards the left + + @param acc.y -initial y direction acceleration, starts it off moving towards ground + */ + +void player_Score_Position(); + +void game_timer_isr(); + + +/** Draws the ball and updates the screen, called from the Nokia 5110 library + taken from "2645_Physics_Engine_Example" + +@param pos.x -the position of the ball is drawn, corresponding to the calculated position. + +@param pos.y-the position of the ball is drawn, corresponding to the calculated position. + +@param radius - deffined as 2 + +@param fill - set as 0.5 so that it is just an outline + + +*/ +void redraw_screen(); + + +/** Calculates the new position (pos+vel) and velocity (vel+acc) of the ball + taken from 2645_Physics_Engine_Example and subsequently adapted + +@param vel.x - The current x velocity of ball + +@param vel.y - The current y velocity of ball + +@param acc.x - The current x acceleration of ball + +@param acc.y - The current y acceleration of ball + +@param pos.x The current x position of ball + +@param pos.y - The current y position of ball + +@returns vel.x - New calculated x velocity of ball + +@returns vel.y - New calculated y velocity of ball + +@returns pos.x - New calculated x position of ball + +@returns pos.y- New calculated y position of ball + +*/ + + +void update_physics_engine(); + +/** Checks whether or not the ball has come into contact with the paddles, roof or the floor + taken from 2645_Physics_Engine_Example and subsequently adapted + +@param pos.x - The current x position of ball + +@param pos.y - The current x position of ball + +@param yc - The position of the paddle + +@param yp - the position of user paddle + +@return pos.x - if contact has been made new position is given + +@return pos.y - if contact has been made new position is given + + +@return vel.x - if contact has been made velocity inverted + +@return vel.y if contact has been made velocity inverted + +@return acc.x - if contact has been made acceleration inverted + +@return acc.y if contact has been made acceleration inverted + + +*/ +void check_collisions(); + + +/** sets up the use of the button +*/ + +void init_K64F(); + + +/** Appears at the start of the game and allows user to choose difficulty + +@param yin - used to navigate up and down the menu + +@param difficulty - value of 1,2,3 Easy, Med, Hard, sets value in moveComputerPaddle + +*/ +void menu(); + + +void clearCells(); +void refreshCells(); + +/** allows the user to move their paddle with the joystick + +@param yin - gives a reading between 0-1. if below 0.4 yp-- occurs if 0.6 yp++. If inbetween yp = yp + +@returns yp - The co-ordinate of the first pixel within the paddle, moves according to yin value + +*/ +void moveUserPaddle(); + +/** Moves the computer paddle + + +@param pos.y - value is read +@param difficulty - value that is used to set how far off the pace the paddle is + +@returns yc - returned from pos.y-difficulty +*/ +void moveComputerPaddle(); + +/**prevents user paddle moving off screen by forcing position of yp + +@param yp - the position of the paddle + +*/ +void paddleLimits(); + + +/**prevents computer paddle moving off screen by forcing position of yp + +@param yc - the position of the paddle + +*/ +void ComputerpaddleLimits(); + +/** Determines which player has scored, if any + +@param pos.x - The position of the ball + +@return computerScore - ++ if ball touches left hand side + +@return playerScore - ++ if ball touches right hand side +*/ + +void Scoring(); + +/** Resets ball to a position, depending on who scored + + @param pos.x - if hits wall the ball will return to default position depending on who scored + +*/ +void resetBall(); + +/** + +@param - playerScore -the current score of player + +@return - message stating victory if playerScore > 10 + + +*/ +void victory(); +void redraw_screen(); + +/** + +@param - computerScore -the current score of computer + +@return - message stating defeat if playerScore > 10 + + +*/ + +void loss(); + + + + + +void init_K64F() +{ + select.mode(PullDown); +} + +void menu() +{ + while(select) { + lcd.printString("EASY", 20,1); + lcd.printString("MED", 20,2); + lcd.printString("HARD", 20,3); + if(difficulty == 1) { + + } else if(difficulty == 2) { + } else if(difficulty ==3) { + } + if(yin < 0.6f) { + difficulty++; + } else if(yin >0.4f) { + difficulty--; + } + wait(0.1); + } +} + + + +void clearCells() //loop and clear +{ + for (int i = 0; i < nx ; i++) { + for (int j = 0; j < ny ; j++) { + lcd.clearPixel(i,j); + } + } + lcd.refresh(); //refresh +} + +void refreshCells() +{ + for (int i = 0; i< 84 ; i++) { + for (int j = 0; j < 48 ; j++) { + if (Array[i][j]) { + lcd.setPixel(i,j); + } + + else { + lcd.clearPixel(i,j); + } + + + + } + + } + +} + + + +void moveUserPaddle() //used to control paddle + +{ + if(yin > 0.6f) { //if potentimeter is greater than 0.6 value the paddle moves up + yp= yp-3; + } + + else if(yin < 0.4f) { //as above but the paddle will move down + yp = yp+3; + } +} + +void moveComputerPaddle() + +{ + yc=pos.y-difficulty; +} + + +void paddleLimits() //makes it so that the paddles remain upon the screen + +{ + if (yp <= 0) { //stops paddle disapearing above the screen + + yp=0; + } + + else if (yp >= 38) { //stops paddle disapearing bellow the screen, value of 40 must be used because of 8 pixel long paddle + yp=40; + } +} + +void ComputerpaddleLimits() //makes it so that the paddles remain upon the screen + +{ + if (yc <= 0) { //stops paddle disapearing above the screen + + yc=0; + } + + else if (yc >= 38) { //stops paddle disapearing bellow the screen, value of 40 must be used because of 8 pixel long paddle + yc=38; + } +} + +void Scoring() + +{ + + if (pos.x - BALLRADIUS < 0) { + + computerScore = computerScore++; + + } else if (pos.x + BALLRADIUS > 83) { + + playerScore = playerScore++; + } + + +} + +void resetBall() +{ + + if (pos.x - BALLRADIUS < 0) { + + wait(0.5); + init_ball(); + } else if (pos.x + BALLRADIUS > 83) { + + wait (0.5); + player_Score_Position(); + } + + +} + +void victory() +{ + + if (playerScore >=10) + + { + refreshCells(); + lcd.init(); + lcd.printString("Welldone,",15,0); //display intro & title to game + lcd.printString("You've Won!",10,1); + lcd.printString("Is your name",5,2); + lcd.printString("Roger Federer?",1,3); + wait (5); + lcd.refresh(); + + } + +} + +void loss() +{ + + if (computerScore >=10) + + { + refreshCells(); + lcd.init(); + lcd.printString("Unlucky Pal",10,0); //display intro & title to game + lcd.printString("You Lose, you",5,1); + lcd.printString("absoloute mug",5,2); + wait (5); + lcd.refresh(); + + } + + + + +} + +void redraw_screen() +{ + + lcd.drawCircle(pos.x,pos.y,BALLRADIUS,0.5); + lcd.refresh(); +} + + +void check_collisions() +{ + // see if ball has hit the floor (subtract the radius since the position is the centre of the ball) + if ( pos.y >= 47 - BALLRADIUS ) { + pos.y = 47 - BALLRADIUS; // need to force this or else ball can end up going 'underground' + vel.y = -0.6 * vel.y; // y velocity is reflected and dampened + acc.y = -acc.y; + // y accleration is still gravity + } + + if ( pos.y <= 5 - BALLRADIUS ) { + pos.y = 5 - BALLRADIUS; // need to force this or else ball can end up going 'underground' + vel.y = -0.6 * vel.y; // y velocity is reflected and dampened + acc.y = -acc.y; + // y accleration is still gravity + } + + // has ball gone off the right-hand side? + if (( pos.x >= 83 - BALLRADIUS ) && (pos.y > yc) && (pos.y < yc + 12)&&(pos.y > yc - 3)) { + pos.x = 83 - BALLRADIUS; // need to force this or else ball can end up going off screen + vel.x = -0.6 * vel.x; // reflect and damp velocity + acc.x = -acc.x; // reflect accleration + } + + // what about the left? + if (( pos.x <= BALLRADIUS ) && (pos.y > yp) && (pos.y < yp + 12)&&(pos.y > yp - 3)) { + pos.x = BALLRADIUS; // need to force this or else ball can end up going off screen + vel.x = -0.6 * vel.x; // reflect and damp velocity + acc.x = -acc.x; // reflect accleration + } + +} + +void update_physics_engine() +{ + // from Newton's Laws + + acc.x = 1.0F*acc.x; // reduce a little due to air friction + + // calc new velocity (assume 'unit' time) + vel.x = vel.x + acc.x; // * g_gt; + vel.y = vel.y + acc.y; // * g_gt; + + // calc new position (assume 'unit' time) + pos.x = (pos.x + vel.x) * 1; + pos.y = (pos.y + vel.y) * 1; + + // should really multiply the above by the time-step, + // but since the pixel can only be a integer value, + // it makes the motion a little 'jumpy'. + +} + +void init_ball() +{ + pos.x = 3; + pos.y = 4; + vel.x = 0.0; + vel.y = 0.0; + acc.x = 0.5; + acc.y = 0.075; +} + +void player_Score_Position() +{ + // initial position (top-left) + pos.x = 80; + pos.y = 4; + // initial velocity - still + vel.x = 0.0; + vel.y = 0.0; + // initial acceleration - gravity and a bit of push to right + acc.x = -0.5; + acc.y = 0.075; // +ve so ball accelerates to bottom of display (top of screen is y=0, bottom is y=47) + // should be 9.8, but can play with value to get a 'nice' ball movement +} + +void init_display() +{ + lcd.init(); + lcd.normalMode(); // normal colour mode + lcd.setBrightness(0.5); // put LED backlight on 50% +} \ No newline at end of file
--- a/main.cpp Fri Mar 11 09:52:11 2016 +0000 +++ b/main.cpp Thu May 05 14:18:21 2016 +0000 @@ -1,54 +1,109 @@ #include "mbed.h" #include "N5110.h" +#include "functions.h" -#define BALLRADIUS 2 +void UserPaddle() //Paddle used by user + +{ + lcd.setPixel(0,yp); + lcd.setPixel(0,yp+1); + lcd.setPixel(0,yp+2); + lcd.setPixel(0,yp+3); + lcd.setPixel(0,yp+4); + lcd.setPixel(0,yp+5); + lcd.setPixel(0,yp+6); + lcd.setPixel(0,yp+7); + lcd.setPixel(0,yp+8); + lcd.setPixel(0,yp+9); -// VCC, SCE, RST, D/C, MOSI, SCLK, LED -N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3); -// Can also power (VCC) directly from VOUT (3.3 V) - -// Can give better performance due to current limitation from GPIO pin -Ticker game_timer; +} + +void ComputerPaddle() //Paddle controlled by the computer -// struct used to store 2D vectors -typedef struct vector_t vector_t; -struct vector_t { - float x; - float y; -}; +{ + lcd.setPixel(83,yc); + lcd.setPixel(83,yc+1); + lcd.setPixel(83,yc+2); + lcd.setPixel(83,yc+3); + lcd.setPixel(83,yc+4); + lcd.setPixel(83,yc+5); + lcd.setPixel(83,yc+6); + lcd.setPixel(83,yc+7); + lcd.setPixel(83,yc+8); + lcd.setPixel(83,yc+9); -// function prototypes -void init_display(); -void init_ball(); -void game_timer_isr(); -void redraw_screen(); -void update_physics_engine(); -void check_collisions(); +} -vector_t pos; // ball position -vector_t vel; // ball velocity -vector_t acc; // ball acceleration +void net() +{ + lcd.setPixel (42,0); + lcd.setPixel (42,2); + lcd.setPixel (42,4); + lcd.setPixel (42,6); + lcd.setPixel (42,8); + lcd.setPixel (42,10); + lcd.setPixel (42,12); + lcd.setPixel (42,14); + lcd.setPixel (42,16); + lcd.setPixel (42,18); + lcd.setPixel (42,20); + lcd.setPixel (42,22); + lcd.setPixel (42,24); + lcd.setPixel (42,26); + lcd.setPixel (42,28); + lcd.setPixel (42,30); + lcd.setPixel (42,32); + lcd.setPixel (42,34); + lcd.setPixel (42,36); + lcd.setPixel (42,38); + lcd.setPixel (42,40); + lcd.setPixel (42,42); + lcd.setPixel (42,44); + lcd.setPixel (42,46); + lcd.setPixel (42,48); +} -float refresh_rate = 10.0; // how often to update display (Hz) -float g_dt = 1.0F/refresh_rate; // global to store time step (F makes it a float, gets rid of compiler warning) -volatile int g_timer_flag = 0; + int main() { wait(2.0); // short delay for power to settle init_display(); // first need to initialise display + init_K64F(); + menu(); + wait(3); + init_ball(); // setup ticker - game_timer.attach(&game_timer_isr,g_dt); + game_timer.attach(&game_timer_isr,0.1); redraw_screen(); // draw initial screen while(1) { + sprintf(score1, "%d", playerScore); + lcd.printString(score1,30,0); + sprintf(score2, "%d", computerScore); + lcd.printString(score2,50,0); + if ( g_timer_flag ) { // ticker interrupt g_timer_flag = 0; // clear flag + UserPaddle(); + ComputerPaddle(); + moveUserPaddle(); + moveComputerPaddle(); + paddleLimits(); + ComputerpaddleLimits(); + net(); + Scoring(); + victory(); + loss(); + resetBall(); update_physics_engine(); check_collisions(); redraw_screen(); + lcd.refresh(); + refreshCells(); } sleep(); // sleep until next interrupt @@ -56,80 +111,10 @@ } } -void redraw_screen() -{ - lcd.clear(); - lcd.drawCircle(pos.x,pos.y,BALLRADIUS,1); // x,y,radius,black fill - lcd.refresh(); // update display -} -void check_collisions() -{ - // see if ball has hit the floor (subtract the radius since the position is the centre of the ball) - if ( pos.y >= 47 - BALLRADIUS ) { - pos.y = 47 - BALLRADIUS; // need to force this or else ball can end up going 'underground' - vel.y = -0.89 * vel.y; // y velocity is reflected and dampened - // y accleration is still gravity - } - - // has ball gone off the right-hand side? - if ( pos.x >= 83 - BALLRADIUS ) { - pos.x = 83 - BALLRADIUS; // need to force this or else ball can end up going off screen - vel.x = -0.5 * vel.x; // reflect and damp velocity - acc.x = -acc.x; // reflect accleration - } - - // what about the left? - if ( pos.x <= BALLRADIUS ) { - pos.x = BALLRADIUS; // need to force this or else ball can end up going off screen - vel.x = -0.5 * vel.x; // reflect and damp velocity - acc.x = -acc.x; // reflect accleration - } - -} - -void update_physics_engine() -{ - // from Newton's Laws - - acc.x = 0.9F*acc.x; // reduce a little due to air friction - - // calc new velocity (assume 'unit' time) - vel.x = vel.x + acc.x; // * g_gt; - vel.y = vel.y + acc.y; // * g_gt; - - // calc new position (assume 'unit' time) - pos.x = pos.x + vel.x;// * g_gt; - pos.y = pos.y + vel.y;// * g_dt; - - // should really multiply the above by the time-step, - // but since the pixel can only be a integer value, - // it makes the motion a little 'jumpy'. - -} - -void init_ball() -{ - // initial position (top-left) - pos.x = BALLRADIUS; - pos.y = BALLRADIUS; - // initial velocity - still - vel.x = 0.0; - vel.y = 0.0; - // initial acceleration - gravity and a bit of push to right - acc.x = 0.5; - acc.y = 2.0; // +ve so ball accelerates to bottom of display (top of screen is y=0, bottom is y=47) - // should be 9.8, but can play with value to get a 'nice' ball movement -} void game_timer_isr() { g_timer_flag = 1; } -void init_display() -{ - lcd.init(); - lcd.normalMode(); // normal colour mode - lcd.setBrightness(0.5); // put LED backlight on 50% -} \ No newline at end of file