Mercurial > hg > index.fcgi > lj > lj046-2players
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 +}