void Player::Update() { if (m_isLoggedIn) { Ve1ObjectChar::Update(); } else if (m_sceneNode) { Matrix m; m.Translate(m_pos); m_sceneNode->SetLocalTransform(m); // Set shadow AABB to same as Scene Node so we don't cull it by mistake m_shadow->SetAABB(*(m_sceneNode->GetAABB())); static const float XSIZE = ROConfig()->GetFloat("player-aabb-x", 30.0f); static const float YSIZE = ROConfig()->GetFloat("player-aabb-y", 100.0f); GetAABB()->Set( m_pos.x - XSIZE, m_pos.x + XSIZE, m_pos.y, m_pos.y + YSIZE, m_pos.z - XSIZE, m_pos.z + XSIZE); /* DISABLED for 2D look and feel TurnToFaceDir(); */ } if (m_hidden) { return; } // Stop moving if we are close enough to the destination // TODO This ends up happening every frame, only do it if we are moving if (true) //m_isMoving) { Vec3f dir = GetPos() - m_newPos; dir.y = 0; // ignore y coord for now static const float STOP_DISTANCE = ROConfig()->GetFloat("stop-dist", 20.0f); if (dir.SqLen() < STOP_DISTANCE) { SetVel(Vec3f(0, 0, 0)); m_newPos = GetPos(); SetArrowVis(false); m_isMoving = false; } } else { //Assert(GetVel().SqLen() == 0); } if (m_sceneNode) { // Set shadow AABB to same as Scene Node so we don't cull it by mistake m_nameTag->SetAABB(*(m_sceneNode->GetAABB())); } if (m_ignorePortalId != -1) { GameObject* g = TheGame::Instance()->GetGameObject(m_ignorePortalId); if (g) { const AABB& aabb = g->GetAABB(); if (!GetAABB()->Intersects(aabb)) { // No longer intersecting portal m_ignorePortalId = -1; } } else { m_ignorePortalId = -1; // ? } } if (IsLocalPlayer()) { TheGSMain::Instance()->SetHeartNum(m_stamina); if (m_stamina <= 0) { // Player now has to go back to the spaceship to regenerate or something. if (!m_isDead) { LurkMsg lm("You need to return to your spaceship to recover from your injuries!", Colour(1, 1, 1, 1), Colour(1, 0, 0, 1), AMJU_CENTRE); TheLurker::Instance()->Queue(lm); } m_isDead = true; } } }
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; }