6a5e0eafcbde6474bf604a910ee3de4b656531ec
[rocksndiamonds.git] / src / game_sp / MainGameLoop.c
1 // ----------------------------------------------------------------------------
2 // MainGameLoop.c
3 // ----------------------------------------------------------------------------
4
5 #include "MainGameLoop.h"
6
7 // static char *VB_Name = "modMainGameLoop";
8
9 // --- Option Explicit
10
11 int GameLoopRunning;
12 boolean bPlaying;
13 int LeadOutCounter, EnterRepeatCounter;
14 int ForcedExitFlag;
15 int ExitToMenuFlag;
16 int SavedGameFlag;
17 boolean UserDragFlag;
18 boolean AutoScrollFlag;
19
20 // ==========================================================================
21 //                              SUBROUTINE
22 // Play a game/demo
23 // ==========================================================================
24
25 int subMainGameLoop()
26 {
27   int subMainGameLoop;
28
29   // int al, bx;
30   int bx;
31 #if 0
32   TickCountObject Clock;
33   currency LastFrame;
34 #endif
35
36   if (DemoFlag != 0)
37   {
38     printf("::: playing demo ...\n");
39
40     // EP set level success byte: demo, not game
41     WasDemoFlag = 1;
42     EP_GameDemoVar0DAA = 0; // demo
43   }
44   else // loc_g_1836:
45   {
46     printf("::: playing game ...\n");
47
48     // EP set level success byte: game, not demo
49     WasDemoFlag = 0;
50     EP_GameDemoVar0DAA = 1; // game
51   }
52
53   // RestartGameLoop:
54   //  If RecordDemoFlag = 1 Then
55   //    RecordDemoFlag = 0 ' clear Demo Recording flag
56   //    Call subDisplayPlayingTime                 ' playing time on screen
57   //    ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
58   //    While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
59   //      ' yes -> wait until released
60   //      ' should we DoEvents here???? ... depends on how ... but yes!
61   //      ' ...or we can rather poll the keyboardstate inside this loop???
62   //    Wend
63   //    Call subInitGameConditions     ' Init game conditions (vars)
64   //    If MusicOnFlag = 0 Then Call subMusicInit
65   //    WasDemoFlag = 0          ' no demo anymore
66   //    EP_GameDemoVar0DAA = 1 ' force game
67   //  End If
68
69   // This was a bug in the original Supaplex: sometimes red disks could not
70   // be released.  This happened If Murphy was killed DURING a red disk release
71   // and the next try started.
72
73   RedDiskReleasePhase = 0; // (re-)enable red disk release
74   UpdatedFlag = 0;
75   GameLoopRunning = 1;
76   LevelStatus = 0;
77
78   // ----------------------------------------------------------------------------
79   // --------------------- START OF GAME-BUSY LOOP ------------------------------
80   // ----------------------------------------------------------------------------
81
82 locRepeatMainGameLoop:                           // start repeating game loop
83
84   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
85   // FS   synchronization
86   while (PauseMode != 0)
87   {
88     DoEvents();
89   }
90
91   do
92   {
93     DoEvents(); // user may klick on menus or move the window here ...
94   }
95 #if 1
96   while (0);
97 #else
98   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
99 #endif
100
101   //   never any additional code between here!
102 #if 0
103   LastFrame = Clock.TickNow(); // store the frame time
104 #endif
105   //   never any additional code between here!
106   if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
107     Stage.Blt();
108
109   // FS   end of synchronization
110   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111   if (EndFlag)
112     goto locExitMainGameLoop;
113
114   // If DemoFlag = 0 Then Call subCheckJoystick    ' check joystick
115   // bx = subCheckRightMouseButton()                ' check (right) mouse button
116   // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
117
118   //  If DebugVersionFlag <> 0 Then ' debug mode on?
119   //    If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
120   //    If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
121   //                                          ' fixes ENTER bug If no mouse driver!
122   //    If bx <> 1 Then GoTo loc_g_186F  ' Left button=Init game field
123   //                                    ' Also Enter If no mouse!
124   //    If Data_SubRest <> 0 Then GoTo loc_g_186F
125   //    Data_SubRest = 10
126   //    Call subRestoreFancy
127   //    Call subDisplayLevel         ' Paint (Init) game field
128   //    Call subConvertToEasySymbols ' Convert to easy symbols
129   //  End If
130
131   // loc_g_186F:
132
133   subProcessKeyboardInput();                 // Check keyboard, act on keys
134
135   // 'HACK:
136   //  TimerVar = TimerVar + 1
137   //  DoEvents
138   //  GoTo loc_g_186F
139   // 'END HACK
140   // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
141
142   // ----------------------------------------------------------------------------
143   //
144
145   printf("::: MainGameLoop.c: subDoGameStuff() START\n");
146
147   subDoGameStuff();                 // do all game stuff
148
149   printf("::: MainGameLoop.c: subDoGameStuff() END\n");
150
151   //
152   // ----------------------------------------------------------------------------
153
154   //  Call subDisplayPlayingTime                 ' playing time on screen
155
156   subCheckRestoreRedDiskCountDisplay();    // Restore panel: red-disk hole
157
158   subRedDiskReleaseExplosion();       // Red Disk release and explode
159   subFollowUpExplosions();  // every explosion may cause up to 8 following explosions
160
161   bx = subCalculateScreenScrollPos();     // calculate screen start addrs
162
163   ScreenPosition = bx;
164
165   // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
166   data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
167   data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
168   if ((! UserDragFlag) && AutoScrollFlag)
169     ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
170
171   if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
172     goto locExitMainGameLoop;
173
174   TimerVar = TimerVar + 1;
175
176 #if 0
177   if (bCapturePane)
178     MainForm.SaveSnapshot(TimerVar);
179 #endif
180
181   //  If Not NoDisplayFlag Then
182   //    With MainForm.lblFrameCount
183   //      .Caption = TimerVar
184   //      .Refresh
185   //    End With
186   //  End If
187   if (ExitToMenuFlag == 1)
188     goto locExitMainGameLoop;
189
190   if (LeadOutCounter == 0) // no lead-out: game busy
191     goto locRepeatMainGameLoop;
192
193   // ----------------------------------------------------------------------------
194   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
195   // ----------------------------------------------------------------------------
196   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
197   if (LeadOutCounter != 0) // lead-out not ready: more
198     goto locRepeatMainGameLoop;
199
200   // lead-out done: exit now
201   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
202
203 locExitMainGameLoop:
204   do
205   {
206     DoEvents(); // user may klick on menus or move the window here ...
207   }
208 #if 1
209   while (0);
210 #else
211   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
212 #endif
213
214   Stage.Blt(); // blit the last frame
215   GameLoopRunning = 0;
216
217 #if 0
218   MainForm.menStop_Click();
219   MainForm.PanelVisible = True;
220 #endif
221
222   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
223   if (SavedGameFlag != 0) // after savegame: no update!
224   {
225     SavedGameFlag = 0;
226     return subMainGameLoop;
227   }
228
229   SavedGameFlag = 0;
230   if (UpdateTimeFlag == 0) // update time?
231     return subMainGameLoop;
232
233   if (UpdatedFlag == 0) // update playing time
234     subUpdatePlayingTime();
235
236
237   return subMainGameLoop;
238 } // subMainGameLoop
239
240 void subUpdatePlayingTime()
241 {
242 }
243
244 int subCalculateScreenScrollPos()
245 {
246   int subCalculateScreenScrollPos;
247
248   int ax, Ay;
249
250   if (ExplosionShake != 0)
251   {
252     subGetRandomNumber();
253   }
254
255   {
256     ax = MainForm.picPane.Width / 2;
257     Ay = MainForm.picPane.Height / 2;
258   }
259
260 #if 1
261   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
262   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
263 #else
264   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
265   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
266 #endif
267
268 #if 0
269   printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
270          MainForm.picPane.Width, MainForm.picPane.Height,
271          MurphyScreenXPos, MurphyScreenYPos,
272          ScreenScrollXPos, ScreenScrollYPos);
273 #endif
274
275   return subCalculateScreenScrollPos;
276 }