void GameEngine::render() const { // HAUKAP - game engine shouldn't be rendering. // CGfxOpenGL::render() should take a list of renderables and render them Status stat = m_background->render(); assert(StatusSucceeded(stat)); GameObjects objects = m_levelObjects->getObjectsInPortal(); CHUint sz = (CHUint)objects.size(); for( CHUint i=0; i<sz; ++i ) { stat = objects[i]->render(); assert(StatusSucceeded(stat)); } stat = m_mainCharacter->render(); assert(StatusSucceeded(stat)); sz = (CHUint)g_projectiles.size(); for( CHUint i=0; i<sz; ++i ) { stat = g_projectiles[i]->render(); assert(StatusSucceeded(stat)); } }
GameObjectsView find_with_tag(const String &tag){ GameObjectsView result; std::copy_if(game_objects.begin(), game_objects.end(), std::back_inserter(result), [&](auto &item){ return item->tag == tag; }); return result; }
void EventManager::fire(Event* event) { GameObjects receivers = event->getReceivers(); GameObjects::iterator i = receivers.begin(); for(; i < receivers.end(); i++) { (*i)->receiveEvent(event); } delete event; }
void GameEngine::initializePostMenu() { OggPlayer* bgMusic = OggController::getOggPlayer(g_bgMusicHandle); bgMusic->play(); m_levelObjects->startLevel(); GameObjects objects = m_levelObjects->getAllObjects(); CHUint sz = (CHUint)objects.size(); for( CHUint i=0; i<sz; ++i ) m_objectScroller->addObject( objects[i] ); }
GameObjects LevelObjects::getObjectsInPortal() { GameObjects objects; CHUint sz = (CHUint)m_data->objects.size(); for( CHUint i=0; i<sz; ++i ) { if( isObjectWithinPortal( *(m_data->objects[i])) ) objects.push_back(m_data->objects[i]); } return objects; }
void GSVe3ViewOtherPlayers::NextPlayer() { Player* localPlayer = GetLocalPlayer(); GameObjects* gos = TheObjectManager::Instance()->GetGameObjects(); int id = -1; if (m_player) { id = m_player->GetId(); } // Remember first player, go to if we reach the end Player* first = 0; bool found = false; for (auto it = gos->begin(); it != gos->end(); ++it) { GameObject* go = it->second; Player* p = dynamic_cast<Player*>(go); if (p == localPlayer) { continue; } if (p && !first) { first = p; } if (p && p->GetId() > id) { m_player = p; found = true; break; } } if (!found) { m_player = first; // wrap around if poss } if (m_player) { ShowPlayer(m_player, m_gui); } }
GameObjects gameObjectsAllFromFile(const filesys::path& file) { GameObjects obj; //Read in source IFileStream stream(file.c_str(), std::ios::in); if (!stream.is_open()) { LOG_ERROR(General, "Cant open file for reading (%s).", file.c_str()); return obj; } String line; while(std::getline(stream, line)){ std::transform(line.begin(), line.end(), line.begin(), ::tolower); if(line.compare("start obj") == 0){ obj.push_back(gameObjectFromStream(stream)); } } stream.close(); return obj; }
float obj_ParticleSystem::DrawPropertyEditor(float scrx, float scry, float scrw, float scrh, const AClass* startClass, const GameObjects& selected) { float starty = scry; starty += parent::DrawPropertyEditor(scrx, scry, scrw, scrh, startClass, selected ); if( IsParentOrEqual( &ClassData, startClass ) ) { int temp = m_isSerializable?1:0; starty += imgui_Checkbox(scrx, starty, "Serializable", &temp, 1); bool btemp = temp?true:false; PropagateChange( btemp, &obj_ParticleSystem::m_isSerializable, this, selected ) ; temp = DoFreese ? 1 : 0; static float freeseTimeOffset = 0; starty += imgui_Value_Slider(scrx, starty, "Pause time", &freeseTimeOffset, 0.0f, Torch->PD->EmitTime, "%.2f"); starty += imgui_Checkbox(scrx, starty, "Pause", &temp, 1); if (!!temp != DoFreese) { float freeseTime = r3dGetTime() + freeseTimeOffset; bool doFreese = !!temp; if (doFreese) { Restart(); // Advance to particle pause position while (UpdateTime < freeseTime) { Update(); } } DoFreese = doFreese; } if( selected.Count() <= 1 ) { void ParticleEditorSetDefaultParticle ( const char * ); ParticleEditorSetDefaultParticle ( Name.c_str() ); if ( imgui_Button ( scrx,starty, 180.0f, 25.0f, "Edit Particle" ) ) { void ParticleEditorSetDefaultParticle ( const char * ); void SetHud ( int ); ParticleEditorSetDefaultParticle ( Name.c_str() ); SetHud ( 3 ); } } starty += 25.0f; } return starty-scry; }
void DeleteDeadObjects() { static Game* game = TheGame::Instance(); GameObjects* objs = game->GetGameObjects(); // map for (auto it = objs->begin(); it != objs->end(); ) { PGameObject obj = it->second; ++it; WWGameObject* ww = dynamic_cast<WWGameObject*>(obj.GetPtr()); if (ww && ww->IsDead()) { #ifdef DEBUG_DELETE_DEAD std::cout << "Deleting object " << Describe(ww) << "\n"; #endif ww->RemoveFromGame(); } } }
void GameEngine::objectCleanup() { if(m_mainCharacter->isMarkedForRemoval()) { if(m_mainCharacter->canRespawn()) { m_mainCharacter->respawn(); m_mainCharacter->decrementLife(); } else { m_levelObjects->restartLevel(); m_objectScroller->clear(); GameObjects objects = m_levelObjects->getAllObjects(); CHUint sz = (CHUint)objects.size(); for( CHUint i=0; i<sz; ++i ) m_objectScroller->addObject( objects[i] ); m_mainCharacter->gainLives(3); m_mainCharacter->respawn(); } } for( std::vector<Projectile*>::iterator iter = g_projectiles.begin(); iter != g_projectiles.end(); ++ iter ) { if((*iter)->isMarkedForRemoval()) { g_projectiles.erase(iter); if( g_projectiles.empty() ) break; else iter = g_projectiles.begin(); } } }
float obj_Building::DrawPropertyEditor(float scrx, float scry, float scrw, float scrh, const AClass* startClass, const GameObjects& selected) { float starty = scry; starty += parent::DrawPropertyEditor(scrx, scry, scrw,scrh, startClass, selected ); if( IsParentOrEqual( &ClassData, startClass ) ) { starty += imgui_Static(scrx, starty, "Building properties"); std::string sDir = FileName.c_str(); int iPos1 = sDir.find_last_of('\\'); int iPos2 = sDir.find_last_of('/'); if ( ( iPos1 < iPos2 && iPos2 != std::string::npos ) || ( iPos1 == std::string::npos ) ) iPos1 = iPos2; if ( iPos1 != std::string::npos ) sDir.erase(iPos1 + 1,sDir.length() - iPos1 - 1 ); std::string sDirFind = sDir + "*.sco"; if(m_Animation.pSkeleton && MeshLOD[0]->IsSkeletal() ) { int useAnim = m_bAnimated; starty += imgui_Checkbox(scrx, starty, "Animated", &m_bAnimated, 1); if(useAnim != m_bAnimated) { PropagateChange( &obj_Building::ChangeAnim, selected ) ; } if(m_bAnimated) { int check = m_bGlobalAnimFolder ; starty += imgui_Checkbox(scrx, starty, "Global Anim Folder", &check, 1); PropagateChange( 1, &obj_Building::m_bAnimated, selected ) ; PropagateChange( check, &obj_Building::m_bGlobalAnimFolder, this, selected ) ; static char sAnimSelected[256] = {0}; static float fAnimListOffset = 0; std::string sDirFind ; if( m_bGlobalAnimFolder ) { // try global animation folder sDirFind = GLOBAL_ANIM_FOLDER "\\*.anm" ; } else { sDirFind = sDir + "Animations\\*.anm"; } r3dscpy(sAnimSelected, m_sAnimName); if ( imgui_FileList (scrx, starty, 360, 200, sDirFind.c_str (), sAnimSelected, &fAnimListOffset, true ) ) { r3dscpy(m_sAnimName, sAnimSelected); PropagateChange( &obj_Building::ChangeAnim, selected ) ; } starty += 200; } } if( m_HitPoints > 0 ) { if ( imgui_Button ( scrx, starty, 360, 20, "Destroy" ) ) { PropagateChange( &obj_Building::DestroyBuilding, selected ) ; } } else { if ( imgui_Button ( scrx, starty, 360, 20, "Ressurect" ) ) { PropagateChange( &obj_Building::FixBuilding, selected ) ; } } starty += 22.f ; if( selected.Count() <= 1 ) { if ( imgui_Button ( scrx, starty, 360, 20, m_pDamageLibEntry ? "To Destruction Params" : "Create Destruction Params" ) ) { LevelEditor.ToDamageLib( GetMeshLibKey().c_str() ); } } starty += 22.0f; } return starty - scry ; }
float obj_ItemSpawnPoint::DrawPropertyEditor(float scrx, float scry, float scrw, float scrh, const AClass* startClass, const GameObjects& selected) { float starty = scry; starty += parent::DrawPropertyEditor(scrx, scry, scrw,scrh, startClass, selected ); if( IsParentOrEqual( &ClassData, startClass ) ) { starty += imgui_Static ( scrx, starty, "Item Spawn Point Parameters" ); starty += imgui_Value_Slider(scrx, starty, "Tick Period (sec)", &m_TickPeriod, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "Cooldown (sec)", &m_Cooldown, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "De-spawn (sec)", &m_DestroyItemTimer, 0.0f, 50000.0f, "%.2f"); int isOneItemSpawn = m_OneItemSpawn?1:0; starty += imgui_Checkbox(scrx, starty, "One Item Spawn", &isOneItemSpawn, 1); m_OneItemSpawn = isOneItemSpawn?true:false; if(!m_OneItemSpawn) { static stringlist_t lootBoxNames; static int* lootBoxIDs = NULL; static int numLootBoxes = 0; if(numLootBoxes == 0) { struct tempS { char* name; uint32_t id; }; std::vector<tempS> lootBoxes; { tempS holder; holder.name = "EMPTY"; holder.id = 0; lootBoxes.push_back(holder); } g_pWeaponArmory->startItemSearch(); while(g_pWeaponArmory->searchNextItem()) { uint32_t itemID = g_pWeaponArmory->getCurrentSearchItemID(); const BaseItemConfig* cfg = g_pWeaponArmory->getConfig(itemID); if( cfg->category == storecat_LootBox ) { tempS holder; holder.name = cfg->m_StoreName; holder.id = cfg->m_itemID; lootBoxes.push_back(holder); } } numLootBoxes = (int)lootBoxes.size(); lootBoxIDs = new int[numLootBoxes]; for(int i=0; i<numLootBoxes; ++i) { lootBoxNames.push_back(lootBoxes[i].name); lootBoxIDs[i] = lootBoxes[i].id; } } int sel = 0; static float offset = 0; for(int i=0; i<numLootBoxes; ++i) if(m_LootBoxID == lootBoxIDs[i]) sel = i; starty += imgui_Static ( scrx, starty, "Loot box:" ); if(imgui_DrawList(scrx, starty, 360, 122, lootBoxNames, &offset, &sel)) { m_LootBoxID = lootBoxIDs[sel]; PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } starty += 122; } else { starty += imgui_Value_SliderI(scrx, starty, "ItemID", (int*)&m_LootBoxID, 0, 1000000, "%d", false); PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } // don't allow multi edit of this if( selected.Count() <= 1 ) { { if(imgui_Button(scrx, starty, 200, 25, "Check locations")) { for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ++it) { PxVec3 from(it->pos.x, it->pos.y+1.0f, it->pos.z); PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC)); if(g_pPhysicsWorld->raycastSingle(from, PxVec3(0,-1,0), 10000, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter)) { r3dPoint3D hitPos(hit.impact.x, hit.impact.y, hit.impact.z); if(R3D_ABS(it->pos.y - hitPos.y) > 2.0f) { gCam = it->pos + r3dPoint3D(0,1,0); break; } } } } starty += 30; } if(imgui_Button(scrx+110, starty, 100, 25, "Add Location")) { ItemSpawn itemSpawn; itemSpawn.pos = GetPosition() + r3dPoint3D(2, 0, 2); m_SpawnPointsV.push_back(itemSpawn); m_SelectedSpawnPoint = m_SpawnPointsV.size()-1; } starty += 25; int i=0; for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ) { // selection button char tempStr[32]; sprintf(tempStr, "Location %d", i+1); if(imgui_Button(scrx, starty, 100, 25, tempStr, i==m_SelectedSpawnPoint)) { // shift click on location will set camera to it if(Keyboard->IsPressed(kbsLeftShift)) { extern BaseHUD* HudArray[6]; extern int CurHUDID; HudArray[CurHUDID]->FPS_Position = m_SpawnPointsV[i].pos; HudArray[CurHUDID]->FPS_Position.y += 0.1f; } m_SelectedSpawnPoint = i; } // delete button if(m_SpawnPointsV.size() > 1) { if(imgui_Button(scrx + 110, starty, 100, 25, "DEL")) { it = m_SpawnPointsV.erase(it); continue; } m_SelectedSpawnPoint = R3D_CLAMP(m_SelectedSpawnPoint, 0, (int)m_SpawnPointsV.size()-1); } starty += 25; ++it; ++i; } extern r3dPoint3D UI_TargetPos; if((Mouse->IsPressed(r3dMouse::mLeftButton)) && Keyboard->IsPressed(kbsLeftControl)) m_SpawnPointsV[m_SelectedSpawnPoint].pos = UI_TargetPos; } } return starty-scry; }
void GameEngine::resolveCollisions() { std::vector<AICharacter*> enemies; std::vector<ForegroundObject*> terrain; GameObjects objects = m_levelObjects->getObjectsInPortal(); CHUint sz = (CHUint)objects.size(); for(CHUint i=0; i<sz; ++i) { if(objects[i]->collidableType() == Collidable::CollidableTerrain) terrain.push_back(dynamic_cast<ForegroundObject*>(objects[i])); else if(objects[i]->collidableType() == Collidable::CollidableCharacter) enemies.push_back(dynamic_cast<AICharacter*>(objects[i])); } CHUint numTerrain = (CHUint)terrain.size(); for(CHUint i=0; i<numTerrain; ++i) { if(m_mainCharacter->collidedWith( *(terrain[i]) ) ) { m_mainCharacter->resolveCollision( *(terrain[i]) ); terrain[i]->resolveCollision( *m_mainCharacter ); } CHUint numEnemies = (CHUint)enemies.size(); for(CHUint j=0; j<numEnemies; ++j) { if(terrain[i]->collidedWith( *(enemies[j]) )) { terrain[i]->resolveCollision( *(enemies[j]) ); enemies[j]->resolveCollision( *(terrain[i]) ); } } CHUint numProjectiles = (CHUint)g_projectiles.size(); for(CHUint j=0; j<numProjectiles; ++j) { if(g_projectiles[j]->collidedWith( *m_mainCharacter )) { g_projectiles[j]->resolveCollision( *m_mainCharacter ); m_mainCharacter->resolveCollision( *(g_projectiles[j]) ); } } } CHUint numEnemies = (CHUint)enemies.size(); for(CHUint i=0; i<numEnemies; ++i ) { if(m_mainCharacter->collidedWith( *(enemies[i]) ) ) { m_mainCharacter->resolveCollision( *(enemies[i]) ); enemies[i]->resolveCollision( *m_mainCharacter ); } CHUint numProjectiles = (CHUint)g_projectiles.size(); for(CHUint j=0; j<numProjectiles; ++j) { if(g_projectiles[j]->collidedWith( *(enemies[i]) )) { g_projectiles[j]->resolveCollision( *(enemies[i]) ); enemies[i]->resolveCollision( *(g_projectiles[j]) ); } } } }
void GameEngine::process() { m_levelObjects->process(); processCamera(); Status stat = m_mainCharacter->process(); assert(StatusSucceeded(stat)); GameObjects objects = m_levelObjects->getObjectsInPortal(); CHUint sz = (CHUint)objects.size(); for( CHUint i=0; i<sz; ++i ) { if(objects[i]->isEnemy()) { ScribbleEnemy* enemy = dynamic_cast<ScribbleEnemy*>( objects[i] ); if(enemy->isBoss()) { g_boss = dynamic_cast<Level1Boss*>( enemy ); } } stat = objects[i]->process(); assert(StatusSucceeded(stat)); } if(!bossMusicPlaying && g_boss != NULL) { OggController::getOggPlayer(g_bgMusicHandle)->stop(); OggController::getOggPlayer(g_bossMusicHandle)->play(); bossMusicPlaying = true; } sz = (CHUint)g_projectiles.size(); for( CHUint i=0; i<sz; ++i ) { stat = g_projectiles[i]->process(); assert(StatusSucceeded(stat)); } resolveCollisions(); objectCleanup(); m_objectScroller->process(); // ensure Hero stays on screen Vector3 mainPos(m_mainCharacter->position()); if(mainPos.x < m_boundaryLeft) { mainPos.x = m_boundaryLeft; m_mainCharacter->setPosition(mainPos); } else if( mainPos.x > m_boundaryRight ) { mainPos.x = m_boundaryRight; m_mainCharacter->setPosition(mainPos); } if(mainPos.y < -12.0f) { m_mainCharacter->setVelocity( Vector3(0.0f, 0.0f, 0.0f) ); m_mainCharacter->setPosition( mainPos.x, -12.0f, 0.0f); } }
void GSMain::Update() { static Lurker* lurker = TheLurker::Instance(); static Game* game = TheGame::Instance(); SceneGraph* scenegraph = GetGameSceneGraph(); lurker->Update(); // Disable pause button if Lurk msg showing // Freeze if displaying tutorial text if (lurker->IsDisplayingMsg()) { m_pauseButton->SetVisible(false); scenegraph->Update(); // DO still update the scene graph? // TODO Also still update Bird? GameObjects* objs = game->GetGameObjects(); for (auto it = objs->begin(); it != objs->end(); ++it) { GameObject* obj = it->second; if (dynamic_cast<Bird*>(obj)) { obj->Update(); } } } else if (m_exitState == IS_EXITING) { m_pauseButton->SetVisible(false); scenegraph->Update(); // DO still update the scene graph? // TODO Also still update Bird? GameObjects* objs = game->GetGameObjects(); for (auto it = objs->begin(); it != objs->end(); ++it) { GameObject* obj = it->second; if (dynamic_cast<Player*>(obj)) { obj->Update(); } Pet* pet = dynamic_cast<Pet*>(obj); if (pet && pet->IsTeleporting()) { pet->Update(); } if (dynamic_cast<Exit*>(obj)) { obj->Update(); } } } else { if (m_exitState == FINISHED_EXITING) { m_exitTimer += TheTimer::Instance()->GetDt(); static const float EXIT_DELAY_2 = ROConfig()->GetFloat("exit-delay-2"); if (m_exitTimer > EXIT_DELAY_2) { game->SetCurrentState(TheGSLevelComplete::Instance()); } } else { m_pauseButton->SetVisible(true); Player* player = Player::GetPlayer(AMJU_P1); float y = -(player->GetPos().y); DepthUpdate(y); TheProcGen::Instance()->AddLayerWhenReady(player->GetPos().x); ThePowerUpManager::Instance()->Update(); game->UpdateGameObjects(); DeleteDeadObjects(); TheCollisionManager::Instance()->Update(); scenegraph->Update(); TheShadowManager::Instance()->Update(); } } }
void register_object(GameObject *game_object){ game_objects.emplace_back(game_object); }
GameObject* PickObject(const Vec2f& mouseScreen) { // Get object carried by player - don't pick Ve1Object* carried = 0; Player* player = GetLocalPlayer(); if (player) { carried = player->GetCarrying(); } Vec3f mouseWorldNear; Vec3f mouseWorldFar; Unproject(mouseScreen, 0, &mouseWorldNear); Unproject(mouseScreen, 1, &mouseWorldFar); LineSeg lineSeg(mouseWorldNear, mouseWorldFar); GameObject* selectedObj = 0; GameObjects* objs = TheGame::Instance()->GetGameObjects(); float bestDist = 9e20f; for (GameObjects::iterator it = objs->begin(); it != objs->end(); ++it) { GameObject* pgo = it->second; Assert(pgo); Ve1Object* v = dynamic_cast<Ve1Object*>(pgo); Assert(v); if (!v->IsPickable()) { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " is not pickable.\n"; #endif continue; } if (v == carried) { // Can't select it then! std::cout << "Skipping carried object " << *v << "\n"; continue; } const AABB& aabb = pgo->GetAABB(); if (Clip(lineSeg, aabb, 0)) { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " IS PICKED!\n"; #endif // Line seg intersects this box // Choose object whose centre (position) is closest to line seg..? // float dist = LineSeg(mouseWorldNear, mouseWorldFar).SqDist(pgo->GetPos()); float dist = (mouseWorldNear - pgo->GetPos()).SqLen(); // pick closest // Treat skybox as least attractive option, followed by terrain if (dynamic_cast<Skybox*>(v)) { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " skybox so treated as far away\n"; #endif dist = 9e19f; } else if (dynamic_cast<Terrain*>(v)) { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " terrain so treated as far away\n"; #endif dist = 9e18f; } #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " sqDist: " << dist << "\n"; #endif if (dist < bestDist) { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " AND IS CLOSEST!\n"; #endif bestDist = dist; selectedObj = pgo; } } else { #ifdef PICK_DEBUG std::cout << " Obj " << pgo->GetId() << " is not picked.\n"; #endif } } return selectedObj; }
int main (int argc, char * const argv[]) { GameObjectManager* objectManager = GameObjectManager::getInstance(); NodeManager *nodeManager = NodeManager::getInstance(); { Node *node; for (int y = 0; y <= 14; y++) { for (int x = 0; x <= 19; x++) { node = new Node(x * 32, y * 32); nodeManager->addNode(node); } } } Hill* hill1 = new Hill(StrainYellow, nodeManager->getEmptyRandomNode()); Hill* hill2 = new Hill(StrainRed, nodeManager->getEmptyRandomNode()); Hill* hill3 = new Hill(StrainBlue, nodeManager->getEmptyRandomNode()); objectManager->add(hill1); objectManager->add(hill2); objectManager->add(hill3); Ants ants; Strain antStrains[4] = { StrainYellow, StrainRed, StrainBlue, StrainRed }; for (int i = 0; i < 4; i++) { Ant* ant = new Ant(antStrains[i], nodeManager->getEmptyRandomNode()); objectManager->add(ant); ants.push_back(ant); } for (int i = 0; i < 10; i++) { Spice *spice = new Spice(nodeManager->getEmptyRandomNode()); objectManager->addSpice(spice); } sf::RenderWindow App(sf::VideoMode(640, 480), "Ants"); App.SetFramerateLimit(60); while (App.IsOpened()) { sf::Event Event; while (App.GetEvent(Event)) { if (Event.Type == sf::Event::Closed) App.Close(); if (Event.Type == sf::Event::MouseButtonPressed) { const sf::Input& Input = App.GetInput(); cout << "Mouse cursor position: " << Input.GetMouseX() << "/" << Input.GetMouseY() << endl; sf::Vector2f mouse(Input.GetMouseX(), Input.GetMouseY()); bool shiftDown = Input.IsKeyDown(sf::Key::LShift) || Input.IsKeyDown(sf::Key::RShift); // cycle all gameobjects // if position matches mouse input -> select // if nothing matches -> deselect all GameObjects allObjects = objectManager->getObjects(); GameObjects::iterator i = allObjects.begin(); for (; i < allObjects.end(); i++) { GameObject* object = *i; sf::Vector2f left_upper = object->getSprite()->GetPosition(); sf::Vector2f right_lower = left_upper; // TODO: clean up with new vector2f class left_upper.x -= 16; left_upper.y -= 16; right_lower.x += PIXELS_PER_NODE/2; right_lower.y += PIXELS_PER_NODE/2; if (left_upper.x <= mouse.x && right_lower.x >= mouse.x && left_upper.y <= mouse.y && right_lower.y >= mouse.y) { object->setSelectionStatus(true); } else if (!shiftDown) { object->setSelectionStatus(false); } } } } App.Clear(); // trigger updates objectManager->trigger(); //display nodes Nodes nodes = nodeManager->getNodes(); Nodes::iterator n = nodes.begin(); for (; n < nodes.end(); n++) { App.Draw(*(*n)->getSprite()); } // update ants Ants::iterator a = ants.begin(); for(; a < ants.end(); a++) { (*a)->handleCurrentAction(App.GetFrameTime()); } // display game objects GameObjects objects = objectManager->getObjects(); GameObjects::iterator i = objects.begin(); for (; i < objects.end(); i++) { GameObject* object = *i; if (object->hasSprite()) { App.Draw(*object->getSprite()); if (object->isSelected()) { // draw rect sf::Vector2f position = object->getSprite()->GetPosition(); sf::Vector2f new_position = position; // TODO: clean up with new vector2f class position.x -= 16; position.y -= 16; new_position.x += PIXELS_PER_NODE/2; new_position.y += PIXELS_PER_NODE/2; sf::Shape rect = sf::Shape::Rectangle(position, new_position, object->getSelectionColor(), true, object->getSelectionColor()); rect.EnableFill(false); App.Draw(rect); } } } App.Display(); } return EXIT_SUCCESS; }