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.
MainTask_SpaceEvader.c
00001 /********************************************************************* 00002 * SEGGER Microcontroller GmbH * 00003 * Solutions for real time microcontroller applications * 00004 ********************************************************************** 00005 * * 00006 * (c) 1996 - 2018 SEGGER Microcontroller GmbH * 00007 * * 00008 * Internet: www.segger.com Support: support@segger.com * 00009 * * 00010 ********************************************************************** 00011 00012 ** emWin V5.48 - Graphical user interface for embedded applications ** 00013 All Intellectual Property rights in the Software belongs to SEGGER. 00014 emWin is protected by international copyright laws. Knowledge of the 00015 source code may not be used to write a similar product. This file may 00016 only be used in accordance with the following terms: 00017 00018 The software has been licensed to Cypress Semiconductor Corporation, 00019 whose registered office is situated at 198 Champion Ct. San Jose, CA 00020 95134 USA solely for the purposes of creating libraries for Cypress 00021 PSoC3 and PSoC5 processor-based devices, sublicensed and distributed 00022 under the terms and conditions of the Cypress End User License 00023 Agreement. 00024 Full source code is available at: www.segger.com 00025 00026 We appreciate your understanding and fairness. 00027 ---------------------------------------------------------------------- 00028 Licensing information 00029 Licensor: SEGGER Microcontroller Systems LLC 00030 Licensed to: Cypress Semiconductor Corp, 198 Champion Ct., San Jose, CA 95134, USA 00031 Licensed SEGGER software: emWin 00032 License number: GUI-00319 00033 License model: Services and License Agreement, signed June 10th, 2009 00034 Licensed platform: Any Cypress platform (Initial targets are: PSoC3, PSoC5) 00035 ---------------------------------------------------------------------- 00036 Support and Update Agreement (SUA) 00037 SUA period: 2009-06-12 - 2022-07-27 00038 Contact to extend SUA: sales@segger.com 00039 ---------------------------------------------------------------------- 00040 File : MainTask_SpaceEvader.c 00041 Purpose : Spaceship game, evade the asteroids. 00042 ---------------------------END-OF-HEADER------------------------------ 00043 */ 00044 00045 #include "GUI.h" 00046 #include "GUI_Private.h" 00047 #include "WM.h" 00048 00049 #include "stdlib.h" 00050 00051 /********************************************************************* 00052 * 00053 * External dependencies 00054 * 00055 ********************************************************************** 00056 */ 00057 extern GUI_CONST_STORAGE GUI_BITMAP bmSpaceShipTop_Small; 00058 extern GUI_CONST_STORAGE GUI_BITMAP bmSpaceShipLeft_Small; 00059 extern GUI_CONST_STORAGE GUI_BITMAP bmSpaceShipRight_Small; 00060 extern GUI_CONST_STORAGE GUI_BITMAP bmSpaceShipBottom_Small; 00061 extern GUI_CONST_STORAGE GUI_BITMAP bmSpaceShip; 00062 extern GUI_CONST_STORAGE GUI_BITMAP bmAsteroid; 00063 extern GUI_CONST_STORAGE GUI_BITMAP bmBang; 00064 00065 /********************************************************************* 00066 * 00067 * Defines 00068 * 00069 ********************************************************************** 00070 */ 00071 00072 #define XSIZE_DISPLAY LCD_GetXSize() 00073 #define YSIZE_DISPLAY LCD_GetYSize() 00074 00075 #define PERIOD_GAME 20000 00076 #define PERIOD_INTRO 2000 00077 00078 #define YSIZE_BAR 12 00079 00080 #define DIR_NONE 0 00081 #define DIR_LEFT 1 00082 #define DIR_RIGHT 2 00083 00084 #define CONTROL_TYPE_PID 0 00085 #define CONTROL_TYPE_JOY 1 00086 #define CONTROL_TYPE CONTROL_TYPE_PID 00087 00088 /********************************************************************* 00089 * 00090 * Types 00091 * 00092 ********************************************************************** 00093 */ 00094 typedef struct { 00095 int xPos; 00096 int yPos; 00097 GUI_CONST_STORAGE GUI_BITMAP * pBitmap; 00098 } SHIP; 00099 00100 typedef struct { 00101 int xPos; 00102 int yPos; 00103 } ASTEROID; 00104 00105 /********************************************************************* 00106 * 00107 * Static code 00108 * 00109 ********************************************************************** 00110 */ 00111 /********************************************************************* 00112 * 00113 * _GetDirection() 00114 * 00115 * Function description: 00116 * This function returns the direction the space ship should fly. 00117 * It might be necessary to adapt this function depending on the 00118 * hardware used. 00119 * 00120 * CONTROL_TYPE_PID: 00121 * Use the PID input to move the ship left or right. The ship 00122 * will move to the left if clicked left of the ship and to the 00123 * right if clicked right of it. 00124 * 00125 * CONTROL_TYPE_JOY: 00126 * Use this if the pid buffer gets filled by a joystick. 00127 * If State.x is bigger than 0 the stick is pushed to the right. 00128 * If State.x is smaler than 0 the stick is pushed to the left. 00129 * This was originally for the SEGGER emPower evaluation board. 00130 */ 00131 static int _GetDirection(SHIP * pShip) { 00132 #if (CONTROL_TYPE == CONTROL_TYPE_PID) 00133 // 00134 // CONTROL_TYPE_PID 00135 // 00136 GUI_PID_STATE State; 00137 int Direction; 00138 int Center; 00139 00140 GUI_PID_GetState(&State); // Get the current PID state 00141 Direction = DIR_NONE; 00142 if (pShip) { // If we have a ship 00143 if (State.Pressed) { // Check if it is pressed 00144 Center = pShip->xPos + pShip->pBitmap->XSize / 2; // If pressed get the center of the ship 00145 if (State.x > Center) { // Pressed right of the ship 00146 Direction = DIR_RIGHT; 00147 } else if (State.x < Center) { // Pressed left of the ship 00148 Direction = DIR_LEFT; 00149 } 00150 } 00151 } else { // We have no ship 00152 if (State.Pressed == 1) { // Anyway, if pressed return a value 00153 Direction = DIR_LEFT; 00154 } 00155 } 00156 return Direction; 00157 #elif (CONTROL_TYPE == CONTROL_TYPE_JOY) 00158 // 00159 // CONTROL_TYPE_KEY 00160 // 00161 GUI_PID_STATE State; 00162 int Direction; 00163 00164 GUI_PID_GetState(&State); // Get the current PID state 00165 if (pShip) { // If we have a ship 00166 if (State.x > 0) { // Pressed right of the ship 00167 Direction = DIR_RIGHT; 00168 } else if (State.x < 0) { // Pressed left of the ship 00169 Direction = DIR_LEFT; 00170 } else { 00171 Direction = DIR_NONE; // No pressed state 00172 } 00173 } else { // We have no ship 00174 if (State.x != 0) { // Anyway, if pressed return a value 00175 Direction = DIR_LEFT; 00176 } else { 00177 Direction = DIR_NONE; 00178 } 00179 } 00180 return Direction; 00181 #endif 00182 } 00183 00184 /********************************************************************* 00185 * 00186 * _Game() 00187 */ 00188 static void _Game(SHIP * pShip) { 00189 int Direction; 00190 // 00191 // Clear previous shape 00192 // 00193 GUI_ClearRect(pShip->xPos, pShip->yPos, pShip->xPos + pShip->pBitmap->XSize - 1, pShip->yPos + pShip->pBitmap->YSize - 1); 00194 // 00195 // Check which direction 00196 // 00197 Direction = _GetDirection(pShip); 00198 switch (Direction) { 00199 case DIR_RIGHT: 00200 // 00201 // Set the proper bitmap 00202 // 00203 pShip->pBitmap = &bmSpaceShipRight_Small; 00204 // 00205 // Clear a rectangle left of the bitmap 00206 // 00207 GUI_ClearRect(pShip->xPos, pShip->yPos, 00208 pShip->xPos + 5, pShip->yPos + bmSpaceShipTop_Small.YSize); 00209 // 00210 // Set new x-position 00211 // 00212 pShip->xPos += (pShip->xPos + 5 < LCD_GetXSize() - bmSpaceShipTop_Small.XSize) ? 5 : 0; 00213 break; 00214 case DIR_LEFT: 00215 // 00216 // Set the proper bitmap 00217 // 00218 pShip->pBitmap = &bmSpaceShipLeft_Small; 00219 // 00220 // Clear a rectangle left of the bitmap 00221 // 00222 GUI_ClearRect(pShip->xPos + bmSpaceShipTop_Small.XSize - 5, pShip->yPos, 00223 pShip->xPos + bmSpaceShipTop_Small.XSize, pShip->yPos + bmSpaceShipTop_Small.YSize); 00224 // 00225 // Set new x-position 00226 // 00227 pShip->xPos -= (pShip->xPos - 5 > 0) ? 5 : 0; 00228 break; 00229 default: 00230 // 00231 // No button is pressed, set the default bitmap 00232 // 00233 pShip->pBitmap = &bmSpaceShipTop_Small; 00234 break; 00235 } 00236 // 00237 // Draw bitmap 00238 // 00239 GUI_DrawBitmap(pShip->pBitmap, pShip->xPos, pShip->yPos); 00240 } 00241 00242 /********************************************************************* 00243 * 00244 * _Asteroid() 00245 */ 00246 static void _Asteroid(ASTEROID * pAsteroid) { 00247 // 00248 // Clear a rectangle above the bitmap 00249 // 00250 GUI_ClearRect(pAsteroid->xPos, pAsteroid->yPos, 00251 pAsteroid->xPos + bmAsteroid.XSize, pAsteroid->yPos + 10); 00252 // 00253 // Set a new y-position 00254 // 00255 pAsteroid->yPos += 5; 00256 // 00257 // Draw the bitmap 00258 // 00259 GUI_DrawBitmap(&bmAsteroid, pAsteroid->xPos, pAsteroid->yPos); 00260 // 00261 // If the bitmap is no longer visible, set a new x- and y-position 00262 // 00263 if (pAsteroid->yPos >= LCD_GetYSize()) { 00264 pAsteroid->xPos = rand() % (XSIZE_DISPLAY - bmAsteroid.XSize); 00265 pAsteroid->yPos = -((int)bmAsteroid.YSize); 00266 } 00267 } 00268 00269 /********************************************************************* 00270 * 00271 * _CheckCollision() 00272 */ 00273 static int _CheckCollision(ASTEROID * pAsteroid, ASTEROID * pAsteroid2, SHIP * pShip) { 00274 GUI_RECT RectShip, RectAsteroid; 00275 int xPos, yPos; 00276 int i, r; 00277 LCD_PIXELINDEX Index; 00278 00279 r = 0; 00280 RectShip.x0 = pShip->xPos; 00281 RectShip.y0 = pShip->yPos; 00282 RectShip.x1 = RectShip.x0 + pShip->pBitmap->XSize - 1; 00283 RectShip.y1 = RectShip.y0 + pShip->pBitmap->YSize - 1; 00284 RectAsteroid.x0 = pAsteroid->xPos; 00285 RectAsteroid.y0 = pAsteroid->yPos; 00286 RectAsteroid.x1 = RectAsteroid.x0 + bmAsteroid.XSize - 1; 00287 RectAsteroid.y1 = RectAsteroid.y0 + bmAsteroid.YSize - 1; 00288 // 00289 // First a simple check if rectangles of bitmaps overlap 00290 // 00291 if (GUI_RectsIntersect(&RectShip, &RectAsteroid)) { 00292 // 00293 // Check if lower row of asteroid collides with plane 00294 // 00295 yPos = RectAsteroid.y0 - RectShip.y0 + bmAsteroid.YSize - 1; 00296 if (yPos < pShip->pBitmap->XSize) { 00297 for (i = 0; i < bmAsteroid.XSize; i++) { 00298 xPos = RectAsteroid.x0 - RectShip.x0 + i; 00299 if ((xPos >= 0) && (xPos < pShip->pBitmap->XSize)) { 00300 Index = GUI_GetBitmapPixelIndex(pShip->pBitmap, xPos, yPos); 00301 if ((Index > 0) && (Index < 255)) { 00302 GUI_Clear(); 00303 GUI_DrawBitmap(&bmBang, 0, 20); 00304 LCD_ControlCache(LCD_CC_UNLOCK); 00305 LCD_ControlCache(LCD_CC_LOCK); 00306 GUI_Delay(1000); 00307 GUI_Clear(); 00308 pAsteroid->yPos = pAsteroid2->yPos - YSIZE_DISPLAY / 2; 00309 r = 1; 00310 break; 00311 } 00312 } 00313 } 00314 } 00315 } 00316 return r; 00317 } 00318 00319 /********************************************************************* 00320 * 00321 * _ShowTitle 00322 */ 00323 static void _ShowTitle(void) { 00324 GUI_Clear(); 00325 GUI_DispStringHCenterAt("emWin Space Evader", XSIZE_DISPLAY / 2, 2); 00326 GUI_DrawHLine(YSIZE_BAR - 1, 0, XSIZE_DISPLAY - 1); 00327 } 00328 00329 /********************************************************************* 00330 * 00331 * _Intro() 00332 */ 00333 static void _Intro(void) { 00334 int t0, tEnd, tNow, tUsed; 00335 int yPos; 00336 00337 _ShowTitle(); 00338 t0 = GUI_GetTime(); 00339 tEnd = t0 + PERIOD_INTRO; 00340 do { 00341 tNow = GUI_GetTime(); 00342 tUsed = tNow - t0; 00343 tUsed = (tUsed > PERIOD_INTRO) ? PERIOD_INTRO : tUsed; 00344 yPos = YSIZE_DISPLAY - (tUsed * (YSIZE_DISPLAY - YSIZE_BAR)) / PERIOD_INTRO; 00345 GUI_DrawBitmap(&bmSpaceShip, (XSIZE_DISPLAY - bmSpaceShip.XSize) / 2, yPos); 00346 } while (tNow < tEnd); 00347 GUI_Delay(1000); 00348 GUI_Clear(); 00349 } 00350 00351 /********************************************************************* 00352 * 00353 * _Explain() 00354 */ 00355 static void _Explain(void) { 00356 int yPos, ySizeFont; 00357 unsigned i; 00358 const char * apText[] = { 00359 "Use buttons PB0", 00360 "and PB1 for moving", 00361 "the starship.", 00362 "", 00363 "Remaining time is", 00364 "shown in the the", 00365 "lower right edge", 00366 "of the display.", 00367 }; 00368 int Direction; 00369 00370 _ShowTitle(); 00371 ySizeFont = GUI_GetFontSizeY() + 2; 00372 yPos = (YSIZE_DISPLAY - ySizeFont * GUI_COUNTOF(apText)) / 2; 00373 for (i = 0; i < GUI_COUNTOF(apText); i++) { 00374 GUI_DispStringHCenterAt(apText[i], XSIZE_DISPLAY / 2, yPos); 00375 yPos += ySizeFont; 00376 } 00377 GUI_DispStringHCenterAt("PRESS BUTTON TO START", XSIZE_DISPLAY / 2, YSIZE_DISPLAY - 10); 00378 do { 00379 Direction = _GetDirection(NULL); 00380 if (Direction) { 00381 break; 00382 } 00383 GUI_X_Delay(10); 00384 } while (1); 00385 GUI_Clear(); 00386 GUI_DispStringHCenterAt("Good luck...", XSIZE_DISPLAY / 2, YSIZE_DISPLAY / 2 - 4); 00387 GUI_Delay(1000); 00388 GUI_Clear(); 00389 } 00390 00391 /********************************************************************* 00392 * 00393 * _ShowResult 00394 */ 00395 static void _ShowResult(unsigned Cnt) { 00396 _ShowTitle(); 00397 if (Cnt) { 00398 GUI_DispStringHCenterAt("Ships lost in space:\n\n", XSIZE_DISPLAY / 2, YSIZE_DISPLAY / 2 - 10); 00399 GUI_GotoXY(XSIZE_DISPLAY / 2 - 4, YSIZE_DISPLAY / 2); 00400 GUI_DispDecMin(Cnt); 00401 } else { 00402 GUI_DispStringHCenterAt("CONGRATULATIONS\n\nNo ship lost", XSIZE_DISPLAY / 2, YSIZE_DISPLAY / 2 - 10); 00403 } 00404 GUI_Delay(2000); 00405 } 00406 00407 /********************************************************************* 00408 * 00409 * Public code 00410 * 00411 ********************************************************************** 00412 */ 00413 /********************************************************************* 00414 * 00415 * MainTask() 00416 */ 00417 void MainTask(void) { 00418 SHIP Ship; 00419 ASTEROID aAsteroid[2]; 00420 unsigned i, Cnt; 00421 GUI_TIMER_TIME t0, tEnd, tNow; 00422 00423 // 00424 // Initialize GUI 00425 // 00426 GUI_Init(); 00427 // 00428 // Set foreground color to black 00429 // 00430 GUI_SetColor(GUI_BLACK); 00431 GUI_SetBkColor(GUI_WHITE); 00432 // 00433 // Explanation 00434 // 00435 _Explain(); 00436 // 00437 // Run forever... 00438 // 00439 while (1) { 00440 // 00441 // Initialize some structures 00442 // 00443 Ship.xPos = (XSIZE_DISPLAY - bmSpaceShipTop_Small.XSize) / 2; 00444 Ship.yPos = YSIZE_DISPLAY - bmSpaceShipTop_Small.YSize - 5; 00445 Ship.pBitmap = &bmSpaceShipTop_Small; 00446 for (i = 0; i < GUI_COUNTOF(aAsteroid); i++) { 00447 aAsteroid[i].xPos = rand() % (XSIZE_DISPLAY - bmAsteroid.XSize); 00448 aAsteroid[i].yPos = -((int)bmAsteroid.YSize) - i * 64; 00449 } 00450 // 00451 // Intro 00452 // 00453 _Intro(); 00454 // 00455 // The game 00456 // 00457 t0 = GUI_GetTime(); 00458 tEnd = t0 + PERIOD_GAME; 00459 Cnt = 0; 00460 do { 00461 // 00462 // Lock cache, output is written to cache only 00463 // 00464 LCD_ControlCache(LCD_CC_LOCK); 00465 // 00466 // Handle drawing of the ship 00467 // 00468 _Game(&Ship); 00469 // 00470 // Handle drawing of the asteroid 00471 // 00472 for (i = 0; i < GUI_COUNTOF(aAsteroid); i++) { 00473 _Asteroid(&aAsteroid[i]); 00474 // 00475 // Check collision 00476 // 00477 if (_CheckCollision(&aAsteroid[i], &aAsteroid[1 - i], &Ship)) { 00478 Cnt++; 00479 } 00480 } 00481 tNow = GUI_GetTime(); 00482 // 00483 // Show remaining time 00484 // 00485 GUI_GotoXY(XSIZE_DISPLAY - 12 - 1, YSIZE_DISPLAY - 8 - 1); 00486 GUI_DispDecSpace((tEnd - tNow + 1000) / 1000, 2); 00487 // 00488 // Show content of cache 00489 // 00490 LCD_ControlCache(LCD_CC_UNLOCK); 00491 // 00492 // Wait a while... 00493 // 00494 GUI_Delay(50); 00495 } while (GUI_GetTime() < tEnd); 00496 // 00497 // Show result 00498 // 00499 _ShowResult(Cnt); 00500 } 00501 } 00502 00503 /****** End of File *************************************************/
Generated on Thu Jul 14 2022 12:58:41 by
