#include #include #include "pieces.h" #include "pad.h" #include "main.h" #include "game.h" #include "play.h" typedef struct { int startx[4]; int starty[4]; int rotx[4][4]; int roty[4][4]; } PIECE; #define SECOND (REFRATE) //time in refresh rate intervals #define FIRSTSHIFT (SECOND*2/5) //horz shift accelerates if holding #define RESTSHIFT (SECOND/10) #define STARTWAIT (SECOND/10) //first piece to wait #define DOWNWAIT (SECOND/25) //time to wait if pressing down #define LEFT (-1) #define RIGHT (1) void drawPlayOn(GsOT *ot); void drawPlayPaused(GsOT *ot); void drawPlayNoPad(GsOT *ot); void drawPlayEnd(GsOT *ot); int padToPause(long padstate,long time); void processLeft(long padstate,int timediff); void processRight(long padstate,int timediff); void processClock(long padstate); void processAnti(long padstate); void processDown(long padstate,int timediff); int getSpeed(void); void checkLines(void); void delLines(void); void flashLines(void); void updateStats(void); extern PIECE pieces[7]; //need access to display next piece static int state; //state of play static int prevstate; //using this to draw play static int pausedstate; //state of play when paused int playarea[COLLEN][ROWLEN]; //play area holding pieces static int nextpiece; //next piece static int prevtime; //last recorded time static int prevpad; //last recorded padstate static int startwait; //waiting time for first piece to fall static int score; //score static int level; //level static int lines; //lines made static int dropwait; //time till piece automatically falls static int flashwait; //time for flashing complete lines static int newpiece; //can't down a piece if not shown static int endwait; //time for showing "game over" static int countend; //number of stuck pieces to show at end static int maybelines; //piece fixed, may have lines static int havelines; //number of lines made static int linefilled[COLLEN]; //which lines are filled int initPlay(int levelnum,long time) { int i,j; initPieces(); for (i=0;i 0) //not ready to play startwait -= timediff; else state = PLAY_ON; //go! break; case PLAY_ON: //playing game if (padToPause(padstate,time)) //checking pad status return GAME_PLAY; if (maybelines) { if (havelines) { if (flashwait <= 0) { //had lines, finished flashing delLines(); //update stuff updateStats(); havelines = 0; } else if (flashwait%10 == 0) { flashLines(); //flash at intervals flashwait -= timediff; } else flashwait -= timediff; } else { if (newPiece(nextpiece)) //set up the next piece state = PLAY_END; dropwait = getSpeed(); //set up the drop wait nextpiece = rand()*7/RAND_MAX; newpiece = 1; maybelines = 0; } } else { processLeft(padstate,timediff); //falling process padstate processRight(padstate,timediff); processClock(padstate); processAnti(padstate); processDown(padstate,timediff); } break; case PLAY_PAUSED: if ((padConnected(0)==PADout)||(padType(0)!=PADstandard)) { state = PLAY_NOPAD; //paused and then pad removed prevtime = time; prevpad = PADstart; return GAME_PLAY; } else if ((padstate & PADstart)&&(!(prevpad & PADstart))) state = pausedstate; //start pressed and unpause break; case PLAY_NOPAD: if ((padConnected(0) == PADin)&&(padType(0) == PADstandard)) state = PLAY_PAUSED; //pause game when attach pad break; case PLAY_END: if (countend) { newPiece(nextpiece); //stuck pieces fixPiece(); nextpiece = rand()*7/RAND_MAX; countend--; } else { if ((endwait <= 0)|| ((padstate & PADstart)&&(!(prevpad & PADstart)))) return GAME_RESET; //show "game over" else endwait -= timediff; } break; } prevtime = time; prevpad = padstate; return GAME_PLAY; } int padToPause(long padstate,long time) { if ((padConnected(0)==PADout)||(padType(0)!=PADstandard)) { pausedstate = state; //pause the game if pad removed state = PLAY_NOPAD; prevtime = time; prevpad = PADstart; return 1; } if ((padstate & PADstart)&&(!(prevpad & PADstart))) { pausedstate = state; //pause the game if "start" state = PLAY_PAUSED; prevtime = time; prevpad = padstate; return 1; } return 0; } void processLeft(long padstate,int timediff) { static int shiftwait = FIRSTSHIFT; if (padstate & PADLleft) { if (prevpad & PADLleft) { // was and still holding if (shiftwait <= 0) { // ready to move tryShift(LEFT); if (moveOK()) makeMove(); shiftwait = RESTSHIFT; } else // not ready to move shiftwait -= timediff; } else { // not holding and now holding tryShift(LEFT); if (moveOK()) makeMove(); shiftwait -= timediff; } } else { // not holding shiftwait = FIRSTSHIFT; } } void processRight(long padstate,int timediff) { static int shiftwait = FIRSTSHIFT; if (padstate & PADLright) { if (prevpad & PADLright) { // was and still holding if (shiftwait <= 0) { // ready to move tryShift(RIGHT); if (moveOK()) makeMove(); shiftwait = RESTSHIFT; } else // not ready to move shiftwait -= timediff; } else { // not holding and now holding tryShift(RIGHT); if (moveOK()) makeMove(); shiftwait -= timediff; } } else { // not holding shiftwait = FIRSTSHIFT; } } void processClock(long padstate) { if (padstate & PADRright) if (!(prevpad & PADRright)) { //rotate clockwise tryRotClock(); if (moveOK()) makeMove(); } } void processAnti(long padstate) { if (padstate & PADRdown) if (!(prevpad & PADRdown)) { //rotate anticlockwise tryRotAnti(); if (moveOK()) makeMove(); } } void processDown(long padstate,int timediff) { static int downwait = 0; static int downdist = 0; if (!(padstate & PADLdown)) //i'm not going to even try newpiece = 0; //to comment this function! if ((padstate & PADLdown)&&(!newpiece)) { if (!downwait) { //just read it... tryDown(); if (moveOK()) { makeMove(); downdist++; downwait = DOWNWAIT; return; } else { fixPiece(); score += downdist; downdist = 0; downwait = 0; checkLines(); maybelines = 1; return; } } else { downwait -= timediff; return; } } else if (!dropwait) { downdist = 0; downwait = 0; tryDown(); if (moveOK()) { makeMove(); dropwait = getSpeed(); return; } else { fixPiece(); checkLines(); maybelines = 1; return; } } else { downdist = 0; downwait = 0; dropwait -= timediff; } } int getSpeed(void) { //0.08s speed up per level int basic = SECOND; //1 second for first level int speedup = level * (4*SECOND/50); return (basic-speedup); } void checkLines(void) { int i,j; int fills; havelines = 0; for (i=0;i level) //may have level high through menu level = lines/10; } void drawPlay(GsOT* ot) { switch (prevstate) { case PLAY_START: case PLAY_ON: drawPlayOn(ot); break; case PLAY_PAUSED: drawPlayPaused(ot); break; case PLAY_NOPAD: drawPlayNoPad(ot); break; case PLAY_END: if (countend) drawPlayOn(ot); else drawPlayEnd(ot); break; } } void drawPlayOn(GsOT *ot) { int i,j,k; int tlx = (SCNW-ROWLEN*SIZE)/2; int tly = (SCNH-COLLEN*SIZE)/2; GsLINE line; GsBOXF box; FntPrint("\n\n\n\n\n"); FntPrint("SCORE %d\n\n",score); FntPrint("LEVEL %d\n\n",level); FntPrint("LINES %d\n\n",lines); FntPrint("NEXT\n"); line.attribute = 0; line.r = line.g = line.b = 255; line.x0 = tlx; line.y0 = tly; line.x1 = tlx+ROWLEN*SIZE; line.y1 = tly; for (i=0;i 0) { box.w = SIZE; box.x = tlx+j*SIZE; box.y = tly+COLLEN*SIZE-i*SIZE-SIZE; for (k=j+1;k