void drawShowCountDown(SDL_Surface* screen,int i) { psysSet_t ps; drawSprite(screen, graphics.countDownSpr[i], HSCREENW-140/2,HSCREENH-60/2); if(i!=lastShown) { ps.layer=PSYS_LAYER_TOP; ps.x=HSCREENW-140/2; ps.y=HSCREENH-60/2; ps.vel=20; // +/- in each dir ps.life=1000; ps.lifeVar=1300; ps.fade=0; ps.gravity=0; ps.bounce=1; //If 1, particles will bounce off screen borders ( (vel * -1)/2 ) ps.fadeColor=0x00; ps.srcImg=graphics.countDownSpr[i]->img; ps.srcRect=graphics.countDownSpr[i]->clip; spawnParticleSystem(&ps); lastShown=i; } }
void drawTitle(SDL_Surface* screen, msg_t* m) { SDL_Rect srcCut; int vis; ticksToNextPs += getTicks(); if(ticksToNextPs > 60) { ticksToNextPs=0; ps.layer=PSYS_LAYER_TOP; ps.bounce=0; ps.x=m->rTitle.x; ps.y=m->rTitle.y; ps.srcImg=m->surfTitle; ps.srcRect.w=m->surfTitle->w; ps.srcRect.h=m->surfTitle->h; spawnParticleSystem( &ps ); } srcCut.x=0; srcCut.y=0; vis = (HSCREENW+160)-m->rTitle.x; srcCut.w= (vis<0)?0:vis; srcCut.h=m->surfTitle->h; SDL_BlitSurface( m->surfTitle, &srcCut, screen, &m->rTitle ); }
void draw(cursorType* cur, playField* pf, SDL_Surface* screen) { int x,y; listItem* t; //general purpose, reusable psysSet_t ps; SDL_BlitSurface(graphics.boardImg , NULL, screen, &(setting()->bgPos) ); for(x=0;x<NUMTILES;x++) { playAni(graphics.tileAni[x]); } //Draw static bricks for(y=0; y < FIELDSIZE; y++) { for(x=0; x < FIELDSIZE; x++) { //Bricks-Walls if(pf->board[x][y] && pf->board[x][y]->type != RESERVED) { //We treat walls/glue/oneways/switches/evilbricks/copybricks and rembricks as walls (they will have the walltile defined) if( isWall(pf, x, y) ) { drawSprite(screen, graphics.walls[pf->board[x][y]->wall], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } if( pf->board[x][y]->type != STDWALL && graphics.tiles[pf->board[x][y]->type-1]) { //We draw the animated extra-tiles if they exist. if(graphics.tileAni[pf->board[x][y]->type-1]) { if( !isSwitch( pf->board[x][y] ) ) { drawAni(screen, graphics.tileAni[pf->board[x][y]->type-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } else { //We only end here when it's a switch if( (pf->board[x][y]->type==SWON)?pf->board[x][y]->isActive:!pf->board[x][y]->isActive) { drawAni(screen, graphics.tileAni[SWON-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } else { drawAni(screen, graphics.tileAni[SWOFF-1], pf->board[x][y]->pxx-5, pf->board[x][y]->pxy-5); } } //Fall back to the static non-moving tiles if no animation is found. } else { if( !isSwitch( pf->board[x][y] ) ) { drawSprite(screen, graphics.tiles[pf->board[x][y]->type-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } else { if( (pf->board[x][y]->type==SWON)?pf->board[x][y]->isActive:!pf->board[x][y]->isActive) { drawSprite(screen, graphics.tiles[SWON-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } else { drawSprite(screen, graphics.tiles[SWOFF-1], pf->board[x][y]->pxx, pf->board[x][y]->pxy); } } } } // not a wall. } //Not a reserved brick. /*else if( pf->board[x][y] && pf->board[x][y]->type == RESERVED ) { drawSprite(screen, graphics.tiles[RESERVED-1], x*brickSize+boardOffsetX, y*brickSize+boardOffsetY); }*/ } } //xy loop //Draw moving bricks t=pf->movingList; brickType* b; while( (t = t->next) ) { b=(brickType*)t->data; if(graphics.tileAni[b->type-1]) { drawAni(screen, graphics.tileAni[b->type-1], b->pxx-5, b->pxy-5); } else { drawSprite(screen, graphics.tiles[b->type-1], b->pxx, b->pxy); } } //Particle systems that are between bricks and die animantion runParticlesLayer(screen, PSYS_LAYER_UNDERDEATHANIM); //Draw dying bricks, animation? t=pf->removeList; while( (t = t->next) ) { b=(brickType*)t->data; //Draw base brick if time enough left if(b->tl > (pf->levelInfo->brick_die_ticks/2)) { if(graphics.tileAni[b->type-1]) { drawAni(screen, graphics.tileAni[b->type-1], b->pxx-5, b->pxy-5); } else { drawSprite(screen, graphics.tiles[b->type-1], b->pxx, b->pxy); } } int explFrame = 16*(pf->levelInfo->brick_die_ticks-b->tl)/pf->levelInfo->brick_die_ticks; drawAniFrame(screen, graphics.brickExpl[b->type-1], b->pxx-5, b->pxy-5,explFrame); //Spawn particles for brick death if(explFrame==8 && pf->levelInfo->brickDieParticles) { ps.layer=pf->levelInfo->brickDieParticles; ps.x=b->pxx; ps.y=b->pxy; ps.vel=50; ps.life=750; ps.lifeVar=1000; ps.gravity=0; ps.bounce=0; ps.srcImg=graphics.tiles[b->type-1]->img; ps.srcRect=graphics.tiles[b->type-1]->clip; spawnParticleSystem(&ps); } } //Teleport overlay t = pf->levelInfo->teleList; telePort_t* tp; while( (t=t->next) ) { tp = (telePort_t*)t->data; if(graphics.tileAni[TELESRC-1]) { drawAni(screen, graphics.tileAni[TELESRC-1], boardOffsetX+20*tp->sx-5, boardOffsetY+20*tp->sy-5); } else { drawSprite(screen, graphics.tiles[TELESRC-1], boardOffsetX+20*tp->sx, boardOffsetY+20*tp->sy); } //if cursor is on it, draw the path too if(cur->x == tp->sx && cur->y == tp->sy) { drawTelePath( screen, tp, 1 ); } } //Particles runParticles(screen); //Cursor updateCursor(cur); if(!cur->lock) drawSprite(screen, graphics.curSpr[0], cur->px, cur->py); else drawSprite(screen, graphics.curSpr[1], cur->px, cur->py); if(graphics.curSpr[0] && cur->moving ) { ps.layer=PSYS_LAYER_TOP; ps.x=cur->px; ps.y=cur->py; ps.vel=50; ps.life=100; ps.lifeVar=100; ps.gravity=0; ps.srcImg=graphics.curSpr[0]->img; ps.srcRect=graphics.curSpr[0]->clip; spawnParticleSystem(&ps); } }
int runGame(SDL_Surface* screen) { if(gameState==GAMESTATEPLAYING) { getInpPointerState()->escEnable=1; //Handle input int lim=1; //Limit cursor travel... int goUp=0, goDown=0, goLeft=0, goRight=0; if( getButton( C_UP ) ) { restartConfirm=0; if( getBtnTime( C_UP ) > REPEATDELAY ) { goUp=1; } else if(getBtnTime(C_UP)==0) { goUp=1; lim=0; } } if( getButton( C_DOWN ) ) { restartConfirm=0; if( getBtnTime( C_DOWN ) > REPEATDELAY ) { goDown=1; } else if(getBtnTime(C_DOWN)==0) { goDown=1; lim=0; } } if( getButton( C_LEFT ) ) { restartConfirm=0; if( getBtnTime( C_LEFT ) > REPEATDELAY ) { goLeft=1; } else if(getBtnTime(C_LEFT)==0) { goLeft=1; lim=0; } } if( getButton( C_RIGHT ) ) { restartConfirm=0; if( getBtnTime( C_RIGHT ) > REPEATDELAY ) { goRight=1; } else if(getBtnTime(C_RIGHT)==0) { goRight=1; lim=0; } } //Pause ? if( getButton( C_BTNMENU ) || isPointerEscapeClicked() ) { resetBtn( C_BTNMENU ); gamePause(screen); return(STATEMENU); } //Retry if( getButton( C_BTNSELECT ) || (getInpPointerState()->timeSinceMoved<POINTER_SHOW_TIMEOUT && isBoxClicked(&ptrRestartRect)) ) { resetBtn( C_BTNSELECT ); resetMouseBtn(); if(!restartConfirm) { restartConfirm=1; } else if(restartConfirm) { gameRestart(screen); } } //Handle mouse input if( getInpPointerState()->timeSinceMoved==0 && !cur.lock ) { setCursor(&cur, getInpPointerState()->curX,getInpPointerState()->curY ); } if(!getInpPointerState()->isDown) { mouseGrab=0; //Allow moving the cursor around with the input device when no brick is below, just for effect } else { brickType* b=brickUnderCursor(&pf, cur.x,cur.y); //We're over a brick, tell curser it's position, it will be locked later because we grab it now if( b ) { getInpPointerState()->startX=b->dx; getInpPointerState()->startY=b->dy; if( !cur.lock ) { mouseGrab=1; getInpPointerState()->startX=getInpPointerState()->curX; getInpPointerState()->startY=getInpPointerState()->curY; } else { if( b->dx > getInpPointerState()->curX ) { //Drag Left if( b->dx == b->sx && getInpPointerState()->startX != getInpPointerState()->curX ) { goLeft=1; } } else if( b->dx < getInpPointerState()->curX ) { //Drag Right if( b->dx == b->sx && getInpPointerState()->startX != getInpPointerState()->curX ) { goRight=1; } } } } else { mouseGrab=0; } } // printf("x:%i\n", getInpPointerState()->curX ); //Drag if( getButton( C_BTNX ) || getButton( C_BTNB ) || mouseGrab || isPointerClicked() ) { //Remove "Restart" question restartConfirm=0; //Magnet to brick if it's moving brickType* b=brickUnderCursor(&pf, cur.dx, cur.dy); if( !cur.lock && b ) { //Attach cursor cur.lock=1; b->curLock=1; cur.x=cur.dx; cur.y=cur.dy; cur.px = b->pxx-4; cur.py = b->pxy-4; sndPlay( SND_BRICKGRAB, cur.px ); } int movedBrick=0; //We're holding a brick, and it's not falling if( b ) { if( (goRight && curMoveBrick(&pf,b, DIRRIGHT)) || (goLeft && curMoveBrick(&pf,b, DIRLEFT)) ) { movedBrick=1; b->curLock=1; cur.lock=1; } } //Moved brick if(movedBrick) { player()->hsEntry.moves++; sndPlay(SND_BRICKMOVE, cur.px); ps.layer=PSYS_LAYER_TOP; ps.x=b->pxx; ps.y=b->pxy+18; ps.vel=50; ps.life=500; ps.lifeVar=250; ps.gravity=1; ps.srcImg=stealGfxPtr()->tiles[b->type-1]->img; ps.srcRect=stealGfxPtr()->tiles[b->type-1]->clip; ps.srcRect.y += 18; ps.srcRect.h = 2; spawnParticleSystem(&ps); } } else { cur.lock=0; } if(!cur.lock) { if( goLeft ) moveCursor(&cur, DIRLEFT, 0, lim); if( goRight ) moveCursor(&cur, DIRRIGHT, 0, lim); if( goUp ) moveCursor(&cur, 0, DIRUP, lim); if( goDown ) moveCursor(&cur, 0, DIRDOWN, lim); } //Sim first, so moving blocks get evaluated before getting moved again simField(&pf, &cur); //Do rules int ret=doRules(&pf); //Draw scene draw(&cur,&pf, screen); //Draw a path to show where we are pulling the brick if( mouseGrab ) drawPath( screen, getInpPointerState()->startX,getInpPointerState()->startY,getInpPointerState()->curX,getInpPointerState()->startY,1 ); //If no more bricks, countdown time left. if(ret == NOBRICKSLEFT) { if( !justWon ) { sndPlay(SND_WINNER,160); } justWon++; pf.levelInfo->time -= 1000; player()->hsEntry.score +=1; if(getButton(C_BTNX) || getButton(C_BTNB) || isPointerClicked() ) { resetBtn(C_BTNX); resetBtn(C_BTNB); resetMouseBtn(); while(pf.levelInfo->time > 0) { player()->hsEntry.score +=1; pf.levelInfo->time -= 1000; } } if(justWon > 50) { sndPlayOnce(SND_SCORECOUNT, 160); } if(pf.levelInfo->time < 1) { //Completed level player()->timeouts=0; pf.levelInfo->time=0; sndPlay(SND_VICTORY, 160); if(!player()->inEditor) { //Don't submit if it was from the leveleditor statsSubmitBest(); setMenu(menuStateFinishedLevel); if(pf.levelInfo->stopImg) { gameState=GAMESTATESTOPIMAGE; return(STATEPLAY); } } else { setLevelCompletable(pf.levelInfo->file, 1); } cleanUpGame(); startTransition(screen, TRANSITION_TYPE_ROLL_IN, 700); return(STATEMENU); } } else if(ret > 0) //Player destroyed bricks. { if(ret > 2) //Check for combo's { ///TODO: Some nice text effect? How about dissolving an image into a particle system? printf("%i Combo!\n",ret); player()->hsEntry.combos++; } player()->hsEntry.score += ret*ret*11*(player()->level+1); } //if ret > -1 then ret == number of bricks destroyed if(ret>-1) { //Update time: pf.levelInfo->time -= getTicks(); player()->hsEntry.time += getTicks(); if(pf.levelInfo->time < 1 && ret!=NOBRICKSLEFT ) { countdown=4000; gameState=GAMESTATEOUTOFTIME; if( !player()->inEditor ) { player()->timeouts++; } sndPlay(SND_TIMEOUT, 160); } } //Check if level is unsolvable. if(ret==UNSOLVABLE) { countdown=2000; gameState=GAMESTATEUNSOLVABLE; if( !player()->inEditor ) { player()->timeouts++; } sndPlay(SND_LOSER, 160); } else if(ret==LIFELOST) { countdown=2000; gameState=GAMESTATELIFELOST; if( !player()->inEditor ) { player()->timeouts++; } sndPlay(SND_LOSER, 160); } //Draw question if(restartConfirm) { sprintf(buf,STR_GAME_RESTARTWARNING); txtWriteCenter(screen, GAMEFONTMEDIUM, buf, HSCREENW, HSCREENH-20); sprintf(buf,STR_GAME_RESTARTCONFIRM); txtWriteCenter(screen, GAMEFONTSMALL, buf, HSCREENW, HSCREENH); } else { //Draw text drawUi(screen); } //Show the restart icon if(getInpPointerState()->timeSinceMoved<POINTER_SHOW_TIMEOUT && getInpPointerState()->escEnable) { SDL_Rect ptrRestartRectC = ptrRestartRect; SDL_BlitSurface( ptrRestart,NULL, screen, &ptrRestartRectC ); } } else if(gameState==GAMESTATECOUNTDOWN) { draw(&cur,&pf, screen); countdown -=getTicks(); if( getButton( C_BTNMENU ) ) { resetBtn( C_BTNMENU ); countdownSeconds=0; countdown=0; } if( (getButton( C_BTNX ) || getButton( C_BTNB ) || getInpPointerState()->isDown ) && countdownSeconds ) { countdownSeconds=0; countdown=500; } drawShowCountDown(screen, countdownSeconds); drawUi(screen); if(countdown < 1) { countdown=1000; countdownSeconds--; if(countdownSeconds == -1) { gameState=GAMESTATEPLAYING; return(STATEPLAY); } if(countdownSeconds==0) { countdown=500; sndPlay(SND_START, 160); } else { sndPlay(SND_COUNTDOWNTOSTART, 160); } } } else if(gameState==GAMESTATEOUTOFTIME) //Menu was last in "Entering level" so it will return to that if timeout { draw(&cur,&pf, screen); //drawUi(screen); countdown-=getTicks(); //Offer to skip after dying twice on same level, but only if it is not the last level in the pack. if( player()->timeouts > 1 && player()->level+1 < getNumLevels() ) { int skipLevel = skipLevelDialog(screen); if( skipLevel==1 ) { gameState=GAMESTATESKIPLEVEL; countdown=500; } txtWriteCenter(screen, GAMEFONTMEDIUM, STR_GAME_OUTOFTIME, HSCREENW,HSCREENH-24-31); } else { if( lostLifeMsg(&cur, &pf, screen, STR_GAME_OUTOFTIME, "lostlife-timeout" ) ) { return(STATEMENU); } } } else if(gameState==GAMESTATEUNSOLVABLE) //The same as out-of-time, but with another graphics. { draw(&cur,&pf, screen); //drawUi(screen); countdown-=getTicks(); //Offer to skip after dying twice on same level, but only if it is not the last level in the pack. if( player()->timeouts > 1 && player()->level+1 < getNumLevels() ) { int skipLevel = skipLevelDialog(screen); if( skipLevel==1 ) { gameState=GAMESTATESKIPLEVEL; countdown=500; } txtWriteCenter(screen, GAMEFONTMEDIUM, buf, HSCREENW,HSCREENH-24-31); } else { if( lostLifeMsg(&cur, &pf, screen, STR_GAME_UNSOLVABLE, "lostlife-unsolvable" ) ) { return(STATEMENU); } } } else if(gameState==GAMESTATELIFELOST) { if( lostLifeMsg(&cur, &pf, screen, STR_GAME_LOSTLIFE, "lostlife-evilbrick" ) ) { return(STATEMENU); } } else if(gameState==GAMESTATESTARTIMAGE) { if(!startStopImg) { startStopImgCounter=0; startStopImg = loadImg( packGetFile("themes/", pf.levelInfo->startImg) ); if(!startStopImg) { printf("Couldn't load '%s'\n",packGetFile("themes/", pf.levelInfo->startImg)); } } startStopImgCounter+=getTicks(); if((startStopImgCounter > 500 && ( getButton(C_BTNB) || isPointerClicked() ) ) || !startStopImg) { if(startStopImg) SDL_FreeSurface(startStopImg); startStopImg=0; resetBtn(C_BTNB); resetMouseBtn(); gameState=GAMESTATECOUNTDOWN; } SDL_BlitSurface( startStopImg, 0, screen, &(setting()->bgPos) ); if(startStopImgCounter>4000) txtWriteCenter(screen, GAMEFONTSMALL, STR_GAME_PRESSB, HSCREENW,HSCREENH+80); } else if(gameState==GAMESTATESTOPIMAGE) { if(!startStopImg) { startStopImgCounter=0; startStopImg = loadImg( packGetFile("themes/", pf.levelInfo->stopImg) ); if(!startStopImg) { printf("Couldn't load '%s'\n",packGetFile("themes/", pf.levelInfo->stopImg)); } } startStopImgCounter+=getTicks(); if((startStopImgCounter > 500 && (getButton(C_BTNB) || isPointerClicked() ) ) || !startStopImg) { if(startStopImg) SDL_FreeSurface(startStopImg); startStopImg=0; resetBtn(C_BTNB); resetMouseBtn(); cleanUpGame(); startTransition(screen, TRANSITION_TYPE_ROLL_IN, 700); return(STATEMENU); } SDL_BlitSurface( startStopImg, 0, screen, &(setting()->bgPos) ); if(countdownSeconds>4000) txtWriteCenter(screen, GAMEFONTSMALL, STR_GAME_PRESSB, HSCREENW,HSCREENH+80); } else if(gameState==GAMESTATESKIPLEVEL) { doRules(&pf); simField(&pf, &cur); draw(&cur,&pf, screen); countdown-=getTicks(); if( countdown < 1 ) { countdown=500; if( boardDestroyNextBrick(&pf) == 0 ) { //Tell that we chose to skip level statsUpload(player()->level, player()->hsEntry.time, player()->hsEntry.moves,player()->hsEntry.combos,player()->hsEntry.score, "skip-level",0, NULL); pf.levelInfo->time=0; player()->hsEntry.score=0; cleanUpGame(); startTransition(screen, TRANSITION_TYPE_ROLL_IN, 700); clearParticles(); setMenu(menuStatePrepareNextLevel); return(STATEMENU); } } drawUi(screen); } return(STATEPLAY); }
void runCredits(SDL_Surface* screen) { switch(cm->state) { case MSGSTATE_TITLE_SLIDING_IN: cm->rTitle.x -= 10; if( cm->rTitle.x <= (HSCREENW-(cm->surfTitle->w/2)) ) { cm->rTitle.x=(HSCREENW-(cm->surfTitle->w/2)); cm->stateTicks += getTicks(); //wait 250 ms if(cm->stateTicks >= 250) { cm->state=MSGSTATE_NAME_SLIDING_IN; cm->stateTicks=0; } } drawTitle(screen, cm); break; case MSGSTATE_NAME_SLIDING_IN: //Draw title drawTitle(screen, cm); //Slide in name cm->nameWaving.x += 7; if( cm->nameWaving.x >= ( HSCREENW-cm->nameWaving.img->w/2 ) ) { cm->nameWaving.x = ( HSCREENW-cm->nameWaving.img->w/2 ); cm->state=MSGSTATE_NAME_DECREASE_WAVE; } waveImg( &cm->nameWaving ); break; case MSGSTATE_NAME_DECREASE_WAVE: //Draw title SDL_BlitSurface( cm->surfTitle, 0, screen, &cm->rTitle ); cm->stateTicks += getTicks(); if(cm->stateTicks > 0) { cm->stateTicks=0; cm->nameWaving.amount--; if(cm->nameWaving.amount==0) { cm->stateTicks=0; cm->state=MSGSTATE_NAME_SHAKING; //Set r.x=cm->nameWaving.x; r.y=cm->nameWaving.y; } } waveImg( &cm->nameWaving ); break; case MSGSTATE_NAME_SHAKING: if(cm->stateTicks<500) SDL_BlitSurface( cm->surfTitle, 0, screen, &cm->rTitle ); //shake cm->nWander.x=((rand()%6000)-3000)/1000; cm->nWander.y=((rand()%4000)-2000)/1000; if( abs(cm->nameWaving.x - (r.x+cm->nWander.x)) > 5) cm->nWander.x *=-1; if( abs(cm->nameWaving.y - (r.y+cm->nWander.y)) > 3) cm->nWander.y *=-1; r.x += cm->nWander.x; r.y += cm->nWander.y; if(cm->stateTicks <1500) SDL_BlitSurface( cm->nameWaving.img, 0, screen, &r ); cm->stateTicks += getTicks(); if(cm->stateTicks >= 500 && cm->stateTicks-getTicks() <= 500) { ps.layer=PSYS_LAYER_TOP; ps.vel=200; ps.life=1000; ps.lifeVar=500; spawnParticleSystem( &ps ); spawnParticleSystem( &ps ); spawnParticleSystem( &ps ); spawnParticleSystem( &ps ); } else if(cm->stateTicks >= 1500 && cm->stateTicks-getTicks() <= 1500) { ps.layer=PSYS_LAYER_TOP; ps.vel=400; ps.life=1500; ps.lifeVar=500; ps.x=cm->nameWaving.x; ps.y=cm->nameWaving.y; ps.srcImg=cm->nameWaving.img; ps.srcRect.w=cm->nameWaving.img->w; ps.srcRect.h=cm->nameWaving.img->h; spawnParticleSystem( &ps ); spawnParticleSystem( &ps ); } else if(cm->stateTicks > 3000) { //Next cm->state=MSGSTATE_NEXT_MSG; } break; case MSGSTATE_NEXT_MSG: //Update current msg currentMsgIndex++; if(currentMsgIndex == msgList->count) currentMsgIndex=0; setCurrent(); break; }; }