Chris Dick
/
Gameduino_Frogger_game
Frogger game for the Gameduino
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 #include "mbed.h" 00002 #include "GD.h" 00003 #include "frogger_background.h" 00004 #include "frogger_sprite.h" 00005 #include "shield.h" 00006 00007 00008 Serial debug(USBTX, USBRX); 00009 GDClass GD(ARD_MOSI, ARD_MISO, ARD_SCK, ARD_D9, USBTX, USBRX) ; 00010 00011 #define CONTROL_LEFT 1 00012 #define CONTROL_RIGHT 2 00013 #define CONTROL_UP 4 00014 #define CONTROL_DOWN 8 00015 DigitalIn down(ARD_A2); 00016 DigitalIn up(ARD_A3); 00017 DigitalIn left(ARD_A1); 00018 DigitalIn right(ARD_A0); 00019 00020 class Controller { 00021 public: 00022 00023 void begin() { 00024 down.mode(PullUp); 00025 up.mode(PullUp); 00026 left.mode(PullUp); 00027 right.mode(PullUp); 00028 prev = 0; 00029 } 00030 00031 byte read() { 00032 byte r = 0; 00033 if (!down) 00034 r |= CONTROL_DOWN; 00035 if (!up) 00036 r |= CONTROL_UP; 00037 if (!left) 00038 r |= CONTROL_LEFT; 00039 if (!right) 00040 r |= CONTROL_RIGHT; 00041 byte edge = r & ~prev; 00042 prev = r; 00043 return edge; 00044 } 00045 private: 00046 byte prev; 00047 }; 00048 00049 static Controller Control; 00050 00051 #define BG_BLUE 0 00052 #define BG_ZERO 12 00053 #define BG_BLACK 34 00054 #define BG_LIFE 35 00055 00056 static int atxy(byte x, byte y) { 00057 return RAM_PIC + 64 * y + (x + 11); 00058 } 00059 00060 static void draw_score(uint16_t dst, long n) { 00061 GD.wr(dst + 0, BG_ZERO + (n / 10000) % 10); // ten-thousands 00062 GD.wr(dst + 1, BG_ZERO + (n / 1000) % 10); // thousands 00063 GD.wr(dst + 2, BG_ZERO + (n / 100) % 10); // hundreds 00064 GD.wr(dst + 3, BG_ZERO + (n / 10) % 10); // tens 00065 GD.wr(dst + 4, BG_ZERO + n % 10); // ones 00066 } 00067 00068 // Game variables 00069 static unsigned int t; 00070 static int frogx, frogy; // screen position 00071 static int leaping; // 0 means not leaping, 1-8 animates the leap 00072 static int frogdir; // while leaping, which direction is the leap? 00073 static int frogface; // which way is the frog facing, as a sprite ROT field 00074 static int dying; // 0 means not dying, 1-64 animation counter 00075 static long score; 00076 static long hiscore; 00077 static byte lives; 00078 static byte done[5]; 00079 static byte homes[5] = { 24, 72, 120, 168, 216 }; 00080 00081 void frog_start() { 00082 frogx = 120; 00083 frogy = 232; 00084 leaping = 0; 00085 frogdir = 0; 00086 frogface = 0; 00087 dying = 0; 00088 } 00089 00090 void level_start() { 00091 for (byte i = 0; i < 5; i++) 00092 done[i] = 0; 00093 00094 GD.begin(); 00095 //wait_ms(500); 00096 GD.copy(RAM_CHR, froggerbg_chr, sizeof(froggerbg_chr)); 00097 GD.copy(RAM_PAL, froggerbg_pal, sizeof(froggerbg_pal)); 00098 GD.fill(RAM_PIC, BG_BLACK, 4096); 00099 for (byte y = 0; y < 32; y++) 00100 GD.copy(atxy(0, y), froggerbg_pic + y * 28, 28); 00101 GD.fill(1 * 64 + 11, BG_BLUE, 28); 00102 00103 byte i = 255; 00104 for (int y = 0; y < 256; y += 16) { 00105 GD.sprite(i--, 0, y, 63, 0); 00106 GD.sprite(i--, 16, y, 63, 0); 00107 GD.sprite(i--, 24, y, 63, 0); 00108 GD.sprite(i--, 40, y, 63, 0); 00109 GD.sprite(i--, 56, y, 63, 0); 00110 GD.sprite(i--, 72, y, 63, 0); 00111 GD.sprite(i--, 72 + 240, y, 63, 0); 00112 GD.sprite(i--, 72 + 256, y, 63, 0); 00113 GD.sprite(i--, 72 + 272, y, 63, 0); 00114 GD.sprite(i--, 72 + 288, y, 63, 0); 00115 GD.sprite(i--, 72 + 304, y, 63, 0); 00116 GD.sprite(i--, 72 + 320, y, 63, 0); 00117 GD.sprite(i--, 72 + 336, y, 63, 0); 00118 } 00119 00120 GD.copy(PALETTE16A, sprite_sprpal, sizeof(sprite_sprpal)); 00121 GD.uncompress(RAM_SPRIMG, sprite_sprimg); 00122 } 00123 00124 void game_start() { 00125 lives = 4; 00126 score = 0; 00127 } 00128 00129 void setup() { 00130 Control.begin(); 00131 00132 game_start(); 00133 level_start(); 00134 frog_start(); 00135 } 00136 00137 static void sprite(byte x, byte y, byte anim, byte rot = 0) { 00138 draw_sprite(x + 80, y, anim, rot); 00139 } 00140 00141 static void turtle3(byte x, byte y) { 00142 byte anim = 50 + ((t / 32) % 3); 00143 sprite(x, y, anim); 00144 sprite(x + 16, y, anim); 00145 sprite(x + 32, y, anim); 00146 } 00147 00148 static void turtle2(byte x, byte y) { 00149 byte anim = 50 + ((t / 32) % 3); 00150 sprite(x, y, anim); 00151 sprite(x + 16, y, anim); 00152 } 00153 00154 void log1(byte x, byte y) { 00155 sprite(x, y, 86); 00156 sprite(x + 16, y, 87); 00157 sprite(x + 32, y, 88); 00158 } 00159 00160 void log(byte length, byte x, byte y) { 00161 sprite(x, y, 86); 00162 while (length--) { 00163 x += 16; 00164 sprite(x, y, 87); 00165 } 00166 sprite(x + 16, y, 88); 00167 } 00168 00169 static int riverat(byte y, uint16_t tt) { 00170 switch (y) { 00171 case 120: 00172 return -tt; 00173 case 104: 00174 return tt; 00175 case 88: 00176 return 5 * tt / 4; 00177 case 72: 00178 return -tt / 2; 00179 case 56: 00180 return tt / 2; 00181 default: 00182 return 0; 00183 } 00184 } 00185 00186 // midi frequency table 00187 static int midifreq[128] = { 00188 32,34,36,38,41,43,46,48,51,55,58,61,65,69,73,77,82,87,92,97,103,110,116,123,130,138,146,155,164,174,184,195,207,220,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543,13289,14080,14917,15804,16744,17739,18794,19912,21096,22350,23679,25087,26579,28160,29834,31608,33488,35479,37589,39824,42192,44701,47359,50175 00189 }; 00190 00191 //#define MIDI(n) pgm_read_word(midifreq + (n)) 00192 00193 static void squarewave(uint16_t freq, byte amp) { 00194 GD.voice(0, 0, freq, amp, amp); 00195 GD.voice(1, 0, 3 * freq, amp/3, amp/3); 00196 GD.voice(2, 0, 5 * freq, amp/5, amp/5); 00197 GD.voice(3, 0, 7 * freq, amp/7, amp/7); 00198 GD.voice(4, 0, 9 * freq, amp/9, amp/9); 00199 GD.voice(5, 0, 11 * freq, amp/11, amp/11); 00200 } 00201 00202 static void sound() { 00203 byte note; 00204 00205 if (dying) { 00206 note = 84 - (dying / 2); 00207 squarewave(midifreq[note], 100); 00208 } else if (leaping) { 00209 if (leaping & 1) 00210 note = 60 + leaping; 00211 else 00212 note = 72 + leaping; 00213 squarewave(midifreq[note], 100); 00214 } else { 00215 squarewave(0, 0); // silence 00216 } 00217 } 00218 00219 void loop() { 00220 GD.__wstartspr(0); 00221 00222 // Completed homes 00223 for (byte i = 0; i < 5; i++) { 00224 if (done[i]) 00225 sprite(homes[i], 40, 63); 00226 } 00227 00228 // Yellow cars 00229 sprite(-t, 216, 3); 00230 sprite(-t + 128, 216, 3); 00231 00232 // Dozers 00233 sprite(t, 200, 4); 00234 sprite(t + 50, 200, 4); 00235 sprite(t + 150, 200, 4); 00236 00237 // Purple cars 00238 sprite(-t, 184, 7); 00239 sprite(-t + 75, 184, 7); 00240 sprite(-t + 150, 184, 7); 00241 00242 // Green and white racecars 00243 sprite(2 * t, 168, 8); 00244 00245 // Trucks 00246 sprite(-t/2, 152, 5); 00247 sprite(-t/2 + 16, 152, 6); 00248 sprite(-t/2 + 100, 152, 5); 00249 sprite(-t/2 + 116, 152, 6); 00250 00251 // Turtles 00252 for (int i = 0; i < 256; i += 64) 00253 turtle3(riverat(120, t) + i, 120); 00254 00255 // Short logs 00256 for (int i = 0; i < 240; i += 80) 00257 log(1, riverat(104, t) + i, 104); 00258 00259 // Long logs 00260 for (int i = 0; i < 256; i += 128) 00261 log(5, riverat(88, t) + i, 88); 00262 00263 // Turtles again, but slower 00264 for (int i = 0; i < 250; i += 50) 00265 turtle2(riverat(72, t) + i, 72); 00266 00267 // Top logs 00268 for (int i = 0; i < 210; i += 70) 00269 log(2, riverat(56, t) + i, 56); 00270 00271 // The frog himself, or his death animation 00272 byte frogspr = GD.spr; // record which sprite slot frog got, for collision check below 00273 00274 if (!dying) { 00275 static byte frog_anim[] = {2, 1, 0, 0, 2}; 00276 sprite(frogx, frogy, frog_anim[leaping / 2], frogface); 00277 } else { 00278 static byte die_anim[] = {31, 32, 33, 30}; 00279 sprite(frogx, frogy, die_anim[dying / 16], frogface); 00280 } 00281 00282 GD.__end(); 00283 t++; 00284 00285 // player control. If button pressed, start the 'leaping' counter 00286 byte con = Control.read(); 00287 if (!dying && (leaping == 0) && con) { 00288 frogdir = con; 00289 leaping = 1; 00290 score += 10; 00291 } else if (leaping > 0) { 00292 if (leaping <= 8) { 00293 if (frogdir == CONTROL_LEFT) { 00294 frogx -= 2; 00295 frogface = 3; 00296 } 00297 if (frogdir == CONTROL_RIGHT) { 00298 frogx += 2; 00299 frogface = 5; 00300 } 00301 if (frogdir == CONTROL_UP) { 00302 frogy -= 2; 00303 frogface = 0; 00304 } 00305 if (frogdir == CONTROL_DOWN) { 00306 frogy += 2; 00307 frogface = 6; 00308 } 00309 leaping++; 00310 } else { 00311 leaping = 0; 00312 } 00313 } 00314 00315 GD.waitvblank(); 00316 byte touching = (GD.rd(COLLISION + frogspr) != 0xff); 00317 00318 if (dying) { 00319 if (++dying == 64) { 00320 if (--lives == 0) { 00321 game_start(); 00322 level_start(); 00323 } 00324 frog_start(); 00325 } 00326 } else if (frogx < 8 || frogx > 224) { 00327 dying = 1; 00328 } else if (frogy >= 136) { // road section 00329 // if touching something, frog dies 00330 if (touching) 00331 dying = 1; 00332 } else if (frogy > 40) { // river section 00333 if (!leaping) { 00334 // if touching something, frog is safe 00335 if (touching) { 00336 // move frog according to lane speed 00337 int oldx = riverat(frogy, t - 1); 00338 int newx = riverat(frogy, t); 00339 int river_velocity = newx - oldx; 00340 frogx += river_velocity; 00341 } else { 00342 dying = 1; 00343 } 00344 } 00345 } else { // riverbank section 00346 if (!leaping) { 00347 byte landed = 0; 00348 for (byte i = 0; i < 5; i ++) { 00349 if (!done[i] && abs(homes[i] - frogx) < 4) { 00350 done[i] = 1; 00351 landed = 1; 00352 score += 10; 00353 } 00354 } 00355 if (landed) { 00356 if (done[0] && done[1] && done[2] && done[3] && done[4]) 00357 level_start(); 00358 frog_start(); 00359 } else // if frog did not land in a home, die! 00360 dying = 1; 00361 } 00362 } 00363 sound(); 00364 if (score > hiscore) { 00365 hiscore = score; 00366 } 00367 draw_score(atxy(3, 1), score); 00368 draw_score(atxy(11, 1), hiscore); 00369 for (byte i = 0; i < 16; i++) 00370 GD.wr(atxy(i, 30), (i < lives) ? BG_LIFE : BG_BLACK); 00371 } 00372 00373 00374 int main() { 00375 setup(); 00376 while (1) { 00377 loop(); 00378 } 00379 } 00380
Generated on Thu Jul 14 2022 23:53:02 by 1.7.2