void GameSessionInput::selectUnit() { if(!leftShiftPressed) unselectAll(); vec3 clickPos = Root::shared().getDepthResult(); vec2 clickPos2(clickPos.x, clickPos.z); Faction* lf = session->getLocalFaction(); if(!lf) return; Unit* best_unit = 0; float best_distance = 100.0; float dist; for(list<Unit*>::iterator it = lf->getUnits().begin(); it != lf->getUnits().end(); ++it) { dist = glm::distance((*it)->getPosition2(), clickPos2); if(dist < 2.0 * (*it)->getInfo()->radius && dist < best_distance) { best_distance = dist; best_unit = (*it); } } if(best_unit) { SoundManager::shared().play(best_unit->getInfo()->selectionSound); best_unit->setSelected(true); if(leftControlPressed) best_unit->getDebugText(); } }
void GameSessionInput::selectUnits(float x_min, float x_max, float y_min, float y_max) { if(!leftShiftPressed) unselectAll(); Faction* lf = session->getLocalFaction(); bool firstUnitSelected = false; if(!lf) return; for(list<Unit*>::iterator it = lf->getUnits().begin(); it != lf->getUnits().end(); ++it) { vec2 onScreen = (*it)->getScreenPosition(); if((onScreen.x > x_min && onScreen.x < x_max) && (onScreen.y > y_min && onScreen.y < y_max)) { (*it)->setSelected(true); if(!firstUnitSelected) { SoundManager::shared().play((*it)->getInfo()->selectionSound); } firstUnitSelected = true; if(leftControlPressed) (*it)->getDebugText(); } } }
void GameSessionClient::updateGameLogic(int elapsedTime) { if(!localFaction) return; gameTimer += elapsedTime; //First purge units that have to be deleted for(auto fIter : getFactionMap()) { Faction* faction = fIter.second; for(auto it = faction->getUnits().begin(); it != faction->getUnits().end(); ) { if ((*it)->readyToDelete()) { delete *it; it = faction->getUnits().erase(it); } else { ++it; } } } //Update all units //mat4 vpMatrix = Arya::Locator::getRoot().getGraphics()->getCamera()->getVPMatrix(); for(auto unitIter : getUnitMap()) { Unit* unit = unitIter.second; //vec4 onScreen(unit->getEntity()->getPosition(), 1.0); //onScreen = vpMatrix * onScreen; //onScreen.x /= onScreen.w; //onScreen.y /= onScreen.w; //unit->setScreenPosition(vec2(onScreen.x, onScreen.y)); unit->update(gameTimer); } for(auto unit : localFaction->getUnits()) unit->checkForEnemies(); }
void GameSessionInput::selectAll() { Faction* lf = session->getLocalFaction(); if(!lf) return; for(list<Unit*>::iterator it = lf->getUnits().begin(); it != lf->getUnits().end(); ++it) (*it)->setSelected(true); }
void GameSessionInput::moveSelectedUnits() { vec3 clickPos = Root::shared().getDepthResult(); vec2 clickPos2(clickPos.x, clickPos.z); Faction* lf = session->getLocalFaction(); if(!lf) return; // did we click on an enemy unit Unit* best_unit = 0; float best_distance = 100.0; //Faction* from_faction = 0; float dist; for(unsigned int j = 0; j < session->getFactions().size(); ++j) { if(session->getFactions()[j] == lf) continue; for(list<Unit*>::iterator it = session->getFactions()[j]->getUnits().begin(); it != session->getFactions()[j]->getUnits().end(); ++it) { dist = glm::distance((*it)->getPosition2(), clickPos2); if(dist < (*it)->getInfo()->radius && dist < best_distance) { best_distance = dist; best_unit = (*it); } } } vec2 centerPos(0,0); //average position of selected units vector<int> unitIds; vector<vec2> unitPositions; for(list<Unit*>::iterator it = lf->getUnits().begin(); it != lf->getUnits().end(); ++it) if((*it)->isSelected()) { centerPos += (*it)->getPosition2(); unitPositions.push_back((*it)->getPosition2()); unitIds.push_back((*it)->getId()); } int numSelected = unitIds.size(); if(!numSelected) return; centerPos /= (float)numSelected; //FOR NOW: we only use pathfinding for normal walking, not for attacking if(best_unit) { Event& ev = Game::shared().getEventManager()->createEvent(EVENT_ATTACK_MOVE_UNIT_REQUEST); ev << numSelected; for(unsigned int i = 0; i < unitIds.size(); ++i) ev << unitIds[i] << best_unit->getId(); ev.send(); } else { //Movement from centerPos to clickPos vec2 target(clickPos.x, clickPos.z); //Find a path std::vector<vec2> pathNodes; //session->findPath(centerPos,target,pathNodes); if(pathNodes.empty()) pathNodes.push_back(target); //Now calculate the position of each unit relative to each other vector<vec2> relativePositions(unitIds.size()); vec2 direction = glm::normalize(target - centerPos); vec2 perpendicular(-direction.y, direction.x); //right hand rule float spread = 20.0f; int perRow = (int)(glm::sqrt((float)numSelected) + 0.99); direction *= spread; perpendicular *= spread; vector<bool> unitTaken(unitIds.size(),false); for(int i = 0; i < numSelected; ++i) { //This loops over the target spots in such a way that it first loops the points that are furthest away. //When the units are coming from the BOTTOM the order is like this: //1 2 3 //4 5 6 //7 8 9 vec2 targetSpot = target + float(perRow/2 - i/perRow)*direction + float(i%perRow - perRow/2)*perpendicular; //Select closest unit int bestIndex = -1; float bestDistance = 0; for(int j = 0; j < numSelected; ++j) { if(unitTaken[j]) continue; float dist = glm::distance(unitPositions[j],targetSpot); if(bestIndex == -1 || dist < bestDistance) { bestIndex = j; bestDistance = dist; } } relativePositions[bestIndex] = targetSpot - target; unitTaken[bestIndex] = true; } //Relative positions to center have been calculated. Now send the packet Event& ev = Game::shared().getEventManager()->createEvent(EVENT_MOVE_UNIT_REQUEST); ev << numSelected; for(int i = 0; i < numSelected; ++i) { ev << unitIds[i]; ev << (int)pathNodes.size(); for(unsigned int j = 0; j < pathNodes.size(); ++j) { ev << pathNodes[j] + relativePositions[i]; } } ev.send(); } }
void Server::handlePacket(ServerClientHandler* clienthandler, Packet& packet) { clientIterator iter = clientList.find(clienthandler); if(iter == clientList.end()) { LOG_WARNING("Received packet from unkown client!"); return; } ServerClient* client = iter->second; switch(packet.getId()){ case EVENT_JOIN_GAME: { client->setClientId(clientIdFactory++); Packet* pak = createPacket(EVENT_CLIENT_ID); *pak << client->getClientId(); clienthandler->sendPacket(pak); //Create faction client->createFaction(); client->createStartUnits(); int joinedCount = 0; for(clientIterator iter = clientList.begin(); iter != clientList.end(); ++iter) { if( iter->second->getClientId() != -1 ) ++joinedCount; } LOG_INFO("Clients joined: " << joinedCount); if(joinedCount >= 1) { pak = createPacket(EVENT_GAME_READY); //Send to all clients sendToAllClients(pak); pak = createPacket(EVENT_GAME_FULLSTATE); //------------------------------------ // Package structure: // + joinedCount // - clientID // - Serialized faction // + UnitCount // - Serialized unit //------------------------------------ *pak << joinedCount; //player count //for each player: for(clientIterator iter = clientList.begin(); iter != clientList.end(); ++iter) { if(iter->second->getClientId() == -1) continue; *pak << iter->second->getClientId(); Faction* faction = iter->second->getFaction(); faction->serialize(*pak); int unitCount = (int)faction->getUnits().size(); *pak << unitCount; for(std::list<Unit*>::iterator iter = faction->getUnits().begin(); iter != faction->getUnits().end(); ++iter) (*iter)->serialize(*pak); } sendToAllClients(pak); } break; } default: LOG_INFO("Unknown package received.."); break; } return; }