Esempio n. 1
0
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;
  }

}
Esempio n. 2
0
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 );
}
Esempio n. 3
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);
  }

}
Esempio n. 4
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);
}
Esempio n. 5
0
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;
  };
}