diff src/ljplay.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/ljplay.c	Fri Mar 13 00:39:12 2009 -0700
     1.3 @@ -0,0 +1,216 @@
     1.4 +/* Game loop frontend for LOCKJAW, an implementation of the Soviet Mind Game
     1.5 +
     1.6 +Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net>
     1.7 +
     1.8 +This work is free software; you can redistribute it and/or modify
     1.9 +it under the terms of the GNU General Public License as published by
    1.10 +the Free Software Foundation; either version 2 of the License, or
    1.11 +(at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU General Public License
    1.19 +along with this program; if not, write to the Free Software
    1.20 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +Original game concept and design by Alexey Pajitnov.
    1.23 +The Software is not sponsored or endorsed by Alexey Pajitnov[player], Elorg,
    1.24 +or The Tetris Company LLC.
    1.25 +
    1.26 +*/
    1.27 +
    1.28 +#include "ljplay.h"
    1.29 +#ifndef WITH_REPLAY
    1.30 +#define WITH_REPLAY 0
    1.31 +#endif
    1.32 +
    1.33 +#if WITH_REPLAY
    1.34 +#include "ljreplay.h"
    1.35 +extern const char demoFilename[];
    1.36 +
    1.37 +#endif
    1.38 +
    1.39 +
    1.40 +void play(LJView *const v[], size_t nPlayers) {
    1.41 +  int canceled = 0;
    1.42 +
    1.43 +  for (unsigned int player = 0; player < nPlayers; ++player) {
    1.44 +    LJField *const p = v[player]->field;
    1.45 +    LJControl *const ctl = v[player]->control;
    1.46 +
    1.47 +    ctl->countdown = 6;
    1.48 +    ctl->presses = 0;
    1.49 +
    1.50 +    /* Load replay if needed */
    1.51 +#if WITH_REPLAY
    1.52 +    if (p->gimmick < 0) {
    1.53 +      ctl->replaySrc = openReplay(demoFilename, p);
    1.54 +      if (!ctl->replaySrc) {
    1.55 +        return;
    1.56 +      }
    1.57 +      v[player]->backDirty = ~0;
    1.58 +      playRedrawScreen(v[player]);
    1.59 +    } else {
    1.60 +      ctl->replaySrc = 0;
    1.61 +    }
    1.62 +#endif
    1.63 +  }
    1.64 +  if (!v[0]->control->replaySrc) {
    1.65 +    for (unsigned int player = 0; player < nPlayers; ++player) {
    1.66 +      LJField *const p = v[player]->field;
    1.67 +      newGame(p);
    1.68 +      initGimmicks(p);
    1.69 +      v[player]->nLockTimes = 0;
    1.70 +      v[player]->hideNext = 0;
    1.71 +      updField(v[player], ~0);
    1.72 +    }
    1.73 +    startingAnimation(v[0]);
    1.74 +    for (unsigned int player = 0; player < nPlayers; ++player) {
    1.75 +      v[player]->control->lastKeys = 0;
    1.76 +      v[player]->control->repressKeys = 0;
    1.77 +      blitField(v[player]);
    1.78 +    }
    1.79 +  }
    1.80 +
    1.81 +  int lastTime = getTime();
    1.82 +
    1.83 +  while(v[0]->field->state != LJS_GAMEOVER && !canceled) {
    1.84 +    if (getTime() == lastTime) {
    1.85 +      yieldCPU();
    1.86 +    }
    1.87 +    canceled |= ljHandleConsoleButtons(v[0]);
    1.88 +    while (getTime() - lastTime > 0) {
    1.89 +      for (unsigned int player = 0; player < nPlayers; ++player) {
    1.90 +        LJField *const p = v[player]->field;
    1.91 +        LJControl *const ctl = v[player]->control;
    1.92 +        LJInput in = {0, 0, 0, 0};
    1.93 +        int curTime = getTime();
    1.94 +      
    1.95 +        addKeysToInput(&in, readPad(player), p, ctl);
    1.96 +
    1.97 +        // when returning from pause, catch up the speed control
    1.98 +        if (curTime - lastTime > 10
    1.99 +            || curTime - lastTime < -10) {
   1.100 +          lastTime = curTime;
   1.101 +        }
   1.102 +
   1.103 +        {
   1.104 +          int irsAttempted = (p->sounds & (LJSND_SPAWN | LJSND_HOLD))
   1.105 +                             && in.rotation && ctl->initialRotate;
   1.106 +                           
   1.107 +          // The next line does ALL the game logic.
   1.108 +          LJBits updatedRows = frame(p, &in) | gimmicks(p, ctl);
   1.109 +        
   1.110 +          v[player]->backDirty |= updatedRows;
   1.111 +          if (irsAttempted && (p->sounds & LJSND_ROTATE)) {
   1.112 +            p->sounds |= LJSND_IRS;
   1.113 +          }
   1.114 +        }
   1.115 +
   1.116 +        // items is a partly view-based gimmick
   1.117 +        if (p->gimmick == LJGM_ITEMS && (p->sounds & LJSND_SPAWN)) {
   1.118 +          v[player]->hideNext = (v[player]->field->nPieces > 7);
   1.119 +          v[player]->frontDirty |= LJ_DIRTY_NEXT;
   1.120 +        }
   1.121 +
   1.122 +        // five, four, three, two, one
   1.123 +        int curCountdown = ctl->countdown;
   1.124 +        if (p->gimmick == LJGM_ULTRA && p->gameTime >= 10500) {
   1.125 +          curCountdown = (int)(10859 - p->gameTime) / 60;
   1.126 +        } else if (p->gimmick == LJGM_BTYPE) {
   1.127 +          curCountdown = 40 - p->lines;
   1.128 +        } else if (p->gimmick == LJGM_BABY) {
   1.129 +          curCountdown = (309 - v[player]->control->presses) / 10;
   1.130 +        } else if (p->gimmick == LJGM_DRILL && (p->sounds & LJSND_LINE)) {
   1.131 +          int line = bfffo(p->tempRows);
   1.132 +          if (line < curCountdown)
   1.133 +          curCountdown = line;
   1.134 +        }
   1.135 +      
   1.136 +        // we have to wait for the new piece to come out
   1.137 +        // so that the score is credited properly
   1.138 +        if (curCountdown <= 0
   1.139 +            && (p->state == LJS_NEW_PIECE
   1.140 +                || p->state == LJS_FALLING
   1.141 +                || p->state == LJS_LANDED)) {
   1.142 +          p->state = LJS_GAMEOVER;
   1.143 +        }
   1.144 +      
   1.145 +        playSoundEffects(v[player], p->sounds, curCountdown);
   1.146 +        ctl->countdown = curCountdown;
   1.147 +
   1.148 +        // Update speedometer
   1.149 +        if (p->sounds & LJSND_LOCK) {
   1.150 +          for (int i = N_SPEED_METER_PIECES - 2; i >= 0; --i) {
   1.151 +            v[player]->lockTime[i + 1] = v[player]->lockTime[i];
   1.152 +          }
   1.153 +          v[player]->lockTime[0] = p->gameTime;
   1.154 +          if (v[player]->nLockTimes < N_SPEED_METER_PIECES) {
   1.155 +            ++v[player]->nLockTimes;
   1.156 +          }
   1.157 +          v[player]->frontDirty = LJ_DIRTY_SCORE;
   1.158 +        }
   1.159 +
   1.160 +        // If the piece was just spawned, move the trail to the piece's
   1.161 +        // starting position and redraw next pieces.
   1.162 +        if (p->sounds & (LJSND_SPAWN | LJSND_HOLD)) {
   1.163 +          v[player]->trailY = p->y;
   1.164 +          v[player]->frontDirty |= LJ_DIRTY_NEXT;
   1.165 +        }
   1.166 +      }
   1.167 +
   1.168 +      ++lastTime;
   1.169 +    }
   1.170 +
   1.171 +    for (unsigned int player = 0; player < nPlayers; ++player) {
   1.172 +      LJField *const p = v[player]->field;
   1.173 +      if (p->state == LJS_GAMEOVER && v[player]->hidePF) {
   1.174 +        v[player]->hidePF = 0;
   1.175 +        v[player]->backDirty |= (1 << LJ_PF_VIS_HT) - 1;
   1.176 +      }
   1.177 +    
   1.178 +      updField(v[player], v[player]->backDirty);
   1.179 +      v[player]->frontDirty |= v[player]->backDirty;
   1.180 +      v[player]->backDirty = 0;
   1.181 +    
   1.182 +      // If piece is falling or landed, and it wasn't just spawned,
   1.183 +      // draw the piece and its shadow.
   1.184 +
   1.185 +      if (p->sounds & (LJSND_SPAWN | LJSND_HOLD)) {
   1.186 +        // piece was just spawned, so don't draw the piece
   1.187 +      }
   1.188 +      // Otherwise, if the piece is falling or landed, draw it.
   1.189 +      else if (p->state == LJS_FALLING || p->state == LJS_LANDED
   1.190 +                || p->sounds & LJSND_LOCK) {
   1.191 +        if (v[player]->hideShadow != LJSHADOW_NO_FALLING) {
   1.192 +          if (p->state == LJS_FALLING && v[player]->hideShadow < LJSHADOW_NONE) {
   1.193 +            drawShadow(v[player]);
   1.194 +          }
   1.195 +          drawFallingPiece(v[player]);
   1.196 +        }
   1.197 +      }
   1.198 +
   1.199 +      ljBeginDraw(v[player], getTime() - lastTime < 2);
   1.200 +      drawScore(v[player]);
   1.201 +      blitField(v[player]);
   1.202 +      ljEndDraw(v[player]);
   1.203 +    }
   1.204 +  }
   1.205 +  
   1.206 +#if WITH_REPLAY
   1.207 +  {
   1.208 +    int player = 0;
   1.209 +    if (v[player]->control->replaySrc) {
   1.210 +      replayClose(v[player]->control->replaySrc);
   1.211 +      v[player]->control->replaySrc = NULL;
   1.212 +    }
   1.213 +    if (v[player]->control->replayDst) {
   1.214 +      replayClose(v[player]->control->replayDst);
   1.215 +      v[player]->control->replayDst = NULL;
   1.216 +    }
   1.217 +  }
   1.218 +#endif
   1.219 +}