igra
This commit is contained in:
@@ -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) {
|
||||
return;
|
||||
(void)deltaTime;
|
||||
|
||||
auto* player = GameManager::getEntityByName<Player>("Player");
|
||||
if (!player) {
|
||||
mIsVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enemies are always visible
|
||||
mIsVisible = true;
|
||||
|
||||
// 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) {
|
||||
LOG("Enemy '" << getName() << "' collided with '" << other->getName() << "' (onCollisionEnter); Killing myself now!");
|
||||
GameManager::setSharedData("enemyActiveCount", GameManager::getSharedData<int>("enemyActiveCount") - 1);
|
||||
|
||||
// Find in state
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user