Pokitto Community Team / Pokittris

Dependencies:   PWMOut Pokitto

Fork of Pokittris by Nicolas Mougin

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tetris.cpp Source File

tetris.cpp

00001 // music - 8bit archade4 from www.dl-sounds.com
00002 
00003 #include "Pokitto.h"
00004 #include "tetris_gfx.h"
00005 #include "easing.h"
00006 
00007 #define REPSPEED 12
00008 
00009 Pokitto::Core game;
00010 
00011 #define HELD 0
00012 #define NEW 1
00013 #define RELEASE 2
00014 byte CompletePad, ExPad, TempPad, myPad;
00015 bool _A[3], _B[3], _C[3], _Up[3], _Down[3], _Left[3], _Right[3];
00016 bool bgNum = 1;
00017 char musicName[] = "pokittris.raw";
00018 byte palNum = 0;
00019 
00020 int topLine;
00021 byte unlockedPal=0;
00022 bool removeLine[19];
00023 byte linesToRemove=0;
00024 byte animCount;
00025 bool splodeOK=0;
00026 byte animSplode=0;
00027 
00028 void UPDATEPAD(int pad, int var) {
00029   _C[pad] = (var >> 1)&1;
00030   _B[pad] = (var >> 2)&1;
00031   _A[pad] = (var >> 3)&1;
00032   _Down[pad] = (var >> 4)&1;
00033   _Left[pad] = (var >> 5)&1;
00034   _Right[pad] = (var >> 6)&1;
00035   _Up[pad] = (var >> 7)&1;
00036 }
00037 
00038 void UpdatePad(int joy_code){
00039   ExPad = CompletePad;
00040   CompletePad = joy_code;
00041   UPDATEPAD(HELD, CompletePad); // held
00042   UPDATEPAD(RELEASE, (ExPad & (~CompletePad))); // released
00043   UPDATEPAD(NEW, (CompletePad & (~ExPad))); // newpress
00044 }
00045 
00046 byte updateButtons(byte var){
00047    var = 0;
00048    if (game.buttons.cBtn()) var |= (1<<1);
00049    if (game.buttons.bBtn()) var |= (1<<2);
00050    if (game.buttons.aBtn()) var |= (1<<3);
00051    if (game.buttons.downBtn()) var |= (1<<4);
00052    if (game.buttons.leftBtn()) var |= (1<<5);
00053    if (game.buttons.rightBtn()) var |= (1<<6);
00054    if (game.buttons.upBtn()) var |= (1<<7);
00055 
00056    return var;
00057 }
00058 
00059 
00060 
00061 // some globals...
00062 long int frameNumber = 0;
00063 long int myDelay;
00064 long int tempTime;
00065 int dropTime = 0;
00066 int slideTime = 0;
00067 byte gameMode = 0;
00068 bool paused = 0;
00069 byte menuItem;
00070 bool bgmusic = 1;
00071 
00072 byte px, py, ps, pr; // player x,y,shape,rotation
00073 byte nextTile;
00074 byte lineCount, level;
00075 int score, lines;
00076 bool okToContinue = 0;
00077 byte slideSpeed = 10;
00078 
00079 
00080 void loadPal(char num){
00081     unsigned short curPal[4];
00082     curPal[0] = pallet[(num*4)];
00083     curPal[1] = pallet[(num*4)+1];
00084     curPal[2] = pallet[(num*4)+2];
00085     curPal[3] = pallet[(num*4)+3];
00086     game.display.load565Palette(curPal);
00087 }
00088 
00089 void drawShape(byte x1, signed char y1, byte shape, byte frame) {
00090   for (char y = 0; y < 4; y++) {
00091     if (y1 + y > 1) {
00092       for (char x = 0; x < 4; x++) {
00093         byte mt = pgm_read_byte(shapeMap + (x + 4 * y) + shape * 64 + (frame * 16));
00094         if (mt > 1) {
00095           game.display.drawBitmap((x1 + x)*8, (y1 + y)*8, tile_gfx[(mt-1)+shape*6]);
00096         }
00097       }
00098     }
00099   }
00100 }
00101 
00102 bool check(signed char x1, signed char y1, char rot) {
00103     byte ret=0;
00104   for (char y = 0; y < 4; y++) {
00105     if (y1 + y >= 0) {
00106       for (char x = 0; x < 4; x++) {
00107         byte mt = pgm_read_byte(shapeMap + (x + 4 * y) + ps * 64 + (rot * 16));
00108         if (mt > 1) {
00109           if ( playfield[(x1 + x) + 16 * (y1 + y)] != 0) {
00110             ret= 1;
00111           }
00112         }
00113       }
00114     }
00115   }
00116   return ret;
00117 }
00118 
00119 void stamp(signed char x1, signed char y1, byte shape, byte rot) {
00120   for (char y = 0; y < 4; y++) {
00121     if (y1 + y >= 0) {
00122       for (char x = 0; x < 4; x++) {
00123         byte mt = pgm_read_byte(shapeMap + (x + 4 * y) + shape * 64 + (rot * 16));
00124         if (mt > 1) {
00125           playfield[(x1 + x) + 16 * (y1 + y)] = (mt-1)+shape*6;
00126         }
00127       }
00128     }
00129   }
00130 }
00131 
00132 
00133 void clearPlayfield() {
00134   for (char y = 0; y < 19; y++) {
00135     for (char x = 3; x < 13; x++) {
00136       playfield[x + 16 * y] = 0;
00137     }
00138   }
00139 }
00140 
00141 void drawBackground(){
00142   for (char y = 0; y < 22; y++) {
00143     for (char x = 0; x < 28; x++) {
00144       byte mt = bg_map[x + 28 * y + (616*bgNum)];
00145       game.display.drawBitmap(x*8, y*8, bg_gfx[mt]);
00146     }
00147   }
00148 }
00149 
00150 void drawPlayfield() {
00151     drawBackground();
00152 
00153   for (char y = 1; y < 19; y++) {
00154     for (char x = 3; x < 13; x++) {
00155       byte mt = playfield[x + 16 * y];
00156       game.display.drawBitmap((x + 5)*8, (y+1 )*8, tile_gfx[mt]);
00157     }
00158   }
00159 
00160     if(animSplode==0){
00161         // current shape
00162         drawShape(px+5, py+1, ps, pr);
00163     }
00164     // next shape?
00165     drawShape(19, 14, nextTile, 0);
00166 
00167     char text[] = "        ";
00168     sprintf(text, "%05d", score);
00169     game.display.setCursor(152,56);
00170     game.display.color=3;
00171     game.display.print(text);
00172     sprintf(text, "%5d", level);
00173     game.display.setCursor(16,96);
00174     game.display.print(text);
00175     sprintf(text, "%5d", lines);
00176     game.display.setCursor(16,48);
00177     game.display.print(text);
00178 
00179 }
00180 
00181 
00182 
00183 void checkLine() {
00184 
00185     for(char t=0; t<19; t++){
00186         removeLine[t]=0;
00187     }
00188 
00189   if (py <= 0) {
00190     loadPal(1); // default green palette
00191     gameMode = 3;  // gameOver if off top of screen
00192     frameNumber=0;
00193     return;
00194   }
00195 
00196   score++; // increase score here as it's called whenever a tile drops
00197   topLine = 0;
00198 
00199   for (char y = 0; y < 19; y++) {
00200     char line = 0;
00201     for (char x = 3; x < 13; x++) {
00202       line += playfield[x + 16 * y] != 0 ? 1 : 0;
00203     }
00204     if (line == 10) { // remove line
00205         removeLine[y]=1;
00206         linesToRemove++;
00207         if(linesToRemove==4){splodeOK=1;}
00208         lineCount++;
00209         if (lineCount == 10) {
00210             lineCount = 0;
00211             level++;
00212         }
00213         lines++;
00214         score += 10;
00215         }
00216     }
00217 
00218   for (char y = 0; y < 10; y++) {
00219     char line = 0;
00220     for (char x = 3; x < 13; x++) {
00221       topLine += playfield[x + 16 * y] != 0 ? 1 : 0;
00222     }
00223   }
00224 
00225 
00226     // mess with the palette
00227 
00228       int percent = 100;
00229       int diff = topLine;
00230 
00231       unsigned short *p;
00232       palNum = 0;//level & 31;
00233       p=pallet+(palNum*4);
00234       unsigned short curPal[4];
00235 
00236       curPal[0] = pallet[(palNum*4)];
00237       curPal[1] = pallet[(palNum*4)+1];
00238       curPal[2] = pallet[(palNum*4)+2];
00239       curPal[3] = pallet[(palNum*4)+3];
00240 
00241      int greyPal[] = {0xF800,0xF8000,0xF800,0xF800}; // it's actually RED for danger!
00242 
00243     unsigned short red[4], green[4], blue[4], red1[4], green1[4], blue1[4], red2[4], green2[4], blue2[4];
00244 
00245     for(char t=0; t<4; t++){
00246         red1[t] = (curPal[t]>>11) & 31;
00247         red2[t] = (greyPal[t]>> 11) & 31;
00248         green1[t] = (curPal[t]>> 5) & 63;
00249         green2[t] = (greyPal[t]>> 5) & 63;
00250         blue1[t] = curPal[t] & 31;
00251         blue2[t] = greyPal[t] & 31;
00252 
00253         red[t] = red1[t]+((red2[t]-red1[t])*diff/percent);
00254         green[t] = green1[t]+((green2[t]-green1[t])*diff/percent);
00255         blue[t] = blue1[t]+((blue2[t]-blue1[t])*diff/percent);
00256 
00257         curPal[t] = (red[t]<<11)+(green[t]<<5)+blue[t];
00258 
00259     }
00260 
00261     game.display.load565Palette(curPal);
00262 
00263 }
00264 
00265 
00266 // transparent 2bit bitmap with mask
00267 void drawMyBitmap(int16_t x, int16_t y, const uint8_t* bitmap, const uint8_t* mask)
00268 {
00269     int16_t w = *bitmap;
00270     int16_t h = *(bitmap + 1);
00271     bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
00272     /** visibility check */
00273     if (y<-h || y>game.display.height) return; //invisible
00274     if (x<-w || x>game.display.width) return;  //invisible
00275 
00276     /** 2 bpp mode */
00277     int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
00278     for (i = 0; i < w; i++) {
00279         byteNum = i / 4;
00280         bitNum = (i % 4)<<1;
00281         for (j = 0; j < h; j++) {
00282             uint8_t source = *(bitmap + j * byteWidth + byteNum);
00283             uint8_t source2 = *(mask + j * byteWidth + byteNum+2);
00284             uint8_t output = (source & (0xC0 >> bitNum));
00285             output >>= (6-bitNum);
00286 
00287             uint8_t output2 = (source2 & (0xC0 >> bitNum));
00288             output2 >>= (6-bitNum);
00289 
00290             if (output2 != 0) {
00291                 game.display.setColor(output);
00292                 game.display.drawPixel(x + i, y + j);
00293             }
00294         }
00295 
00296     //return;
00297     }
00298 }
00299 
00300 
00301 
00302 void titleScreen(){
00303 
00304   // background
00305   for (char y = 0; y < 22; y++) {
00306     for (char x = 0; x < 28; x++) {
00307       byte mt = bg_map[x + 28 * y];
00308       game.display.drawBitmap(x*8, y*8, bg_gfx[mt]);
00309     }
00310   }
00311 
00312 int y=48;
00313     if(frameNumber<=64){
00314                         // time, start, distance, duration
00315         #ifdef POK_SIM
00316         y = easeOutBounce(frameNumber, -48, 48+48, 64);
00317         #else
00318         y = easeOutBounce(frameNumber*4, -48, 48+48, 64);
00319         if (y>48) y=48;
00320         #endif
00321     }
00322     drawMyBitmap(16, y, title_bitmap, title_mask);
00323 
00324 
00325     char text[] = " Press A to Start ";
00326     game.display.setCursor(40,120);
00327     game.display.color=3;
00328     game.display.print(text);
00329 
00330   if(_A[NEW]){
00331     // make sure the playfield is clear!
00332       for (char y = 18; y > 0; y--) {
00333         for (char x = 3; x < 13; x++) {
00334           playfield[x + 16 * y] = 0;
00335         }
00336       }
00337 
00338     loadPal(0); // default green palette
00339     gameMode = 1;
00340   }
00341 
00342 }
00343 
00344 void gameOver(){
00345   // background
00346   for (char y = 0; y < 22; y++) {
00347     for (char x = 0; x < 28; x++) {
00348       byte mt = bg_map[x + 28 * y];
00349       game.display.drawBitmap(x*8, y*8, bg_gfx[mt]);
00350     }
00351   }
00352 
00353     int y=48;
00354     if(frameNumber<=64){
00355                         // time, start, distance, duration
00356         y = easeOutBounce(frameNumber, -48, 48+48, 64);
00357     }
00358     drawMyBitmap(1, y, gameover_bitmap, gameover_mask);
00359 
00360     char text[] = " Press A ";
00361     game.display.setCursor(62,120);
00362     game.display.color=3;
00363     game.display.print(text);
00364 
00365   if(_A[NEW]){
00366     gameMode = 0;
00367     frameNumber = 0;
00368     score=0;
00369     lines=0;
00370     level=0;
00371     splodeOK=0;
00372     animSplode=0;
00373   }
00374 
00375 }
00376 
00377 void playGame(){
00378     #ifdef POK_SIM
00379     #define SLIDECOUNT 6
00380     #define DROPCOUNT 20
00381     #else
00382     #define SLIDECOUNT 1
00383     #define DROPCOUNT 2
00384     #endif
00385 
00386     if(linesToRemove==0 && animSplode==0){
00387 
00388         if (_Left[NEW]) {
00389           if (check(px - 1, py, pr) == 0) {
00390             px--;
00391             slideTime = 0;
00392           }
00393         }
00394         if (_Right[NEW]) {
00395           if (check(px + 1, py, pr) == 0) {
00396             px++;
00397             slideTime = 0;
00398           }
00399         }
00400         if (_Left[HELD] && slideTime++ > SLIDECOUNT) {
00401           if (check(px - 1, py, pr) == 0) {
00402             px--;
00403             slideTime = 12;
00404           }
00405         }
00406         if (_Right[HELD] && slideTime++ > SLIDECOUNT) {
00407           if (check(px + 1, py, pr) == 0) {
00408             px++;
00409             slideTime = 12;
00410           }
00411         }
00412 
00413         if ((_Down[HELD]) || (dropTime++ > DROPCOUNT - (level * 2))) {
00414           dropTime = 0;
00415           if (check(px, py+1, pr) == 0) {
00416             py++;
00417           } else {
00418             // place shape and create new one
00419             stamp(px, py, ps, pr);
00420             checkLine();
00421             py = 0; px = 6; ps = nextTile; nextTile = random(6); pr = 0;
00422           }
00423         }
00424         if (_Up[NEW] && splodeOK==1) {
00425                 splodeOK=0;
00426                 animSplode=1;
00427         }
00428 
00429         if (_A[NEW]) {
00430           if (check(px, py, (pr - 1) & 3) == 0) {
00431             pr--;
00432           } else if (check(px - 1, py, (pr - 1) & 3) == 0) {
00433             pr--; px--;
00434           } else if (check(px + 1, py, (pr - 1) & 3) == 0) {
00435             pr--; px++;
00436           } else if (check(px - 2, py, (pr - 1) & 3) == 0) {
00437             pr--; px -= 2;
00438           } else if (check(px + 2, py, (pr - 1) & 3) == 0) {
00439             pr--; px += 2;
00440           }
00441           pr &= 3;
00442         }
00443 
00444         if (_B[NEW]) {
00445           if (check(px, py, (pr + 1) & 3) == 0) {
00446             pr++;
00447           } else if (check(px - 1, py, (pr + 1) & 3) == 0) {
00448             pr++; px--;
00449           } else if (check(px + 1, py, (pr + 1) & 3) == 0) {
00450             pr++; px++;
00451           } else if (check(px - 2, py, (pr + 1) & 3) == 0) {
00452             pr++; px -= 2;
00453           } else if (check(px + 2, py, (pr + 1) & 3) == 0) {
00454             pr++; px += 2;
00455           }
00456           pr &= 3;
00457         }
00458 
00459         animCount=0;
00460     }
00461 
00462         if(linesToRemove!=0){
00463             // remove some lines
00464             for(byte t=0; t<19; t++){
00465                 if(removeLine[t]==1){
00466                     if(animCount<5){
00467                         for (char x = 3; x < 13; x++) {
00468                             playfield[x + 16 * t] = 5+animCount*6;
00469                         } // x
00470                     }else{
00471                         removeLine[t]=0;
00472                         linesToRemove--;
00473                         for (char y1 = t; y1 > 0; y1--) {
00474                             for (char x = 3; x < 13; x++) {
00475                                 playfield[x + 16 * y1] = playfield[x + 16 * (y1 - 1)];
00476                             }
00477                         }
00478                     }
00479                 }
00480             }
00481             animCount++;
00482         }
00483 
00484         if(animSplode!=0){
00485 
00486             if(animSplode<6){
00487                 for (char y = 0; y < 4; y++) {
00488                     if (py + y >= 0) {
00489                         for (char x = 0; x < 4; x++) {
00490                             byte mt = pgm_read_byte(shapeMap + (x + 4 * y) + ps * 64 + (pr * 16));
00491                             if (mt > 1) {
00492                                 playfield[(px + x) + 16 * (py + y)] = 5+animSplode*6;
00493                             }
00494                         }
00495                     }
00496                 }
00497                 animSplode++;
00498             }else{
00499 
00500                 for (char y = 0; y < 4; y++) {
00501                     if (py + y >= 0) {
00502                         for (char x = 0; x < 4; x++) {
00503                             byte mt = pgm_read_byte(shapeMap + (x + 4 * y) + ps * 64 + (pr * 16));
00504                             if (mt > 1) {
00505                                 playfield[(px + x) + 16 * (py + y)] = 0;
00506                             }
00507                         }
00508                     }
00509                 }
00510                 py = 0; px = 6; ps = nextTile;
00511                 nextTile = random(6); pr = 0;
00512                 animSplode=0;
00513             }
00514         }
00515 
00516     // render screen
00517     drawPlayfield();
00518 }
00519 
00520 
00521 
00522 
00523 int main(){
00524 
00525     game.begin();
00526     game.display.width = 220; // full size
00527     game.display.height = 176;
00528     game.display.setFont(fontC64);
00529     //game.display.charSpacingAdjust = 0; //needed for the non-proportional C64 font (normal value=1)
00530     game.display.fixedWidthFont = true;
00531 
00532     loadPal(1); // default green palette
00533 
00534     px=6;
00535     gameMode=0;
00536     char oldMode = 50;
00537     myDelay=40;
00538 
00539     game.sound.playMusicStream(musicName);
00540 
00541     frameNumber=0;
00542     animCount=0;
00543     splodeOK=0;
00544     animSplode=0;
00545 
00546    while (game.isRunning()) {
00547 
00548         // if it is time to update the screen
00549         if (game.update()){
00550 
00551             frameNumber++;
00552             game.sound.updateStream();
00553             game.buttons.update();
00554             myPad = updateButtons(myPad);
00555             UpdatePad(myPad);
00556 
00557             switch (gameMode) {
00558             case 0:
00559               titleScreen();
00560                 break;
00561             case 1:
00562                 if (paused) {
00563             //        pauseMenu();
00564                 } else {
00565                     playGame();
00566                 }
00567                 break;
00568             case 3:
00569               gameOver();
00570               break;
00571             }
00572 
00573         }
00574     }
00575     return 0;
00576 }