comparison src/ljplay.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:c238b868767a
1 /* Game loop frontend for LOCKJAW, an implementation of the Soviet Mind Game
2
3 Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net>
4
5 This work is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Original game concept and design by Alexey Pajitnov.
20 The Software is not sponsored or endorsed by Alexey Pajitnov[player], Elorg,
21 or The Tetris Company LLC.
22
23 */
24
25 #include "ljplay.h"
26 #ifndef WITH_REPLAY
27 #define WITH_REPLAY 0
28 #endif
29
30 #if WITH_REPLAY
31 #include "ljreplay.h"
32 extern const char demoFilename[];
33
34 #endif
35
36
37 void play(LJView *const v[], size_t nPlayers) {
38 int canceled = 0;
39
40 for (unsigned int player = 0; player < nPlayers; ++player) {
41 LJField *const p = v[player]->field;
42 LJControl *const ctl = v[player]->control;
43
44 ctl->countdown = 6;
45 ctl->presses = 0;
46
47 /* Load replay if needed */
48 #if WITH_REPLAY
49 if (p->gimmick < 0) {
50 ctl->replaySrc = openReplay(demoFilename, p);
51 if (!ctl->replaySrc) {
52 return;
53 }
54 v[player]->backDirty = ~0;
55 playRedrawScreen(v[player]);
56 } else {
57 ctl->replaySrc = 0;
58 }
59 #endif
60 }
61 if (!v[0]->control->replaySrc) {
62 for (unsigned int player = 0; player < nPlayers; ++player) {
63 LJField *const p = v[player]->field;
64 newGame(p);
65 initGimmicks(p);
66 v[player]->nLockTimes = 0;
67 v[player]->hideNext = 0;
68 updField(v[player], ~0);
69 }
70 startingAnimation(v[0]);
71 for (unsigned int player = 0; player < nPlayers; ++player) {
72 v[player]->control->lastKeys = 0;
73 v[player]->control->repressKeys = 0;
74 blitField(v[player]);
75 }
76 }
77
78 int lastTime = getTime();
79
80 while(v[0]->field->state != LJS_GAMEOVER && !canceled) {
81 if (getTime() == lastTime) {
82 yieldCPU();
83 }
84 canceled |= ljHandleConsoleButtons(v[0]);
85 while (getTime() - lastTime > 0) {
86 for (unsigned int player = 0; player < nPlayers; ++player) {
87 LJField *const p = v[player]->field;
88 LJControl *const ctl = v[player]->control;
89 LJInput in = {0, 0, 0, 0};
90 int curTime = getTime();
91
92 addKeysToInput(&in, readPad(player), p, ctl);
93
94 // when returning from pause, catch up the speed control
95 if (curTime - lastTime > 10
96 || curTime - lastTime < -10) {
97 lastTime = curTime;
98 }
99
100 {
101 int irsAttempted = (p->sounds & (LJSND_SPAWN | LJSND_HOLD))
102 && in.rotation && ctl->initialRotate;
103
104 // The next line does ALL the game logic.
105 LJBits updatedRows = frame(p, &in) | gimmicks(p, ctl);
106
107 v[player]->backDirty |= updatedRows;
108 if (irsAttempted && (p->sounds & LJSND_ROTATE)) {
109 p->sounds |= LJSND_IRS;
110 }
111 }
112
113 // items is a partly view-based gimmick
114 if (p->gimmick == LJGM_ITEMS && (p->sounds & LJSND_SPAWN)) {
115 v[player]->hideNext = (v[player]->field->nPieces > 7);
116 v[player]->frontDirty |= LJ_DIRTY_NEXT;
117 }
118
119 // five, four, three, two, one
120 int curCountdown = ctl->countdown;
121 if (p->gimmick == LJGM_ULTRA && p->gameTime >= 10500) {
122 curCountdown = (int)(10859 - p->gameTime) / 60;
123 } else if (p->gimmick == LJGM_BTYPE) {
124 curCountdown = 40 - p->lines;
125 } else if (p->gimmick == LJGM_BABY) {
126 curCountdown = (309 - v[player]->control->presses) / 10;
127 } else if (p->gimmick == LJGM_DRILL && (p->sounds & LJSND_LINE)) {
128 int line = bfffo(p->tempRows);
129 if (line < curCountdown)
130 curCountdown = line;
131 }
132
133 // we have to wait for the new piece to come out
134 // so that the score is credited properly
135 if (curCountdown <= 0
136 && (p->state == LJS_NEW_PIECE
137 || p->state == LJS_FALLING
138 || p->state == LJS_LANDED)) {
139 p->state = LJS_GAMEOVER;
140 }
141
142 playSoundEffects(v[player], p->sounds, curCountdown);
143 ctl->countdown = curCountdown;
144
145 // Update speedometer
146 if (p->sounds & LJSND_LOCK) {
147 for (int i = N_SPEED_METER_PIECES - 2; i >= 0; --i) {
148 v[player]->lockTime[i + 1] = v[player]->lockTime[i];
149 }
150 v[player]->lockTime[0] = p->gameTime;
151 if (v[player]->nLockTimes < N_SPEED_METER_PIECES) {
152 ++v[player]->nLockTimes;
153 }
154 v[player]->frontDirty = LJ_DIRTY_SCORE;
155 }
156
157 // If the piece was just spawned, move the trail to the piece's
158 // starting position and redraw next pieces.
159 if (p->sounds & (LJSND_SPAWN | LJSND_HOLD)) {
160 v[player]->trailY = p->y;
161 v[player]->frontDirty |= LJ_DIRTY_NEXT;
162 }
163 }
164
165 ++lastTime;
166 }
167
168 for (unsigned int player = 0; player < nPlayers; ++player) {
169 LJField *const p = v[player]->field;
170 if (p->state == LJS_GAMEOVER && v[player]->hidePF) {
171 v[player]->hidePF = 0;
172 v[player]->backDirty |= (1 << LJ_PF_VIS_HT) - 1;
173 }
174
175 updField(v[player], v[player]->backDirty);
176 v[player]->frontDirty |= v[player]->backDirty;
177 v[player]->backDirty = 0;
178
179 // If piece is falling or landed, and it wasn't just spawned,
180 // draw the piece and its shadow.
181
182 if (p->sounds & (LJSND_SPAWN | LJSND_HOLD)) {
183 // piece was just spawned, so don't draw the piece
184 }
185 // Otherwise, if the piece is falling or landed, draw it.
186 else if (p->state == LJS_FALLING || p->state == LJS_LANDED
187 || p->sounds & LJSND_LOCK) {
188 if (v[player]->hideShadow != LJSHADOW_NO_FALLING) {
189 if (p->state == LJS_FALLING && v[player]->hideShadow < LJSHADOW_NONE) {
190 drawShadow(v[player]);
191 }
192 drawFallingPiece(v[player]);
193 }
194 }
195
196 ljBeginDraw(v[player], getTime() - lastTime < 2);
197 drawScore(v[player]);
198 blitField(v[player]);
199 ljEndDraw(v[player]);
200 }
201 }
202
203 #if WITH_REPLAY
204 {
205 int player = 0;
206 if (v[player]->control->replaySrc) {
207 replayClose(v[player]->control->replaySrc);
208 v[player]->control->replaySrc = NULL;
209 }
210 if (v[player]->control->replayDst) {
211 replayClose(v[player]->control->replayDst);
212 v[player]->control->replayDst = NULL;
213 }
214 }
215 #endif
216 }