00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032
00033
00034
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #if defined(DEBUG)
00039 #include <setjmp.h>
00040 #endif
00041
00042 #include "stratagus.h"
00043 #include "video.h"
00044 #include "map.h"
00045 #include "font.h"
00046 #include "sound.h"
00047 #include "sound_server.h"
00048 #include "unitsound.h"
00049 #include "unittype.h"
00050 #include "player.h"
00051 #include "unit.h"
00052 #include "cursor.h"
00053 #include "minimap.h"
00054 #include "actions.h"
00055 #include "missile.h"
00056 #include "interface.h"
00057 #include "menus.h"
00058 #include "network.h"
00059 #include "ui.h"
00060 #include "unit.h"
00061 #include "trigger.h"
00062 #include "results.h"
00063 #include "settings.h"
00064 #include "replay.h"
00065 #include "pathfinder.h"
00066 #include "editor.h"
00067 #include "sound.h"
00068 #include "script.h"
00069 #include "particle.h"
00070
00071 #include <guichan.h>
00072 void DrawGuichanWidgets();
00073
00074
00075
00076
00077
00079 int KeyScrollState = ScrollNone;
00080
00082 int MouseScrollState = ScrollNone;
00083
00084 EventCallback GameCallbacks;
00085 EventCallback EditorCallbacks;
00086
00087
00088
00089
00090
00100 void DoScrollArea(int state, bool fast)
00101 {
00102 CViewport *vp;
00103 int stepx;
00104 int stepy;
00105 static int remx = 0;
00106 static int remy = 0;
00107
00108 if (state == ScrollNone) {
00109 return;
00110 }
00111
00112 vp = UI.SelectedViewport;
00113
00114 if (fast) {
00115 stepx = vp->MapWidth / 2 * TileSizeX * FRAMES_PER_SECOND;
00116 stepy = vp->MapHeight / 2 * TileSizeY * FRAMES_PER_SECOND;
00117 } else {
00118
00119 stepx = TileSizeX * FRAMES_PER_SECOND;
00120 stepy = TileSizeY * FRAMES_PER_SECOND;
00121 }
00122 if ((state & (ScrollLeft | ScrollRight)) &&
00123 (state & (ScrollLeft | ScrollRight)) != (ScrollLeft | ScrollRight)) {
00124 stepx = stepx * 100 * 100 / VideoSyncSpeed / FRAMES_PER_SECOND / (SkipFrames + 1);
00125 remx += stepx - (stepx / 100) * 100;
00126 stepx /= 100;
00127 if (remx > 100) {
00128 ++stepx;
00129 remx -= 100;
00130 }
00131 } else {
00132 stepx = 0;
00133 }
00134 if ((state & (ScrollUp | ScrollDown)) &&
00135 (state & (ScrollUp | ScrollDown)) != (ScrollUp | ScrollDown)) {
00136 stepy = stepy * 100 * 100 / VideoSyncSpeed / FRAMES_PER_SECOND / (SkipFrames + 1);
00137 remy += stepy - (stepy / 100) * 100;
00138 stepy /= 100;
00139 if (remy > 100) {
00140 ++stepy;
00141 remy -= 100;
00142 }
00143 } else {
00144 stepy = 0;
00145 }
00146
00147 if (state & ScrollUp) {
00148 stepy = -stepy;
00149 }
00150 if (state & ScrollLeft) {
00151 stepx = -stepx;
00152 }
00153 vp->Set(vp->MapX, vp->MapY, vp->OffsetX + stepx, vp->OffsetY + stepy);
00154
00155
00156 HandleMouseMove(CursorX, CursorY);
00157 }
00158
00162 void DrawMapArea(void)
00163 {
00164
00165 for (CViewport *vp = UI.Viewports; vp < UI.Viewports + UI.NumViewports; ++vp) {
00166
00167 if (vp->Unit) {
00168 if (vp->Unit->Destroyed ||
00169 vp->Unit->Orders[0]->Action == UnitActionDie) {
00170 vp->Unit = NoUnitP;
00171 } else {
00172 vp->Center(vp->Unit->X, vp->Unit->Y,
00173 vp->Unit->IX + TileSizeX / 2, vp->Unit->IY + TileSizeY / 2);
00174 }
00175 }
00176
00177 vp->Draw();
00178 }
00179 }
00180
00187 void UpdateDisplay(void)
00188 {
00189 if (GameRunning || Editor.Running == EditorEditing) {
00190 DrawMapArea();
00191 DrawMessages();
00192
00193 if (CursorState == CursorStateRectangle) {
00194 DrawCursor();
00195 }
00196
00197 if (!BigMapMode) {
00198 for (int i = 0; i < (int)UI.Fillers.size(); ++i) {
00199 UI.Fillers[i].G->DrawClip(UI.Fillers[i].X, UI.Fillers[i].Y);
00200 }
00201 DrawMenuButtonArea();
00202
00203 UI.Minimap.Draw(UI.SelectedViewport->MapX, UI.SelectedViewport->MapY);
00204 UI.Minimap.DrawCursor(UI.SelectedViewport->MapX,
00205 UI.SelectedViewport->MapY);
00206
00207 UI.InfoPanel.Draw();
00208 UI.ButtonPanel.Draw();
00209 DrawResources();
00210 UI.StatusLine.Draw();
00211 }
00212
00213 DrawCosts();
00214 DrawTimer();
00215 }
00216
00217 DrawPieMenu();
00218
00219 DrawGuichanWidgets();
00220
00221 if (CursorState != CursorStateRectangle) {
00222 DrawCursor();
00223 }
00224
00225
00226
00227
00228 Invalidate();
00229 }
00230
00231 static void InitGameCallbacks(void)
00232 {
00233 GameCallbacks.ButtonPressed = HandleButtonDown;
00234 GameCallbacks.ButtonReleased = HandleButtonUp;
00235 GameCallbacks.MouseMoved = HandleMouseMove;
00236 GameCallbacks.MouseExit = HandleMouseExit;
00237 GameCallbacks.KeyPressed = HandleKeyDown;
00238 GameCallbacks.KeyReleased = HandleKeyUp;
00239 GameCallbacks.KeyRepeated = HandleKeyRepeat;
00240 GameCallbacks.NetworkEvent = NetworkEvent;
00241 }
00242
00253 void GameMainLoop(void)
00254 {
00255 #ifdef DEBUG // removes the setjmp warnings
00256 static bool showtip;
00257 #else
00258 bool showtip;
00259 #endif
00260 int player;
00261 const EventCallback *old_callbacks;
00262
00263 InitGameCallbacks();
00264
00265 old_callbacks = GetCallbacks();
00266 SetCallbacks(&GameCallbacks);
00267
00268 SetVideoSync();
00269 GameCursor = UI.Point.Cursor;
00270 GameRunning = true;
00271
00272 CParticleManager::init();
00273
00274 showtip = false;
00275
00276 MultiPlayerReplayEachCycle();
00277
00278 CclCommand("GameStarting()");
00279
00280 while (GameRunning) {
00281
00282
00283 SaveGameLoading = false;
00284
00285
00286
00287 if (!GamePaused && NetworkInSync && !SkipGameCycle) {
00288 SinglePlayerReplayEachCycle();
00289 ++GameCycle;
00290 MultiPlayerReplayEachCycle();
00291 NetworkCommands();
00292 UnitActions();
00293 MissileActions();
00294 PlayersEachCycle();
00295 UpdateTimer();
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 switch (GameCycle % CYCLES_PER_SECOND) {
00308 case 0:
00309 if (GameCycle == 0) {
00310 for (player = 0; player < NumPlayers; ++player) {
00311 PlayersEachSecond(player);
00312 }
00313 }
00314 break;
00315 case 1:
00316 break;
00317 case 2:
00318 break;
00319 case 3:
00320 UI.Minimap.Update();
00321 break;
00322 case 4:
00323 break;
00324 case 5:
00325 break;
00326 case 6:
00327 RescueUnits();
00328 break;
00329 default:
00330
00331 player = (GameCycle % CYCLES_PER_SECOND) - 7;
00332 Assert(player >= 0);
00333 if (player < NumPlayers) {
00334 PlayersEachSecond(player);
00335 }
00336 }
00337 }
00338
00339 TriggersEachCycle();
00340 UpdateMessages();
00341 ParticleManager.update();
00342
00343 CheckMusicFinished();
00344
00345
00346
00347
00348 DoScrollArea(MouseScrollState | KeyScrollState, (KeyModifiers & ModifierControl) != 0);
00349
00350 if (FastForwardCycle <= GameCycle || GameCycle <= 10 || !(GameCycle & 0x3f)) {
00351
00352
00353
00354 UpdateDisplay();
00355
00356
00357
00358
00359
00360
00361 RealizeVideoMemory();
00362 }
00363
00364 if (FastForwardCycle <= GameCycle || !(GameCycle & 0x3f)) {
00365 WaitEventsOneFrame();
00366 }
00367 if (!NetworkInSync) {
00368 NetworkRecover();
00369 }
00370 }
00371
00372
00373
00374
00375 NetworkQuit();
00376 EndReplayLog();
00377
00378 CParticleManager::exit();
00379
00380 FlagRevealMap = 0;
00381 ReplayRevealMap = 0;
00382 GamePaused = false;
00383 GodMode = false;
00384
00385 SetCallbacks(old_callbacks);
00386 }
00387