igra
This commit is contained in:
@@ -7,16 +7,24 @@
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <game/agame/enemy.hpp>
|
||||
#include <game/agame/trash.hpp>
|
||||
#include <game/agame/friendly.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
GAME_ENTITY(Background)
|
||||
public:
|
||||
void render(Game::Renderer::Renderer* renderer, Game::Renderer::RendererConfig config) override;
|
||||
void onWindowResized(int newWidth, int newHeight) override;
|
||||
private:
|
||||
float mEnemySpawnTimer = 0.f;
|
||||
float mTimeToSpawn = 5.f;
|
||||
void spawnLevel(int stage);
|
||||
void spawnFriendly(int stage, int count);
|
||||
int mW, mH;
|
||||
int mMaxLevels = 2;
|
||||
float mLandBoundaryX = 0.f;
|
||||
bool mPendingLevelSpawn = false;
|
||||
int mPendingLevelStage = 0;
|
||||
std::shared_ptr<Game::Renderer::Texture> mSeaTex;
|
||||
std::shared_ptr<Game::Renderer::Texture> mEnemyTex;
|
||||
std::shared_ptr<Game::Renderer::Texture> mTrashTex;
|
||||
std::shared_ptr<Game::Renderer::Texture> mFriendlyTex;
|
||||
END_GAME_ENTITY()
|
||||
}
|
||||
@@ -10,5 +10,10 @@ namespace Game::AGame {
|
||||
GAME_ENTITY(Enemy)
|
||||
public:
|
||||
void onCollisionEnter(Object::Entity* other) override;
|
||||
bool hasAdjacentEnemy();
|
||||
private:
|
||||
float mMoveSpeedX = 0.f;
|
||||
float mMoveSpeedY = 0.f;
|
||||
float mDirectionChangeTimer = 0.f;
|
||||
END_GAME_ENTITY()
|
||||
}
|
||||
18
include/game/agame/friendly.hpp
Normal file
18
include/game/agame/friendly.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <object/entity.hpp>
|
||||
#include <renderer/texture.hpp>
|
||||
#include <renderer/font.hpp>
|
||||
#include <object/sound.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
GAME_ENTITY(Friendly)
|
||||
public:
|
||||
void onCollisionEnter(Object::Entity* other) override;
|
||||
private:
|
||||
float mMoveSpeedX = 0.f;
|
||||
float mMoveSpeedY = 0.f;
|
||||
float mDirectionChangeTimer = 0.f;
|
||||
END_GAME_ENTITY()
|
||||
}
|
||||
14
include/game/agame/hudtext.hpp
Normal file
14
include/game/agame/hudtext.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <object/ui/uitext.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
class HUDText : public Object::UIText {
|
||||
using Object::UIText::UIText;
|
||||
|
||||
public:
|
||||
~HUDText() override = default;
|
||||
void start() override;
|
||||
void update(float deltaTime) override;
|
||||
};
|
||||
}
|
||||
@@ -7,9 +7,19 @@
|
||||
|
||||
namespace Game::AGame {
|
||||
GAME_ENTITY(Player)
|
||||
public:
|
||||
void setShipTexture(std::shared_ptr<Game::Renderer::Texture> tex);
|
||||
void setGroundTexture(std::shared_ptr<Game::Renderer::Texture> tex);
|
||||
void respawnRandomSea(float landBoundaryX);
|
||||
bool isShipMode() const { return mIsShipMode; }
|
||||
void onCollisionEnter(Object::Entity* other) override;
|
||||
private:
|
||||
Object::Sound mSound;
|
||||
float mSpeed = 200.f; // Pixels per second
|
||||
[[maybe_unused]] float mHealth = 100.f;
|
||||
std::shared_ptr<Game::Renderer::Texture> mShipTex;
|
||||
std::shared_ptr<Game::Renderer::Texture> mGroundTex;
|
||||
bool mIsShipMode = true;
|
||||
float mShoreMargin = 40.f;
|
||||
END_GAME_ENTITY()
|
||||
}
|
||||
@@ -6,7 +6,13 @@
|
||||
#include <renderer/font.hpp>
|
||||
#include <object/sound.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
class Player;
|
||||
}
|
||||
|
||||
namespace Game::AGame {
|
||||
GAME_ENTITY(Trash)
|
||||
public:
|
||||
void onCollisionEnter(Object::Entity* other) override;
|
||||
END_GAME_ENTITY()
|
||||
}
|
||||
BIN
resources/l3friendly.png
Normal file
BIN
resources/l3friendly.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 393 B |
BIN
resources/l3player.png
Normal file
BIN
resources/l3player.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 393 B |
BIN
resources/l3sea.png
Normal file
BIN
resources/l3sea.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 179 B |
@@ -1,19 +1,37 @@
|
||||
#include <game/agame/background.hpp>
|
||||
#include <game/agame/player.hpp>
|
||||
#include <window/window.hpp>
|
||||
#include <object/camera.hpp>
|
||||
#include <algorithm>
|
||||
#include <utils.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Background::start() {
|
||||
mSeaTex = std::make_shared<Game::Renderer::Texture>("../resources/l3sea.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "seaTex");
|
||||
mEnemyTex = std::make_shared<Game::Renderer::Texture>("../resources/l3enemy.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "enemyTex");
|
||||
mTrashTex = std::make_shared<Game::Renderer::Texture>("../resources/l3trash.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "trashTex");
|
||||
mFriendlyTex = std::make_shared<Game::Renderer::Texture>("../resources/l3friendly.png", SDL_GetRenderer(Window::Window::getSDLWindowBackend()), "friendlyTex");
|
||||
GameManager::setSharedData("enemyActiveCount", 0);
|
||||
GameManager::setSharedData("trashActiveCount", 0);
|
||||
GameManager::setSharedData("friendlyActiveCount", 0);
|
||||
GameManager::setSharedData("gameStage", 1);
|
||||
GameManager::setSharedData("gameWon", false);
|
||||
GameManager::setSharedData("gameLost", false);
|
||||
|
||||
mZIndex = -1; // Ensure background renders behind other entities
|
||||
mTex->setTiled(true); // Set the background texture to be tiled
|
||||
if (mSeaTex) {
|
||||
mSeaTex->setTiled(true);
|
||||
}
|
||||
mTiledScale = 0.5f;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &mW, &mH);
|
||||
|
||||
// Land boundary: left 1/3 of map in centered coordinates
|
||||
// For 1280px window: -640 (left) + 426.67 (1/3) = -213.33
|
||||
mLandBoundaryX = -static_cast<float>(mW) / 2.f + static_cast<float>(mW) / 3.f;
|
||||
GameManager::setSharedData("terrainLandBoundaryX", mLandBoundaryX);
|
||||
GameManager::setSharedData("enemyRevealRadius", 260.f);
|
||||
|
||||
mTransform.scaleX *= 10.f;
|
||||
mTransform.scaleY *= 10.f;
|
||||
|
||||
@@ -21,72 +39,147 @@ namespace Game::AGame {
|
||||
mTransform.y -= mTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
|
||||
|
||||
LOG("W: " << mW << " H: " << mH);
|
||||
spawnLevel(1);
|
||||
}
|
||||
|
||||
mTransform.x = mW / 2.f - (mW / 3.f);
|
||||
mTransform.y = -mH;
|
||||
void Background::render(Game::Renderer::Renderer* renderer, Game::Renderer::RendererConfig config) {
|
||||
if (!renderer || !mTex || !mSeaTex) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float worldLeft = -static_cast<float>(mW) / 2.f;
|
||||
const float worldRight = static_cast<float>(mW) / 2.f;
|
||||
const float worldTop = -static_cast<float>(mH) / 2.f;
|
||||
const float worldBottom = static_cast<float>(mH) / 2.f;
|
||||
|
||||
const float landLeft = worldLeft;
|
||||
const float landRight = mLandBoundaryX;
|
||||
const float seaLeft = mLandBoundaryX;
|
||||
const float seaRight = worldRight;
|
||||
|
||||
auto drawSection = [&](const std::shared_ptr<Game::Renderer::Texture>& tex, float startX, float endX) {
|
||||
if (!tex) {
|
||||
return;
|
||||
}
|
||||
|
||||
float tileW = 0.f;
|
||||
float tileH = 0.f;
|
||||
SDL_GetTextureSize(tex->getSDLTexture(), &tileW, &tileH);
|
||||
tileW *= mTiledScale;
|
||||
tileH *= mTiledScale;
|
||||
if (tileW <= 0.f || tileH <= 0.f) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float screenStartX = startX - config.camX + config.screenW / 2.f;
|
||||
const float screenEndX = endX - config.camX + config.screenW / 2.f;
|
||||
const float screenStartY = worldTop - config.camY + config.screenH / 2.f;
|
||||
const float screenEndY = worldBottom - config.camY + config.screenH / 2.f;
|
||||
|
||||
for (float x = screenStartX; x < screenEndX; x += tileW) {
|
||||
for (float y = screenStartY; y < screenEndY; y += tileH) {
|
||||
SDL_FRect dst{ x, y, tileW, tileH };
|
||||
SDL_RenderTexture(renderer->getSDLRenderer(), tex->getSDLTexture(), nullptr, &dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
drawSection(mTex, landLeft, landRight);
|
||||
drawSection(mSeaTex, seaLeft, seaRight);
|
||||
}
|
||||
|
||||
void Background::spawnFriendly(int stage, int count) {
|
||||
const float viewLeft = -mW / 2.f;
|
||||
const float viewTop = -mH / 2.f;
|
||||
const float viewBottom = mH / 2.f;
|
||||
|
||||
Object::Transform tS;
|
||||
tS.rotation = 0.f;
|
||||
tS.scaleX = 6.f;
|
||||
tS.scaleY = 6.f;
|
||||
|
||||
const float halfFriendlyW = mFriendlyTex->getWidth() * tS.adjustedScaleX() / 2.f;
|
||||
const float halfFriendlyH = mFriendlyTex->getHeight() * tS.adjustedScaleY() / 2.f;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
tS.x = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(viewLeft + halfFriendlyW + 25.f), static_cast<int>(mLandBoundaryX - halfFriendlyW - 25.f)));
|
||||
tS.y = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(viewTop + halfFriendlyH + 100.f), static_cast<int>(viewBottom - halfFriendlyH - 100.f)));
|
||||
GameManager::instantiateEntity(std::make_unique<AGame::Friendly>("Friendly" + std::to_string(stage) + "_" + std::to_string(i + 1), mFriendlyTex, tS));
|
||||
}
|
||||
}
|
||||
|
||||
void Background::spawnLevel(int stage) {
|
||||
const float viewLeft = -mW / 2.f;
|
||||
const float viewRight = mW / 2.f;
|
||||
const float viewTop = -mH / 2.f;
|
||||
const float viewBottom = mH / 2.f;
|
||||
|
||||
const int enemyCount = 2 + stage * 2;
|
||||
const int trashCount = 4 + stage * 3;
|
||||
const int friendlyCount = 1 + (stage - 1);
|
||||
|
||||
GameManager::setSharedData("gameStage", stage);
|
||||
GameManager::setSharedData("enemyActiveCount", enemyCount);
|
||||
GameManager::setSharedData("trashActiveCount", trashCount);
|
||||
GameManager::setSharedData("friendlyActiveCount", friendlyCount);
|
||||
|
||||
if (stage > 1) {
|
||||
auto* player = GameManager::getEntityByName<Player>("Player");
|
||||
if (player) {
|
||||
player->respawnRandomSea(mLandBoundaryX);
|
||||
}
|
||||
}
|
||||
|
||||
Object::Transform tS;
|
||||
tS.rotation = 0.f;
|
||||
|
||||
tS.scaleX = 7.f;
|
||||
tS.scaleY = 7.f;
|
||||
const float halfEnemyW = mEnemyTex->getWidth() * tS.adjustedScaleX() / 2.f;
|
||||
const float halfEnemyH = mEnemyTex->getHeight() * tS.adjustedScaleY() / 2.f;
|
||||
for (int i = 0; i < enemyCount; ++i) {
|
||||
tS.x = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(viewLeft + halfEnemyW + 25.f), static_cast<int>(mLandBoundaryX - halfEnemyW - 25.f)));
|
||||
tS.y = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(viewTop + halfEnemyH + 100.f), static_cast<int>(viewBottom - halfEnemyH - 100.f)));
|
||||
GameManager::instantiateEntity(std::make_unique<AGame::Enemy>("Enemy" + std::to_string(stage) + "_" + std::to_string(i + 1), mEnemyTex, tS));
|
||||
}
|
||||
|
||||
tS.scaleX = 5.5f;
|
||||
tS.scaleY = 5.5f;
|
||||
const float halfTrashW = mTrashTex->getWidth() * tS.adjustedScaleX() / 2.f;
|
||||
const float halfTrashH = mTrashTex->getHeight() * tS.adjustedScaleY() / 2.f;
|
||||
for (int i = 0; i < trashCount; ++i) {
|
||||
tS.x = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(mLandBoundaryX + halfTrashW + 25.f), static_cast<int>(viewRight - halfTrashW - 25.f)));
|
||||
tS.y = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(viewTop + halfTrashH + 100.f), static_cast<int>(viewBottom - halfTrashH - 100.f)));
|
||||
GameManager::instantiateEntity(std::make_unique<AGame::Trash>("Trash" + std::to_string(stage) + "_" + std::to_string(i + 1), mTrashTex, tS));
|
||||
}
|
||||
|
||||
spawnFriendly(stage, friendlyCount);
|
||||
}
|
||||
|
||||
void Background::update(float deltaTime) {
|
||||
mEnemySpawnTimer += deltaTime;
|
||||
(void)deltaTime;
|
||||
|
||||
int cnt = GameManager::getSharedData<int>("enemyActiveCount");
|
||||
if (mEnemySpawnTimer >= mTimeToSpawn && cnt < 5) {
|
||||
mEnemySpawnTimer = 0.f; // RESET
|
||||
GameManager::setSharedData("enemyActiveCount", cnt + 1);
|
||||
// Spawn Enemy on grass
|
||||
Object::Transform tS;
|
||||
tS.scaleY = 7.f;
|
||||
tS.scaleX = 7.f;
|
||||
tS.rotation = 0.f;
|
||||
const int enemyCount = GameManager::getSharedData<int>("enemyActiveCount");
|
||||
const int trashCount = GameManager::getSharedData<int>("trashActiveCount");
|
||||
const int stage = GameManager::getSharedData<int>("gameStage");
|
||||
|
||||
float camX, camY;
|
||||
Object::Camera::getInstance().getPosition(camX, camY);
|
||||
|
||||
const float halfEnemyW = mEnemyTex->getWidth() * tS.adjustedScaleX() / 2.f;
|
||||
const float halfEnemyH = mEnemyTex->getHeight() * tS.adjustedScaleY() / 2.f;
|
||||
|
||||
const float viewLeft = camX - (mW / 2.f);
|
||||
const float viewRight = camX + (mW / 2.f);
|
||||
const float viewTop = camY - (mH / 2.f);
|
||||
const float viewBottom = camY + (mH / 2.f);
|
||||
|
||||
// Right 1/3 of the currently visible screen, in world coordinates.
|
||||
int spawnMinX = static_cast<int>(viewLeft + (2.f * mW / 3.f) + halfEnemyW);
|
||||
int spawnMaxX = static_cast<int>(viewRight - halfEnemyW - 25.f);
|
||||
int spawnMinY = static_cast<int>(viewTop + halfEnemyH + 100.f);
|
||||
int spawnMaxY = static_cast<int>(viewBottom - halfEnemyH - 100.f);
|
||||
|
||||
// Safety for tiny windows / huge sprites.
|
||||
if (spawnMinX > spawnMaxX) spawnMinX = spawnMaxX = static_cast<int>(camX);
|
||||
if (spawnMinY > spawnMaxY) spawnMinY = spawnMaxY = static_cast<int>(camY);
|
||||
|
||||
tS.x = static_cast<float>(Utils::getUtils().rirng32(spawnMinX, spawnMaxX));
|
||||
tS.y = static_cast<float>(Utils::getUtils().rirng32(spawnMinY, spawnMaxY));
|
||||
GameManager::instantiateEntity(std::make_unique<AGame::Enemy>("Enemy" + std::to_string(cnt + 1), mEnemyTex, tS));
|
||||
|
||||
// Spawn Trash at shoreline
|
||||
tS.scaleX = 5.5f;
|
||||
tS.scaleY = 5.5f;
|
||||
tS.rotation = 0.f;
|
||||
tS.x = mTransform.x - 75.f;
|
||||
tS.y = static_cast<float>(Utils::getUtils().rirng32(spawnMinY, spawnMaxY));
|
||||
GameManager::instantiateEntity(std::make_unique<AGame::Trash>("Trash" + std::to_string(cnt + 1), mTrashTex, tS));
|
||||
if (mPendingLevelSpawn) {
|
||||
if (enemyCount <= 0 && trashCount <= 0) {
|
||||
GameManager::processPendingEntityRemovals();
|
||||
mPendingLevelSpawn = false;
|
||||
spawnLevel(mPendingLevelStage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*const bool* state = SDL_GetKeyboardState(nullptr);
|
||||
if (state[SDL_SCANCODE_P]) {
|
||||
mTransform.scaleX *= 2.f;
|
||||
mTransform.scaleY *= 2.f;
|
||||
if (enemyCount <= 0 && trashCount <= 0) {
|
||||
if (stage < mMaxLevels) {
|
||||
mPendingLevelSpawn = true;
|
||||
mPendingLevelStage = stage + 1;
|
||||
} else if (!GameManager::getSharedData<bool>("gameWon")) {
|
||||
GameManager::setSharedData("gameWon", true);
|
||||
LOG("All levels cleared");
|
||||
}
|
||||
}
|
||||
if (state[SDL_SCANCODE_L]) {
|
||||
mTransform.scaleX *= 0.5f;
|
||||
mTransform.scaleY *= 0.5f;
|
||||
}*/
|
||||
//mTransform.rotation += 1.f; // Rotate clockwise for testing
|
||||
//mTransform.scaleX = 1.f + 1.f * std::sin(RUNNING_TIME() / 0.5f); // Pulsate scale for testing
|
||||
//mTransform.scaleY = 1.f + 0.5f * std::cos(RUNNING_TIME() / 0.5f); // Pulsate scale for testing
|
||||
|
||||
//Object::Camera::getInstance().move(1.f, 0.f);
|
||||
}
|
||||
|
||||
void Background::onWindowResized(int newWidth, int newHeight) {
|
||||
|
||||
@@ -1,22 +1,129 @@
|
||||
#include <game/agame/enemy.hpp>
|
||||
#include <object/components/boxcollider.hpp>
|
||||
#include <game/agame/player.hpp>
|
||||
#include <state/gamestate.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <utils.hpp>
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <window/window.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Enemy::start() {
|
||||
mZIndex = 20;
|
||||
addComponent<Object::Components::BoxCollider>();
|
||||
LOG("Enemy started: " << getName());
|
||||
|
||||
// Initialize random movement
|
||||
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
|
||||
const float speed = 20.f + static_cast<float>(Utils::getUtils().rirng32(0, 30));
|
||||
mMoveSpeedX = std::cos(angle) * speed;
|
||||
mMoveSpeedY = std::sin(angle) * speed;
|
||||
mDirectionChangeTimer = 0.f;
|
||||
}
|
||||
|
||||
void Enemy::update(float deltaTime) {
|
||||
(void)deltaTime;
|
||||
|
||||
auto* player = GameManager::getEntityByName<Player>("Player");
|
||||
if (!player) {
|
||||
mIsVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
void Enemy::onCollisionEnter(Object::Entity* other) {
|
||||
LOG("Enemy '" << getName() << "' collided with '" << other->getName() << "' (onCollisionEnter); Killing myself now!");
|
||||
GameManager::setSharedData("enemyActiveCount", GameManager::getSharedData<int>("enemyActiveCount") - 1);
|
||||
// Enemies are always visible
|
||||
mIsVisible = true;
|
||||
|
||||
// Find in state
|
||||
// Semi-random movement with periodic direction changes
|
||||
mDirectionChangeTimer += deltaTime;
|
||||
if (mDirectionChangeTimer > 2.0f) {
|
||||
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
|
||||
const float speed = 20.f + static_cast<float>(Utils::getUtils().rirng32(0, 30));
|
||||
mMoveSpeedX = std::cos(angle) * speed;
|
||||
mMoveSpeedY = std::sin(angle) * speed;
|
||||
mDirectionChangeTimer = 0.f;
|
||||
}
|
||||
|
||||
// Move enemy
|
||||
mTransform.x += mMoveSpeedX * deltaTime;
|
||||
mTransform.y += mMoveSpeedY * deltaTime;
|
||||
|
||||
// Clamp to land section
|
||||
const float landBoundaryX = GameManager::getSharedData<float>("terrainLandBoundaryX");
|
||||
const float entityWidth = getTexture() ? getTexture()->getWidth() * mTransform.adjustedScaleX() : 0.f;
|
||||
const float entityHeight = getTexture() ? getTexture()->getHeight() * mTransform.adjustedScaleY() : 0.f;
|
||||
const float halfWidth = entityWidth / 2.f;
|
||||
const float halfHeight = entityHeight / 2.f;
|
||||
|
||||
// Get window dimensions for boundary calculations
|
||||
int w = 0, h = 0;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
|
||||
const float leftEdge = -w / 2.f + 25.f;
|
||||
|
||||
if (mTransform.x - halfWidth < leftEdge) {
|
||||
mTransform.x = leftEdge + halfWidth;
|
||||
mMoveSpeedX = std::abs(mMoveSpeedX);
|
||||
}
|
||||
if (mTransform.x + halfWidth > landBoundaryX - 25.f) {
|
||||
mTransform.x = landBoundaryX - 25.f - halfWidth;
|
||||
mMoveSpeedX = -std::abs(mMoveSpeedX);
|
||||
}
|
||||
if (mTransform.y - halfHeight < -h / 2.f + 25.f) {
|
||||
mTransform.y = -h / 2.f + 25.f + halfHeight;
|
||||
mMoveSpeedY = std::abs(mMoveSpeedY);
|
||||
}
|
||||
if (mTransform.y + halfHeight > h / 2.f - 25.f) {
|
||||
mTransform.y = h / 2.f - 25.f - halfHeight;
|
||||
mMoveSpeedY = -std::abs(mMoveSpeedY);
|
||||
}
|
||||
}
|
||||
|
||||
bool Enemy::hasAdjacentEnemy() {
|
||||
if (!getTexture()) return false;
|
||||
|
||||
const float detectionRadius = 40.f;
|
||||
const float enemyWidth = getTexture()->getWidth() * mTransform.adjustedScaleX();
|
||||
const float enemyHeight = getTexture()->getHeight() * mTransform.adjustedScaleY();
|
||||
const float centerX = mTransform.x + enemyWidth / 2.f;
|
||||
const float centerY = mTransform.y + enemyHeight / 2.f;
|
||||
|
||||
auto entities = GameManager::getEntityByName<Object::Entity>("Dummy");
|
||||
if (!entities) {
|
||||
auto snapshot = State::GameState::getInstance().getEntitiesSnapshot();
|
||||
for (auto* other : snapshot) {
|
||||
if (!other || other == this || !dynamic_cast<Enemy*>(other)) continue;
|
||||
auto* otherEnemy = dynamic_cast<Enemy*>(other);
|
||||
if (!otherEnemy || !otherEnemy->getTexture()) continue;
|
||||
const float otherWidth = otherEnemy->getTexture()->getWidth() * otherEnemy->getTransform()->adjustedScaleX();
|
||||
const float otherHeight = otherEnemy->getTexture()->getHeight() * otherEnemy->getTransform()->adjustedScaleY();
|
||||
const float otherCenterX = otherEnemy->getTransform()->x + otherWidth / 2.f;
|
||||
const float otherCenterY = otherEnemy->getTransform()->y + otherHeight / 2.f;
|
||||
const float dx = centerX - otherCenterX;
|
||||
const float dy = centerY - otherCenterY;
|
||||
if (dx * dx + dy * dy <= detectionRadius * detectionRadius) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Enemy::onCollisionEnter(Object::Entity* other) {
|
||||
auto* player = dynamic_cast<Player*>(other);
|
||||
if (!player || !mIsVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAdjacentEnemy()) {
|
||||
LOG("Player collided with a strong group of polluters; game over!");
|
||||
GameManager::setSharedData("gameLost", true);
|
||||
GameManager::destroyEntity(player);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Enemy '" << getName() << "' collided with player; removing polluter and awarding points");
|
||||
GameManager::setSharedData("enemyActiveCount", std::max(0, GameManager::getSharedData<int>("enemyActiveCount") - 1));
|
||||
GameManager::setSharedData("gameScore", GameManager::getSharedData<int>("gameScore") + 100);
|
||||
GameManager::destroyEntity(this);
|
||||
}
|
||||
}
|
||||
81
src/game/agame/friendly.cpp
Normal file
81
src/game/agame/friendly.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <game/agame/friendly.hpp>
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <game/agame/player.hpp>
|
||||
#include <object/components/boxcollider.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <utils.hpp>
|
||||
#include <window/window.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Friendly::start() {
|
||||
mZIndex = 20;
|
||||
addComponent<Object::Components::BoxCollider>();
|
||||
LOG("Friendly started: " << getName());
|
||||
|
||||
// Initialize random movement
|
||||
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
|
||||
const float speed = 20.f + static_cast<float>(Utils::getUtils().rirng32(0, 30));
|
||||
mMoveSpeedX = std::cos(angle) * speed;
|
||||
mMoveSpeedY = std::sin(angle) * speed;
|
||||
mDirectionChangeTimer = 0.f;
|
||||
}
|
||||
|
||||
void Friendly::update(float deltaTime) {
|
||||
(void)deltaTime;
|
||||
|
||||
// Semi-random movement with periodic direction changes
|
||||
mDirectionChangeTimer += deltaTime;
|
||||
if (mDirectionChangeTimer > 2.0f) {
|
||||
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
|
||||
const float speed = 20.f + static_cast<float>(Utils::getUtils().rirng32(0, 30));
|
||||
mMoveSpeedX = std::cos(angle) * speed;
|
||||
mMoveSpeedY = std::sin(angle) * speed;
|
||||
mDirectionChangeTimer = 0.f;
|
||||
}
|
||||
|
||||
// Move friendly
|
||||
mTransform.x += mMoveSpeedX * deltaTime;
|
||||
mTransform.y += mMoveSpeedY * deltaTime;
|
||||
|
||||
// Clamp to land section
|
||||
const float landBoundaryX = GameManager::getSharedData<float>("terrainLandBoundaryX");
|
||||
const float entityWidth = getTexture() ? getTexture()->getWidth() * mTransform.adjustedScaleX() : 0.f;
|
||||
const float entityHeight = getTexture() ? getTexture()->getHeight() * mTransform.adjustedScaleY() : 0.f;
|
||||
const float halfWidth = entityWidth / 2.f;
|
||||
const float halfHeight = entityHeight / 2.f;
|
||||
|
||||
// Get window dimensions for boundary calculations
|
||||
int w = 0, h = 0;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
|
||||
const float leftEdge = -w / 2.f + 25.f;
|
||||
|
||||
if (mTransform.x - halfWidth < leftEdge) {
|
||||
mTransform.x = leftEdge + halfWidth;
|
||||
mMoveSpeedX = std::abs(mMoveSpeedX);
|
||||
}
|
||||
if (mTransform.x + halfWidth > landBoundaryX - 25.f) {
|
||||
mTransform.x = landBoundaryX - 25.f - halfWidth;
|
||||
mMoveSpeedX = -std::abs(mMoveSpeedX);
|
||||
}
|
||||
if (mTransform.y - halfHeight < -h / 2.f + 25.f) {
|
||||
mTransform.y = -h / 2.f + 25.f + halfHeight;
|
||||
mMoveSpeedY = std::abs(mMoveSpeedY);
|
||||
}
|
||||
if (mTransform.y + halfHeight > h / 2.f - 25.f) {
|
||||
mTransform.y = h / 2.f - 25.f - halfHeight;
|
||||
mMoveSpeedY = -std::abs(mMoveSpeedY);
|
||||
}
|
||||
}
|
||||
|
||||
void Friendly::onCollisionEnter(Object::Entity* other) {
|
||||
auto* player = dynamic_cast<Player*>(other);
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameManager::setSharedData("friendlyActiveCount", std::max(0, GameManager::getSharedData<int>("friendlyActiveCount") - 1));
|
||||
GameManager::setSharedData("gameScore", GameManager::getSharedData<int>("gameScore") - 50);
|
||||
GameManager::destroyEntity(this);
|
||||
}
|
||||
}
|
||||
56
src/game/agame/hudtext.cpp
Normal file
56
src/game/agame/hudtext.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <game/agame/hudtext.hpp>
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <window/window.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace Game::AGame {
|
||||
void HUDText::start() {
|
||||
mZIndex = 1000;
|
||||
Object::UIText::start();
|
||||
setText("Level 1 | Score 0 | Trash 0 | Polluters 0");
|
||||
}
|
||||
|
||||
void HUDText::update(float deltaTime) {
|
||||
(void)deltaTime;
|
||||
|
||||
int windowW = 0;
|
||||
int windowH = 0;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &windowW, &windowH);
|
||||
float camX = 0.f;
|
||||
float camY = 0.f;
|
||||
Object::Camera::getInstance().getPosition(camX, camY);
|
||||
|
||||
auto anchorTopRight = [&]() {
|
||||
if (!mTex) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float marginX = 24.f;
|
||||
const float marginY = 24.f;
|
||||
const float textWidth = mTex->getWidth() * mTransform.adjustedScaleX();
|
||||
mTransform.x = camX + windowW / 2.f - marginX - textWidth;
|
||||
mTransform.y = camY - windowH / 2.f + marginY;
|
||||
};
|
||||
|
||||
if (GameManager::getSharedData<bool>("gameLost")) {
|
||||
setText("You Died!");
|
||||
anchorTopRight();
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameManager::getSharedData<bool>("gameWon")) {
|
||||
setText("You Won!");
|
||||
anchorTopRight();
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream stream;
|
||||
stream << "Level " << GameManager::getSharedData<int>("gameStage")
|
||||
<< " | Točke " << GameManager::getSharedData<int>("gameScore")
|
||||
<< " | Smeti " << GameManager::getSharedData<int>("trashActiveCount")
|
||||
<< " | Sovražniki " << GameManager::getSharedData<int>("enemyActiveCount");
|
||||
|
||||
setText(stream.str());
|
||||
anchorTopRight();
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,60 @@
|
||||
#include <cmath>
|
||||
#include <game/input.hpp>
|
||||
#include <game/gamemanager.hpp>
|
||||
#include <utils.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Player::setShipTexture(std::shared_ptr<Game::Renderer::Texture> tex) {
|
||||
mShipTex = std::move(tex);
|
||||
if (mIsShipMode && mShipTex) {
|
||||
setTexture(mShipTex);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::setGroundTexture(std::shared_ptr<Game::Renderer::Texture> tex) {
|
||||
mGroundTex = std::move(tex);
|
||||
if (!mIsShipMode && mGroundTex) {
|
||||
setTexture(mGroundTex);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::respawnRandomSea(float landBoundaryX) {
|
||||
auto spawnTex = mShipTex ? mShipTex : mTex;
|
||||
if (!spawnTex) {
|
||||
return;
|
||||
}
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
|
||||
|
||||
const float halfWidth = spawnTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
|
||||
const float halfHeight = spawnTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
|
||||
|
||||
const float minCenterX = landBoundaryX + mShoreMargin + halfWidth;
|
||||
const float maxCenterX = w / 2.f - halfWidth - 10.f;
|
||||
const float minCenterY = -h / 2.f + halfHeight;
|
||||
const float maxCenterY = h / 2.f - halfHeight;
|
||||
|
||||
float centerX = minCenterX;
|
||||
if (maxCenterX > minCenterX) {
|
||||
centerX = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(minCenterX), static_cast<int>(maxCenterX)));
|
||||
}
|
||||
|
||||
float centerY = 0.f;
|
||||
if (maxCenterY > minCenterY) {
|
||||
centerY = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(minCenterY), static_cast<int>(maxCenterY)));
|
||||
}
|
||||
|
||||
mTransform.x = centerX - halfWidth;
|
||||
mTransform.y = centerY - halfHeight;
|
||||
|
||||
mIsShipMode = true;
|
||||
if (mShipTex) {
|
||||
setTexture(mShipTex);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::start() {
|
||||
//mSound = Object::Sound("../resources/example.wav", Object::Format::WAV);
|
||||
//mSound.play();
|
||||
@@ -12,15 +64,41 @@ namespace Game::AGame {
|
||||
Game::GameManager::setSharedData("gameStage", 1);
|
||||
Game::GameManager::setSharedData("gameScore", 0);
|
||||
|
||||
int w, h;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
|
||||
|
||||
mTransform.scaleX = 8.f;
|
||||
mTransform.scaleY = 8.f;
|
||||
|
||||
if (!mShipTex) {
|
||||
mShipTex = mTex;
|
||||
}
|
||||
if (!mGroundTex) {
|
||||
mGroundTex = mTex;
|
||||
}
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
|
||||
|
||||
const float halfWidth = mTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
|
||||
const float halfHeight = mTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
|
||||
const float minX = -w / 2.f + halfWidth;
|
||||
const float maxX = w / 2.f - halfWidth;
|
||||
const float minY = -h / 2.f + halfHeight;
|
||||
const float maxY = h / 2.f - halfHeight;
|
||||
|
||||
const float landBoundaryX = Game::GameManager::getSharedData<float>("terrainLandBoundaryX");
|
||||
mTransform.x = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(minX), static_cast<int>(maxX)));
|
||||
mTransform.y = static_cast<float>(Utils::getUtils().rirng32(static_cast<int>(minY), static_cast<int>(maxY)));
|
||||
mIsShipMode = (mTransform.x + halfWidth) >= landBoundaryX;
|
||||
|
||||
mTransform.x -= mTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
|
||||
mTransform.y -= mTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
|
||||
|
||||
if (mIsShipMode && mShipTex) {
|
||||
setTexture(mShipTex);
|
||||
} else if (!mIsShipMode && mGroundTex) {
|
||||
setTexture(mGroundTex);
|
||||
}
|
||||
|
||||
LOG("W: " << w << " H: " << h);
|
||||
//mSound.~Sound();
|
||||
}
|
||||
@@ -31,11 +109,41 @@ namespace Game::AGame {
|
||||
//mTransform.scaleY = 1.f + 0.5f * std::cos(RUNNING_TIME() / 0.5f); // Pulsate scale for testing
|
||||
//Object::Camera::getInstance().move(1.f, 0.f);
|
||||
|
||||
const float landBoundaryX = Game::GameManager::getSharedData<float>("terrainLandBoundaryX");
|
||||
const float halfWidth = mTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
|
||||
|
||||
if (Input::isKeyPressed(SDL_SCANCODE_E)) {
|
||||
const bool nearShore = std::abs((mTransform.x + halfWidth) - landBoundaryX) <= mShoreMargin;
|
||||
if (nearShore) {
|
||||
mIsShipMode = !mIsShipMode;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple movement
|
||||
if (Input::isKeyPressed(SDL_SCANCODE_W)) { mTransform.y -= mSpeed * deltaTime; }
|
||||
if (Input::isKeyPressed(SDL_SCANCODE_S)) { mTransform.y += mSpeed * deltaTime; }
|
||||
if (Input::isKeyPressed(SDL_SCANCODE_A)) { mTransform.x -= mSpeed * deltaTime; mIsFlipped = false; }
|
||||
if (Input::isKeyPressed(SDL_SCANCODE_D)) { mTransform.x += mSpeed * deltaTime; mIsFlipped = true; }
|
||||
mSpeed = Input::isKeyPressed(SDL_SCANCODE_LSHIFT) ? 400.f : 200.f;
|
||||
|
||||
if (mIsShipMode && (mTransform.x + halfWidth) < landBoundaryX + mShoreMargin) {
|
||||
mTransform.x = landBoundaryX + mShoreMargin - halfWidth;
|
||||
}
|
||||
if (!mIsShipMode && (mTransform.x + halfWidth) > landBoundaryX - mShoreMargin) {
|
||||
mTransform.x = landBoundaryX - mShoreMargin - halfWidth;
|
||||
}
|
||||
|
||||
if (mIsShipMode && mShipTex) {
|
||||
setTexture(mShipTex);
|
||||
} else if (!mIsShipMode && mGroundTex) {
|
||||
setTexture(mGroundTex);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::onCollisionEnter(Object::Entity* other) {
|
||||
(void)other;
|
||||
if (GameManager::getSharedData<bool>("gameLost")) {
|
||||
GameManager::destroyEntity(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,27 @@
|
||||
#include <game/agame/trash.hpp>
|
||||
#include <game/agame/player.hpp>
|
||||
#include <object/components/boxcollider.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Trash::start() {
|
||||
mZIndex = 20;
|
||||
addComponent<Object::Components::BoxCollider>();
|
||||
}
|
||||
|
||||
void Trash::update(float deltaTime) {
|
||||
(void)deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
void Trash::onCollisionEnter(Object::Entity* other) {
|
||||
auto* player = dynamic_cast<Player*>(other);
|
||||
if (!player || !player->isShipMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameManager::setSharedData("trashActiveCount", std::max(0, GameManager::getSharedData<int>("trashActiveCount") - 1));
|
||||
GameManager::setSharedData("gameScore", GameManager::getSharedData<int>("gameScore") + 25);
|
||||
GameManager::destroyEntity(this);
|
||||
}
|
||||
}
|
||||
17
src/main.cpp
17
src/main.cpp
@@ -5,6 +5,7 @@
|
||||
#include <object/transform.hpp>
|
||||
#include <game/agame/player.hpp>
|
||||
#include <game/agame/background.hpp>
|
||||
#include <game/agame/hudtext.hpp>
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <renderer/texture.hpp>
|
||||
#include <renderer/font.hpp>
|
||||
@@ -20,16 +21,16 @@ int main() {
|
||||
Window::Window window = Window::Window();
|
||||
window.init(1280, 720, "Game Window");
|
||||
|
||||
State::GameState::getInstance().addEntity(std::make_unique<AGame::SampleTextBox>("Sample Text Box", std::make_shared<Game::Renderer::Font>("../resources/roboto.ttf", window.getRenderer()->getSDLRenderer(), 48, "Roboto"), Object::DEFAULT_TRANSFORM, 640.f, 360.f));
|
||||
|
||||
//Object::Transform t1{100.f, 100.f, 0.f, 1.f, 1.f};
|
||||
State::GameState::getInstance().addEntity(std::make_unique<AGame::Background>("BG", std::make_shared<Game::Renderer::Texture>("../resources/bgtest.png", window.getRenderer()->getSDLRenderer()), Object::DEFAULT_TRANSFORM));
|
||||
Object::Entity* player = State::GameState::getInstance().addEntity(std::make_unique<AGame::Player>("Player", std::make_shared<Game::Renderer::Texture>("../resources/l3ladja.png", window.getRenderer()->getSDLRenderer()), Object::DEFAULT_TRANSFORM));
|
||||
player->addComponent<Object::Components::BoxCollider>();
|
||||
//State::GameState::getInstance().addEntity(std::make_unique<AGame::Player>("Player2", std::make_shared<Game::Renderer::Font>("../resources/roboto.ttf", window.getRenderer()->getSDLRenderer(), 128, "Roboto"), t1));
|
||||
|
||||
// Sample textbox
|
||||
State::GameState::getInstance().addEntity(std::make_unique<AGame::SampleTextBox>("Sample Text Box", std::make_shared<Game::Renderer::Font>("../resources/roboto.ttf", window.getRenderer()->getSDLRenderer(), 48, "Roboto"), Object::DEFAULT_TRANSFORM, 640.f, 360.f));
|
||||
auto* player = dynamic_cast<AGame::Player*>(State::GameState::getInstance().addEntity(std::make_unique<AGame::Player>("Player", std::make_shared<Game::Renderer::Texture>("../resources/l3ladja.png", window.getRenderer()->getSDLRenderer()), Object::DEFAULT_TRANSFORM)));
|
||||
if (player) {
|
||||
player->addComponent<Object::Components::BoxCollider>();
|
||||
player->setShipTexture(std::make_shared<Game::Renderer::Texture>("../resources/l3ladja.png", window.getRenderer()->getSDLRenderer()));
|
||||
player->setGroundTexture(std::make_shared<Game::Renderer::Texture>("../resources/l3player.png", window.getRenderer()->getSDLRenderer()));
|
||||
}
|
||||
|
||||
State::GameState::getInstance().addEntity(std::make_unique<AGame::HUDText>("HUD", std::make_shared<Game::Renderer::Font>("../resources/roboto.ttf", window.getRenderer()->getSDLRenderer(), 72, "HUDFont"), Object::Transform{0.f, 0.f, 0.f, 1.f, 1.f}, 320.f, 40.f));
|
||||
|
||||
window.run();
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Game::Object::Components {
|
||||
width = std::max(1.f, width);
|
||||
height = std::max(1.f, height);
|
||||
|
||||
// Transform position is used as top-left in rendering, so match that convention for collision bounds.
|
||||
// Entity rendering uses top-left transform coordinates; collider must match that space.
|
||||
float left = transform->x;
|
||||
float right = transform->x + width;
|
||||
float top = transform->y;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <algorithm>
|
||||
#include <utils.hpp>
|
||||
#include <state/gamestate.hpp>
|
||||
#include <object/entity.hpp>
|
||||
@@ -57,12 +58,26 @@ namespace Game::Renderer {
|
||||
RendererConfig config{ camX, camY, screenW, screenH };
|
||||
|
||||
try {
|
||||
auto entities = Game::State::GameState::getInstance().getEntitiesSnapshot(true);
|
||||
for (auto* entity : entities) {
|
||||
Game::State::GameState::getInstance().withEntitiesLocked([&](auto& entities) {
|
||||
std::vector<Game::Object::Entity*> renderOrder;
|
||||
renderOrder.reserve(entities.size());
|
||||
for (auto& [name, entity] : entities) {
|
||||
(void)name;
|
||||
if (entity) {
|
||||
renderOrder.push_back(entity.get());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(renderOrder.begin(), renderOrder.end(), [](Game::Object::Entity* a, Game::Object::Entity* b) {
|
||||
return a->getZIndex() < b->getZIndex();
|
||||
});
|
||||
|
||||
for (auto* entity : renderOrder) {
|
||||
if (entity && entity->isActive()) {
|
||||
entity->render(this, config);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
ERROR("Exception while rendering frame: " << e.what());
|
||||
}
|
||||
|
||||
@@ -108,8 +108,9 @@ namespace Game::Window {
|
||||
const float scaleX = canScale ? static_cast<float>(newWidth) / static_cast<float>(oldWidth) : 1.f;
|
||||
const float scaleY = canScale ? static_cast<float>(newHeight) / static_cast<float>(oldHeight) : 1.f;
|
||||
|
||||
auto entities = State::GameState::getInstance().getEntitiesSnapshot();
|
||||
for (auto* entity : entities) {
|
||||
State::GameState::getInstance().withEntitiesLocked([&](auto& entities) {
|
||||
for (auto& [name, entity] : entities) {
|
||||
(void)name;
|
||||
if (entity) {
|
||||
if (canScale) {
|
||||
Object::Transform* transform = entity->getTransform();
|
||||
@@ -119,6 +120,7 @@ namespace Game::Window {
|
||||
entity->onWindowResized(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mLastWindowWidth = newWidth;
|
||||
mLastWindowHeight = newHeight;
|
||||
|
||||
Reference in New Issue
Block a user