Test 3.a
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* 00002 The MIT License (MIT) 00003 00004 Copyright (c) 2016 Lancaster University. 00005 00006 Permission is hereby granted, free of charge, to any person obtaining a 00007 copy of this software and associated documentation files (the "Software"), 00008 to deal in the Software without restriction, including without limitation 00009 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00010 and/or sell copies of the Software, and to permit persons to whom the 00011 Software is furnished to do so, subject to the following conditions: 00012 00013 The above copyright notice and this permission notice shall be included in 00014 all copies or substantial portions of the Software. 00015 00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00019 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00021 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00022 DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 // 00027 // 00028 // A simple game of Space Invaders for the BBC micro:bit, using the 00029 // accelerometer and buttons to control the player's ship. 00030 // 00031 // As well as illustrating the use of sensors, the display and events, 00032 // this demonstration also provides a highly elegant example of 00033 // how fibers can be used to create safe and elegant programs... Note the 00034 // use of event handlers when the player fires, and the indepenent fibers 00035 // used to control the players ship, aliens, bullets and screen refresh... 00036 // 00037 // 00038 00039 #include "MicroBit.h" 00040 00041 #define GAME_ON 0 00042 #define GAME_OVER 1 00043 00044 struct Point 00045 { 00046 int x; 00047 int y; 00048 }; 00049 00050 MicroBit uBit; 00051 MicroBitImage invaders(5,5); 00052 int score; 00053 int game_over; 00054 int level; 00055 int INVADER_SPEED = 750; 00056 int PLAYER_SPEED = 150; 00057 int BULLET_SPEED = 50; 00058 Point player; 00059 Point bullet; 00060 00061 /** 00062 * Add a new row of space invaders to the game. 00063 */ 00064 int 00065 addRow() 00066 { 00067 // If we're adding a row of invaders, but we're out of space, it's game over!! 00068 for (int x=0; x<5; x++) 00069 if (invaders.getPixelValue(x,4)) 00070 return GAME_OVER; 00071 00072 // Otherwise, move down the invaders, and add a new role at the top. 00073 invaders.shiftDown(1); 00074 00075 for (int x=1; x<4; x++) 00076 invaders.setPixelValue(x,0,255); 00077 00078 return GAME_ON; 00079 } 00080 00081 /* 00082 * Display Game Over and show the player's score. 00083 */ 00084 void 00085 gameOver() 00086 { 00087 uBit.display.clear(); 00088 00089 uBit.display.scroll("You Lost! SCORE:"); 00090 uBit.display.scroll(score); 00091 } 00092 00093 /* 00094 * Calculate the speed of an invaders movement, based on the game level 00095 */ 00096 int 00097 invaderSpeed() 00098 { 00099 return max(INVADER_SPEED - level*50, 50); 00100 } 00101 00102 /* 00103 * Determine if the are any space invaders in the given column 00104 */ 00105 bool 00106 invadersInColumn(int x) 00107 { 00108 for (int y = 0; y < 5; y++) 00109 if (invaders.getPixelValue(x,y)) 00110 return true; 00111 00112 return false; 00113 } 00114 00115 /* 00116 * Determine the number of space invaders currently on screen 00117 */ 00118 bool 00119 invaderCount() 00120 { 00121 int count = 0; 00122 00123 for (int x=0; x<5; x++) 00124 for (int y=0; y<5; y++) 00125 if (invaders.getPixelValue(x,y)) 00126 count++; 00127 00128 return count; 00129 } 00130 00131 /* 00132 * Move space invaders on the screen. 00133 */ 00134 void 00135 invaderUpdate() 00136 { 00137 bool movingRight = true; 00138 00139 while(!game_over) 00140 { 00141 // Wait for next update; 00142 uBit.sleep(invaderSpeed()); 00143 00144 if (movingRight) 00145 { 00146 if(invadersInColumn(4)) 00147 { 00148 movingRight = false; 00149 if (addRow() == GAME_OVER) 00150 { 00151 game_over = true; 00152 return; 00153 } 00154 } 00155 else 00156 { 00157 invaders.shiftRight(1); 00158 } 00159 } 00160 else 00161 { 00162 if(invadersInColumn(0)) 00163 { 00164 movingRight = true; 00165 if (addRow() == GAME_OVER) 00166 { 00167 game_over = true; 00168 return; 00169 } 00170 } 00171 else 00172 { 00173 invaders.shiftLeft(1); 00174 } 00175 } 00176 00177 if (invaderCount() == 0) 00178 { 00179 level++; 00180 addRow(); 00181 } 00182 } 00183 } 00184 00185 /* 00186 * Move the bullet up the screen 00187 */ 00188 void 00189 bulletUpdate() 00190 { 00191 while (!game_over) 00192 { 00193 uBit.sleep(BULLET_SPEED); 00194 if (bullet.y != -1) 00195 bullet.y--; 00196 00197 if (invaders.getPixelValue(bullet.x, bullet.y) > 0) 00198 { 00199 score++; 00200 invaders.setPixelValue(bullet.x, bullet.y, 0); 00201 bullet.x = -1; 00202 bullet.y = -1; 00203 } 00204 } 00205 } 00206 00207 /* 00208 * Move the player across the screen. 00209 */ 00210 void 00211 playerUpdate() 00212 { 00213 while (!game_over) 00214 { 00215 uBit.sleep(PLAYER_SPEED); 00216 00217 if(uBit.accelerometer.getX() < -300 && player.x > 0) 00218 player.x--; 00219 00220 if(uBit.accelerometer.getX() > 300 && player.x < 4) 00221 player.x++; 00222 } 00223 } 00224 00225 /* 00226 * Fire a new missile from the player 00227 */ 00228 void 00229 fire(MicroBitEvent) 00230 { 00231 if (bullet.y == -1) 00232 { 00233 bullet.y = 4; 00234 bullet.x = player.x; 00235 } 00236 } 00237 00238 /* 00239 * A simple game of space invaders 00240 */ 00241 void 00242 spaceInvaders() 00243 { 00244 // Reset all game state. 00245 game_over = 0; 00246 level = 0; 00247 score = 0; 00248 player.x = 2; 00249 player.y = 4; 00250 00251 bullet.x = -1; 00252 bullet.y = -1; 00253 00254 // Add a single row of invaders at the start.. cannon fodder! 00255 invaders.clear(); 00256 addRow(); 00257 00258 // Spawn independent fibers to handle the movement of each player 00259 create_fiber(invaderUpdate); 00260 create_fiber(bulletUpdate); 00261 create_fiber(playerUpdate); 00262 00263 // Register event handlers for button presses (either button fires!) 00264 uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, fire); 00265 uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, fire); 00266 00267 // Now just keep the screen refreshed. 00268 while (!game_over) 00269 { 00270 uBit.sleep(10); 00271 uBit.display.image.paste(invaders); 00272 uBit.display.image.setPixelValue(player.x, player.y, 255); 00273 uBit.display.image.setPixelValue(bullet.x, bullet.y, 255); 00274 } 00275 00276 // Display GAME OVER and score 00277 gameOver(); 00278 } 00279 00280 int main() 00281 { 00282 // Initialise the micro:bit runtime. 00283 uBit.init(); 00284 00285 // Welcome message 00286 uBit.display.scroll("INVADERS!"); 00287 00288 // Keep playing forever 00289 while(1) 00290 spaceInvaders(); 00291 } 00292
Generated on Fri Jul 22 2022 08:31:08 by 1.7.2