selecting units by left clicking

This commit is contained in:
devZoGok
2023-11-05 16:28:33 +02:00
parent 4a9e9bd4c9
commit 464abc1c00
13 changed files with 189 additions and 106 deletions
+8 -8
View File
@@ -12,14 +12,14 @@ resources = {
},
unitCornerPoints = {
{
{x = .9, y = -1, z = -6},
{x = -.9, y = -1, z = -6},
{x = -.9, y = -1, z = 5.8},
{x = .9, y = -1, z = 5.8},
{x = .9, y = 3.5, z = -6},
{x = -.9, y = 3.5, z = -6},
{x = -.9, y = 3.5, z = 5.8},
{x = .9, y = 3.5, z = 5.8}
{x = 1, y = .571, z = -1},
{x = -1, y = .571, z = -1},
{x = -1, y = .571, z = 1},
{x = 1, y = .571, z = 1},
{x = 1, y = .571, z = -1},
{x = -1, y = .571, z = -1},
{x = -1, y = .571, z = 1},
{x = 1, y = .571, z = 1}
}
}
}
+8 -8
View File
@@ -40,14 +40,14 @@ units = {
unitCornerPoints = {
{
{x = .9, y = -1, z = -6},
{x = -.9, y = -1, z = -6},
{x = -.9, y = -1, z = 5.8},
{x = .9, y = -1, z = 5.8},
{x = .9, y = 3.5, z = -6},
{x = -.9, y = 3.5, z = -6},
{x = -.9, y = 3.5, z = 5.8},
{x = .9, y = 3.5, z = 5.8}
{x = 1.45, y = -4.11, z = -1.21},
{x = -1.45, y = -4.11, z = -1.21},
{x = -1.45, y = -4.11, z = 1.21},
{x = 1.45, y = -4.11, z = 1.21},
{x = 1.45, y = 4.11, z = -1.21},
{x = -1.45, y = 4.11, z = -1.21},
{x = -1.45, y = 4.11, z = 1.21},
{x = 1.45, y = 4.11, z = 1.21}
},
{
{x = .5, y = -.5, z = -7.05},
+100 -61
View File
@@ -63,7 +63,7 @@ namespace battleship{
mat->addBoolUniform("diffuseColorEnabled", false);
mat->addVec4Uniform("diffuseColor", Vector4(.5, .5, .5, .5));
dragbox = new Quad(Vector3::VEC_ZERO, false);
Quad *dragbox = new Quad(Vector3::VEC_ZERO, false);
dragbox->setMaterial(mat);
dragboxNode = new Node();
dragboxNode->attachMesh(dragbox);
@@ -107,9 +107,15 @@ namespace battleship{
wealthText->getText(0)->setText(L"Wealth: " + to_wstring(mainPlayer->getWealth()));
researchText->getText(0)->setText(L"Research: " + to_wstring(mainPlayer->getResearch()));
if (isSelectionBox)
if(!isSelectionBox && leftMouseClicked && getTime() - lastLeftMouseClicked > 10)
isSelectionBox = true;
else if (isSelectionBox)
updateSelectionBox();
dragboxNode->setVisible(isSelectionBox);
updateGameObjHoveredOn();
vector<Unit*> selectedUnits = mainPlayer->getSelectedUnits();
if(!selectingDestOrient && leftMouseClicked && !selectedUnits.empty() && getTime() - lastLeftMouseClicked > 100){
@@ -123,8 +129,6 @@ namespace battleship{
fc->addGameObjectFrame(GameObjectFrame(unit->getId(), GameObject::Type::UNIT));
}
dragboxNode->setVisible(isSelectionBox);
renderUnits();
CameraController *camCtr = CameraController::getSingleton();
@@ -138,6 +142,36 @@ namespace battleship{
ufCtr->update();
}
void ActiveGameState::updateGameObjHoveredOn(){
vector<GameObject*> gameObjs;
vector<Player*> players = Game::getSingleton()->getPlayers();
for(Player *pl : players){
vector<ResourceDeposit*> resDeps = pl->getResourceDeposits();
vector<Unit*> units = pl->getUnits();
for(ResourceDeposit *rd : resDeps)
gameObjs.push_back((GameObject*)rd);
for(Unit *u : units)
gameObjs.push_back((GameObject*)u);
}
Vector2 cursorPos = getCursorPos();
for(GameObject *gameObj : gameObjs){
Vector2 rectSize = gameObj->calculateSelectionRect();
Vector2 screenPos = gameObj->getScreenPos();
if(fabs(cursorPos.x - screenPos.x) < .5 * rectSize.x && fabs(cursorPos.y - screenPos.y) < .5 * rectSize.y){
gameObjHoveredOn = gameObj;
return;
}
}
gameObjHoveredOn = nullptr;
}
void ActiveGameState::deselectUnits(){
mainPlayer->deselectUnits();
GameObjectFrameController *ufCtr = GameObjectFrameController::getSingleton();
@@ -158,14 +192,11 @@ namespace battleship{
for (Unit *u : units) {
if (u->getPlayer() == mainPlayer){
Vector3 selectionBoxOrigin = dragboxNode->getPosition();
Vector3 selectionBoxEnd = selectionBoxOrigin + dragbox->getSize();
Vector3 dragboxSize = ((Quad*)dragboxNode->getMesh(0))->getSize();
Vector3 dragboxOrigin = dragboxNode->getPosition(), dragboxEnd = dragboxOrigin + dragboxSize;
Vector2 pos = u->getScreenPos();
if(isSelectionBox &&
pos.x >= selectionBoxOrigin.x && pos.x <= selectionBoxEnd.x &&
pos.y >= selectionBoxOrigin.y && pos.y <= selectionBoxEnd.y){
if(isSelectionBox && fabs(pos.x - dragboxOrigin.x) < .5 * dragboxSize.x && fabs(pos.y - dragboxOrigin.y) < .5 * dragboxSize.y){
if(!u->isSelected()){
if(!shiftPressed)
deselectUnits();
@@ -173,14 +204,12 @@ namespace battleship{
mainPlayer->selectUnit(u);
u->toggleSelection(true);
if(engineersSelected()){
if(unitClassSelected(UnitClass::ENGINEER)){
ConcreteGuiManager *guiManager = ConcreteGuiManager::getSingleton();
guiManager->readLuaScreenScript("engineerCommands.lua");
}
}
}
u->getNode()->setVisible(true);
}
else{
Vector3 rendUnPos = u->getPos();
@@ -229,12 +258,14 @@ namespace battleship{
}
Vector3 size = Vector3(selectionBoxEnd.x - selectionBoxOrigin.x, selectionBoxEnd.y - selectionBoxOrigin.y, 0);
Quad *dragbox = (Quad*)dragboxNode->getMesh(0);
dragbox->setSize(size);
dragbox->updateVerts(dragbox->getMeshBase());
dragboxNode->setPosition(Vector3(selectionBoxOrigin.x, selectionBoxOrigin.y, 0));
}
//TODO fix ejectable unit selection with multiple transports selected
void ActiveGameState::issueOrder(Order::TYPE type, bool addOrder) {
void ActiveGameState::issueOrder(Order::TYPE type, vector<Order::Target> targets, bool addOrder) {
Vector3 color;
switch(type){
@@ -242,7 +273,6 @@ namespace battleship{
color = Vector3::VEC_J;
break;
case Order::TYPE::ATTACK:
case Order::TYPE::LAUNCH:
color = Vector3::VEC_I;
break;
case Order::TYPE::PATROL:
@@ -255,9 +285,7 @@ namespace battleship{
break;
}
if(type == Order::TYPE::PATROL){
}
else if(type == Order::TYPE::EJECT){
if(type == Order::TYPE::EJECT){
vector<Unit*> units = mainPlayer->getSelectedUnits();
for(Unit *u : units){
@@ -268,53 +296,40 @@ namespace battleship{
targets.push_back(Order::Target((Unit*)slot.vehicle));
}
}
else
else if(type != Order::TYPE::PATROL)
targets.push_back(Order::Target());
LineRenderer *lineRenderer = LineRenderer::getSingleton();
for (int i = 0; i < mainPlayer->getNumSelectedUnits(); ++i) {
Unit *u = mainPlayer->getSelectedUnit(i);
lineRenderer->addLine(u->getPos(), targets[i].pos, color);
vector<LineRenderer::Line> lines = lineRenderer->getLines();
LineRenderer::Line line = lines[lines.size() - 1];
Vector3 destDir = (selectingDestOrient ? GameObjectFrameController::getSingleton()->getGameObjectFrame(0).getDirVec() : Vector3::VEC_ZERO);
Order order(type, line, targets, destDir);
if (type != Order::TYPE::LAUNCH) {
if (addOrder)
u->addOrder(order);
else
u->setOrder(order);
}
if (addOrder)
u->addOrder(order);
else
u->setOrder(order);
}
targets.clear();
this->targets.clear();
}
void ActiveGameState::addTarget() {
void ActiveGameState::castRayToTerrain() {
Camera *cam = Root::getSingleton()->getCamera();
Vector3 camPos = cam->getPosition();
Vector3 endPos = screenToSpace(getCursorPos());
Vector3 rayDir = (endPos - camPos).norm();
vector<RayCaster::CollisionResult> results = RayCaster::cast(camPos, rayDir, Map::getSingleton()->getNodeParent());
std::map<Node*, Unit*> unitData;
if(!results.empty()){
vector<Node*> ancestors = results[0].mesh->getNode()->getAncestors();
Node *node = ancestors[ancestors.size() - 2];
std::map<Node*, Unit*>::iterator it = unitData.find(node);
Unit *unit = nullptr;
GameObjectFrameController *ufCtr = GameObjectFrameController::getSingleton();
if(ufCtr->isPlacingFrames()){
GameObjectFrame goFr = ufCtr->getGameObjectFrame(0);
unit = new Structure(mainPlayer, goFr.getId(), goFr.getModel()->getPosition(), goFr.getModel()->getOrientation());
mainPlayer->addUnit(unit);
}
Map *map = Map::getSingleton();
for(Unit *u : mainPlayer->getSelectedUnits()){
@@ -340,52 +355,76 @@ namespace battleship{
}
}
targets.push_back(Order::Target((it != unitData.end() ? unitData[node] : unit), results[0].pos));
targets.push_back(Order::Target(nullptr, results[0].pos));
}
}
bool ActiveGameState::engineersSelected(){
bool ActiveGameState::unitClassSelected(UnitClass uc){
for(Unit *u : mainPlayer->getSelectedUnits())
if(u->getUnitClass() == UnitClass::ENGINEER)
if(u->getUnitClass() == uc)
return true;
return false;
}
void ActiveGameState::onAction(int bind, bool isPressed) {
GameManager *gm = GameManager::getSingleton();
InGameAppState *inGameState = (InGameAppState*) gm->getStateManager()->getAppStateByType((int)AppStateType::IN_GAME_STATE);
GameObjectFrameController *ufCtr = GameObjectFrameController::getSingleton();
switch((Bind)bind){
case Bind::DRAG_BOX:
isSelectionBox = isPressed;
leftMouseClicked = isPressed;
clickPoint = getCursorPos();
if(isPressed)
if(isPressed){
clickPoint = getCursorPos();
lastLeftMouseClicked = getTime();
}
else{
if (mainPlayer->getNumSelectedUnits() > 0){
addTarget();
if(selectingPatrolPoints){
castRayToTerrain();
if(!(targets.empty() || selectingPatrolPoints)){
Order::TYPE type = Order::TYPE::MOVE;
if(controlPressed || (targets[0].unit && targets[0].unit->getPlayer()->getSide() != mainPlayer->getSide()))
type = Order::TYPE::ATTACK;
else if(ufCtr->isPlacingFrames() && !selectingDestOrient)
type = Order::TYPE::BUILD;
issueOrder(type, shiftPressed);
if(!shiftPressed){
issueOrder(Order::TYPE::PATROL, targets, shiftPressed);
selectingPatrolPoints = false;
}
}
else if(selectingPatrolPoints && !shiftPressed){
issueOrder(Order::TYPE::PATROL, false);
selectingPatrolPoints = false;
else{
bool canSelect = canSelectHoveredOnGameObj();
if(gameObjHoveredOn && gameObjHoveredOn->getPlayer()->getSide() != mainPlayer->getSide())
issueOrder(Order::TYPE::ATTACK, vector<Order::Target>{Order::Target((Unit*)gameObjHoveredOn, Vector3())}, shiftPressed);
else if(controlPressed){
castRayToTerrain();
issueOrder(Order::TYPE::ATTACK, targets, shiftPressed);
}
else if(ufCtr->isPlacingFrames() && !selectingDestOrient){
castRayToTerrain();
issueOrder(Order::TYPE::BUILD, targets, shiftPressed);
}
else if(canSelect){
if(!shiftPressed)
deselectUnits();
mainPlayer->selectUnit((Unit*)gameObjHoveredOn);
}
else if(!canSelect){
castRayToTerrain();
issueOrder(Order::TYPE::MOVE, targets, shiftPressed);
}
}
}
else{
if(canSelectHoveredOnGameObj()){
if(!shiftPressed)
deselectUnits();
mainPlayer->selectUnit((Unit*)gameObjHoveredOn);
}
}
selectingDestOrient = false;
isSelectionBox = false;
ufCtr->setPlacingFrames(false);
ufCtr->setRotatingFrames(false);
ufCtr->removeGameObjectFrames();
+9 -6
View File
@@ -4,6 +4,7 @@
#include "guiAppState.h"
#include "player.h"
#include "map.h"
#include "unit.h"
namespace vb01{
class Node;
@@ -14,6 +15,8 @@ namespace vb01Gui{
}
namespace battleship{
class GameObject;
class ActiveGameState : public gameBase::AbstractAppState {
public:
ActiveGameState(GuiAppState*, int);
@@ -28,24 +31,24 @@ namespace battleship{
inline Player* getPlayer(){return mainPlayer;}
inline std::vector<Unit*>& getUnitGroup(int i){return unitGroups[i];}
private:
void updateGameObjHoveredOn();
void initDragbox();
vb01::Node* initText(vb01::Vector2);
void deselectUnits();
void renderUnits();
void updateSelectionBox();
void updateStructureFrames();
void addTarget();
void issueOrder(Order::TYPE, bool);
void castRayToTerrain();
void issueOrder(Order::TYPE, std::vector<Order::Target>, bool);
bool isInLineOfSight(vb01::Vector3, float, Unit*);
bool engineersSelected();
bool unitClassSelected(UnitClass);
inline bool canSelectHoveredOnGameObj(){return gameObjHoveredOn && gameObjHoveredOn->isSelectable() && gameObjHoveredOn->getPlayer() == mainPlayer;}
GuiAppState *guiState;
Player *mainPlayer;
vb01::Quad *dragbox = nullptr;
GameObject *gameObjHoveredOn = nullptr;
vb01::Node *dragboxNode = nullptr, *textNode = nullptr, *refinedsText = nullptr, *wealthText = nullptr, *researchText = nullptr;
vb01::Vector2 clickPoint;
std::vector<vb01::Vector2> unitScreenPosVec;
std::vector<vb01::Node*> unitLightNodes;
std::vector<Unit*> unitGroups[9];
std::vector<Order::Target> targets;
std::vector<vb01Gui::Button*> buttons;
+44
View File
@@ -20,6 +20,7 @@ namespace battleship{
leftVec = model->getGlobalAxis(0);
upVec = model->getGlobalAxis(1);
dirVec = model->getGlobalAxis(2);
screenPos = spaceToScreen(pos);
}
void GameObject::placeAt(Vector3 p) {
@@ -33,6 +34,16 @@ namespace battleship{
}
void GameObject::initProperties(){
sol::table SOL_LUA_STATE = generateView()[GameObject::getGameObjTableName()];
for(int i = 0; i < 8; i++){
sol::table cornerTable = SOL_LUA_STATE["unitCornerPoints"][id + 1][i + 1];
corners[i] = Vector3(cornerTable["x"], cornerTable["y"], cornerTable["z"]);
}
width = corners[0].x - corners[1].x;
height = corners[4].y - corners[0].y;
length = corners[3].z - corners[0].z;
}
void GameObject::destroyModel(){
@@ -101,4 +112,37 @@ namespace battleship{
return "resources";
}
}
int GameObject::sortCorners(vector<Vector2> &cornersOnScreen, bool vertical, bool max){
const int NUM_CORNERS = cornersOnScreen.size();
int ans = 0;
for(int i = 0; i < NUM_CORNERS; i++){
if(vertical && ((max && cornersOnScreen[ans].y < cornersOnScreen[i].y) || (!max && cornersOnScreen[ans].y > cornersOnScreen[i].y)))
ans = i;
else if(!vertical && ((max && cornersOnScreen[ans].x < cornersOnScreen[i].x) || (!max && cornersOnScreen[ans].x > cornersOnScreen[i].x)))
ans = i;
}
return ans;
}
Vector2 GameObject::calculateSelectionRect(){
const int NUM_CORNERS = 8;
vector<Vector2> cornersOnScreen;
for(int i = 0; i < NUM_CORNERS; i++){
Vector3 cornerInWorld = leftVec * corners[i].x + upVec * corners[i].y + dirVec * corners[i].z;
cornersOnScreen.push_back(spaceToScreen(cornerInWorld));
}
int leftMostPointId = sortCorners(cornersOnScreen, false, false);
int rightMostPointId = sortCorners(cornersOnScreen, false, true);
int topMostPointId = sortCorners(cornersOnScreen, true, false);
int bottomMostPointId = sortCorners(cornersOnScreen, true, true);
float sizeX = cornersOnScreen[rightMostPointId].x - cornersOnScreen[leftMostPointId].x;
float sizeY = cornersOnScreen[bottomMostPointId].y - cornersOnScreen[topMostPointId].y;
return Vector2(sizeX, sizeY);
}
}
+5 -1
View File
@@ -24,6 +24,8 @@ namespace battleship{
void placeAt(vb01::Vector3);
void orientAt(vb01::Quaternion);
std::string getGameObjTableName();
vb01::Vector2 calculateSelectionRect();
inline vb01::Vector2 getScreenPos(){return screenPos;}
inline vb01::Vector3 getCorner(int i){return corners[i];}
inline bool isSelected(){return selected;}
inline bool isSelectable(){return selectable;}
@@ -42,6 +44,7 @@ namespace battleship{
inline int getId() {return id;}
inline Type getType(){return type;}
private:
int sortCorners(std::vector<vb01::Vector2>&, bool, bool);
protected:
virtual void initProperties();
virtual void destroyModel();
@@ -57,8 +60,9 @@ namespace battleship{
sf::Sound *deathSfx;
vb01::Model *model = nullptr;
vb01::Vector3 pos = vb01::Vector3(0, 0, 0), upVec = vb01::Vector3(0, 1, 0), dirVec = vb01::Vector3(0, 0, 1), leftVec = vb01::Vector3(1, 0, 0), corners[8];
vb01::Vector2 screenPos;
vb01::Quaternion rot;
bool selected = false, selectable, debugging = false;
bool selected = false, selectable = false, debugging = false;
float width, height, length;
};
}
+2 -1
View File
@@ -4,7 +4,6 @@
#include <model.h>
#include <material.h>
#include <quaternion.h>
#include <rayCaster.h>
#include <stateManager.h>
@@ -43,6 +42,8 @@ namespace battleship{
}
void Projectile::initProperties(int weaponId){
GameObject::initProperties();
sol::table SOL_LUA_STATE = generateView()[GameObject::getGameObjTableName()];
rayLength = SOL_LUA_STATE["rayLength"][id + 1][weaponTypeId + 1][weaponId + 1];
damage = SOL_LUA_STATE["damage"][id + 1][weaponTypeId + 1][weaponId + 1];
+1 -3
View File
@@ -4,11 +4,9 @@ namespace battleship{
using namespace vb01;
ResourceDeposit::ResourceDeposit(Player *player, int id, Vector3 pos, Quaternion rot) : GameObject(GameObject::Type::RESOURCE_DEPOSIT, id, player, pos, rot){
initProperties();
initModel();
placeAt(pos);
orientAt(rot);
}
void ResourceDeposit::update(){
}
}
-1
View File
@@ -7,7 +7,6 @@ namespace battleship{
class ResourceDeposit : public GameObject{
public:
ResourceDeposit(Player*, int, vb01::Vector3, vb01::Quaternion);
void update();
private:
};
}
+3 -11
View File
@@ -27,6 +27,7 @@ namespace battleship{
Unit::Unit(Player *player, int id, Vector3 pos, Quaternion rot) : GameObject(GameObject::Type::UNIT, id, player, pos, rot){
this->id = id;
this->player = player;
selectable = true;
init();
@@ -51,6 +52,8 @@ namespace battleship{
}
void Unit::initProperties(){
GameObject::initProperties();
sol::table SOL_LUA_STATE = generateView()[GameObject::getGameObjTableName()];
string name = SOL_LUA_STATE["name"][id + 1];
health = SOL_LUA_STATE["health"][id + 1];
@@ -71,16 +74,6 @@ namespace battleship{
garrisonSlots.push_back(GarrisonSlot(bg, fg, pos));
}
string cornerInd = "unitCornerPoints";
for(int i = 0; i < 8; i++){
sol::table cornerTable = SOL_LUA_STATE[cornerInd][id + 1][i + 1];
corners[i] = Vector3(cornerTable["x"], cornerTable["y"], cornerTable["z"]);
}
width = corners[0].x - corners[1].x;
height = corners[4].y - corners[0].y;
length = corners[3].z - corners[0].z;
}
void Unit::destroySound(){
@@ -151,7 +144,6 @@ namespace battleship{
executeOrders();
screenPos = spaceToScreen(pos);
displayUnitStats(hpForegroundNode, hpBackgroundNode, health, maxHealth);
for(GarrisonSlot &slot : garrisonSlots)
-4
View File
@@ -73,8 +73,6 @@ namespace battleship{
virtual void addOrder(Order);
virtual void reinit();
inline const std::vector<GarrisonSlot>& getGarrisonSlots(){return garrisonSlots;}
inline vb01::Vector3 getCorner(int i){return corners[i];}
inline vb01::Vector2 getScreenPos(){return screenPos;}
inline vb01::Vector3* getPosPtr() {return &pos;}
inline float getLineOfSight() {return lineOfSight;}
inline vb01::Model* getNode() {return model;}
@@ -94,9 +92,7 @@ namespace battleship{
protected:
UnitClass unitClass;
UnitType type;
vb01::Vector2 screenPos;
std::vector<Order> orders;
vb01::Vector3 corners[8];
sf::SoundBuffer *fireSfxBuffer;
sf::Sound *fireSfx = nullptr;
int health, maxHealth, cost, id, playerId, lenHpBar = 200, rateOfFire;
+8 -2
View File
@@ -242,7 +242,7 @@ namespace battleship{
return files;
}
Vector2 spaceToScreen(Vector3 pos){
Vector3 spaceToScreen3d(Vector3 pos){
Root *root = Root::getSingleton();
Camera *cam = root->getCamera();
Vector3 dir = cam->getDirection(), up = cam->getUp();
@@ -255,7 +255,13 @@ namespace battleship{
vec4 ndcPos = proj * view * vec4(pos.x, pos.y, pos.z, 1);
ndcPos.x /= ndcPos.w;
ndcPos.y /= ndcPos.w;
return Vector2(0.5 * width * (1 + ndcPos.x), 0.5 * height * (1 - ndcPos.y));
ndcPos.z /= ndcPos.w;
return Vector3(0.5 * width * (1 + ndcPos.x), 0.5 * height * (1 - ndcPos.y), ndcPos.z);
}
Vector2 spaceToScreen(Vector3 pos){
Vector3 pos3d = spaceToScreen3d(pos);
return Vector2(pos3d.x, pos3d.y);
}
Vector3 screenToSpace(Vector2 pos){
+1
View File
@@ -27,6 +27,7 @@ namespace battleship{
void makeTitlescreenButtons(GuiAppState*);
std::vector<std::string> readDir(std::string, bool);
vb01::Vector2 spaceToScreen(vb01::Vector3);
vb01::Vector3 spaceToScreen3d(vb01::Vector3);
vb01::Vector3 screenToSpace(vb01::Vector2);
}