Great game by Aurelién Rodot for Gamebuin. Ported by Jonne

Dependencies:   PokittoLib

Fork of Asterocks by Pokitto Community Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Crabator.cpp Source File

Crabator.cpp

00001 //#include <SPI.h>
00002 #include <Pokitto.h>
00003 #include "Crabator.h"
00004 Pokitto::Core gb;
00005 //#include <EEPROM.h>
00006 //#include <avr/pgmspace.h>
00007 
00008 uint16_t hazepalette[16];
00009 
00010 extern const byte font3x5[];
00011 extern const byte font5x7[];
00012 
00013 #define WORLD_W 16
00014 #define WORLD_H 12
00015 uint8_t  byteWidth = (WORLD_H + 7) / 8;
00016 
00017 //declare all the sprites which are in the "sprites" tab
00018 extern const byte PROGMEM logo[];
00019 extern const byte PROGMEM world[];
00020 extern const byte PROGMEM tiles[];
00021 extern const byte PROGMEM mobSprite[];
00022 extern const byte PROGMEM bossSprite[];
00023 extern const byte PROGMEM playerSprite[];
00024 extern const byte PROGMEM splashSprite[];
00025 extern const byte PROGMEM crateSprite[];
00026 extern const byte PROGMEM fullHeart[];
00027 extern const byte PROGMEM halfHeart[];
00028 extern const byte PROGMEM emptyHeart[];
00029 
00030 #define playerW 6
00031 #define playerH 6
00032 byte playerSpeed;
00033 int playerX;
00034 int playerY;
00035 int playerLife;
00036 #define playerLifeMax 6
00037 byte playerDir;
00038 int cameraX;
00039 int cameraY;
00040 byte shake_magnitude;
00041 byte shake_timeLeft;
00042 const PROGMEM uint16_t player_damage_sound[] = {0x0045,0x564,0x0000};
00043 
00044 ///////////////////////////////////// MOBS
00045 #define NUMMOBS 16
00046 #define INITNUMMOBS 4
00047 #define MOBSRATE 6 //how often is the mob number increased (every X kills)
00048 #define BOSSFREQ 16//one boss every X kills (initially)
00049 #define BOSSRATE 1 //every boss killed, the next one will spawn X kills earlier
00050 byte boss_nextSpawn;
00051 byte boss_freq;
00052 byte activeMobs;
00053 int  mobs_x[NUMMOBS];
00054 int  mobs_y[NUMMOBS];
00055 byte mobs_dir[NUMMOBS];
00056 int8_t mobs_life[NUMMOBS]; // was char - Jonne
00057 byte mobs_size[NUMMOBS];
00058 byte mob_maxLife = 10;
00059 byte boss_maxLife = 100;
00060 #define boss_size 6
00061 #define mob_size 4
00062 //const PROGMEM uint16_t mob_damage_sound[] = {0x5C1F, 0x0000};
00063 const PROGMEM uint16_t mob_death_sound[] = {0x0045,0x184,0x0000};
00064 
00065 #define NUMSPLASH 16
00066 boolean splash_active[NUMSPLASH];
00067 int splash_x[NUMSPLASH];
00068 int splash_y[NUMSPLASH];
00069 int splash_dir[NUMSPLASH];
00070 
00071 ///////////////////////////////////// WEAPONS
00072 #define NUMBULLETS 10
00073 int     bullets_x[NUMBULLETS];
00074 int     bullets_y[NUMBULLETS];
00075 byte    bullets_dir[NUMBULLETS];
00076 boolean bullets_active[NUMBULLETS];
00077 byte    bullets_weapon[NUMBULLETS];
00078 
00079 int     blast_x;
00080 int     blast_y;
00081 byte    blast_lifespan;
00082 byte    blast_bullet;
00083 
00084 #define NUMWEAPONS 5
00085 byte currentWeapon;
00086 byte nextShot;
00087 
00088 const char str357[] PROGMEM = ".357";
00089 const char strP90[] PROGMEM = "P90";
00090 const char strAK47[] PROGMEM = "AK47";
00091 const char strRPG[] PROGMEM = "RPG";
00092 const char strMG42[] PROGMEM = "MG42";
00093 const char*  const weapon_name[NUMWEAPONS] PROGMEM = {
00094   str357,strP90, strAK47, strRPG, strMG42};
00095 const byte weapon_size[NUMWEAPONS] = {
00096   2, 1, 2, 3, 2};
00097 const byte weapon_damage[NUMWEAPONS] = {
00098   10, 2, 3, 5, 4};
00099 const byte weapon_rate[NUMWEAPONS] = {
00100   30, 1, 2, 30, 1};
00101 const byte weapon_speed[NUMWEAPONS] = {
00102   4, 5, 3, 2, 5};
00103 const byte weapon_spread[NUMWEAPONS] = {
00104   1, 2, 1, 0, 2};
00105 const byte weapon_ennemyRecoil[NUMWEAPONS] = {
00106   3, 2, 3, 0, 3};
00107 const byte weapon_playerRecoil[NUMWEAPONS] = {
00108   0, 0, 1, 3, 3};
00109 const unsigned int weapon_ammo[NUMWEAPONS] = {
00110   9999, 500, 300, 20, 150};
00111 unsigned int ammo;
00112 
00113 const uint16_t magnum_sound[] PROGMEM = {0x0045,0x7049,0x17C,0x784D,0x42C,0x0000};
00114 const uint16_t p90_sound[] PROGMEM = {0x0045, 0x0154, 0x0000};
00115 const uint16_t p90_alternative_sound[] PROGMEM = {0x0045, 0x014C, 0x0000};
00116 const uint16_t ak47_sound[] PROGMEM = {0x0045, 0x012C, 0x0000};
00117 const uint16_t mg42_sound[] PROGMEM = {0x0045,0x140,0x8141,0x7849,0x788D,0x52C,0x0000};
00118 const uint16_t rpg_sound[] PROGMEM = {0x0045,0x8101,0x7F30,0x0000};
00119 
00120 const uint16_t* const weapons_sounds[NUMWEAPONS] PROGMEM= {
00121   magnum_sound, p90_sound, ak47_sound, rpg_sound, mg42_sound};
00122 const uint16_t blast_sound[] PROGMEM = {0x0045,0x7849,0x784D,0xA28,0x0000};
00123 int crate_x, crate_y;
00124 const uint16_t power_up[] PROGMEM = {0x0005,0x140,0x150,0x15C,0x170,0x180,0x16C,0x154,0x160,0x174,0x184,0x14C,0x15C,0x168,0x17C,0x18C,0x0000};
00125 
00126 ///////////////////////////////////// SCORE
00127 #define RANKMAX 5 //number of high scores to save
00128 int score = 0;
00129 //int lastScore = 0;
00130 int kills = 0;
00131 int highscore[RANKMAX];
00132 //byte scoreDisplayTimeLeft;
00133 #define NAMELENGTH 10
00134 char name[RANKMAX][NAMELENGTH+1];
00135 
00136 // predefinitions
00137 
00138 void loadHighscore();
00139 void initGame();
00140 boolean collideWorld(int16_t, int16_t, uint8_t, uint8_t);
00141 void damageMob(byte,byte);
00142 boolean checkMobCollisions(byte);
00143 boolean collideOtherMobs(byte);
00144 void pausem();
00145 void play();
00146 void displayHighScores();
00147 void saveHighscore();
00148 void shakeScreen();
00149 void drawWorld(int16_t, int16_t);
00150 void displayScore();
00151 
00152 /*int16_t random (int lo,int hi) {
00153     return rand() % hi + lo;
00154 }*/
00155 
00156 ///////////////////////////////////// SETUP
00157 void setup() {
00158 
00159     /** Set colors for this game **/
00160 
00161     /** TO ADD COLORS TO YOUR GAMEBUINO GAME, SIMPLY USE VALUES ABOVE 1 !!!! */
00162 
00163     gb.display.palette[1] = COLOR_WHITE;
00164     gb.display.palette[2] = COLOR_CYAN;
00165     gb.display.palette[3] = COLOR_MAGENTA;
00166     gb.display.palette[4] = COLOR_RED;
00167     gb.display.palette[8] = gb.display.RGBto565(0xff,0xfc,0); // small mob
00168     gb.display.palette[7] = gb.display.RGBto565(0x18,0x9a,0x61); // shrub shadow
00169     gb.display.palette[5] = gb.display.RGBto565(0x2c,0xff,0x0b); //world (shrubs)
00170     gb.display.palette[6] = gb.display.RGBto565(0xf7,0xb2,0);// crate
00171     gb.display.palette[9] = gb.display.RGBto565(0xfc,0x14,4);// big mob fc1404
00172     gb.display.palette[10] = gb.display.RGBto565(0,0x53,0xae); // blue shadow
00173     gb.display.palette[15] = gb.display.RGBto565(0xff,0xfd,0xbf); // bright sunlight
00174 
00175     /** YOU HAVE 16 COLORS FREELY SELECTABLE FROM 256000 COLORS !!! **/
00176 
00177     /** NOW LETS REBUILD! **/
00178 
00179 
00180 
00181 for (uint16_t k =0 ; k<16; k++) hazepalette[k] = gb.display.interpolateColor(gb.display.palette[k],gb.display.palette[15],0);
00182     gb.display.paletteptr = hazepalette;
00183   gb.begin();
00184   //while(1) gb.update();
00185   gb.display.setFont(font5x7);
00186   gb.titleScreen(logo);
00187 
00188   gb.pickRandomSeed();
00189   loadHighscore();
00190   initGame();
00191 }
00192 
00193 ///////////////////////////////////// LOOP
00194 void loop() {
00195   play();
00196   if (!gb.isRunning()) return;
00197   pausem();
00198   if (!gb.isRunning()) return;
00199   gb.titleScreen(logo);
00200 }
00201 
00202 ///////////////////////////////////// SCREEN COORD
00203 boolean screenCoord(int absoluteX, int absoluteY, int &x, int &y){
00204   x = absoluteX - cameraX + 8;
00205   x = (x >= 0) ? x%(WORLD_W*8) : WORLD_W*8 + x%(WORLD_W*8);
00206   x -= 8;
00207   y = absoluteY - cameraY + 8;
00208   y = (y >= 0) ? y%(WORLD_H*8) : WORLD_H*8 + y%(WORLD_H*8);
00209   y -= 8;
00210   if((x > LCDWIDTH) || (y > LCDHEIGHT))
00211     return false;
00212   return true;
00213 }
00214 
00215 #define wrap(i, imax) ((imax+i)%(imax))
00216 
00217 ///////////////////////////////////// MOVE XYDS
00218 void moveXYDS(int &x, int &y, byte &dir, int8_t speed){
00219   switch(dir){ //switch case depending on the mob's movement direction
00220   case 0: //going upward
00221     y -= speed;
00222     break;
00223   case 1: //left
00224     x -= speed;
00225     break;
00226   case 2: //downward
00227     y += speed;
00228     break;
00229   case 3: //right
00230     x += speed;
00231     break;
00232   }
00233   x = wrap(x, WORLD_W*8);
00234   y = wrap(y, WORLD_H*8);
00235 }
00236 
00237 ///////////////////////////////////// DISTANCE BETWEEN
00238 byte distanceBetween(int pos1, int pos2, int worldSize){
00239   byte dist = abs(pos1 - pos2);
00240   dist = (dist < worldSize/2) ? dist : worldSize - dist;
00241   return dist;
00242 }
00243 
00244 ///////////////////////////////////// ASSIGN ARRAY
00245 void assignArray(char *array1, char *array2, byte length){
00246   for(byte i=0; i<length; i++)
00247     array1[i] = array2[i];
00248 }
00249 
00250 ///////////////////////////////////// SHOOT
00251 #define min(a,b) (((a)<(b))?(a):(b))
00252 #define max(a,b) (((a)>(b))?(a):(b))
00253 
00254 
00255 void shoot(){
00256   if(ammo){
00257     if(nextShot == 0){
00258       for(byte thisBullet = 0; thisBullet < NUMBULLETS; thisBullet++){
00259         if(!bullets_active[thisBullet]){ //look for the first inactive bullet
00260           bullets_active[thisBullet] = true; //set it to active as it's fired
00261           bullets_weapon[thisBullet] = currentWeapon;
00262 
00263           nextShot = weapon_rate[currentWeapon];
00264           ammo--;
00265           //spawn a bullet with some spreading
00266           int8_t spreadMax = weapon_spread[currentWeapon]; // this was char, jonne
00267           int8_t spreadMin = (weapon_size[currentWeapon]%2==0) ? -spreadMax : -spreadMax-1;
00268           bullets_x[thisBullet] = playerX + playerW/2 + random(spreadMin,spreadMax+1) - weapon_size[currentWeapon]/2;
00269           bullets_y[thisBullet] = playerY + playerH/2 + random(spreadMin,spreadMax+1) - weapon_size[currentWeapon]/2;
00270 
00271           bullets_dir[thisBullet] = playerDir;
00272           blast_bullet = thisBullet;
00273           if(((currentWeapon == 1)||(currentWeapon==4))&&(gb.frameCount%2))
00274           {
00275           }
00276           else{
00277             gb.sound.playPattern((uint16_t*)pgm_read_word(&(weapons_sounds[currentWeapon])), 0);
00278           }
00279           if(currentWeapon == 1){//with P90 cancel every two sounds to avoid continuous beep
00280             if(rand()%2)
00281               gb.sound.playPattern(p90_alternative_sound, 0);
00282           }
00283           //player recoil
00284           byte recoil = weapon_playerRecoil[currentWeapon];
00285           moveXYDS(playerX, playerY, playerDir, -recoil);
00286           for(byte i = 0; i<recoil; i++){
00287             if(collideWorld(playerX, playerY, playerW, playerH))
00288               moveXYDS(playerX, playerY, playerDir, 1);
00289             else
00290               break;
00291           }
00292           if(currentWeapon == 4){ //MG42
00293             shake_magnitude = 1;
00294             shake_timeLeft = 2;
00295           }
00296           break;
00297         }
00298       }
00299     }
00300   }
00301   else{
00302     currentWeapon = max(0, currentWeapon-1); //cut... no, magnum finally
00303     ammo = weapon_ammo[currentWeapon];
00304     nextShot = 20;
00305     gb.popup(("Out of ammo!"), 30);
00306   }
00307 }
00308 
00309 ///////////////////////////////////// MOVE BULLETS
00310 void moveBullets(){
00311   for(byte thisBullet = 0; thisBullet < NUMBULLETS; thisBullet++){
00312     if(bullets_active[thisBullet]){
00313       byte s = weapon_size[bullets_weapon[thisBullet]];
00314       moveXYDS(bullets_x[thisBullet], bullets_y[thisBullet], bullets_dir[thisBullet], weapon_speed[bullets_weapon[thisBullet]]);
00315 
00316       //collide world
00317       if(collideWorld(bullets_x[thisBullet], bullets_y[thisBullet], s, s)){
00318         bullets_active[thisBullet] = false;
00319         if(bullets_weapon[thisBullet] == 3){ //RPG
00320           blast_x = bullets_x[thisBullet];
00321           blast_y = bullets_y[thisBullet];
00322           blast_lifespan = 8;
00323           gb.sound.playPattern(blast_sound, 0);
00324         }
00325         else{
00326         }
00327         continue;
00328       }
00329 
00330       for(byte thisMob=0; thisMob<activeMobs; thisMob++){ //for each mob
00331 
00332         if(gb.collideRectRect(bullets_x[thisBullet], bullets_y[thisBullet], s, s,
00333         mobs_x[thisMob], mobs_y[thisMob], mobs_size[thisMob], mobs_size[thisMob])){
00334 
00335           if(bullets_weapon[thisBullet] == 3){ //RPG
00336             blast_x = bullets_x[thisBullet];
00337             blast_y = bullets_y[thisBullet];
00338             blast_lifespan = 8;
00339             gb.sound.playPattern(blast_sound, 0);
00340           }
00341           else {
00342             damageMob(thisMob, thisBullet);
00343           }
00344           bullets_active[thisBullet] = false;
00345           break;
00346         }
00347       }
00348 
00349     }
00350   }
00351 }
00352 
00353 ///////////////////////////////////// EXPLODE
00354 void explode(){
00355   if(blast_lifespan){
00356     blast_lifespan--;
00357     //gb.buzz(50+random(0,100),40);
00358     shake_magnitude = 4;
00359     shake_timeLeft = 2;
00360     //pick a random blast
00361     byte s = 10 + random (0,6);
00362     int x = blast_x + random(-4,4) -s/2;
00363     int y = blast_y + random(-4,4) -s/2;
00364     //damages
00365     for(byte thisMob=0; thisMob<activeMobs; thisMob++){
00366       if(gb.collideRectRect(mobs_x[thisMob], mobs_y[thisMob], mobs_size[thisMob], mobs_size[thisMob],
00367       x,y,s,s))
00368         damageMob(thisMob,blast_bullet);
00369     }
00370     //display
00371     int x_screen, y_screen;
00372     if(screenCoord(x, y, x_screen, y_screen))
00373       gb.display.fillRect(x_screen, y_screen, s, s);
00374   }
00375 }
00376 
00377 ///////////////////////////////////// DRAW BULLETS
00378 void drawBullets(){
00379   gb.display.setColor(1);
00380   for(byte thisBullet = 0; thisBullet < NUMBULLETS; thisBullet++){
00381     if(bullets_active[thisBullet]){
00382       int x, y;
00383       if(screenCoord(bullets_x[thisBullet], bullets_y[thisBullet], x, y)){
00384         byte s = weapon_size[bullets_weapon[thisBullet]];
00385         if(s==1)
00386           gb.display.drawPixel(x, y);
00387         else
00388           gb.display.fillRect(x, y, s, s);
00389       }
00390     }
00391   }
00392 }
00393 
00394 ///////////////////////////////////// DRAW AMMO OVERLAY
00395 void drawAmmoOverlay(){
00396   if(ammo){
00397     // text shadow
00398     /*
00399     gb.display.setColor(10);
00400     gb.display.cursorX = -1;
00401     gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight-1;
00402     gb.display.print((const __FlashStringHelper*)pgm_read_word(weapon_name+currentWeapon)); //some crazy casts
00403     gb.display.cursorX = -1;
00404     gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight+1;
00405     gb.display.print((const __FlashStringHelper*)pgm_read_word(weapon_name+currentWeapon)); //some crazy casts
00406     gb.display.cursorX = 1;
00407     gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight-1;
00408     gb.display.print((const __FlashStringHelper*)pgm_read_word(weapon_name+currentWeapon)); //some crazy casts
00409     gb.display.cursorX = +1;
00410     gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight+1;
00411     gb.display.print((const __FlashStringHelper*)pgm_read_word(weapon_name+currentWeapon)); //some crazy casts
00412     */
00413     // white on top
00414     gb.display.setColor(2);
00415     gb.display.cursorX = 0;
00416     gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight;
00417     gb.display.print((char*)(weapon_name[currentWeapon])); //some crazy casts
00418 
00419     if(nextShot>2)
00420       gb.display.fillRect(-2,LCDHEIGHT-2,nextShot,2);
00421     if(currentWeapon > 0){ //don't display the ammo of the cut
00422       byte xOffset = 0;
00423       if (ammo < 100)
00424         xOffset += gb.display.fontWidth;
00425       if (ammo < 10)
00426         xOffset += gb.display.fontWidth;
00427       gb.display.cursorX = LCDWIDTH-3*gb.display.fontWidth+xOffset;
00428       gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight;
00429       gb.display.print(ammo);
00430     }
00431     else {
00432       gb.display.cursorX = LCDWIDTH-3*gb.display.fontWidth;
00433       gb.display.cursorY = LCDHEIGHT-gb.display.fontHeight;
00434       gb.display.print(("inf"));
00435     }
00436   }
00437 }
00438 
00439 ///////////////////////////////////// SET SPLASH
00440 void setSplash(int x, int y){
00441   for(byte thisSplash = 0; thisSplash < NUMSPLASH; thisSplash++){
00442     if(!splash_active[thisSplash]){ //look for the first inactive splash
00443       splash_active[thisSplash] = true; //set it to active
00444       splash_x[thisSplash] = x;
00445       splash_y[thisSplash] = y;
00446       splash_dir[thisSplash] = random(0,5);
00447       break;
00448     }
00449   }
00450 }
00451 
00452 ///////////////////////////////////// DRAW SPLASHES
00453 void drawSplashes(){
00454   for(byte thisSplash = 0; thisSplash < NUMSPLASH; thisSplash++){
00455     if(splash_active[thisSplash]){
00456       int x, y;
00457       if(screenCoord(splash_x[thisSplash], splash_y[thisSplash], x, y)){ //if the splash is in the screen
00458         //draw it
00459         gb.display.drawBitmap(x-2, y-2, splashSprite, splash_dir[thisSplash], NOFLIP);
00460       }
00461       else{ //erase it if it is out of the screen
00462         splash_active[thisSplash] = false;
00463       }
00464     }
00465   }
00466 }
00467 
00468 
00469 ///////////////////////////////////// SPAWN CRATE
00470 void spawnCrate(){
00471   boolean okay = false;
00472   while (okay == false){
00473     //pick a random location
00474     crate_x = random(0, WORLD_W) * 8;
00475     crate_y = random(0, WORLD_H) * 8;
00476     okay = true;
00477     //is that in a wall ?
00478     if(collideWorld(crate_x, crate_y, 8, 8)){
00479       okay = false;
00480     }
00481     //is that in the screen ?
00482     int x, y;
00483     if(screenCoord(crate_x, crate_y, x, y)){
00484       okay = false;
00485     }
00486   }
00487 }
00488 
00489 ///////////////////////////////////// COLLIDE CRATE
00490 void collideCrate(){
00491   if(gb.collideRectRect(crate_x+2, crate_y+2, 4, 4, playerX, playerY, playerW, playerH)){
00492     if (score <5){
00493       gb.popup(("Earn $5 first"), 30);
00494       return;
00495     }
00496     if(currentWeapon<(NUMWEAPONS-1)){
00497       gb.popup(("Upgraded !"), 30);
00498       gb.sound.playPattern(power_up,0);
00499     }
00500     else{
00501       gb.popup(("Refilled !"), 30);
00502     }
00503     score -= 5;
00504     spawnCrate();
00505     currentWeapon = min(NUMWEAPONS-1, currentWeapon+1); //upgrade to the next weapon
00506     ammo = weapon_ammo[currentWeapon];
00507     //gb.popup(weapon_name[currentWeapon], 30);
00508     //if(random(0,score/10)==0) //the higher is your score, the less life you will find in crates
00509     playerLife = min(playerLife+1, playerLifeMax);
00510     int hazefactor = (255-42*playerLife)*2/3;
00511     for (uint16_t k =0 ; k<16; k++) hazepalette[k] = gb.display.interpolateColor(gb.display.palette[k],gb.display.palette[4],hazefactor);
00512     //gb.buzz(2000,40);
00513   }
00514 }
00515 
00516 ///////////////////////////////////// DRAW CRATE
00517 void drawCrate(){
00518   int x, y;
00519   if(screenCoord(crate_x, crate_y, x, y)){
00520     gb.display.setColor(8);
00521     gb.display.drawBitmap(x, y, crateSprite);
00522     //gb.display.setColor(6);
00523     //gb.display.drawBitmap(x-1, y, crateSprite);
00524   }
00525 }
00526 
00527 
00528 
00529 ///////////////////////////////////// SPAWN ONE MOB
00530 boolean spawnMob(byte thisMob){
00531   boolean okay = false;
00532   byte timout = 0;
00533   mobs_size[thisMob] = mob_size;
00534   mobs_life[thisMob] = mob_maxLife;
00535   if(!boss_nextSpawn){ //spawn big mobs every 20 kills starting from 15
00536     boss_freq = max(boss_freq - BOSSRATE, 1);
00537     boss_nextSpawn = boss_freq;
00538     mobs_size[thisMob] = boss_size;
00539     mobs_life[thisMob] = boss_maxLife;
00540     //gb.popup("Boss spawned !", 30);
00541   }
00542   while(okay == false){ //do the following until it's okay
00543     //pick a random location
00544     mobs_x[thisMob] = random(0, WORLD_W*2) * 4;
00545     mobs_y[thisMob] = random(0, WORLD_H*2) * 4;
00546     //and check if that position is okay
00547     okay = true;
00548 
00549     if(checkMobCollisions(thisMob)){
00550       okay = false;
00551       continue;
00552     }
00553     //spawn the mobs out of the player's view
00554     if(wrap(mobs_x[thisMob] - cameraX, WORLD_W*8) < LCDWIDTH){
00555       okay = false;
00556       continue;
00557     }
00558     if(wrap(mobs_y[thisMob] - cameraY, WORLD_H*8) < LCDHEIGHT){
00559       okay = false;
00560       continue;
00561     }
00562   }
00563   mobs_dir[thisMob] = rand() % 4; //then pick a random direction
00564   return true;
00565 }
00566 
00567 ///////////////////////////////////// SPAWN ALL MOBS
00568 boolean spawnMobs(){
00569   for(byte thisMob=0; thisMob<activeMobs; thisMob++){ //put mobs far away
00570     mobs_x[thisMob] = 9999;
00571     mobs_y[thisMob] = 9999;
00572   }
00573   for(byte thisMob=0; thisMob<activeMobs; thisMob++){
00574     if(!spawnMob(thisMob)) //try to spawn a mob
00575         return false; //return false if an error occur
00576   }
00577   return true;
00578 }
00579 
00580 ///////////////////////////////////// MOVE MOBS
00581 void moveMobs(){
00582   for(byte thisMob=0; thisMob<activeMobs; thisMob++){ //for each mob
00583     int x = wrap(mobs_x[thisMob] - cameraX, WORLD_W*8);
00584     int y = wrap(mobs_y[thisMob] - cameraY, WORLD_H*8);
00585     //if the mob is close to the screen
00586     if( (distanceBetween(mobs_x[thisMob], playerX, WORLD_W*8) < (LCDWIDTH+32)) &&  (distanceBetween(mobs_y[thisMob], playerY, WORLD_H*8) < (LCDHEIGHT+32))){
00587       moveXYDS(mobs_x[thisMob], mobs_y[thisMob], mobs_dir[thisMob], 1); //go forward
00588 
00589       //if there is a collision, move a step backward and pick a new random direction
00590       if(checkMobCollisions(thisMob)){
00591         moveXYDS(mobs_x[thisMob], mobs_y[thisMob], mobs_dir[thisMob], -1);
00592         mobs_dir[thisMob] = rand()%4;
00593         continue;
00594       }
00595 
00596       //go in a random direction
00597       if(random(0,32)==0){
00598         mobs_dir[thisMob] = rand()%4;
00599         continue;
00600       }
00601 
00602       //go in the direction on the player (randomly choose between X and Y axis)
00603       if(random(0,16)==0){
00604         if(random(0,2)){
00605           //get closer to the player on the X axis
00606           if((LCDWIDTH/2 - x) > 0){ //go to the left if the player is on the left
00607             mobs_dir[thisMob] = 3;
00608           }
00609           else{ // or go to the right if the player is on the right
00610             mobs_dir[thisMob] = 1;
00611           }
00612         }
00613         //if the distance between the player and the mob is larger on the Y axis
00614         else {
00615           //get closer to the player on the Y axis
00616           if((LCDHEIGHT/2 - y) > 0){ //go downward
00617             mobs_dir[thisMob] = 2;
00618           }
00619           else{ //go upward
00620             mobs_dir[thisMob] = 0;
00621           }
00622         }
00623       }
00624     }
00625   }
00626 }
00627 
00628 ///////////////////////////////////// CHECK MOB COLLISIONS
00629 boolean checkMobCollisions(byte thisMob){
00630   //check collision with the world
00631   if(collideWorld(mobs_x[thisMob], mobs_y[thisMob], mobs_size[thisMob], mobs_size[thisMob]))
00632     return true;
00633   //check collision with other mobs
00634   if(collideOtherMobs(thisMob))
00635     return true;
00636   return false;
00637 }
00638 
00639 
00640 ///////////////////////////////////// CHECK IF A MOB COLLIDE ANOTHER ONE
00641 boolean collideOtherMobs(byte thisMob){
00642   for(byte otherMob=0; otherMob<activeMobs; otherMob++){
00643     if(thisMob == otherMob) //don't check collision with iself >_<'
00644       continue;
00645     if(gb.collideRectRect(mobs_x[thisMob], mobs_y[thisMob], mobs_size[thisMob], mobs_size[thisMob],
00646     mobs_x[otherMob], mobs_y[otherMob], mobs_size[otherMob], mobs_size[otherMob])){
00647       return true;
00648     }
00649   }
00650   return false;
00651 }
00652 
00653 ///////////////////////////////////// DRAW MOBS
00654 void drawMobs(){
00655     gb.display.setColor(1); //8
00656   for(byte thisMob=0; thisMob<activeMobs; thisMob++){
00657     //int x = wrap(mobs_x[thisMob] - cameraX + playerW/2, WORLD_W*8);
00658     //int y = wrap(mobs_y[thisMob] - cameraY + playerH/2, WORLD_H*8);
00659     int x, y;
00660     if(screenCoord(mobs_x[thisMob], mobs_y[thisMob], x, y)){
00661       if(mobs_size[thisMob] != boss_size)
00662       {
00663         gb.display.setColor(8);
00664         gb.display.drawBitmap(x-2, y-2, mobSprite, mobs_dir[thisMob], NOFLIP);
00665       } else
00666       { gb.display.setColor(9);
00667         gb.display.drawBitmap(x-1, y-1, bossSprite, mobs_dir[thisMob], NOFLIP);
00668       }
00669       //gb.fillRect(x, y, mobs_size[thisMob], mobs_size[thisMob], BLACK);
00670     }
00671   }
00672 }
00673 
00674 ///////////////////////////////////// DAMAGE MOB
00675 void damageMob(byte thisMob, byte thisBullet){
00676   mobs_life[thisMob] -= weapon_damage[bullets_weapon[thisBullet]];
00677   //recoil
00678   byte recoil = weapon_ennemyRecoil[bullets_weapon[thisBullet]];
00679   if(mobs_size[thisMob] == boss_size)
00680     recoil /= 4;
00681   moveXYDS(mobs_x[thisMob], mobs_y[thisMob], bullets_dir[thisBullet], recoil);
00682   if(checkMobCollisions(thisMob))
00683     moveXYDS(mobs_x[thisMob], mobs_y[thisMob], bullets_dir[thisBullet], -recoil);
00684   mobs_dir[thisMob] = (bullets_dir[thisBullet] + 2) % 4;
00685   //gb.buzz(1200,10);
00686   if(mobs_life[thisMob] <= 0){ //the mob dies
00687     score++;
00688     kills++;
00689     boss_nextSpawn--;
00690     if(bullets_weapon[thisBullet]!=3){ //if it's no the RPG
00691       gb.sound.playPattern(mob_death_sound,0);
00692     }
00693     if(mobs_size[thisMob] == boss_size)
00694       score += 4;
00695     setSplash(mobs_x[thisMob], mobs_y[thisMob]);
00696     int x, y;
00697     if(screenCoord(mobs_x[thisMob], mobs_y[thisMob], x, y)){
00698       gb.display.fillRect(x-1, y-1, mobs_size[thisMob]+1, mobs_size[thisMob]+1);
00699     }
00700     //gb.buzz(1400,20);
00701     spawnMob(thisMob);
00702     if(activeMobs < NUMMOBS){ //if the max isn't reached
00703       if(activeMobs < (kills/MOBSRATE)+INITNUMMOBS){ //every 8 mobs killed
00704         activeMobs++; //add a mob
00705         spawnMob(activeMobs-1); //spawn the mob added
00706       }
00707     }
00708   }
00709   else { //the mob survives
00710   }
00711 }
00712 
00713 
00714 
00715 #define PAUSEMENULENGTH 5
00716 const char strPlay[] PROGMEM = "Play";
00717 const char strRestart[] PROGMEM = "Restart";
00718 const char strHighScores[] PROGMEM = "High scores";
00719 const char strSystemInfo[] PROGMEM = "System Info";
00720 const char strMainMenu[] PROGMEM = "Main Menu";
00721 
00722 
00723 const char* const pauseMenu[PAUSEMENULENGTH] PROGMEM = {
00724   strPlay,
00725   strRestart,
00726   strHighScores,
00727   strSystemInfo,
00728   strMainMenu
00729 };
00730 
00731 ///////////////////////////////////// PAUSE
00732 void pausem(){
00733   while(gb.isRunning()){
00734     if(gb.update()){
00735       switch(gb.menu(pauseMenu, PAUSEMENULENGTH)){
00736       case 0: //resume
00737         gb.wait(100);
00738         gb.display.setFont(font3x5);
00739         play();
00740         gb.display.setFont(font5x7);
00741         gb.battery.show = true;
00742         break;
00743       case 1: //restart
00744         initGame();
00745         gb.display.setFont(font3x5);
00746         play();
00747         gb.display.setFont(font5x7);
00748         gb.battery.show = true;
00749         return;
00750       case 2: //high scores
00751         displayHighScores();
00752         break;
00753       case 3: //System info
00754         gb.display.setFont(font3x5);
00755         while (1) {
00756           if (gb.update()) {
00757             if (gb.buttons.pressed(BTN_C)) {
00758               gb.display.setFont(font5x7);
00759               gb.sound.playCancel();
00760               break;
00761             }
00762             //gb.display.setCursor(0, 0);
00763             gb.display.print(("Bat:"));
00764             gb.display.print(gb.battery.voltage);
00765             gb.display.println(("mV"));
00766 
00767             gb.display.print(("Bat lvl:"));
00768             gb.display.print(gb.battery.level);
00769             gb.display.println(("/4"));
00770 
00771             gb.display.print(("Light:"));
00772             gb.display.println(gb.backlight.ambientLight);
00773 
00774             gb.display.print(("Backlight:"));
00775             gb.display.println(gb.backlight.backlightValue);
00776 
00777             gb.display.print(("Volume:"));
00778             gb.display.print(gb.sound.getVolume());
00779             //gb.display.print(F("/"));
00780             //gb.display.println(gb.sound.volumeMax);
00781 
00782             gb.display.print("Mobs:");
00783             gb.display.print(activeMobs);
00784             gb.display.print("/");
00785             gb.display.println(NUMMOBS);
00786 
00787             gb.display.print("Killed:");
00788             gb.display.println(kills);
00789           }
00790         }
00791         break;
00792       case 4: //change game
00793         //gb.changeGame();
00794         gb.titleScreen(logo);
00795         break;
00796       default:
00797         return;
00798       }
00799     }
00800   }
00801 }
00802 
00803 ///////////////////////////////////// DISPLAY HIGHSCORES
00804 void displayHighScores(){
00805   while(true){
00806     if(gb.update()){
00807       gb.display.cursorX = 9+random(0,2);
00808       gb.display.cursorY = 0+random(0,2);
00809       gb.display.println(("HIGH SCORES"));
00810       gb.display.textWrap = false;
00811       gb.display.cursorX = 0;
00812       gb.display.cursorY = gb.display.fontHeight;
00813       for(byte thisScore=0; thisScore<RANKMAX; thisScore++){
00814         if(highscore[thisScore]==0)
00815           gb.display.print('-');
00816         else
00817           gb.display.print(name[thisScore]);
00818         gb.display.cursorX = LCDWIDTH-3*gb.display.fontWidth;
00819         gb.display.cursorY = gb.display.fontHeight+gb.display.fontHeight*thisScore;
00820         gb.display.println(highscore[thisScore]);
00821       }
00822       if(gb.buttons.pressed(BTN_A) || gb.buttons.pressed(BTN_B) || gb.buttons.pressed(BTN_C)){
00823         gb.sound.playOK();
00824         break;
00825       }
00826     }
00827   }
00828 }
00829 
00830 
00831 
00832 
00833 ///////////////////////////////////// INIT GAME
00834 void initGame(){
00835   //lastScore = score;
00836   if(score > highscore[RANKMAX-1]){ //if the score is better than the worse high score
00837     saveHighscore();
00838   }
00839   //scoreDisplayTimeLeft = 64;
00840   score = 0;
00841   kills = 0;
00842   currentWeapon = 0; //magnum
00843   ammo = 9999;
00844   nextShot = 0;
00845   shake_timeLeft = 0;
00846   playerLife = playerLifeMax;
00847   boss_freq = BOSSFREQ;
00848   boss_nextSpawn = boss_freq;
00849   activeMobs = INITNUMMOBS; //6 initial mobs
00850   do{
00851     do{
00852       playerX = random(0, WORLD_W) * 8;
00853       playerY = random(0, WORLD_H) * 8;
00854     }
00855     while(collideWorld(playerX, playerY, playerW, playerH));
00856     cameraX = playerX - LCDWIDTH/2 + playerW/2;
00857     cameraY = playerY - LCDHEIGHT/2 + playerW/2;
00858   }
00859   while(!spawnMobs()); //do that until mobs are spawned without error
00860   //spawn crate
00861   spawnCrate();
00862   //reset bullets
00863   for(byte thisBullet = 0; thisBullet < NUMBULLETS; thisBullet++){
00864     bullets_active[thisBullet] = false;
00865   }
00866   //reset splashes
00867   for(byte thisSplash = 0; thisSplash < NUMSPLASH; thisSplash++){
00868     splash_active[thisSplash] = false;
00869   }
00870   blast_lifespan = 0; //reset explosion
00871 }
00872 
00873 ///////////////////////////////////// PLAY
00874 void play(){
00875   gb.battery.show = false;
00876   byte i = 0;
00877   while(i < 10 && gb.isRunning()){
00878     if(gb.update()){
00879       gb.display.fontSize = 2;
00880       gb.display.cursorX = 6;
00881       gb.display.cursorY = 16;
00882       gb.display.print(("LET'S GO!"));
00883       i++;
00884     }
00885   }
00886   gb.display.fontSize = 1;
00887   gb.popup(("\x15:shoot \x16:run"), 60);
00888 
00889   while(gb.isRunning()){
00890     if(gb.update()){
00891       if(gb.buttons.pressed(BTN_C)){
00892         gb.sound.playCancel();
00893         return;
00894         //gb.battery.show = true;
00895         //pause();
00896         //gb.battery.show = false;
00897       }
00898       boolean moved = false;
00899       if(gb.buttons.repeat(BTN_RIGHT, 1)){
00900         playerDir = 3;
00901         moved = true;
00902       }
00903       else{
00904         if(gb.buttons.repeat(BTN_LEFT, 1)){
00905           playerDir = 1;
00906           moved = true;
00907         }
00908       }
00909       if(gb.buttons.repeat(BTN_DOWN, 1)){
00910         playerDir = 2;
00911         moved = true;
00912       }
00913       else{
00914         if(gb.buttons.repeat(BTN_UP, 1)){
00915           playerDir = 0;
00916           moved = true;
00917         }
00918       }
00919       if(moved){
00920         moveXYDS(playerX, playerY, playerDir, playerSpeed);
00921         if(collideWorld(playerX, playerY, playerW, playerH))
00922           moveXYDS(playerX, playerY, playerDir, -playerSpeed);
00923       }
00924       cameraX = playerX + playerW/2 - LCDWIDTH/2;
00925       cameraY = playerY + playerH/2 - LCDHEIGHT/2;
00926       shakeScreen();
00927       /*
00928       gb.display.setColor(7); // shrub shadow
00929       drawWorld(cameraX-3, cameraY-3);
00930       gb.display.setColor(5); // shrubs
00931       drawWorld(cameraX, cameraY);
00932       */
00933       int x, y;
00934       screenCoord(playerX, playerY, x, y);
00935       //gb.display.setColor(10); //shadow
00936       int8_t ox=0,oy=0;
00937       ox--;
00938       //gb.display.drawBitmap(x+ox, y+oy, playerSprite, playerDir, NOFLIP);
00939       gb.display.setColor(3); //magenta
00940       gb.display.drawBitmap(x, y, playerSprite, playerDir, NOFLIP);
00941       byte thisSprite = 0;
00942       moveMobs();
00943       drawMobs();
00944       if(nextShot)
00945         nextShot--;
00946       if(gb.buttons.repeat(BTN_A, 1) && !gb.buttons.repeat(BTN_B, 1)){
00947         shoot();
00948       }
00949       if (gb.buttons.repeat(BTN_B, 1)){
00950         playerSpeed = 2;
00951       }
00952       else {
00953         playerSpeed = 1;
00954       }
00955       moveBullets();
00956       drawBullets();
00957       explode();
00958       gb.display.setColor(4);
00959       drawSplashes();
00960       collideCrate();
00961       drawCrate();
00962       /** DRAW WORLD**/
00963       //gb.display.setColor(7); // shrub shadow
00964       //drawWorld(cameraX-2, cameraY-2);
00965       gb.display.setColor(5); // shrubs
00966       drawWorld(cameraX, cameraY);
00967       //life remaining
00968       for(byte i=0; i<=playerLifeMax/2; i+=1){
00969         if((i*2)<=playerLife){
00970           gb.display.setColor(4);
00971           gb.display.drawBitmap(LCDWIDTH-i*9+2, 0, fullHeart);
00972         }
00973         else{
00974           gb.display.setColor(0,0);
00975           gb.display.drawBitmap(LCDWIDTH-i*9+2, 0, fullHeart);
00976           gb.display.setColor(4,0);
00977           gb.display.drawBitmap(LCDWIDTH-i*9+2, 0, emptyHeart);
00978         }
00979       }
00980       if(!playerLife){
00981         if((gb.frameCount%2)==0){
00982           shake_magnitude = 2;
00983           shake_timeLeft = 1;
00984         }
00985       }
00986       else{
00987         if(playerLife == 1){
00988           shake_magnitude = 1;
00989           shake_timeLeft = 1;
00990         }
00991       }
00992 
00993       if(playerLife%2){ //odd number
00994         gb.display.setColor(4,0);
00995         gb.display.drawBitmap(LCDWIDTH-(playerLife/2+1)*9+2, 0, halfHeart);
00996       }
00997 
00998       drawAmmoOverlay();
00999 
01000       displayScore();
01001       for(byte thisMob=0; thisMob<activeMobs; thisMob++){
01002         if(gb.collideRectRect(mobs_x[thisMob],mobs_y[thisMob], mobs_size[thisMob], mobs_size[thisMob],
01003         playerX, playerY, playerW, playerH)){
01004           playerLife--;
01005           //pokConsoleAddMessage(MSG_PRINT,V_INT16,playerLife);
01006           shake_magnitude = 2;
01007           shake_timeLeft = 4;
01008           if(mobs_size[thisMob] == boss_size){
01009             playerLife--;
01010             shake_magnitude = 3;
01011             shake_timeLeft = 4;
01012           }
01013           //int hazefactor = (255-42*playerLife)*2/3;
01014           //for (uint16_t k =0 ; k<16; k++) hazepalette[k] = pokInterpolateColor(palette[k],palette[4],hazefactor);
01015           gb.sound.playPattern(player_damage_sound, 0);
01016           spawnMob(thisMob);
01017           if(playerLife < 0){
01018             byte timer=0;
01019             while(1){
01020               if(gb.update()){
01021                 //gb.display.setColor(1);
01022                 drawMobs();
01023                 drawBullets();
01024                 drawSplashes();
01025                 drawCrate();
01026                 drawAmmoOverlay();
01027                 displayScore();
01028                 drawWorld(cameraX, cameraY);
01029                 gb.display.drawBitmap(x-1, y-1, playerSprite, playerDir, NOFLIP);
01030                 gb.display.setColor(WHITE);
01031                 gb.display.fillRect(0,0,timer*2,LCDHEIGHT);
01032                 gb.display.fillRect(LCDWIDTH-timer*2,0,timer*2,LCDHEIGHT);
01033                 gb.display.setColor(BLACK, WHITE);
01034                 gb.display.cursorX = 12;
01035                 gb.display.cursorY = 1;
01036                 gb.display.print(("GAME OVER!"));
01037                 timer++;
01038                 if(timer==((LCDWIDTH/4)+10))
01039                   break;
01040               }
01041               //int hazefactor = 0;
01042               //for (uint16_t k =0 ; k<16; k++) hazepalette[k] = pokInterpolateColor(palette[k],palette[4],hazefactor);
01043             }
01044             while(1){
01045               if(gb.update()){
01046                 if(score > highscore[RANKMAX-1]){ //if the score is better than the worse high score
01047                   gb.display.cursorX = 2+rand()%2;
01048                   gb.display.cursorY = 0+rand()%2;
01049                   gb.display.print(("NEW HIGHSCORE"));
01050                 }
01051                 else{
01052                   gb.display.cursorX = 12;
01053                   gb.display.cursorY = 1;
01054                   gb.display.print(("GAME OVER!"));
01055                 }
01056                 gb.display.cursorX = 0;
01057                 gb.display.cursorY = 12;
01058                 gb.display.print(("You made $"));
01059                 gb.display.print(score);
01060                 gb.display.print(("\nby killing\n"));
01061                 gb.display.print(kills);
01062                 gb.display.print((" crabs."));
01063                 gb.display.cursorX = 0;
01064                 gb.display.cursorY = 40;
01065                 gb.display.print(("\x15:accept"));
01066                 if(gb.buttons.pressed(BTN_A)){
01067                   gb.sound.playOK();
01068                   break;
01069                 }
01070               }
01071             }
01072             initGame();
01073             break;
01074           }
01075         }
01076       }
01077 
01078     }
01079   }
01080 }
01081 
01082 ///////////////////////////////////// DISPLAY SCORE
01083 void displayScore(){
01084   // blue on bottom
01085   /* gb.display.setColor(10);
01086   gb.display.cursorX = -1;
01087   gb.display.cursorY = -1;
01088   gb.display.print('$');
01089   gb.display.println(score);
01090   gb.display.cursorX = 0;
01091   gb.display.cursorY = -1;
01092   gb.display.print('$');
01093   gb.display.println(score);
01094   gb.display.cursorX = 1;
01095   gb.display.cursorY = -1;
01096   gb.display.print('$');
01097   gb.display.println(score);
01098   gb.display.cursorX = -1;
01099   gb.display.cursorY = 0;
01100   gb.display.print('$');
01101   gb.display.println(score);
01102   gb.display.cursorX = 0;
01103   gb.display.cursorY = 1;
01104   gb.display.print('$');
01105   gb.display.println(score);
01106   gb.display.cursorX = -1;
01107   gb.display.cursorY = 1;
01108   gb.display.print('$');
01109   gb.display.println(score);
01110   gb.display.cursorX = 0;
01111   gb.display.cursorY = 1;
01112   gb.display.print('$');
01113   gb.display.println(score);
01114   gb.display.cursorX = 1;
01115   gb.display.cursorY = 1;
01116   gb.display.print('$');
01117   gb.display.println(score);
01118   gb.display.cursorX = 1;
01119   gb.display.cursorY = 0;
01120   gb.display.print('$');
01121   gb.display.println(score);*/
01122   // white on top
01123   gb.display.setColor(8);
01124   gb.display.cursorX = 0;
01125   gb.display.cursorY = 0;
01126   gb.display.print('$');
01127   gb.display.println(score);
01128 }
01129 
01130 ///////////////////////////////////// SHAKE SCREEN
01131 void shakeScreen(){
01132   if(shake_timeLeft){
01133     shake_timeLeft--;
01134     cameraX += random(-shake_magnitude,shake_magnitude+1);
01135     cameraY += random(-shake_magnitude,shake_magnitude+1);
01136     byte backlightStep = gb.backlight.backlightMax / 4;
01137     gb.backlight.set(gb.backlight.backlightValue-random(0,backlightStep*shake_magnitude));
01138   }
01139 }
01140 
01141 ///////////////////////////////////// LOAD HIGHSCORE
01142 void loadHighscore(){
01143   /*
01144   for(byte thisScore = 0; thisScore < RANKMAX; thisScore++){
01145     for(byte i=0; i<NAMELENGTH; i++){
01146       name[thisScore][i] = EEPROM.read(i + thisScore*(NAMELENGTH+2));
01147     }
01148     highscore[thisScore] = EEPROM.read(NAMELENGTH + thisScore*(NAMELENGTH+2)) & 0x00FF; //LSB
01149     highscore[thisScore] += (EEPROM.read(NAMELENGTH+1 + thisScore*(NAMELENGTH+2)) << 8) & 0xFF00; //MSB
01150     highscore[thisScore] = (highscore[thisScore]==0xFFFF) ? 0 : highscore[thisScore];
01151   }*/ //jonnehw
01152 }
01153 
01154 ///////////////////////////////////// SAVE HIGHSCORE
01155 void saveHighscore(){
01156   //gb.getDefaultName(name[RANKMAX-1]);
01157   gb.display.setFont(font5x7);
01158   gb.keyboard(name[RANKMAX-1], NAMELENGTH+1);
01159   highscore[RANKMAX-1] = score;
01160   for(byte i=RANKMAX-1; i>0; i--){ //bubble sorting FTW
01161     if(highscore[i-1] < highscore[i]){
01162       char tempName[NAMELENGTH];
01163       strcpy(tempName, name[i-1]);
01164       strcpy(name[i-1], name[i]);
01165       strcpy(name[i], tempName);
01166       unsigned int tempScore;
01167       tempScore = highscore[i-1];
01168       highscore[i-1] = highscore[i];
01169       highscore[i] = tempScore;
01170     }
01171     else{
01172       break;
01173     }
01174   }
01175   /*
01176   for(byte thisScore = 0; thisScore < RANKMAX; thisScore++){
01177     for(byte i=0; i<NAMELENGTH; i++){
01178       EEPROM.write(i + thisScore*(NAMELENGTH+2), name[thisScore][i]);
01179     }
01180     EEPROM.write(NAMELENGTH + thisScore*(NAMELENGTH+2), highscore[thisScore] & 0x00FF); //LSB
01181     EEPROM.write(NAMELENGTH+1 + thisScore*(NAMELENGTH+2), (highscore[thisScore] >> 8) & 0x00FF); //MSB
01182   }*/// jonnehw
01183   displayHighScores();
01184 }
01185 
01186 
01187 
01188 const byte PROGMEM logo[] =
01189 {
01190   64,36, //width and height
01191   B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111,
01192   B10000000, B00000000, B00000000, B00000000, B00000000, B00000001, B01000001, B01000001,
01193   B10000000, B00000000, B00000001, B10000000, B00000110, B00000100, B00010100, B00010001,
01194   B10000000, B00000000, B00000001, B10000000, B00000110, B00000000, B10000000, B10000001,
01195   B10000000, B00000000, B00000001, B10000000, B00000110, B00000000, B00000000, B01000001,
01196   B10001111, B00111111, B01111001, B10111001, B11101111, B10011110, B01111110, B00010001,
01197   B10011001, B10111011, B11001101, B11111011, B00110110, B00110011, B01110110, B00100001,
01198   B10011001, B10110011, B00001101, B10011000, B00110110, B00110011, B01100110, B01000101,
01199 
01200   B10011000, B00110000, B01111101, B10011001, B11110110, B00110011, B01100000, B00000011,
01201   B10011000, B00110000, B11001101, B10011011, B00110110, B00110011, B01100001, B01000001,
01202   B10011000, B00110000, B11001101, B10011011, B00110110, B00110011, B01100100, B00010101,
01203   B10011001, B10110000, B11011101, B10011011, B01110110, B00110011, B01100000, B10001001,
01204   B11001111, B00110000, B11111101, B11110011, B11110011, B10011110, B01100000, B01000001,
01205   B10000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000101, B00010101,
01206   B10100000, B00000000, B00000000, B00000000, B00000000, B00100000, B10000000, B10100001,
01207   B11000000, B00000000, B00011000, B00001100, B00000000, B00000000, B00001111, B11110101,
01208 
01209   B10010000, B00000000, B00100100, B01010010, B10000000, B11110000, B00001000, B00010011,
01210   B11010000, B00000010, B10101100, B01010110, B10000001, B11111000, B00001111, B11110001,
01211   B10011001, B01000011, B00110100, B11011010, B11100001, B11111000, B00001010, B00110101,
01212   B10010101, B01000010, B00100101, B01010010, B10000001, B11111000, B00001100, B01011001,
01213   B11011101, B11000010, B00011001, B11001100, B01100001, B01101000, B00001111, B11110001,
01214   B10000000, B01000000, B00000000, B00000000, B00000000, B11110000, B00001000, B00010101,
01215   B10000000, B10000000, B00000000, B00000000, B00000000, B00000000, B00001111, B11110001,
01216   B11000000, B00000000, B00000000, B00000000, B00000110, B00000000, B00000000, B00000101,
01217 
01218   B10000000, B00000000, B00000000, B00000000, B00001111, B00000000, B00000000, B00000011,
01219   B11000000, B00000000, B00000000, B00000000, B00000110, B00000000, B00000000, B00000001,
01220   B10010000, B00000000, B00000000, B00000000, B00001001, B00000000, B00000000, B00000101,
01221   B10000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00001001,
01222   B11000001, B01000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000001,
01223   B10010011, B11010000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000101,
01224   B10100011, B11100000, B00000000, B00000000, B00000000, B00000110, B00000000, B00000001,
01225   B10000011, B11100000, B00000101, B01000101, B01000000, B00001111, B00000101, B01000101,
01226 
01227   B10000011, B11010000, B00000010, B00000010, B00000000, B00000110, B00000010, B00000011,
01228   B10000001, B01000000, B00000001, B01000001, B01000000, B00001001, B00000001, B01000001,
01229   B10000000, B00000000, B00000100, B00010100, B00010000, B00000000, B00000100, B00010101,
01230   B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111,
01231 };
01232 
01233 const byte PROGMEM world[]=
01234 {
01235   B11001111,B11001111,
01236   B10000000,B01000000,
01237   B00000001,B11111100,
01238   B00111001,B11100000,
01239   B00001100,B00000110,
01240   B10000111,B00011111,
01241   B11000011,B11000001,
01242   B10000001,B00000001,
01243   B00111100,B00110011,
01244   B00000111,B11100000,
01245   B10000100,B00001001,
01246   B11000001,B11001111,
01247 };
01248 const byte PROGMEM tiles[]=
01249 {
01250   8,8,
01251   B01010100,
01252   B00100000,
01253   B00010100,
01254   B01000001,
01255   B10001000,
01256   B00000100,
01257   B01010001,
01258   B00001010,
01259 };
01260 const byte PROGMEM mobSprite[]=
01261 {
01262   8,8,
01263   B00000000,
01264   B00000000,
01265   B00011000,
01266   B00111100,
01267   B00011000,
01268   B00100100,
01269   B00000000,
01270   B00000000,
01271 };
01272 const byte PROGMEM bossSprite[]=
01273 {
01274   8,8,
01275   B00000000,
01276   B00100100,
01277   B00011000,
01278   B01111110,
01279   B00111100,
01280   B01111110,
01281   B00111100,
01282   B00000000,
01283 };
01284 const byte PROGMEM playerSprite[]=
01285 {
01286   8,8,
01287   B00000000,
01288   B00111100,
01289   B01011010,
01290   B01111110,
01291   B01111110,
01292   B01111110,
01293   B00111100,
01294   B00000000,
01295 };
01296 const byte PROGMEM splashSprite[]=
01297 {
01298   8,8,
01299   B00000000,
01300   B00001000,
01301   B00000000,
01302   B00011000,
01303   B00111000,
01304   B10110100,
01305   B00000000,
01306   B00010000,
01307 };
01308 const byte PROGMEM crateSprite[]=
01309 {
01310   8,8,
01311   B11111111,
01312   B10000001,
01313   B11111111,
01314   B10100011,
01315   B11000101,
01316   B11111111,
01317   B10000001,
01318   B11111111,
01319 };
01320 const byte PROGMEM fullHeart[]=
01321 {
01322   8,8,
01323   B01101100,
01324   B11111110,
01325   B11111110,
01326   B01111100,
01327   B00111000,
01328   B00010000,
01329   B00000000,
01330   B00000000,
01331 };
01332 const byte PROGMEM halfHeart[]=
01333 {
01334   8,8,
01335   B00000000,
01336   B00001100,
01337   B00011100,
01338   B00011000,
01339   B00010000,
01340   B00000000,
01341   B00000000,
01342   B00000000,
01343 };
01344 const byte PROGMEM emptyHeart[]=
01345 {
01346   8,8,
01347   B01101100,
01348   B10010010,
01349   B10000010,
01350   B01000100,
01351   B00101000,
01352   B00010000,
01353   B00000000,
01354   B00000000,
01355 };
01356 
01357 
01358 
01359 ///////////////////////////////////// GET TILE
01360 boolean getTile(uint8_t i, uint8_t j){
01361 
01362   uint8_t test;
01363   test = (pgm_read_byte(world + (j%WORLD_H)*byteWidth + (i%WORLD_W)/8) & (B10000000 >> (i % 8)));
01364   if(test)
01365     return true;
01366   else
01367     return false;
01368 }
01369 
01370 ///////////////////////////////////// DRAW WORLD
01371 void drawWorld(int16_t x, int16_t y){
01372   int8_t i, j,
01373   w = WORLD_W,
01374   h = WORLD_H;
01375   x = wrap(x,w*8);
01376   y = wrap(y,h*8);
01377   for(j=y/8; j < (LCDHEIGHT/8 + y/8 + 1); j++) {
01378     for(i=x/8; i < (LCDWIDTH/8 + x/8 + 1); i++ ) {
01379       if(getTile(i, j)) {
01380         gb.display.drawBitmap(i*8 - x, j*8 - y, tiles);
01381       }
01382     }
01383   }
01384 }
01385 
01386 ///////////////////////////////////// COLLIDE WORLD
01387 boolean collideWorld(int16_t x, int16_t y, uint8_t w, uint8_t h){
01388   if(getTile(x/8, y/8))
01389     return true;
01390   if(getTile((x+w-1)/8, y/8))
01391     return true;
01392   if(getTile((x+w-1)/8, (y+h-1)/8))
01393     return true;
01394   if(getTile(x/8, (y+h-1)/8))
01395     return true;
01396   return false;
01397 }
01398