int lostLifeMsg( cursorType* cur, playField* pf, SDL_Surface* screen, const char* strmsg, const char* straction ) { draw(cur,pf, screen); //drawUi(screen); countdown-=getTicks(); txtWriteCenter(screen, GAMEFONTMEDIUM, strmsg, HSCREENW,HSCREENH-24); if(countdown < 1000) { txtWriteCenter(screen, GAMEFONTSMALL, STR_MENU_PRESS_B, HSCREENW,HSCREENH+12); //Wait for anykey if(getButton(C_BTNB) || countdown < -6000 || getInpPointerState()->isDown ) { resetBtn(C_BTNB); resetMouseBtn(); //Subtract lives if(!player()->inEditor) { if(player()->lives != -1) { player()->lives--; } if(player()->lives==0) { setGameOver(); } else { //Lost a life, but did not get gameover, upload the death statsUpload(player()->level, player()->hsEntry.time, player()->hsEntry.moves,player()->hsEntry.combos,player()->hsEntry.score, straction,0, NULL); setMenu(menuStateNextLevel); } } //Clear score player()->hsEntry.score=0; //Goto cleanup, then menu cleanUpGame(); startTransition(screen, TRANSITION_TYPE_ROLL_IN, 700); return(1); } } return(0); }
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); }
//Return 0 until a string is present in state->str. int inpStrGet(inpStrState* state, int menuPosX, int menuPosY, int blink) { int cy,cx; char hack[2]={ ' ',0x00 }; int hsKeyboardWasClicked=0; txtWriteCenter(state->dstSurface, FONTSMALL, STR_STRINPUT_CONTROLS, HSCREENW,HSCREENH+108); if( getChar() ) { if( getChar() == SDLK_RETURN ) { //Save menuPosY=4; hsKeyboardWasClicked=1; } if( getChar() == SDLK_BACKSPACE && strlen( state->str ) > 0 ) { state->str[ strlen(state->str)-1 ]=0; } else if( getChar() > 31 && getChar() < 123 && strlen( state->str ) < state->maxLen+1 ) { state->str[ strlen(state->str) ] = getChar(); state->str[ strlen(state->str)+1 ] = 0x0; } } sprintf(state->_buf, "%s %s", state->prompt, state->str); txtWrite(state->dstSurface, FONTSMALL, state->_buf, HSCREENW-110, HSCREENH-45); for(cy=0; cy < kbRows; cy++) { for(cx=0; cx < kbCols; cx++) { if( (menuPosX==cx && menuPosY==cy) && !blink && !( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT ) ) { txtWrite(state->dstSurface, FONTSMALL, "[_]", (HSCREENW-70)+(cx)*16-8, (HSCREENH-9)+cy*15); } hack[0]=(*(state->kb))[cy][cx]; txtWrite(state->dstSurface, FONTSMALL, hack, (HSCREENW-70)+cx*16, (HSCREENH-10)+cy*15); hack[0]=0; if( isBoxClicked( getTxtBox() ) ) { menuPosX=cx; menuPosY=cy; hsKeyboardWasClicked=1; } } } //Blink "Save" underline if selected if( menuPosY==4 && blink) { if(menuPosX > 9) menuPosX=0; txtWriteCenter(state->dstSurface, FONTSMALL, " _____ ", HSCREENW, HSCREENH+50); } txtWriteCenter(state->dstSurface, FONTSMALL, "[ENTER]", HSCREENW, HSCREENH+50); if( isBoxClicked( getTxtBox() ) ) { menuPosY=4; hsKeyboardWasClicked=1; } //Blink "Caps" underline if selected if( menuPosX==10 && blink) { if(menuPosY >3) menuPosY =1; txtWrite( state->dstSurface, FONTSMALL, " ____", HSCREENW-130, HSCREENH+10 ); } txtWrite( state->dstSurface, FONTSMALL, "[Caps]", HSCREENW-130, HSCREENH+10 ); if( isBoxClicked( getTxtBox() )) { menuPosX=10; hsKeyboardWasClicked=1; } //If the cursor is being used, show "delete" button, this is only usable with pointer. if( getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT ) { txtWrite(state->dstSurface, FONTSMALL, "[DEL]", (HSCREENW+38), (HSCREENH-25) ); if( isBoxClicked( getTxtBox() )) { menuPosY=5; hsKeyboardWasClicked=1; } } //Switch layouts if we're at posX 10 if( menuPosX == 10 && (getButton( C_BTNB ) || hsKeyboardWasClicked) ) { resetBtn( C_BTNB ); if(state->kb==&kbl) { state->kb=&kbh; } else if(state->kb==&kbh) { state->kb=&kbl; } } else if( menuPosY==4 && ( getButton( C_BTNB ) || hsKeyboardWasClicked ) ) //Return true { resetBtn( C_BTNB ); if(strlen( state->str ) >= state->minLen) { return(1); } } else if( getButton( C_BTNB ) || (hsKeyboardWasClicked && menuPosY < 5) ) { resetBtn( C_BTNB ); resetMouseBtn(); if( strlen( state->str ) < state->maxLen+1) { state->str[ strlen(state->str) ] = (*(state->kb))[menuPosY][menuPosX]; state->str[ strlen(state->str)+1 ] = 0; } } else if( getButton( C_BTNA ) || (hsKeyboardWasClicked && menuPosY == 5) ) { resetBtn( C_BTNA); if(strlen(state->str) > 0) { state->str[ strlen(state->str)-1 ]=0; } } return(0); }
int runEditor(SDL_Surface* screen) { SDL_Rect selBrickRect; getInpPointerState()->escEnable=1; if( editorState == EDITOR_MAIN ) { if(getButton(C_BTNMENU) || isPointerEscapeClicked() ) { resetBtn( C_BTNMENU ); resetMouseBtn(); changed++; //If it was 0 then it will become 1 (saved) exit. If it was 1 it becomes 2 (not saved). if( changed != 2 ) { editorCleanUp(); startTransition(screen, TRANSITION_TYPE_ROLL_IN, 500 ); return(STATEMENU); } } //We detect if the "preview" brick on the left is clicked, we do this now so we can reset the click so that it does not hit the board selBrickRect.x = HSCREENW-125; selBrickRect.y = HSCREENH-85; selBrickRect.w = selBrickRect.x+20; selBrickRect.h = selBrickRect.y+20; //Also, we can only click it if a teleport destination is not being placed. if( isBoxClicked(&selBrickRect) && teleState==0 ) { editorState=EDITOR_BRICKS_SELECTION; resetMouseBtn(); } //We detect mouse-save input here so it won't hit the board. selBrickRect.x = HSCREENW-145; selBrickRect.y = HSCREENH+42; selBrickRect.w = selBrickRect.x+59; selBrickRect.h = selBrickRect.y+24; if( isBoxClicked(&selBrickRect) && changed>0) { changed=EDITOR_SAVEBTN_CLICKED; resetMouseBtn(); } //We check if the cursor is in the field (if it is not, brick-placement is blocked so we don't place bricks when clicking outside of the field). if( isPointerInBox(&fieldRect) || getInpPointerState()->timeSinceMoved > POINTER_SHOW_TIMEOUT ) { allowBrickToBePlaced=1; } else { allowBrickToBePlaced=0; } //Handle movement if(getButton(C_UP)) { resetBtn(C_UP); moveCursor(&cur, 0,DIRUP, 0); } if(getButton(C_DOWN)) { resetBtn(C_DOWN); moveCursor(&cur, 0,DIRDOWN,0); } if(getButton(C_LEFT)) { resetBtn(C_LEFT); moveCursor(&cur, DIRLEFT,0, 0); } if(getButton(C_RIGHT)) { resetBtn(C_RIGHT); moveCursor(&cur, DIRRIGHT,0, 0); } //Handle mouse input if( getInpPointerState()->timeSinceMoved==0 && !cur.lock ) { setCursor(&cur, getInpPointerState()->curX,getInpPointerState()->curY ); } if(getButton(C_BTNB)) { resetBtn(C_BTNB); selBrick++; if(selBrick==RESERVED) selBrick++; if(selBrick>NUMTILES) selBrick=1; } if(getButton(C_BTNA)) { resetBtn(C_BTNA); selBrick--; if(selBrick==RESERVED) selBrick--; if(selBrick<1) selBrick=NUMTILES; } //Is place brick button being pressed, and if it is, are we allowed to place the brick? if( (getButton(C_BTNX) || getInpPointerState()->isDown ) && selBrick != RESERVED && allowBrickToBePlaced ) { //We remove the brick before placing a new one if it's not a teleport or if it's a switch (not switch-target). if( selBrick!=TELESRC && !((editIsSwitch(selBrick)&&teleState==1) ) ) { editorRemoveBrickUnderCursor(); } if(selBrick==TELESRC || editIsSwitch(selBrick) ) { resetMouseBtn(); resetBtn(C_BTNX); if(teleState==0) { //Save source pos teleSrcPos[0] = cur.x; teleSrcPos[1] = cur.y; teleState++; } else { //Add to list if(editIsSwitch(selBrick)) { teleAddToList( pf.levelInfo->switchList, teleSrcPos[0], teleSrcPos[1], cur.x, cur.y ); //printf("Number of members in switchList: %i\n", listSize(pf.levelInfo->switchList) ); cur.x = teleSrcPos[0]; cur.y = teleSrcPos[1]; editAddToBoard(selBrick); } else { teleAddToList( pf.levelInfo->teleList, teleSrcPos[0], teleSrcPos[1], cur.x, cur.y ); } //Reset state teleState=0; } } else { editAddToBoard(selBrick); } //Not a teleport changed=1; } if( getButton(C_BTNY) ) { //If we are trying to remove an empty teleport if(telePresent(pf.levelInfo->teleList, cur.x, cur.y) && selBrick!=TELESRC) { resetBtn(C_BTNY); selBrick=TELESRC; } else { if(selBrick!=RESERVED) { editorPickBrickUnderCursor(); } editorRemoveBrickUnderCursor(); } } if( getInpPointerState()->isDown && selBrick==RESERVED ) { editorRemoveBrickUnderCursor(); } if(getButton(C_BTNSELECT) || changed==EDITOR_SAVEBTN_CLICKED) { resetBtn(C_BTNSELECT); FILE *f = fopen(fileName, "w"); int x,y; sprintf(buf, "#Author of level\nauthor=%s\n\n", pf.levelInfo->author); fputs(buf,f); sprintf(buf, "#Name of the level\nlevelname=%s\n\n", pf.levelInfo->levelName); fputs(buf,f); sprintf(buf, "#Seconds to complete level\nseconds=%i\n\n", pf.levelInfo->time); fputs(buf,f); sprintf(buf, "bgfile=%s\n", pf.levelInfo->bgFile); fputs(buf,f); sprintf(buf, "tilebase=%s\n", pf.levelInfo->tileBase); fputs(buf,f); sprintf(buf, "explbase=%s\n", pf.levelInfo->explBase); fputs(buf,f); sprintf(buf, "wallbase=%s\n", pf.levelInfo->wallBase); fputs(buf,f); sprintf(buf, "sounddir=%s\n", pf.levelInfo->soundDir); fputs(buf,f); sprintf(buf, "charbase=%s\n", pf.levelInfo->fontName); fputs(buf,f); sprintf(buf, "cursorfile=%s\n", pf.levelInfo->cursorFile); fputs(buf,f); sprintf(buf, "startimage=%s\n", (pf.levelInfo->startImg)?pf.levelInfo->startImg:"none"); fputs(buf,f); sprintf(buf, "stopimage=%s\n", (pf.levelInfo->stopImg)?pf.levelInfo->stopImg:"none"); fputs(buf,f); sprintf(buf, "showtelepath=%i\n", (pf.levelInfo->showTelePath) ); fputs(buf,f); sprintf(buf, "showswitchpath=%i\n", (pf.levelInfo->showSwitchPath) ); fputs(buf,f); //Teleports char* str = teleMkStrings(pf.levelInfo->teleList, "teleport"); if(str) //Returns 0 if there's no teleports { fputs("\n#Teleports\n",f); fputs(str,f); free(str); } //Switches str = teleMkStrings(pf.levelInfo->switchList, "switch"); if(str) //Returns 0 if there's no teleports { fputs("\n#Switches\n",f); fputs(str,f); free(str); } fputs("\n#The level-data block\n[data]",f); if(f) { for(y=0; y < FIELDSIZE; y++) { fputc('\n',f); for(x=0; x < FIELDSIZE; x++) { if(pf.board[x][y]) { fprintf(f,"%02i", pf.board[x][y]->type); } else { fprintf(f,"00"); } } } fputc('\n',f); changed=0; fclose(f); //Refresh the list of userLevels. addUserLevel(fileName); } } } //Editor in main state, don't ignore input draw(&cur, &pf, screen); if(changed==2) { txtWriteCenter(screen, FONTMEDIUM, STR_EDIT_NOT_SAVED_WARNING, HSCREENW,HSCREENH-20); txtWriteCenter(screen, FONTSMALL, STR_EDIT_PRESS_EXIT_TO_EXIT, HSCREENW,HSCREENH); txtWriteCenter(screen, FONTSMALL, STR_EDIT_PRESS_SAVE_TO_SAVE, HSCREENW,HSCREENH+10); } txtWriteCenter(screen, FONTSMALL,STR_EDIT_STATUS, HSCREENW-115,HSCREENH+80); txtWriteCenter(screen, FONTSMALL, (changed)?STR_EDIT_UNSAVED:STR_EDIT_SAVED, HSCREENW-115,HSCREENH+89); txtWriteCenter(screen, FONTSMALL,fileName, HSCREENW,HSCREENH+110); txtWriteCenter(screen, FONTSMALL,STR_EDIT_CONTROLS, HSCREENW,HSCREENH-120); //Write which keys are used to cycle selected brick. txtWriteCenter(screen, FONTSMALL,STR_EDIT_PREVBRICK_KEY,HSCREENW-142,HSCREENH-80); txtWriteCenter(screen, FONTSMALL,STR_EDIT_NEXTBRICK_KEY,HSCREENW-88,HSCREENH-80); //Draw the currently selected brick. drawBrick(screen, selBrick,HSCREENW-125,HSCREENH-85); //Write brick name. txtWriteCenter(screen, FONTSMALL, str_brick_names[selBrick], HSCREENW-116,HSCREENH-56 ); //Tell if we're placing teleport source or destination if(selBrick==TELESRC && teleState==0) { txtWriteCenter(screen, FONTSMALL, "(From)", HSCREENW-115,HSCREENH-41); } else if(teleState) { if(selBrick==TELESRC) { txtWriteCenter(screen, FONTSMALL, "(To)", HSCREENW-115,HSCREENH-41); } else { txtWriteCenter(screen, FONTSMALL, "(Target)", HSCREENW-115,HSCREENH-41); } drawPath(screen, teleSrcPos[0], teleSrcPos[1], cur.x, cur.y, 1); } //Draw all the telepaths. drawAllTelePaths(screen, pf.levelInfo->teleList); //Draw switchpath we hover above listItem* t = &pf.levelInfo->switchList->begin; while( LISTFWD(pf.levelInfo->switchList, t) ) { telePort_t* tp=(telePort_t*)t->data; if(cur.x == tp->sx && cur.y == tp->sy) { drawTelePath( screen, tp, 1 ); } } //Draw all switchpaths drawAllTelePaths(screen, pf.levelInfo->switchList); if( (getInpPointerState()->timeSinceMoved < POINTER_SHOW_TIMEOUT) && (changed > 0) ) { drawSprite(screen, saveBtnSprite, HSCREENW-145, HSCREENH+42 ); } //Draw brick-selection if( editorState == EDITOR_BRICKS_SELECTION ) { SDL_BlitSurface(selBrickBG , NULL, screen, &(setting()->bgPos) ); //Draw bricks in a 6*4 grid int px,py,bnum=BRICKSBEGIN; static int brickSelOfX = HSCREENW - 78 + 8; static int brickSelOfY = HSCREENH - 54 + 8; for(py=0;py < 4; py++) { for(px=0; px < 6; px++) { if( bnum > NUMTILES ) break; selBrickRect.x = brickSelOfX+(24*px); selBrickRect.y = brickSelOfY+(24*py); selBrickRect.w = selBrickRect.x+20; selBrickRect.h = selBrickRect.y+20; //We set bricks on mouseover, this way we get the description too (maybe punch a hole in the dots where the text is?) if( isPointerInBox(&selBrickRect) ) { selBrick=bnum; } //We continue back to the main editor if( isPointerClicked() ) { resetMouseBtn(); editorState=EDITOR_MAIN; } drawBrick(screen, bnum, selBrickRect.x, selBrickRect.y ); bnum++; } } } return(STATEEDIT); }