University project - accelerometer controlled Arkanoid
Dependencies: KS0108 MMA8451Q mbed
main.cpp
- Committer:
- JSindelar
- Date:
- 2015-01-18
- Revision:
- 1:d08d63a7c50d
- Parent:
- 0:9515d58c3408
File content as of revision 1:d08d63a7c50d:
#include "mbed.h" #include "KS0108.h" #include "Arial12.h" #include "SystemFont5x7.h" #include "stdbool.h" #include "MMA8451Q.h" #include <time.h> #include <stdlib.h> #include <math.h> #include <inttypes.h> #define minX (125) #define maxX (39) #define minY (2) #define maxY (62) #define PadLength (10) #define PadY (59) #define LowSpeed (2) #define HighSpeed (4) #define XPadInit ((uint8_t)(0.5*(minX+maxX-PadLength))) #define XBallInit ((uint8_t)(XPadInit+0.5*PadLength)) #define BallD (1) #define YBallInit ((uint8_t)(PadY-BallD)) #define BrickH (4) #define BrickW (20) #define columns (4) #define rows (3) #define maxangle (25) #define velocity (3) #define pi (3.14) #define round(x) ((x)>=0?(int8_t)((x)+0.5):(int8_t)((x)-0.5)) #define AccTres1 (0.12) #define AccTres2 (0.25) #define MMA8451_I2C_ADDRESS (0x1d<<1) KS0108 display (PTE22,PTE23, PTE29, PTE30, PTE20, PTE21, PTC7, PTC0, PTC3, PTC4, PTC5, PTC6, PTC10, PTC11); //prototypes of functions void DrawBorder(); //function for drawing border around gaming area 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 void MovePad(uint8_t* Pad_ptr, bool Start); //function for drawing the accelerometer controlled pad void DrawLogo(void); //function for drawing logo void DrawTable(int8_t sc, int8_t liv); //function for drawing table with score and number of lives 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 void CreateGrid(uint8_t* col, uint8_t* ro, bool* Exists); //function for preparing the grid for array of bricks void DrawBricks(uint8_t col[columns], uint8_t ro[rows], bool exists[rows*columns]); //drawing the array of bricks 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... MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); //main program int main() { srand(time(NULL)); //random seed - will be used for random reflection angle when the game starts/was reset display.ClearScreen(); uint8_t score = 0; //initial score and number of lives uint8_t lives = 3; DrawLogo(); //drawing ARM-kanoid title DrawTable(score,lives); //drawing table with score and number of lives DrawBorder(); //drawing border of the playing area uint8_t XBall = XBallInit; //initial ball position uint8_t YBall = YBallInit; int8_t Balldx; int8_t Balldy; uint8_t PadPos = XPadInit; //initializing position of the paddle bool StartFlag = true; //start flag will be used for reseting the game uint8_t column[columns]; //arrays of brick positions on the display - will be filled by function CreateGrid(...) uint8_t row[rows]; 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(...) CreateGrid(&(column[0]), &(row[0]), &(BrickExists[0])); //creating grid for bricks DrawBricks(column, row, BrickExists); //drawing bricks while(1) { display.TurnOn(); if (StartFlag){ reset(&XBall, &YBall, &Balldx, &Balldy, &PadPos, &StartFlag, &score, &lives, &(column[0]), &(row[0]), &(BrickExists[0])); //reset in case lost ball, lost or won game } BounceBricks(XBall, YBall, &Balldx, &Balldy, &(BrickExists[0]), row, column, &score, lives, &StartFlag); DrawBall(&XBall, &YBall, &Balldx, &Balldy, BallD, PadPos, &StartFlag, &lives); //function for drawing the ball, computing its movement, bounces etc. MovePad(&PadPos, StartFlag); //function for paddle drawing and its control by accelerometer wait(0.05); //waiting time was set empirically - according to feel about the display refresh rate } } void DrawLogo(void){ //draws the logo (ARM-kanoid) display.SelectFont(Arial12,BLACK,ReadData); display.GotoXY(8,8); display.PrintString("ARM"); display.GotoXY(4,24); display.PrintString("kanoid"); } void DrawTable(int8_t sc, int8_t liv){ //draws table with score and lives static char score[5]; static char lives[5]; display.EmptyRectangle(4,38, (maxX-6),56, BLACK); display.FullRectangle(20,39,(maxX-7), 55, WHITE); display.SelectFont(System5x7,BLACK,ReadData); sprintf(score,"S:%2d",sc); sprintf(lives,"L:%2d",liv); display.GotoXY(8,40); display.PrintString(score); display.GotoXY(8,48); display.PrintString(lives); } void DrawBorder(void){ //draws border around gaming area display.HLine(maxX-2, 127,0,BLACK); display.VLine(maxX-2, 0,63,BLACK); display.VLine(minX+2, 0,63,BLACK); } 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 display.FullCircle(*X, *Y, D, WHITE); (*X) += (*dx); (*Y) += (*dy); display.FullCircle(*X, *Y, D, BLACK); if ((((uint8_t)(*X+D)) >= minX)||(((int8_t)(*X-D)) <= maxX)){ *dx = -(*dx); } if (((uint8_t)(*Y-D)) <= minY){ *dy = -(*dy); } if (((int8_t)(*Y+D)) >= PadY){ if ((((uint8_t)(*X+D)) <= (PaddlePos+PadLength+2))&&(((uint8_t)(*X-D)) >= (PaddlePos-2))){ *dy = -(*dy); }else{ *Start = true; if (*lives > 0){ (*lives)--; } } } } void MovePad(uint8_t* Pad_ptr, bool Start){ //drawing the accelerometer-controlled pad uint8_t PaddleDif; if ((abs(acc.getAccY()))>AccTres1){ display.FullRectangle(*Pad_ptr, PadY, *Pad_ptr+PadLength ,PadY+2,WHITE); if(Start){ *Pad_ptr = XPadInit; }else{ if ((abs(acc.getAccY()))>AccTres2){ PaddleDif = HighSpeed; }else{ PaddleDif = LowSpeed; } if ((acc.getAccY() > 0)&&((*Pad_ptr+PadLength) < (minX - 3))){ *Pad_ptr += PaddleDif; } if ((acc.getAccY() < 0)&&(*Pad_ptr > (maxX + 1))){ *Pad_ptr -= PaddleDif; } } } display.FullRectangle(*Pad_ptr, PadY, *Pad_ptr+PadLength ,PadY+2,BLACK); } 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 display.FullCircle(*XBall, *YBall, BallD, WHITE); *XBall = XBallInit; *YBall = YBallInit; display.FullRectangle(*XPaddle, PadY, *XPaddle+PadLength ,PadY+2,WHITE); *XPaddle = XPadInit; wait(1); if (*score == (rows*columns)){ display.ClearScreen(); display.GotoXY(32,32); display.PrintString("YOU WIN!!!"); wait(3); *score = 0; *lives = 3; display.ClearScreen(); DrawLogo(); //drawing ARM-kanoid title DrawTable(*score,*lives); //drawing table with score and number of lives DrawBorder(); //drawing border of the playing area CreateGrid(&(*col), &(*ro), &(*Exists)); DrawBricks(col, ro, Exists); }else if (*lives <= 0){ display.ClearScreen(); display.GotoXY(32,32); display.PrintString("GAME OVER!!!"); wait(3); *score = 0; *lives = 3; display.ClearScreen(); DrawLogo(); //drawing ARM-kanoid title DrawTable(*score,*lives); //drawing table with score and number of lives DrawBorder(); //drawing border of the playing area CreateGrid(&(*col), &(*ro), &(*Exists)); DrawBricks(col, ro, Exists); }else{ display.FullCircle(*XBall, *YBall, BallD, BLACK); display.FullRectangle(*XPaddle, PadY, *XPaddle+PadLength ,PadY+2,BLACK); DrawTable(*score, *lives); float angle = (pi/180)*(90+(rand()%(2*maxangle))); *dxBall = (round(velocity*cos(angle))); if (*dxBall == 0){ *dxBall = 1; } *dyBall = (-round(velocity*sin(angle))); display.GotoXY(0,0); display.PrintNumber(*dxBall); display.GotoXY(15,0); display.PrintNumber(*dyBall); wait(1); *Start = false; } } void CreateGrid(uint8_t* col, uint8_t* ro, bool* exists){ //creates grid that will be later used for drawing bricks int8_t i; for (i = 0; i < columns; i++){ *(col+i) = maxX + i*(BrickW + 2); } for (i = 0; i < rows; i++){ *(ro+i) = minY + i*(BrickH + 2); } int8_t j; for (i = 0; i < rows; i++){ for (j = 0; j < columns; j++){ *(exists+i*columns+j)=true; } } } 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 int8_t i; int8_t j; for (j = 0; j < rows; j++){ for (i = 0; i < columns; i++){ display.FullRectangle(col[i], ro[j], (col[i] + BrickW), (ro[j] + BrickH) ,((exists[j*columns+i])? BLACK:WHITE)); } } } 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... if (YBall <= (ro[rows-1]+BrickH)){ int8_t i, j; for (j = rows - 1; j >= 0; j--){ if (((YBall-BallD) <= (ro[j]+BrickH))&&((YBall+BallD) > ro[j])){ break; } } for (i = columns - 1; i >= 0; i--){ if (((XBall-BallD) <= (col[i]+BrickW))&&((XBall+BallD) > col[i])){ break; } } if (*(BrickExists+j*columns+i)){ *(BrickExists+j*columns+i) = false; display.FullRectangle(col[i], ro[j], (col[i] + BrickW), (ro[j] + BrickH), WHITE); (*score)++; if (*score == (rows*columns)){ *Start = true; } DrawTable(*score, lives); if (!((YBall-*dyBall) <= (minY))){ *dyBall = -(*dyBall); } }else{ if ((YBall-BallD) <= (minY+1)){ *dyBall = -(*dyBall); } } } }