rnd-20090730-1-src
[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 #if 1
39     printf("::: playing demo ...\n");
40 #endif
41
42     // EP set level success byte: demo, not game
43     WasDemoFlag = 1;
44     EP_GameDemoVar0DAA = 0; // demo
45   }
46   else // loc_g_1836:
47   {
48 #if 1
49     printf("::: playing game ...\n");
50 #endif
51
52     // EP set level success byte: game, not demo
53     WasDemoFlag = 0;
54     EP_GameDemoVar0DAA = 1; // game
55   }
56
57   // RestartGameLoop:
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???
66   //    Wend
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
71   //  End If
72
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.
76
77   RedDiskReleasePhase = 0; // (re-)enable red disk release
78   UpdatedFlag = 0;
79   GameLoopRunning = 1;
80   LevelStatus = 0;
81
82   // ----------------------------------------------------------------------------
83   // --------------------- START OF GAME-BUSY LOOP ------------------------------
84   // ----------------------------------------------------------------------------
85
86 locRepeatMainGameLoop:                           // start repeating game loop
87
88   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
89   // FS   synchronization
90   while (PauseMode != 0)
91   {
92     DoEvents();
93   }
94
95   do
96   {
97     DoEvents(); // user may klick on menus or move the window here ...
98   }
99 #if 1
100   while (0);
101 #else
102   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
103 #endif
104
105   //   never any additional code between here!
106 #if 0
107   LastFrame = Clock.TickNow(); // store the frame time
108 #endif
109   //   never any additional code between here!
110   if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
111     Stage.Blt();
112
113   // FS   end of synchronization
114   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
115   if (EndFlag)
116     goto locExitMainGameLoop;
117
118   // If DemoFlag = 0 Then Call subCheckJoystick    ' check joystick
119   // bx = subCheckRightMouseButton()                ' check (right) mouse button
120   // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
121
122   //  If DebugVersionFlag <> 0 Then ' debug mode on?
123   //    If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
124   //    If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
125   //                                          ' fixes ENTER bug If no mouse driver!
126   //    If bx <> 1 Then GoTo loc_g_186F  ' Left button=Init game field
127   //                                    ' Also Enter If no mouse!
128   //    If Data_SubRest <> 0 Then GoTo loc_g_186F
129   //    Data_SubRest = 10
130   //    Call subRestoreFancy
131   //    Call subDisplayLevel         ' Paint (Init) game field
132   //    Call subConvertToEasySymbols ' Convert to easy symbols
133   //  End If
134
135   // loc_g_186F:
136
137   subProcessKeyboardInput();                 // Check keyboard, act on keys
138
139   // 'HACK:
140   //  TimerVar = TimerVar + 1
141   //  DoEvents
142   //  GoTo loc_g_186F
143   // 'END HACK
144   // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
145
146   // ----------------------------------------------------------------------------
147   //
148
149 #if 0
150   printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
151 #endif
152
153   subDoGameStuff();                 // do all game stuff
154
155 #if 0
156   printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
157 #endif
158
159   //
160   // ----------------------------------------------------------------------------
161
162   //  Call subDisplayPlayingTime                 ' playing time on screen
163
164   subCheckRestoreRedDiskCountDisplay();    // Restore panel: red-disk hole
165
166   subRedDiskReleaseExplosion();       // Red Disk release and explode
167   subFollowUpExplosions();  // every explosion may cause up to 8 following explosions
168
169   bx = subCalculateScreenScrollPos();     // calculate screen start addrs
170
171   ScreenPosition = bx;
172
173   // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
174   data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
175   data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
176   if ((! UserDragFlag) && AutoScrollFlag)
177   {
178 #if 0
179     printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
180 #endif
181
182     ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
183   }
184
185   if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
186     goto locExitMainGameLoop;
187
188   TimerVar = TimerVar + 1;
189
190 #if 0
191   if (bCapturePane)
192     MainForm.SaveSnapshot(TimerVar);
193 #endif
194
195   //  If Not NoDisplayFlag Then
196   //    With MainForm.lblFrameCount
197   //      .Caption = TimerVar
198   //      .Refresh
199   //    End With
200   //  End If
201   if (ExitToMenuFlag == 1)
202     goto locExitMainGameLoop;
203
204   if (LeadOutCounter == 0) // no lead-out: game busy
205     goto locRepeatMainGameLoop;
206
207   // ----------------------------------------------------------------------------
208   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
209   // ----------------------------------------------------------------------------
210   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
211   if (LeadOutCounter != 0) // lead-out not ready: more
212     goto locRepeatMainGameLoop;
213
214   // lead-out done: exit now
215   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
216
217 locExitMainGameLoop:
218   do
219   {
220     DoEvents(); // user may klick on menus or move the window here ...
221   }
222 #if 1
223   while (0);
224 #else
225   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
226 #endif
227
228   Stage.Blt(); // blit the last frame
229   GameLoopRunning = 0;
230
231 #if 0
232   MainForm.menStop_Click();
233   MainForm.PanelVisible = True;
234 #endif
235
236   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
237   if (SavedGameFlag != 0) // after savegame: no update!
238   {
239     SavedGameFlag = 0;
240     return subMainGameLoop;
241   }
242
243   SavedGameFlag = 0;
244   if (UpdateTimeFlag == 0) // update time?
245     return subMainGameLoop;
246
247   if (UpdatedFlag == 0) // update playing time
248     subUpdatePlayingTime();
249
250
251   return subMainGameLoop;
252 } // subMainGameLoop
253
254 void subUpdatePlayingTime()
255 {
256 }
257
258 int subCalculateScreenScrollPos()
259 {
260   int subCalculateScreenScrollPos;
261
262   int ax, Ay;
263
264   if (ExplosionShake != 0)
265   {
266     subGetRandomNumber();
267   }
268
269   {
270     ax = MainForm.picPane.Width / 2;
271     Ay = MainForm.picPane.Height / 2;
272   }
273
274 #if 1
275   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
276   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
277 #else
278   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
279   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
280 #endif
281
282 #if 0
283   printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
284          MainForm.picPane.Width, MainForm.picPane.Height,
285          MurphyScreenXPos, MurphyScreenYPos,
286          ScreenScrollXPos, ScreenScrollYPos);
287 #endif
288
289   return subCalculateScreenScrollPos;
290 }