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