University project - accelerometer controlled Arkanoid

Dependencies:   KS0108 MMA8451Q mbed

Committer:
JSindelar
Date:
Sun Jan 18 19:28:22 2015 +0000
Revision:
1:d08d63a7c50d
Parent:
0:9515d58c3408
University project - accelerometer controlled Arkanoid

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JSindelar 0:9515d58c3408 1 #include "mbed.h"
JSindelar 0:9515d58c3408 2 #include "KS0108.h"
JSindelar 0:9515d58c3408 3 #include "Arial12.h"
JSindelar 0:9515d58c3408 4 #include "SystemFont5x7.h"
JSindelar 0:9515d58c3408 5 #include "stdbool.h"
JSindelar 0:9515d58c3408 6 #include "MMA8451Q.h"
JSindelar 0:9515d58c3408 7 #include <time.h>
JSindelar 0:9515d58c3408 8 #include <stdlib.h>
JSindelar 0:9515d58c3408 9 #include <math.h>
JSindelar 0:9515d58c3408 10 #include <inttypes.h>
JSindelar 0:9515d58c3408 11
JSindelar 0:9515d58c3408 12 #define minX (125)
JSindelar 0:9515d58c3408 13 #define maxX (39)
JSindelar 0:9515d58c3408 14 #define minY (2)
JSindelar 0:9515d58c3408 15 #define maxY (62)
JSindelar 0:9515d58c3408 16 #define PadLength (10)
JSindelar 0:9515d58c3408 17 #define PadY (59)
JSindelar 0:9515d58c3408 18 #define LowSpeed (2)
JSindelar 0:9515d58c3408 19 #define HighSpeed (4)
JSindelar 0:9515d58c3408 20 #define XPadInit ((uint8_t)(0.5*(minX+maxX-PadLength)))
JSindelar 0:9515d58c3408 21 #define XBallInit ((uint8_t)(XPadInit+0.5*PadLength))
JSindelar 0:9515d58c3408 22 #define BallD (1)
JSindelar 0:9515d58c3408 23 #define YBallInit ((uint8_t)(PadY-BallD))
JSindelar 0:9515d58c3408 24
JSindelar 0:9515d58c3408 25 #define BrickH (4)
JSindelar 0:9515d58c3408 26 #define BrickW (20)
JSindelar 0:9515d58c3408 27 #define columns (4)
JSindelar 0:9515d58c3408 28 #define rows (3)
JSindelar 0:9515d58c3408 29
JSindelar 0:9515d58c3408 30 #define maxangle (25)
JSindelar 0:9515d58c3408 31 #define velocity (3)
JSindelar 0:9515d58c3408 32 #define pi (3.14)
JSindelar 0:9515d58c3408 33
JSindelar 0:9515d58c3408 34 #define round(x) ((x)>=0?(int8_t)((x)+0.5):(int8_t)((x)-0.5))
JSindelar 0:9515d58c3408 35
JSindelar 0:9515d58c3408 36 #define AccTres1 (0.12)
JSindelar 0:9515d58c3408 37 #define AccTres2 (0.25)
JSindelar 0:9515d58c3408 38
JSindelar 0:9515d58c3408 39 #define MMA8451_I2C_ADDRESS (0x1d<<1)
JSindelar 0:9515d58c3408 40
JSindelar 0:9515d58c3408 41 KS0108 display (PTE22,PTE23, PTE29, PTE30, PTE20, PTE21, PTC7, PTC0, PTC3, PTC4, PTC5, PTC6, PTC10, PTC11);
JSindelar 0:9515d58c3408 42
JSindelar 0:9515d58c3408 43 //prototypes of functions
JSindelar 0:9515d58c3408 44 void DrawBorder(); //function for drawing border around gaming area
JSindelar 0:9515d58c3408 45 void DrawBall(uint8_t* X, uint8_t* Y, int8_t* dx, int8_t* dy, uint8_t D, uint8_t PaddlePos, bool* Start, uint8_t* lives); //function for drawing the ball
JSindelar 0:9515d58c3408 46 void MovePad(uint8_t* Pad_ptr, bool Start); //function for drawing the accelerometer controlled pad
JSindelar 0:9515d58c3408 47 void DrawLogo(void); //function for drawing logo
JSindelar 0:9515d58c3408 48 void DrawTable(int8_t sc, int8_t liv); //function for drawing table with score and number of lives
JSindelar 0:9515d58c3408 49 void reset(uint8_t* XBall, uint8_t* YBall, int8_t* dxBall, int8_t* dyBall, uint8_t* XPaddle, bool* Start, uint8_t *score, uint8_t *lives, uint8_t* col, uint8_t* ro, bool* Exists); //function for reset the game - after the ball was lost, game has been won or lost
JSindelar 0:9515d58c3408 50 void CreateGrid(uint8_t* col, uint8_t* ro, bool* Exists); //function for preparing the grid for array of bricks
JSindelar 0:9515d58c3408 51 void DrawBricks(uint8_t col[columns], uint8_t ro[rows], bool exists[rows*columns]); //drawing the array of bricks
JSindelar 0:9515d58c3408 52 void BounceBricks(uint8_t XBall, uint8_t YBall, int8_t* dxBall, int8_t* dyBall, bool* BrickExists, uint8_t ro[rows], uint8_t col[columns], uint8_t* score, uint8_t lives, bool* Start); //function detecting hits, erasing bricks, counting score etc...
JSindelar 0:9515d58c3408 53
JSindelar 0:9515d58c3408 54 MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
JSindelar 0:9515d58c3408 55 //main program
JSindelar 0:9515d58c3408 56 int main() {
JSindelar 0:9515d58c3408 57 srand(time(NULL)); //random seed - will be used for random reflection angle when the game starts/was reset
JSindelar 0:9515d58c3408 58 display.ClearScreen();
JSindelar 0:9515d58c3408 59
JSindelar 0:9515d58c3408 60 uint8_t score = 0; //initial score and number of lives
JSindelar 0:9515d58c3408 61 uint8_t lives = 3;
JSindelar 0:9515d58c3408 62 DrawLogo(); //drawing ARM-kanoid title
JSindelar 0:9515d58c3408 63 DrawTable(score,lives); //drawing table with score and number of lives
JSindelar 0:9515d58c3408 64 DrawBorder(); //drawing border of the playing area
JSindelar 0:9515d58c3408 65
JSindelar 0:9515d58c3408 66 uint8_t XBall = XBallInit; //initial ball position
JSindelar 0:9515d58c3408 67 uint8_t YBall = YBallInit;
JSindelar 0:9515d58c3408 68 int8_t Balldx;
JSindelar 0:9515d58c3408 69 int8_t Balldy;
JSindelar 0:9515d58c3408 70
JSindelar 0:9515d58c3408 71 uint8_t PadPos = XPadInit; //initializing position of the paddle
JSindelar 0:9515d58c3408 72 bool StartFlag = true; //start flag will be used for reseting the game
JSindelar 0:9515d58c3408 73
JSindelar 0:9515d58c3408 74 uint8_t column[columns]; //arrays of brick positions on the display - will be filled by function CreateGrid(...)
JSindelar 0:9515d58c3408 75 uint8_t row[rows];
JSindelar 0:9515d58c3408 76 bool BrickExists[columns*rows]; //array of bool flags for bricks - true = brick exists, false = brick was already destroyed... will be also filled by function CreateGrid(...)
JSindelar 0:9515d58c3408 77
JSindelar 0:9515d58c3408 78 CreateGrid(&(column[0]), &(row[0]), &(BrickExists[0])); //creating grid for bricks
JSindelar 0:9515d58c3408 79 DrawBricks(column, row, BrickExists); //drawing bricks
JSindelar 0:9515d58c3408 80
JSindelar 0:9515d58c3408 81 while(1) {
JSindelar 0:9515d58c3408 82 display.TurnOn();
JSindelar 0:9515d58c3408 83 if (StartFlag){
JSindelar 0:9515d58c3408 84 reset(&XBall, &YBall, &Balldx, &Balldy, &PadPos, &StartFlag, &score, &lives, &(column[0]), &(row[0]), &(BrickExists[0])); //reset in case lost ball, lost or won game
JSindelar 0:9515d58c3408 85 }
JSindelar 0:9515d58c3408 86 BounceBricks(XBall, YBall, &Balldx, &Balldy, &(BrickExists[0]), row, column, &score, lives, &StartFlag);
JSindelar 0:9515d58c3408 87 DrawBall(&XBall, &YBall, &Balldx, &Balldy, BallD, PadPos, &StartFlag, &lives); //function for drawing the ball, computing its movement, bounces etc.
JSindelar 0:9515d58c3408 88 MovePad(&PadPos, StartFlag); //function for paddle drawing and its control by accelerometer
JSindelar 0:9515d58c3408 89 wait(0.05); //waiting time was set empirically - according to feel about the display refresh rate
JSindelar 0:9515d58c3408 90 }
JSindelar 0:9515d58c3408 91 }
JSindelar 0:9515d58c3408 92
JSindelar 0:9515d58c3408 93 void DrawLogo(void){ //draws the logo (ARM-kanoid)
JSindelar 0:9515d58c3408 94 display.SelectFont(Arial12,BLACK,ReadData);
JSindelar 0:9515d58c3408 95 display.GotoXY(8,8);
JSindelar 0:9515d58c3408 96 display.PrintString("ARM");
JSindelar 0:9515d58c3408 97 display.GotoXY(4,24);
JSindelar 0:9515d58c3408 98 display.PrintString("kanoid");
JSindelar 0:9515d58c3408 99 }
JSindelar 0:9515d58c3408 100
JSindelar 0:9515d58c3408 101 void DrawTable(int8_t sc, int8_t liv){ //draws table with score and lives
JSindelar 0:9515d58c3408 102 static char score[5];
JSindelar 0:9515d58c3408 103 static char lives[5];
JSindelar 0:9515d58c3408 104 display.EmptyRectangle(4,38, (maxX-6),56, BLACK);
JSindelar 0:9515d58c3408 105 display.FullRectangle(20,39,(maxX-7), 55, WHITE);
JSindelar 0:9515d58c3408 106 display.SelectFont(System5x7,BLACK,ReadData);
JSindelar 0:9515d58c3408 107 sprintf(score,"S:%2d",sc);
JSindelar 0:9515d58c3408 108 sprintf(lives,"L:%2d",liv);
JSindelar 0:9515d58c3408 109 display.GotoXY(8,40);
JSindelar 0:9515d58c3408 110 display.PrintString(score);
JSindelar 0:9515d58c3408 111 display.GotoXY(8,48);
JSindelar 0:9515d58c3408 112 display.PrintString(lives);
JSindelar 0:9515d58c3408 113 }
JSindelar 0:9515d58c3408 114
JSindelar 0:9515d58c3408 115 void DrawBorder(void){ //draws border around gaming area
JSindelar 0:9515d58c3408 116 display.HLine(maxX-2, 127,0,BLACK);
JSindelar 0:9515d58c3408 117 display.VLine(maxX-2, 0,63,BLACK);
JSindelar 0:9515d58c3408 118 display.VLine(minX+2, 0,63,BLACK);
JSindelar 0:9515d58c3408 119 }
JSindelar 0:9515d58c3408 120
JSindelar 0:9515d58c3408 121 void DrawBall(uint8_t* X, uint8_t* Y, int8_t* dx, int8_t* dy, uint8_t D, uint8_t PaddlePos, bool* Start, uint8_t* lives){ //draws the ball, computes reflections from border of gaming area
JSindelar 0:9515d58c3408 122
JSindelar 0:9515d58c3408 123 display.FullCircle(*X, *Y, D, WHITE);
JSindelar 0:9515d58c3408 124
JSindelar 0:9515d58c3408 125 (*X) += (*dx);
JSindelar 0:9515d58c3408 126 (*Y) += (*dy);
JSindelar 0:9515d58c3408 127 display.FullCircle(*X, *Y, D, BLACK);
JSindelar 0:9515d58c3408 128 if ((((uint8_t)(*X+D)) >= minX)||(((int8_t)(*X-D)) <= maxX)){
JSindelar 0:9515d58c3408 129 *dx = -(*dx);
JSindelar 0:9515d58c3408 130 }
JSindelar 0:9515d58c3408 131 if (((uint8_t)(*Y-D)) <= minY){
JSindelar 0:9515d58c3408 132 *dy = -(*dy);
JSindelar 0:9515d58c3408 133 }
JSindelar 0:9515d58c3408 134 if (((int8_t)(*Y+D)) >= PadY){
JSindelar 0:9515d58c3408 135 if ((((uint8_t)(*X+D)) <= (PaddlePos+PadLength+2))&&(((uint8_t)(*X-D)) >= (PaddlePos-2))){
JSindelar 0:9515d58c3408 136 *dy = -(*dy);
JSindelar 0:9515d58c3408 137 }else{
JSindelar 0:9515d58c3408 138 *Start = true;
JSindelar 0:9515d58c3408 139 if (*lives > 0){
JSindelar 0:9515d58c3408 140 (*lives)--;
JSindelar 0:9515d58c3408 141 }
JSindelar 0:9515d58c3408 142 }
JSindelar 0:9515d58c3408 143 }
JSindelar 0:9515d58c3408 144 }
JSindelar 0:9515d58c3408 145
JSindelar 0:9515d58c3408 146 void MovePad(uint8_t* Pad_ptr, bool Start){ //drawing the accelerometer-controlled pad
JSindelar 0:9515d58c3408 147 uint8_t PaddleDif;
JSindelar 0:9515d58c3408 148 if ((abs(acc.getAccY()))>AccTres1){
JSindelar 0:9515d58c3408 149 display.FullRectangle(*Pad_ptr, PadY, *Pad_ptr+PadLength ,PadY+2,WHITE);
JSindelar 0:9515d58c3408 150 if(Start){
JSindelar 0:9515d58c3408 151 *Pad_ptr = XPadInit;
JSindelar 0:9515d58c3408 152 }else{
JSindelar 0:9515d58c3408 153 if ((abs(acc.getAccY()))>AccTres2){
JSindelar 0:9515d58c3408 154 PaddleDif = HighSpeed;
JSindelar 0:9515d58c3408 155 }else{
JSindelar 0:9515d58c3408 156 PaddleDif = LowSpeed;
JSindelar 0:9515d58c3408 157 }
JSindelar 0:9515d58c3408 158 if ((acc.getAccY() > 0)&&((*Pad_ptr+PadLength) < (minX - 3))){
JSindelar 0:9515d58c3408 159 *Pad_ptr += PaddleDif;
JSindelar 0:9515d58c3408 160 }
JSindelar 0:9515d58c3408 161 if ((acc.getAccY() < 0)&&(*Pad_ptr > (maxX + 1))){
JSindelar 0:9515d58c3408 162 *Pad_ptr -= PaddleDif;
JSindelar 0:9515d58c3408 163 }
JSindelar 0:9515d58c3408 164 }
JSindelar 0:9515d58c3408 165 }
JSindelar 0:9515d58c3408 166 display.FullRectangle(*Pad_ptr, PadY, *Pad_ptr+PadLength ,PadY+2,BLACK);
JSindelar 0:9515d58c3408 167 }
JSindelar 0:9515d58c3408 168
JSindelar 0:9515d58c3408 169 void reset(uint8_t* XBall, uint8_t* YBall, int8_t* dxBall, int8_t* dyBall, uint8_t* XPaddle, bool* Start, uint8_t *score, uint8_t *lives, uint8_t* col, uint8_t* ro, bool* Exists){ //resets the game in case of lost ball, lost or won game
JSindelar 0:9515d58c3408 170 display.FullCircle(*XBall, *YBall, BallD, WHITE);
JSindelar 0:9515d58c3408 171 *XBall = XBallInit;
JSindelar 0:9515d58c3408 172 *YBall = YBallInit;
JSindelar 0:9515d58c3408 173 display.FullRectangle(*XPaddle, PadY, *XPaddle+PadLength ,PadY+2,WHITE);
JSindelar 0:9515d58c3408 174 *XPaddle = XPadInit;
JSindelar 0:9515d58c3408 175 wait(1);
JSindelar 0:9515d58c3408 176 if (*score == (rows*columns)){
JSindelar 0:9515d58c3408 177 display.ClearScreen();
JSindelar 0:9515d58c3408 178 display.GotoXY(32,32);
JSindelar 0:9515d58c3408 179 display.PrintString("YOU WIN!!!");
JSindelar 0:9515d58c3408 180 wait(3);
JSindelar 0:9515d58c3408 181 *score = 0;
JSindelar 0:9515d58c3408 182 *lives = 3;
JSindelar 0:9515d58c3408 183 display.ClearScreen();
JSindelar 0:9515d58c3408 184 DrawLogo(); //drawing ARM-kanoid title
JSindelar 0:9515d58c3408 185 DrawTable(*score,*lives); //drawing table with score and number of lives
JSindelar 0:9515d58c3408 186 DrawBorder(); //drawing border of the playing area
JSindelar 0:9515d58c3408 187 CreateGrid(&(*col), &(*ro), &(*Exists));
JSindelar 0:9515d58c3408 188 DrawBricks(col, ro, Exists);
JSindelar 0:9515d58c3408 189 }else if (*lives <= 0){
JSindelar 0:9515d58c3408 190 display.ClearScreen();
JSindelar 0:9515d58c3408 191 display.GotoXY(32,32);
JSindelar 0:9515d58c3408 192 display.PrintString("GAME OVER!!!");
JSindelar 0:9515d58c3408 193 wait(3);
JSindelar 0:9515d58c3408 194 *score = 0;
JSindelar 0:9515d58c3408 195 *lives = 3;
JSindelar 0:9515d58c3408 196 display.ClearScreen();
JSindelar 0:9515d58c3408 197 DrawLogo(); //drawing ARM-kanoid title
JSindelar 0:9515d58c3408 198 DrawTable(*score,*lives); //drawing table with score and number of lives
JSindelar 0:9515d58c3408 199 DrawBorder(); //drawing border of the playing area
JSindelar 0:9515d58c3408 200 CreateGrid(&(*col), &(*ro), &(*Exists));
JSindelar 0:9515d58c3408 201 DrawBricks(col, ro, Exists);
JSindelar 0:9515d58c3408 202
JSindelar 0:9515d58c3408 203 }else{
JSindelar 0:9515d58c3408 204 display.FullCircle(*XBall, *YBall, BallD, BLACK);
JSindelar 0:9515d58c3408 205 display.FullRectangle(*XPaddle, PadY, *XPaddle+PadLength ,PadY+2,BLACK);
JSindelar 0:9515d58c3408 206 DrawTable(*score, *lives);
JSindelar 0:9515d58c3408 207 float angle = (pi/180)*(90+(rand()%(2*maxangle)));
JSindelar 0:9515d58c3408 208 *dxBall = (round(velocity*cos(angle)));
JSindelar 0:9515d58c3408 209 if (*dxBall == 0){
JSindelar 0:9515d58c3408 210 *dxBall = 1;
JSindelar 0:9515d58c3408 211 }
JSindelar 0:9515d58c3408 212 *dyBall = (-round(velocity*sin(angle)));
JSindelar 0:9515d58c3408 213 display.GotoXY(0,0);
JSindelar 0:9515d58c3408 214 display.PrintNumber(*dxBall);
JSindelar 0:9515d58c3408 215 display.GotoXY(15,0);
JSindelar 0:9515d58c3408 216 display.PrintNumber(*dyBall);
JSindelar 0:9515d58c3408 217 wait(1);
JSindelar 0:9515d58c3408 218 *Start = false;
JSindelar 0:9515d58c3408 219 }
JSindelar 0:9515d58c3408 220 }
JSindelar 0:9515d58c3408 221
JSindelar 0:9515d58c3408 222 void CreateGrid(uint8_t* col, uint8_t* ro, bool* exists){ //creates grid that will be later used for drawing bricks
JSindelar 0:9515d58c3408 223 int8_t i;
JSindelar 0:9515d58c3408 224 for (i = 0; i < columns; i++){
JSindelar 0:9515d58c3408 225 *(col+i) = maxX + i*(BrickW + 2);
JSindelar 0:9515d58c3408 226 }
JSindelar 0:9515d58c3408 227 for (i = 0; i < rows; i++){
JSindelar 0:9515d58c3408 228 *(ro+i) = minY + i*(BrickH + 2);
JSindelar 0:9515d58c3408 229 }
JSindelar 0:9515d58c3408 230 int8_t j;
JSindelar 0:9515d58c3408 231 for (i = 0; i < rows; i++){
JSindelar 0:9515d58c3408 232 for (j = 0; j < columns; j++){
JSindelar 0:9515d58c3408 233 *(exists+i*columns+j)=true;
JSindelar 0:9515d58c3408 234 }
JSindelar 0:9515d58c3408 235 }
JSindelar 0:9515d58c3408 236 }
JSindelar 0:9515d58c3408 237
JSindelar 0:9515d58c3408 238 void DrawBricks(uint8_t col[columns], uint8_t ro[rows], bool exists[rows*columns]){ //draws bricks in prepared grid - these two functions are separated in case of creating another levels
JSindelar 0:9515d58c3408 239
JSindelar 0:9515d58c3408 240 int8_t i;
JSindelar 0:9515d58c3408 241 int8_t j;
JSindelar 0:9515d58c3408 242 for (j = 0; j < rows; j++){
JSindelar 0:9515d58c3408 243 for (i = 0; i < columns; i++){
JSindelar 0:9515d58c3408 244 display.FullRectangle(col[i], ro[j], (col[i] + BrickW), (ro[j] + BrickH) ,((exists[j*columns+i])? BLACK:WHITE));
JSindelar 0:9515d58c3408 245 }
JSindelar 0:9515d58c3408 246 }
JSindelar 0:9515d58c3408 247 }
JSindelar 0:9515d58c3408 248
JSindelar 0:9515d58c3408 249 void BounceBricks(uint8_t XBall, uint8_t YBall, int8_t* dxBall, int8_t* dyBall, bool* BrickExists, uint8_t ro[rows], uint8_t col[columns], uint8_t* score, uint8_t lives, bool* Start){ //computes reflections from bricks, destroys bricks, counts score etc...
JSindelar 0:9515d58c3408 250 if (YBall <= (ro[rows-1]+BrickH)){
JSindelar 0:9515d58c3408 251 int8_t i, j;
JSindelar 0:9515d58c3408 252 for (j = rows - 1; j >= 0; j--){
JSindelar 0:9515d58c3408 253 if (((YBall-BallD) <= (ro[j]+BrickH))&&((YBall+BallD) > ro[j])){
JSindelar 0:9515d58c3408 254 break;
JSindelar 0:9515d58c3408 255 }
JSindelar 0:9515d58c3408 256 }
JSindelar 0:9515d58c3408 257 for (i = columns - 1; i >= 0; i--){
JSindelar 0:9515d58c3408 258 if (((XBall-BallD) <= (col[i]+BrickW))&&((XBall+BallD) > col[i])){
JSindelar 0:9515d58c3408 259 break;
JSindelar 0:9515d58c3408 260 }
JSindelar 0:9515d58c3408 261 }
JSindelar 0:9515d58c3408 262 if (*(BrickExists+j*columns+i)){
JSindelar 0:9515d58c3408 263 *(BrickExists+j*columns+i) = false;
JSindelar 0:9515d58c3408 264 display.FullRectangle(col[i], ro[j], (col[i] + BrickW), (ro[j] + BrickH), WHITE);
JSindelar 0:9515d58c3408 265 (*score)++;
JSindelar 0:9515d58c3408 266 if (*score == (rows*columns)){
JSindelar 0:9515d58c3408 267 *Start = true;
JSindelar 0:9515d58c3408 268 }
JSindelar 0:9515d58c3408 269 DrawTable(*score, lives);
JSindelar 0:9515d58c3408 270 if (!((YBall-*dyBall) <= (minY))){
JSindelar 0:9515d58c3408 271 *dyBall = -(*dyBall);
JSindelar 0:9515d58c3408 272 }
JSindelar 0:9515d58c3408 273 }else{
JSindelar 0:9515d58c3408 274 if ((YBall-BallD) <= (minY+1)){
JSindelar 0:9515d58c3408 275 *dyBall = -(*dyBall);
JSindelar 0:9515d58c3408 276 }
JSindelar 0:9515d58c3408 277 }
JSindelar 0:9515d58c3408 278 }
JSindelar 0:9515d58c3408 279 }