mirror of
https://github.com/devZoGok/PlanetFleet.git
synced 2026-08-26 19:43:29 +00:00
250 lines
7.5 KiB
C++
250 lines
7.5 KiB
C++
#include <solUtil.h>
|
|
|
|
#include "gameObjectFrameController.h"
|
|
#include "activeGameState.h"
|
|
#include "resourceDeposit.h"
|
|
#include "defConfigs.h"
|
|
#include "player.h"
|
|
#include "game.h"
|
|
#include "unit.h"
|
|
#include "util.h"
|
|
#include "map.h"
|
|
|
|
#include <material.h>
|
|
#include <meshData.h>
|
|
#include <quad.h>
|
|
#include <model.h>
|
|
#include <root.h>
|
|
|
|
#include <stateManager.h>
|
|
|
|
#include <string>
|
|
|
|
namespace battleship{
|
|
using namespace std;
|
|
using namespace vb01;
|
|
using namespace gameBase;
|
|
|
|
static GameObjectFrameController *gameObjectFrameController = nullptr;
|
|
|
|
GameObjectFrameController* GameObjectFrameController::getSingleton(){
|
|
if(!gameObjectFrameController)
|
|
gameObjectFrameController = new GameObjectFrameController();
|
|
|
|
return gameObjectFrameController;
|
|
}
|
|
|
|
void GameObjectFrameController::paintSelect(Vector3 rowEnd){
|
|
Vector3 rowDir = rowEnd - paintSelectRowStart;
|
|
float lenRow = rowDir.getLength();
|
|
float width = gameObjectFrames[0].getWidth();
|
|
float length = gameObjectFrames[0].getLength();
|
|
float hypothenuse = sqrt(width * width + length * length);
|
|
int numStructsInRow = int(lenRow / hypothenuse);
|
|
|
|
while(gameObjectFrames.size() > numStructsInRow && gameObjectFrames.size() > 1)
|
|
removeGameObjectFrame(gameObjectFrames.size() - 1);
|
|
|
|
if(gameObjectFrames.size() < numStructsInRow){
|
|
int structureId = gameObjectFrames[0].getId();
|
|
Vector3 buildDir = rowDir;
|
|
|
|
if(gameObjectFrames.size() > 1)
|
|
buildDir = gameObjectFrames[1].getModel()->getPosition() - gameObjectFrames[0].getModel()->getPosition();
|
|
|
|
Vector3 pos = paintSelectRowStart + buildDir.norm() * hypothenuse * gameObjectFrames.size();
|
|
addGameObjectFrame(GameObjectFrame(structureId, GameObject::Type::UNIT, nullptr, pos));
|
|
}
|
|
}
|
|
|
|
//TODO specify what to snap the frame to
|
|
void GameObjectFrameController::snapToObj(GameObjectFrame &s, GameObject::Type type, int unitId, float maxDist){
|
|
if(s.getType() == GameObject::Type::UNIT && s.getId() == unitId){
|
|
s.status = GameObjectFrame::NOT_PLACEABLE;
|
|
Player *civPl = Game::getSingleton()->getCivilianPlayer();
|
|
|
|
for(ResourceDeposit *dep : civPl->getResourceDeposits()){
|
|
Vector3 depPos = dep->getPos();
|
|
|
|
if(!dep->getExtractor() && s.getPos().getDistanceFrom(depPos) < maxDist){
|
|
s.status = GameObjectFrame::PLACEABLE;
|
|
s.placeAt(depPos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//TODO fix which unit frames light green or red
|
|
void GameObjectFrameController::checkPlacement(GameObjectFrame &s){
|
|
Map *map = Map::getSingleton();
|
|
MeshData meshData = map->getNodeParent()->getChild(0)->getMesh(0)->getMeshBase();
|
|
MeshData::Vertex *verts = meshData.vertices;
|
|
int numVerts = 3 * meshData.numTris;
|
|
|
|
bool placeable = true;
|
|
|
|
if(s.getMaxUnevenness() > 0)
|
|
for(int i = 0; i < numVerts; i++){
|
|
float diffX = fabs(s.getPos().x - verts[i].pos->x);
|
|
float diffY = fabs(s.getPos().y - verts[i].pos->y);
|
|
float diffZ = fabs(s.getPos().z - verts[i].pos->z);
|
|
|
|
if(diffX < 0.5 * s.getWidth() && diffZ < 0.5 * s.getLength() && diffY > s.getMaxUnevenness()){
|
|
placeable = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
vector<Unit*> units;
|
|
|
|
for(Player *player : Game::getSingleton()->getPlayers(true)){
|
|
vector<Unit*> u = player->getUnits();
|
|
units.insert(units.end(), u.begin(), u.end());
|
|
}
|
|
|
|
for(Unit *unit : units){
|
|
if(unit == s.getOriginalUnit()) continue;
|
|
|
|
Vector3 gm1Pos = s.getPos();
|
|
Vector3 gm1Dir = s.getDirVec();
|
|
gm1Dir = Vector3(gm1Dir.x, 0, gm1Dir.z).norm();
|
|
|
|
Vector3 gm1Left = s.getLeftVec();
|
|
gm1Left = Vector3(gm1Left.x, 0, gm1Left.z).norm();
|
|
|
|
Vector3 gm2Pos = unit->getPos();
|
|
|
|
Vector3 gm2Dir = unit->getDirVec();
|
|
gm2Dir = Vector3(gm2Dir.x, 0, gm2Dir.z).norm();
|
|
|
|
Vector3 gm2Left = unit->getLeftVec();
|
|
gm2Left = Vector3(gm2Left.x, 0, gm2Left.z).norm();
|
|
|
|
bool intersects = rectanglesIntersect(
|
|
Vector2(gm1Pos.x, gm1Pos.z),
|
|
Vector2(gm1Dir.x, gm1Dir.z),
|
|
Vector2(gm1Left.x, gm1Left.z),
|
|
Vector2(s.getWidth(), s.getLength()),
|
|
Vector2(gm2Pos.x, gm2Pos.z),
|
|
Vector2(gm2Dir.x, gm2Dir.z),
|
|
Vector2(gm2Left.x, gm2Left.z),
|
|
Vector2(unit->getWidth(), unit->getLength())
|
|
);
|
|
|
|
if(intersects){
|
|
placeable = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Vector4 color;
|
|
|
|
if(placeable){
|
|
s.status = GameObjectFrame::PLACEABLE;
|
|
color = Vector4(0, 1, 0, 1);
|
|
}
|
|
else{
|
|
s.status = GameObjectFrame::NOT_PLACEABLE;
|
|
color = Vector4(1, 0, 0, 1);
|
|
}
|
|
|
|
Material *mat = s.getModel()->getMaterial();
|
|
mat->setVec4Uniform("diffuseColor", color);
|
|
}
|
|
|
|
void GameObjectFrameController::shiftVerticalPlacement(){
|
|
if(!minDepthCalculated){
|
|
Map *map = Map::getSingleton();
|
|
Node *nodeParent = map->getNodeParent();
|
|
Vector3 cellSize = map->getCellSize(), waterBodyPos;
|
|
bool inWater = false;
|
|
|
|
for(int i = 1; i < nodeParent->getNumChildren(); i++){
|
|
Vector3 wPos = nodeParent->getChild(i)->getPosition();
|
|
Vector3 wSize = ((Quad*)nodeParent->getChild(i)->getMesh(0))->getSize();
|
|
|
|
if(fabs(wPos.x - placementPos.x) < .5 * wSize.x && fabs(wPos.z - placementPos.z) < .5 * wSize.y){
|
|
waterBodyPos = wPos;
|
|
inWater = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!inWater) return;
|
|
|
|
vector<RayCaster::CollisionResult> res = map->raycastTerrain(
|
|
Vector3(placementPos.x, 100, placementPos.z),
|
|
-Vector3::VEC_J,
|
|
false
|
|
);
|
|
|
|
vector<Map::Cell> &cells = map->getCells();
|
|
int cid = map->getCellId(placementPos, false);
|
|
int numSubmarineCells = cells[cid].underWaterCellIds.size();
|
|
maxDepth = cells[cid].pos.y;
|
|
minDepth = (numSubmarineCells > 0 ? cells[cells[cid].underWaterCellIds[numSubmarineCells - 1]].pos.y : maxDepth) - .5 * cellSize.y;
|
|
minDepthCalculated = true;
|
|
}
|
|
else{
|
|
ActiveGameState *activeState = (ActiveGameState*)(GameManager::getSingleton()->getStateManager()->getAppStateByType((int)AppStateType::ACTIVE_STATE));
|
|
float newDepth = minDepth + activeState->getDepth() * (maxDepth - minDepth);
|
|
placementPos.y = newDepth;
|
|
}
|
|
}
|
|
|
|
void GameObjectFrameController::updatePlacement(){
|
|
for(GameObjectFrame &frame : gameObjectFrames)
|
|
frame.update();
|
|
|
|
Map *map = Map::getSingleton();
|
|
Vector3 startPos = Root::getSingleton()->getCamera()->getPosition();
|
|
Vector3 endPos = screenToSpace(getCursorPos());
|
|
vector<RayCaster::CollisionResult> results = map->raycastTerrain(startPos, (screenToSpace(getCursorPos()) - startPos).norm(), true);
|
|
|
|
if(results.empty()) return;
|
|
|
|
if(paintSelecting) paintSelect(results[0].pos);
|
|
|
|
if(placingVertically) shiftVerticalPlacement();
|
|
else if(placingOnSurface) placementPos = results[0].pos;
|
|
|
|
for(int i = 0; i < gameObjectFrames.size(); i++){
|
|
if(paintSelecting){
|
|
float width = gameObjectFrames[0].getWidth();
|
|
float length = gameObjectFrames[0].getLength();
|
|
float hypothenuse = sqrt(width * width + length * length);
|
|
Vector3 dir = (results[0].pos - paintSelectRowStart).norm();
|
|
placementPos = paintSelectRowStart + dir * hypothenuse * i;
|
|
}
|
|
|
|
if(!rotating && (placingOnSurface || placingVertically))
|
|
gameObjectFrames[i].placeAt(placementPos);
|
|
|
|
checkPlacement(gameObjectFrames[i]);
|
|
}
|
|
}
|
|
|
|
void GameObjectFrameController::update(){
|
|
updatePlacement();
|
|
|
|
if(!placingVertically) minDepthCalculated = false;
|
|
}
|
|
|
|
void GameObjectFrameController::removeGameObjectFrame(int i){
|
|
gameObjectFrames[i].destroy();
|
|
gameObjectFrames.erase(gameObjectFrames.begin() + i);
|
|
}
|
|
|
|
void GameObjectFrameController::removeGameObjectFrames(){
|
|
while(gameObjectFrames.size() > 0)
|
|
removeGameObjectFrame(0);
|
|
}
|
|
|
|
void GameObjectFrameController::rotateGameObjectFrames(float angle){
|
|
for(GameObjectFrame &s : gameObjectFrames)
|
|
if(s.status != GameObjectFrame::PLACED)
|
|
s.orientAt(Quaternion(angle, Vector3::VEC_J) * s.getRot());
|
|
}
|
|
}
|