/* * 2D Game Engine * Game.cpp: Base Game engine class * Based on pikuma.com 2D game engine in C++ and Lua course * Copyright (c) 2021 986-Studio. All Right Reserved * * Created by Manoƫl Trapier on 09/02/2021. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Game::Game() { this->isRunning = false; this->windowsHeight = 0; this->windowsWidth = 0; this->isDebug = false; this->registry = std::make_unique(); this->assetStore = std::make_unique(); this->eventBus = std::make_unique(); } Game::~Game() { } void Game::Initialize() { int ret; SDL_DisplayMode displayMode; ret = SDL_Init(SDL_INIT_EVERYTHING); if (ret) { Logger::Critical("SDL Initialisation error."); return; } SDL_GetCurrentDisplayMode(0, &displayMode); this->windowsWidth = displayMode.w; this->windowsHeight = displayMode.h; this->window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->windowsWidth, this->windowsHeight, SDL_WINDOW_BORDERLESS); if (!window) { Logger::Critical("SDL window creation error."); return; } this->renderer = SDL_CreateRenderer(this->window, -1, 0); if (!renderer) { Logger::Critical("SDL renderer creation error."); return; } SDL_SetWindowFullscreen(this->window, SDL_WINDOW_FULLSCREEN); this->isRunning = true; } void Game::Destroy() { if (this->renderer) { SDL_DestroyRenderer(this->renderer); } if (this->window) { SDL_DestroyWindow(this->window); } SDL_Quit(); } void Game::Run() { this->Setup(); while(this->isRunning) { this->ProcessInput(); this->Update(); this->Render(); } } void Game::LoadLevel(int level) { this->registry->addSystem(); this->registry->addSystem(); this->registry->addSystem(); this->registry->addSystem(); this->registry->addSystem(); this->registry->addSystem(); this->assetStore->addTexture(this->renderer, "tank-image", "assets/images/tank-panther-right.png"); this->assetStore->addTexture(this->renderer, "truck-image", "assets/images/truck-ford-right.png"); this->assetStore->addTexture(this->renderer, "chopper-image", "assets/images/chopper.png"); this->assetStore->addTexture(this->renderer, "main-tileset", "assets/tilemaps/jungle.png"); this->assetStore->addTexture(this->renderer, "radar-image", "assets/images/radar.png"); Logger::Debug("struct SpriteComponent size is %d", sizeof(struct SpriteComponent)); // jungle.map int tileSize = 32; double tileScale = 2.0; int mapNumCols = 25; int mapNumRows = 20; std::fstream mapFile; mapFile.open("assets/tilemaps/jungle.map"); assert(mapFile.is_open()); for (int y = 0; y < mapNumRows; y++) { for (int x = 0; x < mapNumCols; x++) { char ch[2] = {0, 0}; mapFile.get(ch[0]); int srcRectY = atoi(ch) * tileSize; mapFile.get(ch[0]); int srcRectX = atoi(ch) * tileSize; mapFile.ignore(); Entity tile = registry->createEntity(); tile.addComponent(glm::vec2(x * (tileScale * tileSize), y * (tileScale * tileSize)), glm::vec2(tileScale, tileScale), 0.0); tile.addComponent("main-tileset", 0, tileSize, tileSize, srcRectX, srcRectY); } } mapFile.close(); Entity chopper = this->registry->createEntity(); chopper.addComponent(glm::vec2(10, 100), glm::vec2(1, 1), 0); chopper.addComponent("chopper-image", 2, 32, 32); chopper.addComponent(glm::vec2(0, 0)); chopper.addComponent(2, 15, true); Entity radar = this->registry->createEntity(); radar.addComponent(glm::vec2(this->windowsWidth - 75, 10), glm::vec2(1, 1), 0); radar.addComponent(glm::vec2(0, 0)); radar.addComponent("radar-image", 3, 64, 64); radar.addComponent(8, 5, true); Entity tank = this->registry->createEntity(); tank.addComponent(glm::vec2(500, 10), glm::vec2(1, 1), 0); tank.addComponent(glm::vec2(-30, 0)); tank.addComponent("tank-image", 1, 32, 32); tank.addComponent(32, 32, glm::vec2(0, 0)); Entity truck = this->registry->createEntity(); truck.addComponent(glm::vec2(10, 10), glm::vec2(1, 1), 0); truck.addComponent(glm::vec2(20, 0)); truck.addComponent("truck-image", 1, 32, 32); truck.addComponent(32, 32, glm::vec2(0, 0)); } void Game::Setup() { LoadLevel(1); } void Game::Update() { uint32_t timeToWait = MILLISECS_PER_FRAME - (SDL_GetTicks() - this->millisecsPerviousFrame); if (timeToWait > 0 && timeToWait <= MILLISECS_PER_FRAME) { SDL_Delay(timeToWait); } double deltaTime = (SDL_GetTicks() - this->millisecsPerviousFrame) / 1000.0; this->millisecsPerviousFrame = SDL_GetTicks(); eventBus->reset(); registry->getSystem().subscriptToEvents(eventBus); registry->getSystem().subscriptToEvents(eventBus); registry->getSystem().update(deltaTime); registry->getSystem().update(); registry->getSystem().update(this->eventBus); registry->update(); } void Game::ProcessInput() { SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: this->isRunning = false; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { this->isRunning = false; } else if (event.key.keysym.sym == SDLK_d) { this->isDebug = !this->isDebug; } else { this->eventBus->emitEvent(event.key.keysym.sym); } break; default: break; } } } void Game::Render() { SDL_SetRenderDrawColor(this->renderer, 21, 21, 21, 255); SDL_RenderClear(this->renderer); // Do something here registry->getSystem().update(this->renderer, this->assetStore); if (this->isDebug) { registry->getSystem().debugRender(this->renderer); } SDL_RenderPresent(this->renderer); }