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(byte action, boolean warp_mode)
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(action); // 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)
240 printf("::: ExitToMenuFlag == True\n");
244 goto locExitMainGameLoop;
248 if (ExitToMenuFlag == 1)
249 goto locExitMainGameLoop;
253 if (LeadOutCounter == 0) // no lead-out: game busy
254 return subMainGameLoop;
256 if (LeadOutCounter == 0) // no lead-out: game busy
257 goto locRepeatMainGameLoop;
260 // ----------------------------------------------------------------------------
261 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
262 // ----------------------------------------------------------------------------
263 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
266 printf("::: LeadOutCounter == %d\n", LeadOutCounter);
270 if (LeadOutCounter != 0) // lead-out not ready: more
271 return subMainGameLoop;
273 if (LeadOutCounter != 0) // lead-out not ready: more
274 goto locRepeatMainGameLoop;
277 // lead-out done: exit now
278 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
283 printf("::: locExitMainGameLoop reached [%d]\n", LeadOutCounter);
284 printf("::: [KillMurphyFlag == %d]\n", KillMurphyFlag);
288 /* if the game is not won when reaching this point, then it is lost */
289 if (!game_sp_info.LevelSolved)
290 game_sp_info.GameOver = TRUE;
294 return subMainGameLoop;
301 DoEvents(); // user may klick on menus or move the window here ...
306 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
309 Stage.Blt(); // blit the last frame
313 MainForm.menStop_Click();
314 MainForm.PanelVisible = True;
317 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
318 if (SavedGameFlag != 0) // after savegame: no update!
321 return subMainGameLoop;
325 if (UpdateTimeFlag == 0) // update time?
326 return subMainGameLoop;
328 if (UpdatedFlag == 0) // update playing time
329 subUpdatePlayingTime();
331 return subMainGameLoop;
336 int subMainGameLoop()
343 TickCountObject Clock;
350 printf("::: playing demo ...\n");
353 // EP set level success byte: demo, not game
355 EP_GameDemoVar0DAA = 0; // demo
360 printf("::: playing game ...\n");
363 // EP set level success byte: game, not demo
365 EP_GameDemoVar0DAA = 1; // game
369 // If RecordDemoFlag = 1 Then
370 // RecordDemoFlag = 0 ' clear Demo Recording flag
371 // Call subDisplayPlayingTime ' playing time on screen
372 // ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
373 // While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
374 // ' yes -> wait until released
375 // ' should we DoEvents here???? ... depends on how ... but yes!
376 // ' ...or we can rather poll the keyboardstate inside this loop???
378 // Call subInitGameConditions ' Init game conditions (vars)
379 // If MusicOnFlag = 0 Then Call subMusicInit
380 // WasDemoFlag = 0 ' no demo anymore
381 // EP_GameDemoVar0DAA = 1 ' force game
384 // This was a bug in the original Supaplex: sometimes red disks could not
385 // be released. This happened If Murphy was killed DURING a red disk release
386 // and the next try started.
388 RedDiskReleasePhase = 0; // (re-)enable red disk release
393 // ----------------------------------------------------------------------------
394 // --------------------- START OF GAME-BUSY LOOP ------------------------------
395 // ----------------------------------------------------------------------------
397 locRepeatMainGameLoop: // start repeating game loop
399 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
400 // FS synchronization
401 while (PauseMode != 0)
408 DoEvents(); // user may klick on menus or move the window here ...
413 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
416 // never any additional code between here!
418 LastFrame = Clock.TickNow(); // store the frame time
420 // never any additional code between here!
421 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
424 // FS end of synchronization
425 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
427 goto locExitMainGameLoop;
429 // If DemoFlag = 0 Then Call subCheckJoystick ' check joystick
430 // bx = subCheckRightMouseButton() ' check (right) mouse button
431 // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
433 // If DebugVersionFlag <> 0 Then ' debug mode on?
434 // If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
435 // If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
436 // ' fixes ENTER bug If no mouse driver!
437 // If bx <> 1 Then GoTo loc_g_186F ' Left button=Init game field
438 // ' Also Enter If no mouse!
439 // If Data_SubRest <> 0 Then GoTo loc_g_186F
441 // Call subRestoreFancy
442 // Call subDisplayLevel ' Paint (Init) game field
443 // Call subConvertToEasySymbols ' Convert to easy symbols
448 subProcessKeyboardInput(); // Check keyboard, act on keys
451 // TimerVar = TimerVar + 1
455 // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
457 // ----------------------------------------------------------------------------
461 printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
464 subDoGameStuff(); // do all game stuff
467 printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
471 // ----------------------------------------------------------------------------
473 // Call subDisplayPlayingTime ' playing time on screen
475 subCheckRestoreRedDiskCountDisplay(); // Restore panel: red-disk hole
477 subRedDiskReleaseExplosion(); // Red Disk release and explode
478 subFollowUpExplosions(); // every explosion may cause up to 8 following explosions
480 bx = subCalculateScreenScrollPos(); // calculate screen start addrs
484 // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
485 data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
486 data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
487 if ((! UserDragFlag) && AutoScrollFlag)
490 printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
493 ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
496 if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
497 goto locExitMainGameLoop;
499 TimerVar = TimerVar + 1;
503 MainForm.SaveSnapshot(TimerVar);
506 // If Not NoDisplayFlag Then
507 // With MainForm.lblFrameCount
508 // .Caption = TimerVar
512 if (ExitToMenuFlag == 1)
513 goto locExitMainGameLoop;
515 if (LeadOutCounter == 0) // no lead-out: game busy
516 goto locRepeatMainGameLoop;
518 // ----------------------------------------------------------------------------
519 // ---------------------- END OF GAME-BUSY LOOP -------------------------------
520 // ----------------------------------------------------------------------------
521 LeadOutCounter = LeadOutCounter - 1; // do more lead-out after quit
522 if (LeadOutCounter != 0) // lead-out not ready: more
523 goto locRepeatMainGameLoop;
525 // lead-out done: exit now
526 // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
531 DoEvents(); // user may klick on menus or move the window here ...
536 while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
539 Stage.Blt(); // blit the last frame
543 MainForm.menStop_Click();
544 MainForm.PanelVisible = True;
547 // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
548 if (SavedGameFlag != 0) // after savegame: no update!
551 return subMainGameLoop;
555 if (UpdateTimeFlag == 0) // update time?
556 return subMainGameLoop;
558 if (UpdatedFlag == 0) // update playing time
559 subUpdatePlayingTime();
562 return subMainGameLoop;
567 void subUpdatePlayingTime()
571 int subCalculateScreenScrollPos()
573 int subCalculateScreenScrollPos;
577 if (ExplosionShake != 0)
579 subGetRandomNumber();
583 ax = MainForm.picPane.Width / 2;
584 Ay = MainForm.picPane.Height / 2;
588 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
589 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
591 ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
592 ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
596 printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
597 MainForm.picPane.Width, MainForm.picPane.Height,
598 MurphyScreenXPos, MurphyScreenYPos,
599 ScreenScrollXPos, ScreenScrollYPos);
602 return subCalculateScreenScrollPos;