This commit is contained in:
2026-05-13 07:58:59 +02:00
parent d9769bdbbb
commit 892d8f22eb
18 changed files with 242 additions and 77 deletions

View File

@@ -57,7 +57,10 @@ namespace Game::AGame {
mSeaTex->setTiled(true);
}
mTiledScale = 0.5f;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &mW, &mH);
// Use logical world dimensions (1280×720) not actual screen size
mW = 1280;
mH = 720;
// Land boundary: left 1/3 of map in centered coordinates
// For 1280px window: -640 (left) + 426.67 (1/3) = -213.33
@@ -128,9 +131,11 @@ namespace Game::AGame {
const float viewBottom = mH / 2.f;
Object::Transform tS;
tS.x = 0.f;
tS.y = 0.f;
tS.rotation = 0.f;
tS.scaleX = 6.f;
tS.scaleY = 6.f;
tS.scaleX = 4.0f;
tS.scaleY = 4.0f;
const float halfFriendlyW = mFriendlyTex->getWidth() * tS.adjustedScaleX() / 2.f;
const float halfFriendlyH = mFriendlyTex->getHeight() * tS.adjustedScaleY() / 2.f;
@@ -194,8 +199,8 @@ namespace Game::AGame {
Object::Transform tS;
tS.rotation = 0.f;
tS.scaleX = 7.f;
tS.scaleY = 7.f;
tS.scaleX = 4.7f;
tS.scaleY = 4.7f;
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) {
@@ -268,9 +273,11 @@ namespace Game::AGame {
const bool spawnSea = sideRoll < static_cast<int>(seaProb * 100.f);
Object::Transform tS;
tS.x = 0.f;
tS.y = 0.f;
tS.rotation = 0.f;
tS.scaleX = 6.f;
tS.scaleY = 6.f;
tS.scaleX = 4.0f;
tS.scaleY = 4.0f;
const float viewLeft = -mW / 2.f;
const float viewRight = mW / 2.f;
const float viewTop = -mH / 2.f;
@@ -320,7 +327,8 @@ namespace Game::AGame {
}
void Background::onWindowResized(int newWidth, int newHeight) {
mW = newWidth;
mH = newHeight;
// Always maintain logical world dimensions (1280×720)
mW = 1280;
mH = 720;
}
}

View File

@@ -44,14 +44,31 @@ namespace Game::AGame {
const float dyv = py - ey;
mIsVisible = (dxv * dxv + dyv * dyv) <= (revealRadius * revealRadius);
// 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;
// Check if player is on land (not in ship mode) and within follow distance
const float distanceToPlayer = std::sqrt(dxv * dxv + dyv * dyv);
const bool playerOnLand = !player->isShipMode();
const bool withinFollowRange = distanceToPlayer <= FOLLOW_DISTANCE;
if (playerOnLand && withinFollowRange) {
// Follow player: calculate direction and move at constant speed
mFollowingPlayer = true;
if (distanceToPlayer > 1.f) { // Avoid division by zero
mMoveSpeedX = (dxv / distanceToPlayer) * FOLLOW_SPEED;
mMoveSpeedY = (dyv / distanceToPlayer) * FOLLOW_SPEED;
}
} else {
// Revert to random movement when player is on sea or out of range
mFollowingPlayer = false;
// 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
@@ -68,9 +85,9 @@ namespace Game::AGame {
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);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int w = 1280;
constexpr int h = 720;
const float leftEdge = -w / 2.f + 25.f;
if (mTransform.x - halfWidth < leftEdge) {

View File

@@ -1,9 +1,12 @@
#include <game/agame/friendly.hpp>
#include <game/gamemanager.hpp>
#include <game/agame/player.hpp>
#include <game/agame/trash.hpp>
#include <object/components/boxcollider.hpp>
#include <state/gamestate.hpp>
#include <algorithm>
#include <cmath>
#include <limits>
#include <utils.hpp>
#include <window/window.hpp>
@@ -12,26 +15,105 @@ namespace Game::AGame {
mZIndex = 20;
addComponent<Object::Components::BoxCollider>();
LOG("Zaveznik zagnan: " << getName());
const float landBoundaryX = GameManager::getSharedData<float>("terrainLandBoundaryX");
const float entityWidth = getTexture() ? getTexture()->getWidth() * mTransform.adjustedScaleX() : 0.f;
mOnSea = (mTransform.x + entityWidth / 2.f) > landBoundaryX;
// 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;
if (!mOnSea) {
// Initialize random movement for land friendlies
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
const float speed = LAND_SPEED_MIN + static_cast<float>(Utils::getUtils().rirng32(0, static_cast<int>(LAND_SPEED_MAX - LAND_SPEED_MIN)));
mMoveSpeedX = std::cos(angle) * speed;
mMoveSpeedY = std::sin(angle) * speed;
} else {
mMoveSpeedX = 0.f;
mMoveSpeedY = 0.f;
}
mDirectionChangeTimer = 0.f;
}
void Friendly::update(float deltaTime) {
(void)deltaTime;
// Auto-cleanup nearby trash
const float fw = getTexture() ? getTexture()->getWidth() * mTransform.adjustedScaleX() : 0.f;
const float fh = getTexture() ? getTexture()->getHeight() * mTransform.adjustedScaleY() : 0.f;
const float friendlyCenterX = mTransform.x + fw / 2.f;
const float friendlyCenterY = mTransform.y + fh / 2.f;
const float landBoundaryX = GameManager::getSharedData<float>("terrainLandBoundaryX");
mOnSea = friendlyCenterX > landBoundaryX;
if (mOnSea) {
auto snapshot = State::GameState::getInstance().getEntitiesSnapshot();
Trash* nearestTrash = nullptr;
float nearestDistanceSquared = std::numeric_limits<float>::max();
for (auto* entity : snapshot) {
if (!entity) continue;
auto* trash = dynamic_cast<Trash*>(entity);
if (!trash) continue;
const float tw = trash->getTexture() ? trash->getTexture()->getWidth() * trash->getTransform()->adjustedScaleX() : 0.f;
const float th = trash->getTexture() ? trash->getTexture()->getHeight() * trash->getTransform()->adjustedScaleY() : 0.f;
const float trashCenterX = trash->getTransform()->x + tw / 2.f;
const float trashCenterY = trash->getTransform()->y + th / 2.f;
const float dx = trashCenterX - friendlyCenterX;
const float dy = trashCenterY - friendlyCenterY;
const float distanceSquared = dx * dx + dy * dy;
if (distanceSquared < nearestDistanceSquared) {
nearestDistanceSquared = distanceSquared;
nearestTrash = trash;
}
}
if (nearestTrash) {
const float tw = nearestTrash->getTexture() ? nearestTrash->getTexture()->getWidth() * nearestTrash->getTransform()->adjustedScaleX() : 0.f;
const float th = nearestTrash->getTexture() ? nearestTrash->getTexture()->getHeight() * nearestTrash->getTransform()->adjustedScaleY() : 0.f;
const float trashCenterX = nearestTrash->getTransform()->x + tw / 2.f;
const float trashCenterY = nearestTrash->getTransform()->y + th / 2.f;
const float dx = trashCenterX - friendlyCenterX;
const float dy = trashCenterY - friendlyCenterY;
const float distance = std::sqrt(dx * dx + dy * dy);
if (distance > 0.0001f) {
mMoveSpeedX = (dx / distance) * SEA_SPEED;
mMoveSpeedY = (dy / distance) * SEA_SPEED;
}
}
} else {
// Semi-random movement with periodic direction changes on land
mDirectionChangeTimer += deltaTime;
if (mDirectionChangeTimer > 2.0f) {
const float angle = static_cast<float>(Utils::getUtils().rirng32(0, 360)) * 3.14159f / 180.f;
const float speed = LAND_SPEED_MIN + static_cast<float>(Utils::getUtils().rirng32(0, static_cast<int>(LAND_SPEED_MAX - LAND_SPEED_MIN)));
mMoveSpeedX = std::cos(angle) * speed;
mMoveSpeedY = std::sin(angle) * speed;
mDirectionChangeTimer = 0.f;
}
}
auto snapshot = State::GameState::getInstance().getEntitiesSnapshot();
for (auto* entity : snapshot) {
if (!entity) continue;
auto* trash = dynamic_cast<Trash*>(entity);
if (!trash) continue;
// Calculate distance to trash
const float tw = trash->getTexture() ? trash->getTexture()->getWidth() * trash->getTransform()->adjustedScaleX() : 0.f;
const float th = trash->getTexture() ? trash->getTexture()->getHeight() * trash->getTransform()->adjustedScaleY() : 0.f;
const float trashCenterX = trash->getTransform()->x + tw / 2.f;
const float trashCenterY = trash->getTransform()->y + th / 2.f;
const float dx = friendlyCenterX - trashCenterX;
const float dy = friendlyCenterY - trashCenterY;
const float distanceSquared = dx * dx + dy * dy;
// 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;
if (distanceSquared <= CLEANUP_RADIUS * CLEANUP_RADIUS) {
// Clean up this trash: award points and remove it
GameManager::setSharedData("gameScore", GameManager::getSharedData<int>("gameScore") + CLEANUP_SCORE_BONUS);
GameManager::setSharedData("trashActiveCount", std::max(0, GameManager::getSharedData<int>("trashActiveCount") - 1));
GameManager::destroyEntity(trash);
}
}
// Move friendly
@@ -39,25 +121,26 @@ namespace Game::AGame {
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;
const float halfWidth = fw / 2.f;
const float halfHeight = fh / 2.f;
// Get window dimensions for boundary calculations
int w = 0, h = 0;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int w = 1280;
constexpr int h = 720;
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) {
if (!mOnSea && mTransform.x + halfWidth > landBoundaryX - 25.f) {
mTransform.x = landBoundaryX - 25.f - halfWidth;
mMoveSpeedX = -std::abs(mMoveSpeedX);
}
if (mOnSea && 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);

View File

@@ -13,9 +13,9 @@ namespace Game::AGame {
void HUDText::update(float deltaTime) {
(void)deltaTime;
int windowW = 0;
int windowH = 0;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &windowW, &windowH);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int windowW = 1280;
constexpr int windowH = 720;
float camX = 0.f;
float camY = 0.f;
Object::Camera::getInstance().getPosition(camX, camY);

View File

@@ -26,9 +26,9 @@ namespace Game::AGame {
return;
}
int w = 0;
int h = 0;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int w = 1280;
constexpr int h = 720;
const float halfWidth = spawnTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
const float halfHeight = spawnTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
@@ -64,8 +64,8 @@ namespace Game::AGame {
Game::GameManager::setSharedData("gameStage", 1);
Game::GameManager::setSharedData("gameScore", 0);
mTransform.scaleX = 8.f;
mTransform.scaleY = 8.f;
mTransform.scaleX = 5.3f;
mTransform.scaleY = 5.3f;
if (!mShipTex) {
mShipTex = mTex;
@@ -74,9 +74,9 @@ namespace Game::AGame {
mGroundTex = mTex;
}
int w = 0;
int h = 0;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int w = 1280;
constexpr int h = 720;
const float halfWidth = mTex->getWidth() * mTransform.adjustedScaleX() / 2.f;
const float halfHeight = mTex->getHeight() * mTransform.adjustedScaleY() / 2.f;
@@ -134,9 +134,9 @@ namespace Game::AGame {
if (Input::isKeyPressed(SDL_SCANCODE_D)) { mTransform.x += mSpeed * deltaTime; mIsFlipped = true; }
mSpeed = Input::isKeyPressed(SDL_SCANCODE_LSHIFT) ? 400.f : 200.f;
int w = 0;
int h = 0;
SDL_GetWindowSizeInPixels(Window::Window::getSDLWindowBackend(), &w, &h);
// Use logical world dimensions (1280×720) not actual screen size
constexpr int w = 1280;
constexpr int h = 720;
const float entityWidth = mTex ? mTex->getWidth() * mTransform.adjustedScaleX() : 0.f;
const float entityHeight = mTex ? mTex->getHeight() * mTransform.adjustedScaleY() : 0.f;
const float minX = -w / 2.f;

View File

@@ -11,15 +11,20 @@ namespace Game::AGame {
void Trash::update(float deltaTime) {
(void)deltaTime;
if (mSeaOnly) {
/*if (mSeaOnly) {
const float landBoundaryX = GameManager::getSharedData<float>("terrainLandBoundaryX");
const float margin = 25.f;
const float halfWidth = getTexture() ? getTexture()->getWidth() * mTransform.adjustedScaleX() / 2.f : 0.f;
if (mTransform.x - halfWidth < landBoundaryX + margin) {
mTransform.x = landBoundaryX + margin + halfWidth;
}
}
return;
}*/
// Naključno premikanje
mTransform.x += static_cast<float>(Utils::getUtils().rirng32(-50, 50)) * deltaTime;
mTransform.y += static_cast<float>(Utils::getUtils().rirng32(-50, 50)) * deltaTime;
//return;
}
void Trash::onCollisionEnter(Object::Entity* other) {