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