/* Starshatter: The Open Source Project Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. AUTHOR: John DiCamillo */ #include "Game.h" #include "Mouse.h" #include "Universe.h" #include "Window.h" #include "EventDispatch.h" #include "DataLoader.h" #include "Panic.h" #include "Pcx.h" #include "Bitmap.h" #include "MachineInfo.h" #include "VideoSettings.h" #include "ContentBundle.h" #include "Clock.h" #include "WndProc.h" #include "SoundCard.h" // +--------------------------------------------------------------------+ Game* game = 0; const double MAX_FRAME_TIME_NORMAL = 1.0 / 5.0; // +--------------------------------------------------------------------+ Game::Game() : world(0), video_factory(0), video(0), video_settings(0), soundcard(0), screen(0), totaltime(0), status(Game::OK), exit_code(0) { Clock::Init(); if (!game) { game = this; active = false; paused = false; server = false; show_mouse = false; frame_number = 0; max_frame_length = MAX_FRAME_TIME_NORMAL; video_settings = new VideoSettings; } else status = TOO_MANY; } Game::~Game() { if (game == this) game = 0; Clock::Close(); delete world; delete screen; delete video_factory; delete video; delete soundcard; delete video_settings; if (status == EXIT) ShowStats(); } // +--------------------------------------------------------------------+ bool Game::Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow) { status = OK; if (status == OK) { Print(" Initializing content...\n"); ContentBundle::GetInstance()->Init(); Print(" Initializing game...\n"); if (!InitGame()) { if (Panic::Panicked()) Panic::Panic("Could not initialize the game."); status = INIT_FAILED; } } return status == OK; } // +--------------------------------------------------------------------+ bool Game::InitGame() { if (server) { Print(" InitGame() - server mode.\n"); } return true; } // +--------------------------------------------------------------------+ int Game::Run() { status = RUN; Clock::GetInstance()->Set(); while (status < EXIT && !Panic::Panicked()) { GameLoop(); } return exit_code; } // +--------------------------------------------------------------------+ void Game::Exit() { Print("\n\n*** Game::Exit()\n"); status = EXIT; } // +--------------------------------------------------------------------+ void Game::Activate(bool f) { active = f; if (active && video) video->InvalidateCache(); } // +--------------------------------------------------------------------+ void Game::Pause(bool f) { if (f) { if (soundcard) soundcard->Pause(); paused = true; } else { if (soundcard) soundcard->Resume(); paused = false; } } // +--------------------------------------------------------------------+ bool Game::GameLoop() { bool wait_for_windows_events = true; if (active && !paused) { if (!server) { // Route Events to EventTargets EventDispatch* ed = EventDispatch::GetInstance(); if (ed) ed->Dispatch(); } UpdateWorld(); GameState(); if (!server) { UpdateScreen(); CollectStats(); } wait_for_windows_events = false; } else if (active && paused) { if (GetKey()=='P') Pause(false); } Clock::GetInstance()->Step(); frame_number++; Mouse::w = 0; return wait_for_windows_events; } // +--------------------------------------------------------------------+ void Game::UpdateWorld() { if (world) world->ExecFrame(Clock::GetInstance()->Delta()); } // +--------------------------------------------------------------------+ void Game::GameState() { } // +--------------------------------------------------------------------+ void Game::UpdateScreen() { if (!screen || !video) return; if (screen->Refresh()) { video->Present(); } else { Panic::Panic("Screen refresh failed."); } } // +--------------------------------------------------------------------+ Game* Game::GetInstance() { return game; } // +--------------------------------------------------------------------+ void Game::CollectStats() { if (!totaltime) totaltime = Clock::GetInstance()->RealTime(); if (video) { stats.nframe = video->GetStats().nframe; stats.nverts = video->GetStats().nverts; stats.npolys = video->GetStats().npolys; stats.nlines = video->GetStats().nlines; stats.ncalls += video->GetStats().ncalls; stats.total_verts += stats.nverts; stats.total_polys += stats.npolys; stats.total_lines += stats.nlines; } } // +--------------------------------------------------------------------+ void Game::ShowStats() { if (server) return; totaltime = Clock::GetInstance()->RealTime() - totaltime; Print("\n"); Print("Performance Data:\n"); Print("-----------------\n"); Print(" Time: %d msec\n", totaltime); Print(" Frames: %d\n", stats.nframe); Print(" Polys Rendered: %d\n", stats.total_polys); Print(" Lines Rendered: %d\n", stats.total_lines); Print(" Verts Rendered: %d\n", stats.total_verts); Print(" Render Calls: %d\n", stats.ncalls); Print("\n"); Print("Performance Statistics:\n"); Print("-----------------------\n"); Print(" Frames/Second: %.2f\n", (stats.nframe * 1000.0) / totaltime); Print(" Polys/Frame: %.2f\n", (double) stats.total_polys / (double) stats.nframe); Print(" Polys/Call: %.2f\n", (double) stats.total_polys / (double) stats.ncalls); Print(" Polys/Second: %.2f\n", (stats.total_polys * 1000.0) / totaltime); Print(" Lines/Second: %.2f\n", (stats.total_lines * 1000.0) / totaltime); Print(" Verts/Second: %.2f\n", (stats.total_verts * 1000.0) / totaltime); Print("\n"); } // +====================================================================+ DWORD Game::Frame() { return frame_number; }