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 // ----------------------------------------------------------------------------
95 locRepeatMainGameLoop: // start repeating game loop
98 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100 while (PauseMode != 0)
107 DoEvents(); // user may klick on menus or move the window here ...
112 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
115 // never any additional code between here!
117 LastFrame = Clock.TickNow(); // store the frame time
119 // never any additional code between here!
120 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
123 // FS end of synchronization
124 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128 // (should never happen)
130 // printf("::: EndFlag == True\n");
132 goto locExitMainGameLoop;
136 goto locExitMainGameLoop;
139 // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick
140 // bx = subCheckRightMouseButton() ' check (right) mouse button
141 // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
143 // If DebugVersionFlag <> 0 Then ' debug mode on?
144 // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
145 // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
146 // ' fixes ENTER bug If no mouse driver!
147 // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field
148 // ' Also Enter If no mouse!
149 // If Data_SubRest <> 0 Then GoTo loc_g_186F
151 // Call subRestoreFancy
152 // Call subDisplayLevel ' Paint (Init) game field
153 // Call subConvertToEasySymbols ' Convert to easy symbols
158 subProcessKeyboardInput(); // Check keyboard, act on keys
161 // TimerVar = TimerVar + 1
165 // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
167 // ----------------------------------------------------------------------------
171 printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
174 subDoGameStuff(); // do all game stuff
177 printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
181 // ----------------------------------------------------------------------------
183 // Call subDisplayPlayingTime ' playing time on screen
185 subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole
187 subRedDiskReleaseExplosion(); // Red Disk release and explode
188 subFollowUpExplosions(); // every explosion may cause up to 8 following explosions
190 bx = subCalculateScreenScrollPos(); // calculate screen start addrs
194 // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
195 data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
196 data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
197 if ((! UserDragFlag) && AutoScrollFlag)
200 printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
203 ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
207 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
209 // (should never happen)
211 // printf("::: ForcedExitFlag == True\n");
213 goto locExitMainGameLoop;
216 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
217 goto locExitMainGameLoop;
220 TimerVar = TimerVar + 1;
224 MainForm.SaveSnapshot(TimerVar);
227 // If Not NoDisplayFlag Then
228 // With MainForm.lblFrameCount
229 // .Caption = TimerVar
235 if (ExitToMenuFlag == 1)
237 // happens when demo ends or when Murphy enters exit (to be checked)
239 printf("::: ExitToMenuFlag == True\n");
241 goto locExitMainGameLoop;
244 if (ExitToMenuFlag == 1)
245 goto locExitMainGameLoop;
249 if (LeadOutCounter == 0) // no lead-out: game busy
250 return subMainGameLoop;
252 if (LeadOutCounter == 0) // no lead-out: game busy
253 goto locRepeatMainGameLoop;
256 // ----------------------------------------------------------------------------
257 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
258 // ----------------------------------------------------------------------------
259 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
261 if (LeadOutCounter != 0) // lead-out not ready: more
262 return subMainGameLoop;
264 if (LeadOutCounter != 0) // lead-out not ready: more
265 goto locRepeatMainGameLoop;
268 // lead-out done: exit now
269 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
274 printf("::: locExitMainGameLoop reached [%d]\n", LeadOutCounter);
279 DoEvents(); // user may klick on menus or move the window here ...
284 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
287 Stage.Blt(); // blit the last frame
291 MainForm.menStop_Click();
292 MainForm.PanelVisible = True;
295 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
296 if (SavedGameFlag != 0) // after savegame: no update!
299 return subMainGameLoop;
303 if (UpdateTimeFlag == 0) // update time?
304 return subMainGameLoop;
306 if (UpdatedFlag == 0) // update playing time
307 subUpdatePlayingTime();
310 return subMainGameLoop;
313 int subMainGameLoop()
320 TickCountObject Clock;
327 printf("::: playing demo ...\n");
330 // EP set level success byte: demo, not game
332 EP_GameDemoVar0DAA = 0; // demo
337 printf("::: playing game ...\n");
340 // EP set level success byte: game, not demo
342 EP_GameDemoVar0DAA = 1; // game
346 // If RecordDemoFlag = 1 Then
347 // RecordDemoFlag = 0 ' clear Demo Recording flag
348 // Call subDisplayPlayingTime ' playing time on screen
349 // ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
350 // While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
351 // ' yes -> wait until released
352 // ' should we DoEvents here???? ... depends on how ... but yes!
353 // ' ...or we can rather poll the keyboardstate inside this loop???
355 // Call subInitGameConditions ' Init game conditions (vars)
356 // If MusicOnFlag = 0 Then Call subMusicInit
357 // WasDemoFlag = 0 ' no demo anymore
358 // EP_GameDemoVar0DAA = 1 ' force game
361 // This was a bug in the original Supaplex: sometimes red disks could not
362 // be released. This happened If Murphy was killed DURING a red disk release
363 // and the next try started.
365 RedDiskReleasePhase = 0; // (re-)enable red disk release
370 // ----------------------------------------------------------------------------
371 // --------------------- START OF GAME-BUSY LOOP ------------------------------
372 // ----------------------------------------------------------------------------
374 locRepeatMainGameLoop: // start repeating game loop
376 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
377 // FS synchronization
378 while (PauseMode != 0)
385 DoEvents(); // user may klick on menus or move the window here ...
390 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
393 // never any additional code between here!
395 LastFrame = Clock.TickNow(); // store the frame time
397 // never any additional code between here!
398 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
401 // FS end of synchronization
402 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
404 goto locExitMainGameLoop;
406 // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick
407 // bx = subCheckRightMouseButton() ' check (right) mouse button
408 // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
410 // If DebugVersionFlag <> 0 Then ' debug mode on?
411 // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
412 // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
413 // ' fixes ENTER bug If no mouse driver!
414 // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field
415 // ' Also Enter If no mouse!
416 // If Data_SubRest <> 0 Then GoTo loc_g_186F
418 // Call subRestoreFancy
419 // Call subDisplayLevel ' Paint (Init) game field
420 // Call subConvertToEasySymbols ' Convert to easy symbols
425 subProcessKeyboardInput(); // Check keyboard, act on keys
428 // TimerVar = TimerVar + 1
432 // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
434 // ----------------------------------------------------------------------------
438 printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
441 subDoGameStuff(); // do all game stuff
444 printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
448 // ----------------------------------------------------------------------------
450 // Call subDisplayPlayingTime ' playing time on screen
452 subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole
454 subRedDiskReleaseExplosion(); // Red Disk release and explode
455 subFollowUpExplosions(); // every explosion may cause up to 8 following explosions
457 bx = subCalculateScreenScrollPos(); // calculate screen start addrs
461 // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
462 data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
463 data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
464 if ((! UserDragFlag) && AutoScrollFlag)
467 printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
470 ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
473 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
474 goto locExitMainGameLoop;
476 TimerVar = TimerVar + 1;
480 MainForm.SaveSnapshot(TimerVar);
483 // If Not NoDisplayFlag Then
484 // With MainForm.lblFrameCount
485 // .Caption = TimerVar
489 if (ExitToMenuFlag == 1)
490 goto locExitMainGameLoop;
492 if (LeadOutCounter == 0) // no lead-out: game busy
493 goto locRepeatMainGameLoop;
495 // ----------------------------------------------------------------------------
496 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
497 // ----------------------------------------------------------------------------
498 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
499 if (LeadOutCounter != 0) // lead-out not ready: more
500 goto locRepeatMainGameLoop;
502 // lead-out done: exit now
503 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
508 DoEvents(); // user may klick on menus or move the window here ...
513 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
516 Stage.Blt(); // blit the last frame
520 MainForm.menStop_Click();
521 MainForm.PanelVisible = True;
524 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
525 if (SavedGameFlag != 0) // after savegame: no update!
528 return subMainGameLoop;
532 if (UpdateTimeFlag == 0) // update time?
533 return subMainGameLoop;
535 if (UpdatedFlag == 0) // update playing time
536 subUpdatePlayingTime();
539 return subMainGameLoop;
542 void subUpdatePlayingTime()
546 int subCalculateScreenScrollPos()
548 int subCalculateScreenScrollPos;
552 if (ExplosionShake != 0)
554 subGetRandomNumber();
558 ax = MainForm.picPane.Width / 2;
559 Ay = MainForm.picPane.Height / 2;
563 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
564 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
566 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
567 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
571 printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
572 MainForm.picPane.Width, MainForm.picPane.Height,
573 MurphyScreenXPos, MurphyScreenYPos,
574 ScreenScrollXPos, ScreenScrollYPos);
577 return subCalculateScreenScrollPos;