aligning different units to hilly surfaces

code refactoring
bugfix for units moving by terrain along Z axis
code cleanup
This commit is contained in:
devZoGok
2025-10-21 20:33:37 +03:00
parent d769e5cbf6
commit 3fda274bb1
7 changed files with 50 additions and 113 deletions
@@ -171,7 +171,7 @@ units = {
orderType = OrderType.ATTACK, orderType = OrderType.ATTACK,
rateOfFire = 1000, rateOfFire = 1000,
damage = 200, damage = 200,
maxRange = 25, maxRange = 50,
horizontalNode = {name = 'Turret', rotationSpeed = .05, maxFireAngle = .1}, horizontalNode = {name = 'Turret', rotationSpeed = .05, maxFireAngle = .1},
projectile = {id = ProjectileId.HE_SHELL, parent = 'Turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = 1, x = 0, y = 0, z = 0}}, projectile = {id = ProjectileId.HE_SHELL, parent = 'Turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = 1, x = 0, y = 0, z = 0}},
fireFx = { fireFx = {
@@ -201,6 +201,7 @@ units = {
unitType = UnitType.LAND, unitType = UnitType.LAND,
armor = {ArmorType.STEEL}, armor = {ArmorType.STEEL},
isVehicle = true, isVehicle = true,
alignToSurface = true,
health = 500, health = 500,
buildTime = 1000, buildTime = 1000,
cost = 500, cost = 500,
@@ -213,7 +214,7 @@ units = {
albedoPath = 'tank.jpg', albedoPath = 'tank.jpg',
colorNodes = {'Antenna_S', 'Antenna_L', 'Hatch'}, colorNodes = {'Antenna_S', 'Antenna_L', 'Hatch'},
selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg', selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg',
speed = .1, speed = .4,
destinationOffset = .1, destinationOffset = .1,
anglePrecision = .1, anglePrecision = .1,
maxTurnAngle = .1, maxTurnAngle = .1,
@@ -254,6 +255,7 @@ units = {
unitClass = UnitClass.ARTILLERY, unitClass = UnitClass.ARTILLERY,
unitType = UnitType.LAND, unitType = UnitType.LAND,
armor = {ArmorType.MECHANIC}, armor = {ArmorType.MECHANIC},
alignToSurface = true,
isVehicle = true, isVehicle = true,
health = 500, health = 500,
buildTime = 1000, buildTime = 1000,
@@ -267,7 +269,7 @@ units = {
albedoPath = 'artillery.jpg', albedoPath = 'artillery.jpg',
colorNodes = {'turret'}, colorNodes = {'turret'},
selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg', selectionSfx = PATH .. 'Sounds/Units/Tanks/selection.ogg',
speed = .1, speed = .3,
destinationOffset = .1, destinationOffset = .1,
anglePrecision = .1, anglePrecision = .1,
maxTurnAngle = .1, maxTurnAngle = .1,
@@ -322,6 +324,7 @@ units = {
{ {
unitClass = UnitClass.TRANSPORT, unitClass = UnitClass.TRANSPORT,
unitType = UnitType.HOVER, unitType = UnitType.HOVER,
alignToSurface = true,
isVehicle = true, isVehicle = true,
health = 500, health = 500,
buildTime = 1000, buildTime = 1000,
@@ -348,6 +351,7 @@ units = {
unitClass = UnitClass.TRANSPORT, unitClass = UnitClass.TRANSPORT,
unitType = UnitType.HOVER, unitType = UnitType.HOVER,
armor = {ArmorType.MECHANIC}, armor = {ArmorType.MECHANIC},
alignToSurface = true,
isVehicle = true, isVehicle = true,
health = 500, health = 500,
buildTime = 1000, buildTime = 1000,
@@ -379,6 +383,7 @@ units = {
unitClass = UnitClass.RESOURCE_ROVER, unitClass = UnitClass.RESOURCE_ROVER,
unitType = UnitType.HOVER, unitType = UnitType.HOVER,
armor = {ArmorType.CAST}, armor = {ArmorType.CAST},
alignToSurface = true,
capacity = 3000, capacity = 3000,
loadRate = 1, loadRate = 1,
loadSpeed = 5, loadSpeed = 5,
+1 -1
View File
@@ -21,7 +21,7 @@ namespace battleship{
const std::string DEFAULT_TEXTURE = "Textures/defaultTexture.jpg"; const std::string DEFAULT_TEXTURE = "Textures/defaultTexture.jpg";
const double camPanSpeed = .5, CAMERA_DISTANCE = 100, CAMERA_ZOOM_INCREMENT = 1, cellLength = 7, cellWidth = 7, cellDepth = 7, DIST_FROM_RAY = 15; const double camPanSpeed = .5, CAMERA_DISTANCE = 100, CAMERA_ZOOM_INCREMENT = 1, cellLength = 7, cellWidth = 7, cellDepth = 7, DIST_FROM_RAY = 15;
const int maxNumGroups = 10, NUM_MAX_ZOOMS = 75; const int maxNumGroups = 10, NUM_MAX_ZOOMS = 75, NUM_SUBDIVS = 100;
const vb01::u32 IMPASS_NODE_VAL = 65535; const vb01::u32 IMPASS_NODE_VAL = 65535;
const static int numAppStates = 5; const static int numAppStates = 5;
-1
View File
@@ -72,7 +72,6 @@ namespace battleship{
float *oldLandmassVertHeights = nullptr; float *oldLandmassVertHeights = nullptr;
bool pushing = false, movingTerrainObject = false, scalingTerrainObject = false, weightsGenerated = false, newMap, cellMarkersVisible = false; bool pushing = false, movingTerrainObject = false, scalingTerrainObject = false, weightsGenerated = false, newMap, cellMarkersVisible = false;
const float MIN_RADIUS = 1, MAX_RADIUS = 100, INCREASE_RATE = 1; const float MIN_RADIUS = 1, MAX_RADIUS = 100, INCREASE_RATE = 1;
const int NUM_SUBDIVS = 100;
float circleRadius = MIN_RADIUS, guiThreshold = 200; float circleRadius = MIN_RADIUS, guiThreshold = 200;
vb01::Vector3 pushPos = vb01::Vector3::VEC_ZERO; vb01::Vector3 pushPos = vb01::Vector3::VEC_ZERO;
std::vector<vb01::Texture*> skyTextures, landmassTextures, waterTextures; std::vector<vb01::Texture*> skyTextures, landmassTextures, waterTextures;
+11 -5
View File
@@ -71,6 +71,7 @@ namespace battleship{
vector<int> currTechs = player->getTechnologies(); vector<int> currTechs = player->getTechnologies();
string name = unitTable["name"]; string name = unitTable["name"];
alignToSurface = unitTable["alignToSurface"].get_or(false);
vehicle = unitTable["isVehicle"]; vehicle = unitTable["isVehicle"];
health += game->calcAbilFromTech(Ability::Type::HEALTH, currTechs, (int)GameObject::type, id); health += game->calcAbilFromTech(Ability::Type::HEALTH, currTechs, (int)GameObject::type, id);
maxHealth = unitTable["health"]; maxHealth = unitTable["health"];
@@ -515,12 +516,17 @@ namespace battleship{
void Unit::placeAt(Vector3 p){ void Unit::placeAt(Vector3 p){
Map *map = Map::getSingleton(); Map *map = Map::getSingleton();
if(type == UnitType::LAND){ if(alignToSurface){
vector<RayCaster::CollisionResult> res = RayCaster::cast(Vector3(p.x, 100, p.z), -Vector3::VEC_J, vector<Node*>{map->getNodeParent()->getChild(0)}, 0, 20); vector<RayCaster::CollisionResult> res = RayCaster::cast(Vector3(p.x, 100, p.z), -Vector3::VEC_J, map->getNodeParent()->getChildren(), 0, 20);
float angle = upVec.getAngleBetween(res[0].norm);
if(res.empty() || res[0].mesh->getNode() != map->getNodeParent()->getChild(0))
model->lookAt(Vector3(dirVec.x, 0, dirVec.z).norm(), Vector3::VEC_J);
else if(res[0].mesh->getNode() == map->getNodeParent()->getChild(0)){
float angle = upVec.getAngleBetween(res[0].norm);
if(angle > 0) if(angle > 0)
model->lookAt(leftVec.cross(res[0].norm), res[0].norm); model->lookAt(leftVec.cross(res[0].norm), res[0].norm);
}
} }
ActiveGameState *activeState = (ActiveGameState*)GameManager::getSingleton()->getStateManager()->getAppStateByType(AppStateType::ACTIVE_STATE); ActiveGameState *activeState = (ActiveGameState*)GameManager::getSingleton()->getStateManager()->getAppStateByType(AppStateType::ACTIVE_STATE);
+1 -1
View File
@@ -159,7 +159,7 @@ namespace battleship{
sf::SoundBuffer *selectionSfxBuffer; sf::SoundBuffer *selectionSfxBuffer;
sf::Sound *selectionSfx = nullptr; sf::Sound *selectionSfx = nullptr;
vb01::Node *hpBackgroundNode = nullptr, *hpForegroundNode = nullptr, *losLightNode = nullptr; vb01::Node *hpBackgroundNode = nullptr, *hpForegroundNode = nullptr, *losLightNode = nullptr;
bool vehicle, currOrderStarted = false; bool vehicle, currOrderStarted = false, alignToSurface = false;
Condition condition = Condition::ABLE; Condition condition = Condition::ABLE;
protected: protected:
UnitClass unitClass; UnitClass unitClass;
+28 -101
View File
@@ -10,6 +10,7 @@
#include <quaternion.h> #include <quaternion.h>
#include "pathfinder.h" #include "pathfinder.h"
#include "defConfigs.h"
#include "structure.h" #include "structure.h"
#include "vehicle.h" #include "vehicle.h"
#include "weapon.h" #include "weapon.h"
@@ -105,10 +106,29 @@ namespace battleship{
initProperties(); initProperties();
} }
void Vehicle::arrivedAtPathpoint(bool byPlane, float vertDist){
bool orderHasDir = (orders[0].direction != Vector3::VEC_ZERO);
float angleToOrderDir = dirVec.getAngleBetween(orders[0].direction);
bool destDirWithin = (!orderHasDir || (orderHasDir && angleToOrderDir <= anglePrecision));
if(pathPoints.size() == 1 && !destDirWithin)
turn(calculateRotation(orders[0].direction, angleToOrderDir, maxTurnAngle));
if(byPlane && (
(pathPoints.size() > 1 || (pathPoints.size() == 1 && destDirWithin)) &&
(type != UnitType::UNDERWATER || (type == UnitType::UNDERWATER && vertDist < 0.5 * height))
)
){
removePathpoint();
}
else if(!byPlane && (pathPoints.size() > 1 || (pathPoints.size() == 1 && destDirWithin)))
removePathpoint();
}
void Vehicle::moveByTerrainQuads(Vector3 hypVec, float destOffset){ void Vehicle::moveByTerrainQuads(Vector3 hypVec, float destOffset){
Map *map = Map::getSingleton(); Map *map = Map::getSingleton();
Quad *terrQuad = (Quad*)map->getNodeParent()->getChild(0)->getMesh(0); Quad *terrQuad = (Quad*)map->getNodeParent()->getChild(0)->getMesh(0);
int numVertDiv = 100, numHorDiv = 100; int numVertDiv = configData::NUM_SUBDIVS, numHorDiv = configData::NUM_SUBDIVS;
Vector3 mapSize = map->getMapSize(); Vector3 mapSize = map->getMapSize();
Vector2 sqIdsVec = terrQuad->getSubquadIds(numVertDiv, numHorDiv, pos, mapSize); Vector2 sqIdsVec = terrQuad->getSubquadIds(numVertDiv, numHorDiv, pos, mapSize);
Vector2 sqIdsEndVec = terrQuad->getSubquadIds(numVertDiv, numHorDiv, pathPoints[0], mapSize); Vector2 sqIdsEndVec = terrQuad->getSubquadIds(numVertDiv, numHorDiv, pathPoints[0], mapSize);
@@ -132,7 +152,7 @@ namespace battleship{
float intersecY = (bottom ? c3.z : c1.z); float intersecY = (bottom ? c3.z : c1.z);
float xSolY = a * intersecX + b; float xSolY = a * intersecX + b;
float ySolX = (intersecY - b) / a; float ySolX = (hypVec.x != 0 ? (intersecY - b) / a : points[points.size() - 1].x);
float diff, vertDiff, x, y, z; float diff, vertDiff, x, y, z;
@@ -179,8 +199,8 @@ namespace battleship{
placeAt(endPos); placeAt(endPos);
if(fabs(pathPoints[0].x - pos.x) <= destOffset && fabs(pathPoints[0].z - pos.z) <= destOffset/* && fabs(pathPoints[0].y - pos.y) <= .1*/) if(fabs(pathPoints[0].x - pos.x) <= destOffset && fabs(pathPoints[0].z - pos.z) <= destOffset)
removePathpoint(); arrivedAtPathpoint(false);
} }
void Vehicle::moveByPlane(Vector3 hypVec, float destOffset){ void Vehicle::moveByPlane(Vector3 hypVec, float destOffset){
@@ -203,27 +223,13 @@ namespace battleship{
float dist = pos.y - pathPoints[0].y; float dist = pos.y - pathPoints[0].y;
float movementAmmount = (speed > fabs(dist) ? dist : speed); float movementAmmount = (speed > fabs(dist) ? dist : speed);
if(dist > 0) if(dist > 0) movementAmmount *= -1;
movementAmmount *= -1;
advance(movementAmmount, MoveDir::UP); advance(movementAmmount, MoveDir::UP);
} }
if(pos.getDistanceFrom(linDest) <= destOffset){ if(pos.getDistanceFrom(linDest) <= destOffset)
bool orderHasDir = (orders[0].direction != Vector3::VEC_ZERO); arrivedAtPathpoint(true, vertDist);
float angleToOrderDir = dirVec.getAngleBetween(orders[0].direction);
bool destDirWithin = (!orderHasDir || (orderHasDir && angleToOrderDir <= anglePrecision));
if(pathPoints.size() == 1 && !destDirWithin)
turn(calculateRotation(orders[0].direction, angleToOrderDir, maxTurnAngle));
if(
(pathPoints.size() > 1 || (pathPoints.size() == 1 && destDirWithin)) &&
(type != UnitType::UNDERWATER || (type == UnitType::UNDERWATER && vertDist < 0.5 * height))
){
removePathpoint();
}
}
} }
void Vehicle::navigate(float destOffset){ void Vehicle::navigate(float destOffset){
@@ -250,85 +256,11 @@ namespace battleship{
moveByTerrainQuads(hypVec, destOffset); moveByTerrainQuads(hypVec, destOffset);
else else
moveByPlane(hypVec, destOffset); moveByPlane(hypVec, destOffset);
}
/*
int numHorSubquads = terrQuad->getNumHorSubquads();
int numVertSubquads = terrQuad->getNumVertSubquads();
Vector3 mapSize = map->getMapSize();
Vector2 subquadSize = terrQuad->getSubquadSize();
Vector3 pointA = pos, pointB = pathPoints[0];
if(pointA.x > pointB.x) swap(pointA.x, pointB.x);
if(pointA.z > pointB.z) swap(pointA.z, pointB.z);
// y = ax + b
float a = hypVec.x / hypVec.z;
float b = pos.z / (a * pos.x);
vector<pair<pair<int, int>, float>> intersecPointDists;
for(int x = 0; x < numHorSubquads; x++){
float currX = -.5 * mapSize.x + x * subquadSize.x;
if(!(pointA.x <= currX && currX <= pointB.x)) continue;
Vector2 pos2D = Vector2(pos.x, pos.z);
int y;
for(y = 0; y < numVertSubquads; y++){
float currY = -.5 * mapSize.z + y * subquadSize.y;
if(!(pointA.z <= currY && currY <= pointB.z)) continue;
intersecPointDists.push_back(make_pair(make_pair(x, y), Vector2((currY - b) / a, currY).getDistanceFrom(pos2D)));
}
intersecPointDists.push_back(make_pair(make_pair(x, y), Vector2(currX, a * currX + b).getDistanceFrom(pos2D)));
}
for (int i = 0; i < intersecPointDists.size(); i++)
for (int j = 0; j < intersecPointDists.size() - i - 1; j++)
if (intersecPointDists[j] > intersecPointDists[j + 1])
swap(intersecPointDists[j], intersecPointDists[j + 1]);
float currDist = 0;
int lastId;
for(int i = 0; i < intersecPointDists.size(); i++){
currDist += intersecPointDists[i].second;
lastId = i;
if(currDist + intersecPointDists[i].second > speed) break;
}
Vector3 p1, p2;
//p1 = terrQuad->getSubQuadPoint(intersecPointDists[lastId]);
//p2 = terrQuad->getSubQuadPoint(intersecPointDists[lastId - 1]);
Vector3 vec = p2 - p1;
}
*/
void Vehicle::alignToSurface(){
/*
Map *map = Map::getSingleton();
TerrainObject terr = map->getTerrainObject(0);
vector<RayCaster::CollisionResult> res = RayCaster::cast(Vector3(pos.x, terr.size.y, pos.z), Vector3(0, -1, 0), terr.node);
if(!res.empty()){
placeAt(res[0].pos);
float angle = upVec.getAngleBetween(res[0].norm);
Vector3 axis = upVec.cross(res[0].norm).norm();
Quaternion rotQuat = Quaternion(angle, axis);
orientAt(rotQuat * rot);
}
*/
} }
void Vehicle::move(Order order) { void Vehicle::move(Order order) {
navigate(0.5 * Map::getSingleton()->getCellSize().x); navigate(0.5 * Map::getSingleton()->getCellSize().x);
//if(type == UnitType::LAND) alignToSurface();
if(pathPoints.empty()) if(pathPoints.empty())
removeOrder(0); removeOrder(0);
} }
@@ -524,12 +456,7 @@ namespace battleship{
} }
} }
} }
else{ else navigate(0.5 * Map::getSingleton()->getCellSize().x);
navigate(0.5 * Map::getSingleton()->getCellSize().x);
if(type == UnitType::LAND)
alignToSurface();
}
} }
void Vehicle::select(){ void Vehicle::select(){
+1 -1
View File
@@ -41,12 +41,12 @@ namespace battleship{
std::vector<vb01::Vector3> pathPoints; std::vector<vb01::Vector3> pathPoints;
bool pursuingTarget = false; bool pursuingTarget = false;
void arrivedAtPathpoint(bool, float = 0);
void moveByTerrainQuads(vb01::Vector3, float); void moveByTerrainQuads(vb01::Vector3, float);
void moveByPlane(vb01::Vector3, float); void moveByPlane(vb01::Vector3, float);
void navigate(float = 0.); void navigate(float = 0.);
void navigateToTarget(float); void navigateToTarget(float);
void preparePathpoints(Order&, vb01::Vector3, bool = false); void preparePathpoints(Order&, vb01::Vector3, bool = false);
void alignToSurface();
virtual void attack(Order); virtual void attack(Order);
void garrison(Order); void garrison(Order);
void patrol(Order); void patrol(Order);