From b8051f24df742a2e4f570561e3d82c1e08b94cf8 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Wed, 4 Jun 2025 15:45:27 +0300 Subject: [PATCH] refactored checking if a point is within a cuboid ice sheets can be crushed --- CMakeLists.txt | 2 +- gameObject.cpp | 21 +++++++++++++++++++++ gameObject.h | 1 + gameObjectFactory.cpp | 3 +++ iceSheet.cpp | 24 ++++++++++++++++++++++++ iceSheet.h | 15 +++++++++++++++ map.cpp | 22 ++++++++++++++++++++++ map.h | 2 ++ unit.cpp | 20 ++------------------ 9 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 iceSheet.cpp create mode 100644 iceSheet.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e736351..b0af216 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ set(CONSOLE console.cpp abstractCommand.cpp addUnitCommand.cpp addResourceComman set(CORE gameManager.cpp game.cpp fxManager.cpp defConfigs.cpp ${CONSOLE} ${CONTROLLERS}) set(PROJECTILES projectile.cpp missile.cpp cruiseMissile.cpp shell.cpp) set(VEHICLES vehicle.cpp submarine.cpp engineer.cpp resourceRover.cpp) -set(STRUCTURES structure.cpp factory.cpp pointDefense.cpp extractor.cpp researchStruct.cpp) +set(STRUCTURES structure.cpp factory.cpp pointDefense.cpp extractor.cpp researchStruct.cpp iceSheet.cpp) set(UNITS gameObjectFactory.cpp unit.cpp ${STRUCTURES} ${VEHICLES}) set(CONTENT player.cpp trader.cpp pathfinder.cpp map.cpp gameObject.cpp gameObjectFrame.h resourceDeposit.cpp ${UNITS} ${PROJECTILES}) set(GAME_SRC ${STATES} ${GUI} ${CORE} ${CONTENT} ${UTIL}) diff --git a/gameObject.cpp b/gameObject.cpp index 87526ed..0d82145 100644 --- a/gameObject.cpp +++ b/gameObject.cpp @@ -156,6 +156,27 @@ namespace battleship{ return sfx; } + bool GameObject::pointWithinObj(Vector3 point, float deltaLength, float deltaWidth, bool useHeight, float deltaHeight){ + Vector3 pointDir = point - pos; + bool within = true; + + float forwAngle = std::min(dirVec.getAngleBetween(pointDir.norm()), (-dirVec).getAngleBetween(pointDir.norm())); + float forwDist = pointDir.getLength() * cos(forwAngle); + within &= (forwDist < .5 * (length + deltaLength)); + + float leftAngle = std::min(leftVec.getAngleBetween(pointDir.norm()), (-leftVec).getAngleBetween(pointDir.norm())); + float leftDist = pointDir.getLength() * cos(leftAngle); + within &= (leftDist < .5 * (width + deltaWidth)); + + if(useHeight){ + float upAngle = std::min(upVec.getAngleBetween(pointDir.norm()), (-upVec).getAngleBetween(pointDir.norm())); + float upDist = pointDir.getLength() * cos(upAngle); + within &= (upDist < .5 * (height + deltaHeight)); + } + + return within; + } + void GameObject::initSound(){ deathSfxBuffer = new sf::SoundBuffer(); string sfxPath = generateView()[getGameObjTableName()][id + 1]["deathSfx"]; diff --git a/gameObject.h b/gameObject.h index b281b21..f62f410 100644 --- a/gameObject.h +++ b/gameObject.h @@ -28,6 +28,7 @@ namespace battleship{ std::string getGameObjTableName(); void updateGameStats(Unit*); static sf::Sound* prepareSfx(sf::SoundBuffer*, std::string); + bool pointWithinObj(vb01::Vector3, float = 0, float = 0, bool = false, float = 0); inline vb01::Vector2 getScreenPos(){return screenPos;} inline vb01::Vector3 getCorner(int i){return corners[i];} inline bool isSelectable(){return selectable;} diff --git a/gameObjectFactory.cpp b/gameObjectFactory.cpp index 4712284..5a07ddc 100644 --- a/gameObjectFactory.cpp +++ b/gameObjectFactory.cpp @@ -11,6 +11,7 @@ #include "researchStruct.h" #include "missile.h" #include "cruiseMissile.h" +#include "iceSheet.h" #include "shell.h" #include "defConfigs.h" @@ -51,6 +52,8 @@ namespace battleship{ return new Extractor(player, id, pos, rot, buildStatus); case UnitClass::LAB: return new ResearchStruct(player, id, pos, rot, buildStatus); + case UnitClass::ICE_SHEET: + return new IceSheet(player, id, pos, rot, buildStatus); default: return new Structure(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND); } diff --git a/iceSheet.cpp b/iceSheet.cpp new file mode 100644 index 0000000..b361a3e --- /dev/null +++ b/iceSheet.cpp @@ -0,0 +1,24 @@ +#include "iceSheet.h" +#include "player.h" +#include "game.h" + +namespace battleship{ + using namespace vb01; + using namespace std; + + IceSheet::IceSheet(Player *player, int id, Vector3 pos, Quaternion rot, int bldSt) : Structure(player, id, pos, rot, bldSt, Unit::State::STAND_GROUND){} + + void IceSheet::update(){ + Structure::update(); + + for(Player *pl : Game::getSingleton()->getPlayers(true)){ + vector icebreakers = pl->getUnitsByClass(UnitClass::ICEBREAKER); + + for(Unit *icebreaker : icebreakers) + if(icebreaker->pointWithinObj(pos)){ + player->removeUnit(this); + return; + } + } + } +} diff --git a/iceSheet.h b/iceSheet.h new file mode 100644 index 0000000..83ecf1f --- /dev/null +++ b/iceSheet.h @@ -0,0 +1,15 @@ +#ifndef ICE_SHEET_H +#define ICE_SHEET_H + +#include "structure.h" + +namespace battleship{ + class IceSheet : public Structure{ + public: + IceSheet(Player*, int, vb01::Vector3, vb01::Quaternion, int); + void update(); + private: + }; +} + +#endif diff --git a/map.cpp b/map.cpp index 173546f..71e74b7 100755 --- a/map.cpp +++ b/map.cpp @@ -382,6 +382,28 @@ namespace battleship{ return spawnPointsTbl.size(); } + void Map::blockCells(Unit *unit){ + for(Cell &cell : cells){ + if(cell.blockedBy && cell.blockedBy != unit) continue; + + Vector3 cellDir = (cell.pos - unit->getPos()), dirVec = unit->getDirVec(), leftVec = unit->getLeftVec(); + float forwAngle = std::min(dirVec.getAngleBetween(cellDir.norm()), (-dirVec).getAngleBetween(cellDir.norm())); + float forwDist = cellDir.getLength() * cos(forwAngle); + + float leftAngle = std::min(leftVec.getAngleBetween(cellDir.norm()), (-leftVec).getAngleBetween(cellDir.norm())); + float leftDist = cellDir.getLength() * cos(leftAngle); + + bool within = (forwDist < .5 * (unit->getLength() + CELL_SIZE.x) && leftDist < .5 * (unit->getWidth() + CELL_SIZE.z)); + cell.blockedBy = (within ? unit : nullptr); + } + } + + void Map::unblockCells(Unit *unit){ + for(Cell &cell : cells) + if(cell.blockedBy == unit) + cell.blockedBy = nullptr; + } + void Map::loadSpawnPoints(){ sol::state_view SOL_LUA_VIEW = generateView(); int numSpawnPoints = getNumMapSpawnPoints(); diff --git a/map.h b/map.h index c39d2cf..5bab637 100755 --- a/map.h +++ b/map.h @@ -78,6 +78,8 @@ namespace battleship{ bool isPointWithinTerrainObject(vb01::Vector3, int); void loadPlayerGameObjects(); int getNumMapSpawnPoints(std::string = ""); + void blockCells(Unit*); + void unblockCells(Unit*); inline std::string getMapName(){return mapName;} inline vb01::Node* getNodeParent(){return terrainNode;} inline vb01::Vector3 getCellSize(){return CELL_SIZE;} diff --git a/unit.cpp b/unit.cpp index 7293d40..a71d761 100755 --- a/unit.cpp +++ b/unit.cpp @@ -378,6 +378,7 @@ namespace battleship{ } Unit::~Unit() { + Map::getSingleton()->unblockCells(this); removeBar(hpBackgroundNode); removeBar(hpForegroundNode); destroyWeapons(); @@ -826,24 +827,7 @@ namespace battleship{ //TODO select only the closest cells based on unit size void Unit::placeAt(Vector3 p){ GameObject::placeAt(p); - - Map *map = Map::getSingleton(); - vector &cells = map->getCells(); - Vector3 cellSize = map->getCellSize(); - - for(Map::Cell &cell : cells){ - if(cell.blockedBy && cell.blockedBy != this) continue; - - Vector3 cellDir = (cell.pos - pos); - float forwAngle = std::min(dirVec.getAngleBetween(cellDir.norm()), (-dirVec).getAngleBetween(cellDir.norm())); - float forwDist = cellDir.getLength() * cos(forwAngle); - - float leftAngle = std::min(leftVec.getAngleBetween(cellDir.norm()), (-leftVec).getAngleBetween(cellDir.norm())); - float leftDist = cellDir.getLength() * cos(leftAngle); - - bool within = (forwDist < .5 * (length + cellSize.x) && leftDist < .5 * (width + cellSize.z)); - cell.blockedBy = (within ? this : nullptr); - } + Map::getSingleton()->blockCells(this); } vector Unit::getSelectingPlayers(){