void drawAllTelePaths( SDL_Surface* screen, listItem* l ) { listItem* it = l; telePort_t* t; while( (it=it->next) ) { t = (telePort_t*)it->data; drawTelePath(screen, t, 0); } }
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 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); }