1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
5 #include "MainGameLoop.h"
7 // static char *VB_Name = "modMainGameLoop";
13 int LeadOutCounter, EnterRepeatCounter;
18 boolean AutoScrollFlag;
20 // ==========================================================================
23 // ==========================================================================
25 int subMainGameLoop_Init()
32 TickCountObject Clock;
39 printf("::: playing demo ...\n");
42 // EP set level success byte: demo, not game
44 EP_GameDemoVar0DAA = 0; // demo
49 printf("::: playing game ...\n");
52 // EP set level success byte: game, not demo
54 EP_GameDemoVar0DAA = 1; // game
58 // If RecordDemoFlag = 1 Then
59 // RecordDemoFlag = 0 ' clear Demo Recording flag
60 // Call subDisplayPlayingTime ' playing time on screen
61 // ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
62 // While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
63 // ' yes -> wait until released
64 // ' should we DoEvents here???? ... depends on how ... but yes!
65 // ' ...or we can rather poll the keyboardstate inside this loop???
67 // Call subInitGameConditions ' Init game conditions (vars)
68 // If MusicOnFlag = 0 Then Call subMusicInit
69 // WasDemoFlag = 0 ' no demo anymore
70 // EP_GameDemoVar0DAA = 1 ' force game
73 // This was a bug in the original Supaplex: sometimes red disks could not
74 // be released. This happened If Murphy was killed DURING a red disk release
75 // and the next try started.
77 RedDiskReleasePhase = 0; // (re-)enable red disk release
82 return subMainGameLoop;
85 int subMainGameLoop_Main()
90 // ----------------------------------------------------------------------------
91 // --------------------- START OF GAME-BUSY LOOP ------------------------------
92 // ----------------------------------------------------------------------------
94 locRepeatMainGameLoop: // start repeating game loop
96 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98 while (PauseMode != 0)
105 DoEvents(); // user may klick on menus or move the window here ...
110 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
113 // never any additional code between here!
115 LastFrame = Clock.TickNow(); // store the frame time
117 // never any additional code between here!
118 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
121 // FS end of synchronization
122 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124 goto locExitMainGameLoop;
126 // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick
127 // bx = subCheckRightMouseButton() ' check (right) mouse button
128 // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
130 // If DebugVersionFlag <> 0 Then ' debug mode on?
131 // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
132 // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
133 // ' fixes ENTER bug If no mouse driver!
134 // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field
135 // ' Also Enter If no mouse!
136 // If Data_SubRest <> 0 Then GoTo loc_g_186F
138 // Call subRestoreFancy
139 // Call subDisplayLevel ' Paint (Init) game field
140 // Call subConvertToEasySymbols ' Convert to easy symbols
145 subProcessKeyboardInput(); // Check keyboard, act on keys
148 // TimerVar = TimerVar + 1
152 // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
154 // ----------------------------------------------------------------------------
158 printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
161 subDoGameStuff(); // do all game stuff
164 printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
168 // ----------------------------------------------------------------------------
170 // Call subDisplayPlayingTime ' playing time on screen
172 subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole
174 subRedDiskReleaseExplosion(); // Red Disk release and explode
175 subFollowUpExplosions(); // every explosion may cause up to 8 following explosions
177 bx = subCalculateScreenScrollPos(); // calculate screen start addrs
181 // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
182 data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
183 data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
184 if ((! UserDragFlag) && AutoScrollFlag)
187 printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
190 ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
193 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
194 goto locExitMainGameLoop;
196 TimerVar = TimerVar + 1;
200 MainForm.SaveSnapshot(TimerVar);
203 // If Not NoDisplayFlag Then
204 // With MainForm.lblFrameCount
205 // .Caption = TimerVar
210 if (ExitToMenuFlag == 1)
211 goto locExitMainGameLoop;
214 if (LeadOutCounter == 0) // no lead-out: game busy
215 return subMainGameLoop;
217 if (LeadOutCounter == 0) // no lead-out: game busy
218 goto locRepeatMainGameLoop;
221 // ----------------------------------------------------------------------------
222 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
223 // ----------------------------------------------------------------------------
224 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
225 if (LeadOutCounter != 0) // lead-out not ready: more
226 goto locRepeatMainGameLoop;
228 // lead-out done: exit now
229 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
234 DoEvents(); // user may klick on menus or move the window here ...
239 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
242 Stage.Blt(); // blit the last frame
246 MainForm.menStop_Click();
247 MainForm.PanelVisible = True;
250 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
251 if (SavedGameFlag != 0) // after savegame: no update!
254 return subMainGameLoop;
258 if (UpdateTimeFlag == 0) // update time?
259 return subMainGameLoop;
261 if (UpdatedFlag == 0) // update playing time
262 subUpdatePlayingTime();
265 return subMainGameLoop;
268 int subMainGameLoop()
275 TickCountObject Clock;
282 printf("::: playing demo ...\n");
285 // EP set level success byte: demo, not game
287 EP_GameDemoVar0DAA = 0; // demo
292 printf("::: playing game ...\n");
295 // EP set level success byte: game, not demo
297 EP_GameDemoVar0DAA = 1; // game
301 // If RecordDemoFlag = 1 Then
302 // RecordDemoFlag = 0 ' clear Demo Recording flag
303 // Call subDisplayPlayingTime ' playing time on screen
304 // ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
305 // While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
306 // ' yes -> wait until released
307 // ' should we DoEvents here???? ... depends on how ... but yes!
308 // ' ...or we can rather poll the keyboardstate inside this loop???
310 // Call subInitGameConditions ' Init game conditions (vars)
311 // If MusicOnFlag = 0 Then Call subMusicInit
312 // WasDemoFlag = 0 ' no demo anymore
313 // EP_GameDemoVar0DAA = 1 ' force game
316 // This was a bug in the original Supaplex: sometimes red disks could not
317 // be released. This happened If Murphy was killed DURING a red disk release
318 // and the next try started.
320 RedDiskReleasePhase = 0; // (re-)enable red disk release
325 // ----------------------------------------------------------------------------
326 // --------------------- START OF GAME-BUSY LOOP ------------------------------
327 // ----------------------------------------------------------------------------
329 locRepeatMainGameLoop: // start repeating game loop
331 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
332 // FS synchronization
333 while (PauseMode != 0)
340 DoEvents(); // user may klick on menus or move the window here ...
345 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
348 // never any additional code between here!
350 LastFrame = Clock.TickNow(); // store the frame time
352 // never any additional code between here!
353 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
356 // FS end of synchronization
357 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
359 goto locExitMainGameLoop;
361 // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick
362 // bx = subCheckRightMouseButton() ' check (right) mouse button
363 // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
365 // If DebugVersionFlag <> 0 Then ' debug mode on?
366 // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
367 // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
368 // ' fixes ENTER bug If no mouse driver!
369 // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field
370 // ' Also Enter If no mouse!
371 // If Data_SubRest <> 0 Then GoTo loc_g_186F
373 // Call subRestoreFancy
374 // Call subDisplayLevel ' Paint (Init) game field
375 // Call subConvertToEasySymbols ' Convert to easy symbols
380 subProcessKeyboardInput(); // Check keyboard, act on keys
383 // TimerVar = TimerVar + 1
387 // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
389 // ----------------------------------------------------------------------------
393 printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
396 subDoGameStuff(); // do all game stuff
399 printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
403 // ----------------------------------------------------------------------------
405 // Call subDisplayPlayingTime ' playing time on screen
407 subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole
409 subRedDiskReleaseExplosion(); // Red Disk release and explode
410 subFollowUpExplosions(); // every explosion may cause up to 8 following explosions
412 bx = subCalculateScreenScrollPos(); // calculate screen start addrs
416 // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
417 data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
418 data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
419 if ((! UserDragFlag) && AutoScrollFlag)
422 printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
425 ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
428 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
429 goto locExitMainGameLoop;
431 TimerVar = TimerVar + 1;
435 MainForm.SaveSnapshot(TimerVar);
438 // If Not NoDisplayFlag Then
439 // With MainForm.lblFrameCount
440 // .Caption = TimerVar
444 if (ExitToMenuFlag == 1)
445 goto locExitMainGameLoop;
447 if (LeadOutCounter == 0) // no lead-out: game busy
448 goto locRepeatMainGameLoop;
450 // ----------------------------------------------------------------------------
451 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
452 // ----------------------------------------------------------------------------
453 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
454 if (LeadOutCounter != 0) // lead-out not ready: more
455 goto locRepeatMainGameLoop;
457 // lead-out done: exit now
458 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
463 DoEvents(); // user may klick on menus or move the window here ...
468 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
471 Stage.Blt(); // blit the last frame
475 MainForm.menStop_Click();
476 MainForm.PanelVisible = True;
479 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
480 if (SavedGameFlag != 0) // after savegame: no update!
483 return subMainGameLoop;
487 if (UpdateTimeFlag == 0) // update time?
488 return subMainGameLoop;
490 if (UpdatedFlag == 0) // update playing time
491 subUpdatePlayingTime();
494 return subMainGameLoop;
497 void subUpdatePlayingTime()
501 int subCalculateScreenScrollPos()
503 int subCalculateScreenScrollPos;
507 if (ExplosionShake != 0)
509 subGetRandomNumber();
513 ax = MainForm.picPane.Width / 2;
514 Ay = MainForm.picPane.Height / 2;
518 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
519 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
521 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
522 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
526 printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
527 MainForm.picPane.Width, MainForm.picPane.Height,
528 MurphyScreenXPos, MurphyScreenYPos,
529 ScreenScrollXPos, ScreenScrollYPos);
532 return subCalculateScreenScrollPos;