Simple 'bouncing ball' example. Demonstrates how to use Newton's Law of Motion to implement gravity simulation.

Dependencies:   N5110 mbed

Committer:
eencae
Date:
Fri Mar 11 09:52:11 2016 +0000
Revision:
0:6a561e8d6713
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:6a561e8d6713 1 #include "mbed.h"
eencae 0:6a561e8d6713 2 #include "N5110.h"
eencae 0:6a561e8d6713 3
eencae 0:6a561e8d6713 4 #define BALLRADIUS 2
eencae 0:6a561e8d6713 5
eencae 0:6a561e8d6713 6 // VCC, SCE, RST, D/C, MOSI, SCLK, LED
eencae 0:6a561e8d6713 7 N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);
eencae 0:6a561e8d6713 8 // Can also power (VCC) directly from VOUT (3.3 V) -
eencae 0:6a561e8d6713 9 // Can give better performance due to current limitation from GPIO pin
eencae 0:6a561e8d6713 10 Ticker game_timer;
eencae 0:6a561e8d6713 11
eencae 0:6a561e8d6713 12 // struct used to store 2D vectors
eencae 0:6a561e8d6713 13 typedef struct vector_t vector_t;
eencae 0:6a561e8d6713 14 struct vector_t {
eencae 0:6a561e8d6713 15 float x;
eencae 0:6a561e8d6713 16 float y;
eencae 0:6a561e8d6713 17 };
eencae 0:6a561e8d6713 18
eencae 0:6a561e8d6713 19 // function prototypes
eencae 0:6a561e8d6713 20 void init_display();
eencae 0:6a561e8d6713 21 void init_ball();
eencae 0:6a561e8d6713 22 void game_timer_isr();
eencae 0:6a561e8d6713 23 void redraw_screen();
eencae 0:6a561e8d6713 24 void update_physics_engine();
eencae 0:6a561e8d6713 25 void check_collisions();
eencae 0:6a561e8d6713 26
eencae 0:6a561e8d6713 27 vector_t pos; // ball position
eencae 0:6a561e8d6713 28 vector_t vel; // ball velocity
eencae 0:6a561e8d6713 29 vector_t acc; // ball acceleration
eencae 0:6a561e8d6713 30
eencae 0:6a561e8d6713 31 float refresh_rate = 10.0; // how often to update display (Hz)
eencae 0:6a561e8d6713 32 float g_dt = 1.0F/refresh_rate; // global to store time step (F makes it a float, gets rid of compiler warning)
eencae 0:6a561e8d6713 33 volatile int g_timer_flag = 0;
eencae 0:6a561e8d6713 34
eencae 0:6a561e8d6713 35 int main()
eencae 0:6a561e8d6713 36 {
eencae 0:6a561e8d6713 37 wait(2.0); // short delay for power to settle
eencae 0:6a561e8d6713 38 init_display(); // first need to initialise display
eencae 0:6a561e8d6713 39 init_ball();
eencae 0:6a561e8d6713 40 // setup ticker
eencae 0:6a561e8d6713 41 game_timer.attach(&game_timer_isr,g_dt);
eencae 0:6a561e8d6713 42
eencae 0:6a561e8d6713 43 redraw_screen(); // draw initial screen
eencae 0:6a561e8d6713 44
eencae 0:6a561e8d6713 45 while(1) {
eencae 0:6a561e8d6713 46
eencae 0:6a561e8d6713 47 if ( g_timer_flag ) { // ticker interrupt
eencae 0:6a561e8d6713 48 g_timer_flag = 0; // clear flag
eencae 0:6a561e8d6713 49 update_physics_engine();
eencae 0:6a561e8d6713 50 check_collisions();
eencae 0:6a561e8d6713 51 redraw_screen();
eencae 0:6a561e8d6713 52 }
eencae 0:6a561e8d6713 53
eencae 0:6a561e8d6713 54 sleep(); // sleep until next interrupt
eencae 0:6a561e8d6713 55
eencae 0:6a561e8d6713 56 }
eencae 0:6a561e8d6713 57 }
eencae 0:6a561e8d6713 58
eencae 0:6a561e8d6713 59 void redraw_screen()
eencae 0:6a561e8d6713 60 {
eencae 0:6a561e8d6713 61 lcd.clear();
eencae 0:6a561e8d6713 62 lcd.drawCircle(pos.x,pos.y,BALLRADIUS,1); // x,y,radius,black fill
eencae 0:6a561e8d6713 63 lcd.refresh(); // update display
eencae 0:6a561e8d6713 64 }
eencae 0:6a561e8d6713 65
eencae 0:6a561e8d6713 66 void check_collisions()
eencae 0:6a561e8d6713 67 {
eencae 0:6a561e8d6713 68 // see if ball has hit the floor (subtract the radius since the position is the centre of the ball)
eencae 0:6a561e8d6713 69 if ( pos.y >= 47 - BALLRADIUS ) {
eencae 0:6a561e8d6713 70 pos.y = 47 - BALLRADIUS; // need to force this or else ball can end up going 'underground'
eencae 0:6a561e8d6713 71 vel.y = -0.89 * vel.y; // y velocity is reflected and dampened
eencae 0:6a561e8d6713 72 // y accleration is still gravity
eencae 0:6a561e8d6713 73 }
eencae 0:6a561e8d6713 74
eencae 0:6a561e8d6713 75 // has ball gone off the right-hand side?
eencae 0:6a561e8d6713 76 if ( pos.x >= 83 - BALLRADIUS ) {
eencae 0:6a561e8d6713 77 pos.x = 83 - BALLRADIUS; // need to force this or else ball can end up going off screen
eencae 0:6a561e8d6713 78 vel.x = -0.5 * vel.x; // reflect and damp velocity
eencae 0:6a561e8d6713 79 acc.x = -acc.x; // reflect accleration
eencae 0:6a561e8d6713 80 }
eencae 0:6a561e8d6713 81
eencae 0:6a561e8d6713 82 // what about the left?
eencae 0:6a561e8d6713 83 if ( pos.x <= BALLRADIUS ) {
eencae 0:6a561e8d6713 84 pos.x = BALLRADIUS; // need to force this or else ball can end up going off screen
eencae 0:6a561e8d6713 85 vel.x = -0.5 * vel.x; // reflect and damp velocity
eencae 0:6a561e8d6713 86 acc.x = -acc.x; // reflect accleration
eencae 0:6a561e8d6713 87 }
eencae 0:6a561e8d6713 88
eencae 0:6a561e8d6713 89 }
eencae 0:6a561e8d6713 90
eencae 0:6a561e8d6713 91 void update_physics_engine()
eencae 0:6a561e8d6713 92 {
eencae 0:6a561e8d6713 93 // from Newton's Laws
eencae 0:6a561e8d6713 94
eencae 0:6a561e8d6713 95 acc.x = 0.9F*acc.x; // reduce a little due to air friction
eencae 0:6a561e8d6713 96
eencae 0:6a561e8d6713 97 // calc new velocity (assume 'unit' time)
eencae 0:6a561e8d6713 98 vel.x = vel.x + acc.x; // * g_gt;
eencae 0:6a561e8d6713 99 vel.y = vel.y + acc.y; // * g_gt;
eencae 0:6a561e8d6713 100
eencae 0:6a561e8d6713 101 // calc new position (assume 'unit' time)
eencae 0:6a561e8d6713 102 pos.x = pos.x + vel.x;// * g_gt;
eencae 0:6a561e8d6713 103 pos.y = pos.y + vel.y;// * g_dt;
eencae 0:6a561e8d6713 104
eencae 0:6a561e8d6713 105 // should really multiply the above by the time-step,
eencae 0:6a561e8d6713 106 // but since the pixel can only be a integer value,
eencae 0:6a561e8d6713 107 // it makes the motion a little 'jumpy'.
eencae 0:6a561e8d6713 108
eencae 0:6a561e8d6713 109 }
eencae 0:6a561e8d6713 110
eencae 0:6a561e8d6713 111 void init_ball()
eencae 0:6a561e8d6713 112 {
eencae 0:6a561e8d6713 113 // initial position (top-left)
eencae 0:6a561e8d6713 114 pos.x = BALLRADIUS;
eencae 0:6a561e8d6713 115 pos.y = BALLRADIUS;
eencae 0:6a561e8d6713 116 // initial velocity - still
eencae 0:6a561e8d6713 117 vel.x = 0.0;
eencae 0:6a561e8d6713 118 vel.y = 0.0;
eencae 0:6a561e8d6713 119 // initial acceleration - gravity and a bit of push to right
eencae 0:6a561e8d6713 120 acc.x = 0.5;
eencae 0:6a561e8d6713 121 acc.y = 2.0; // +ve so ball accelerates to bottom of display (top of screen is y=0, bottom is y=47)
eencae 0:6a561e8d6713 122 // should be 9.8, but can play with value to get a 'nice' ball movement
eencae 0:6a561e8d6713 123 }
eencae 0:6a561e8d6713 124
eencae 0:6a561e8d6713 125 void game_timer_isr()
eencae 0:6a561e8d6713 126 {
eencae 0:6a561e8d6713 127 g_timer_flag = 1;
eencae 0:6a561e8d6713 128 }
eencae 0:6a561e8d6713 129
eencae 0:6a561e8d6713 130 void init_display()
eencae 0:6a561e8d6713 131 {
eencae 0:6a561e8d6713 132 lcd.init();
eencae 0:6a561e8d6713 133 lcd.normalMode(); // normal colour mode
eencae 0:6a561e8d6713 134 lcd.setBrightness(0.5); // put LED backlight on 50%
eencae 0:6a561e8d6713 135 }