From 84530e97714a5d33bed60d08bce4ccfabcab7838 Mon Sep 17 00:00:00 2001 From: Allanis Date: Sun, 19 Nov 2017 14:42:30 +0000 Subject: [PATCH] [Add] Body death and associated cleanup. Space::KillBody() to kill a body. --- src/body.cpp | 6 +++ src/body.h | 9 ++++- src/player.cpp | 41 ++++++++++++++++----- src/player.h | 4 +- src/ship.cpp | 16 ++++++-- src/ship.h | 10 +++-- src/space.cpp | 19 ++++++++++ src/space.h | 3 ++ src/space_station.cpp | 2 +- src/static_rigid_body.cpp | 1 + src/world_view.cpp | 77 +++++++++++++++++++++------------------ 11 files changed, 133 insertions(+), 55 deletions(-) diff --git a/src/body.cpp b/src/body.cpp index d8d4eac..ded37d4 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -7,6 +7,12 @@ Body::Body(void) { m_flags = 0; m_projectedPos = vector3d(0.0f, 0.0f, 0.0f); m_onscreen = false; + m_dead = false; +} + +Body::~Body(void) { + /* Do not call delete body. Call Space::KillBody(body). */ + assert(m_dead); } /* f == NULL, then absolute position within system. */ diff --git a/src/body.h b/src/body.h index 126b5ca..aaefcaf 100644 --- a/src/body.h +++ b/src/body.h @@ -11,7 +11,7 @@ class ObjMesh; class Body: public Object { public: Body(void); - virtual ~Body(void) { }; + virtual ~Body(void); virtual Object::Type GetType(void) { return Object::BODY; } virtual void SetPosition(vector3d p) = 0; virtual vector3d GetPosition(void) = 0; /* Within frame. */ @@ -32,6 +32,11 @@ public: bool IsOnscreen() const { return m_onscreen; } void SetOnscreen(const bool onscreen) { m_onscreen = onscreen; } virtual void TimeStepUpdate(const float timeStep) {} + /* Override to clear any pointers you hold to the dying body. */ + virtual void NotifyDeath(const Body* const dyingBody) {} + /* Only Space::KillBody() should call this method. */ + void MarkDead(void) { m_dead = true; } + enum { FLAG_CAN_MOVE_FRAME = 1 }; protected: @@ -43,5 +48,7 @@ private: std::string m_label; bool m_onscreen; vector3d m_projectedPos; + /* Checked in destructor to make sure has been marked dead. */ + bool m_dead; }; diff --git a/src/player.cpp b/src/player.cpp index 7577e6a..dcc7763 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -16,6 +16,11 @@ Player::Player(ShipType::Type shipType) : Ship(shipType) { UpdateMass(); } +Player::~Player(void) { + assert(this == L3D::player); + L3D::player = 0; +} + void Player::Render(const Frame* camFrame) { if(L3D::GetCamType() == L3D::CAM_EXTERNAL) { Ship::Render(camFrame); @@ -134,6 +139,11 @@ void Player::PollControls(void) { if(L3D::KeyState(SDLK_MINUS)) m_external_view_dist += 10; m_external_view_dist = MAX(50, m_external_view_dist); } + + if(GetNavTarget() && L3D::KeyState(SDLK_END)) { + /* Temp test: Kill ("end") the target. */ + Space::KillBody(GetNavTarget()); + } } #define HUD_CROSSHAIR_SIZE 24.0f @@ -171,7 +181,7 @@ void Player::DrawHUD(const Frame* cam_frame) { } } - DrawTargetSquare(); + DrawTargetSquares(); GLdouble pos[3]; @@ -249,13 +259,28 @@ void Player::DrawHUD(const Frame* cam_frame) { Gui::Screen::LeaveOrtho(); } -void Player::DrawTargetSquare(void) { - if(GetTarget() && GetTarget()->IsOnscreen()) { - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); - glColor3f(0.0f, 1.0f, 0.0f); - glLineWidth(2.0f); +void Player::DrawTargetSquares(void) { + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); + glLineWidth(2.0f); - const vector3d& _pos = GetTarget()->GetProjectedPos(); + if(GetNavTarget()) { + glColor3f(0.0f, 1.0f, 0.0f); + DrawTargetSquare(GetNavTarget()); + } + + if(GetCombatTarget()) { + glColor3f(1.0f, 0.0f, 0.0f); + DrawTargetSquare(GetNavTarget()); + } + + glPopAttrib(); +} + +void Player::DrawTargetSquare(const Body* const target) { + if(target->IsOnscreen()) { + glColor3f(0.0f, 1.0f, 0.0f); + + const vector3d& _pos = target->GetProjectedPos(); const float x1 = _pos.x - WorldView::PICK_OBJECT_RECT_SIZE * 0.5f; const float x2 = x1 + WorldView::PICK_OBJECT_RECT_SIZE; const float y1 = _pos.y - WorldView::PICK_OBJECT_RECT_SIZE * 0.5f; @@ -268,8 +293,6 @@ void Player::DrawTargetSquare(void) { glVertex2f(x1, y2); glVertex2f(x1, y1); glEnd(); - - glPopAttrib(); } } diff --git a/src/player.h b/src/player.h index a45e161..3085618 100644 --- a/src/player.h +++ b/src/player.h @@ -5,6 +5,7 @@ class Player : public Ship { public: Player(ShipType::Type shipType); + virtual ~Player(void); void PollControls(void); virtual void Render(const Frame* camFrame); void DrawHUD(const Frame* cam_frame); @@ -12,7 +13,8 @@ public: vector3d GetExternalViewTranslation(void); void ApplyExternalViewRotation(void); private: - void DrawTargetSquare(); + void DrawTargetSquares(); + void DrawTargetSquare(const Body* const target); float m_mouseCMov[2]; float m_external_view_rotx, m_external_view_roty; float m_external_view_dist; diff --git a/src/ship.cpp b/src/ship.cpp index 23e9a14..2169ed6 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -23,10 +23,11 @@ static ObjParams params = { Ship::Ship(ShipType::Type shipType) : RigidBody() { m_wheelTransition = 0; - m_wheelState = 0; - m_dockedWith = 0; - m_target = 0; - m_shipType = shipType; + m_wheelState = 0; + m_dockedWith = 0; + m_navTarget = 0; + m_combatTarget = 0; + m_shipType = shipType; m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0; m_laserCollisionObj.owner = this; m_equipment = EquipSet(shipType); @@ -126,6 +127,13 @@ void Ship::TimeStepUpdate(const float timeStep) { } } +void Ship::NotifyDeath(const Body* const dyingBody) { + if(GetNavTarget() == dyingBody) + SetNavTarget(0); + if(GetCombatTarget() == dyingBody) + SetCombatTarget(0); +} + const ShipType& Ship::GetShipType(void) { return ShipType::types[m_shipType]; } diff --git a/src/ship.h b/src/ship.h index f9c92e7..14fc6ba 100644 --- a/src/ship.h +++ b/src/ship.h @@ -20,8 +20,10 @@ public: virtual Object::Type GetType(void) { return Object::SHIP; } virtual void SetDockedWith(SpaceStation*); SpaceStation* GetDockedWith(void) { return m_dockedWith; } - void SetTarget(Body* const target) { m_target = target; } - Body* GetTarget(void) const { return m_target; } + void SetNavTarget(Body* const target) { m_navTarget = target; } + Body* GetNavTarget(void) const { return m_navTarget; } + void SetCombatTarget(Body* const target) { m_combatTarget = target; } + Body* GetCombatTarget(void) const { return m_combatTarget; } virtual void Render(const Frame* camFrame); void SetThrusterState(enum ShipType::Thruster t, float level); void SetAngThrusterState(int axis, float level) { m_angThrusters[axis] = CLAMP(level, -1, 1); } @@ -32,6 +34,7 @@ public: void UpdateMass(void); void SetWheelState(bool down); virtual void TimeStepUpdate(const float timeStep); + virtual void NotifyDeath(const Body* const dyingBody); class LaserObj : public Object { public: @@ -55,6 +58,7 @@ private: dGeomID m_tempLaserGeom[ShipType::GUNMOUNT_MAX]; LaserObj m_laserCollisionObj; - Body* m_target; + Body* m_navTarget; + Body* m_combatTarget; }; diff --git a/src/space.cpp b/src/space.cpp index 488e196..72a0ffe 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -15,6 +15,7 @@ dWorldID Space::world; std::list Space::bodies; Frame* Space::rootFrame; static dJointGroupID _contactgroup; +std::list Space::corpses; void Space::Init(void) { world = dWorldCreate(); @@ -83,6 +84,11 @@ void Space::AddBody(Body* b) { bodies.push_back(b); } +void Space::KillBody(Body* const b) { + b->MarkDead(); + corpses.push_back(b); +} + void Space::UpdateFramesOfReference(void) { for(std::list::iterator i = bodies.begin(); i != bodies.end(); ++i) { Body* b = *i; @@ -212,6 +218,19 @@ void Space::TimeStep(float step) { for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) { (*i)->TimeStepUpdate(step); } + /* Prune dead bodies. */ + for(bodiesIter_t i = corpses.begin(); i != corpses.end(); i++) { + ProcessCorpse(*i); + } + corpses.clear(); +} + +void Space::ProcessCorpse(Body* const b) { + for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) { + (*i)->NotifyDeath(b); + } + bodies.remove(b); + delete b; } struct body_zsort_t { diff --git a/src/space.h b/src/space.h index 8195557..7de8dde 100644 --- a/src/space.h +++ b/src/space.h @@ -15,6 +15,7 @@ public: static void GenBody(StarSystem* s, StarSystem::SBody* b, Frame* f); static void TimeStep(float step); static void AddBody(Body*); + static void KillBody(Body*); static void Render(const Frame* cam_frame); static Frame* GetRootFrame(void) { return rootFrame; } @@ -24,8 +25,10 @@ public: private: static void UpdateFramesOfReference(void); static void CollideFrame(Frame* f); + static void ProcessCorpse(Body* const b); static Frame* rootFrame; //static std::list rootFrames; + static std::list corpses; }; diff --git a/src/space_station.cpp b/src/space_station.cpp index a6a1683..15eb553 100644 --- a/src/space_station.cpp +++ b/src/space_station.cpp @@ -30,7 +30,7 @@ SpaceStation::SpaceStation(void) : StaticRigidBody() { } SpaceStation::~SpaceStation(void) { - dGeomDestroy(m_geom); + } bool SpaceStation::OnCollision(Body* b) { diff --git a/src/static_rigid_body.cpp b/src/static_rigid_body.cpp index 33dcd78..d15010e 100644 --- a/src/static_rigid_body.cpp +++ b/src/static_rigid_body.cpp @@ -19,6 +19,7 @@ StaticRigidBody::~StaticRigidBody(void) { free(sbreCollMesh->pFlag); free(sbreCollMesh); } + GetFrame()->RemoveGeom(m_geom); dGeomDestroy(m_geom); } diff --git a/src/world_view.cpp b/src/world_view.cpp index c749955..e3df1e4 100644 --- a/src/world_view.cpp +++ b/src/world_view.cpp @@ -67,40 +67,40 @@ void WorldView::Draw3D(void) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - /* Make temporary camera frame at player. */ - Frame* cam_frame = new Frame(L3D::player->GetFrame(), "", Frame::TEMP_VIEWING); + if(L3D::player) { + /* Make temporary camera frame at player. */ + Frame cam_frame(L3D::player->GetFrame(), "", Frame::TEMP_VIEWING); - if(L3D::GetCamType() == L3D::CAM_FRONT) { - cam_frame->SetPosition(L3D::player->GetPosition()); - } else if(L3D::GetCamType() == L3D::CAM_REAR) { - glRotatef(180.0f, 0, 1, 0); - cam_frame->SetPosition(L3D::player->GetPosition()); - } else { /* CAM_EXTERNAL */ - cam_frame->SetPosition(L3D::player->GetPosition() + L3D::player->GetExternalViewTranslation()); - L3D::player->ApplyExternalViewRotation(); + if(L3D::GetCamType() == L3D::CAM_FRONT) { + cam_frame.SetPosition(L3D::player->GetPosition()); + } else if(L3D::GetCamType() == L3D::CAM_REAR) { + glRotatef(180.0f, 0, 1, 0); + cam_frame.SetPosition(L3D::player->GetPosition()); + } else { /* CAM_EXTERNAL */ + cam_frame.SetPosition(L3D::player->GetPosition() + L3D::player->GetExternalViewTranslation()); + L3D::player->ApplyExternalViewRotation(); + } + L3D::player->ViewingRotation(); + + glGetDoublev(GL_MODELVIEW_MATRIX, &viewingRotation[0]); + + glCallList(m_bgstarsDlist); + /* Position light at sol. */ + vector3d lpos = Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), &cam_frame); + float lightPos[4]; + lightPos[0] = lpos.x; + lightPos[1] = lpos.y; + lightPos[2] = lpos.z; + lightPos[3] = 0; + glLightfv(GL_LIGHT0, GL_POSITION, lightPos); + glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, lightCol); + glLightfv(GL_LIGHT0, GL_SPECULAR, lightCol); + + Space::Render(&cam_frame); + L3D::player->DrawHUD(&cam_frame); + + L3D::player->GetFrame()->RemoveChild(&cam_frame); } - - L3D::player->ViewingRotation(); - - glGetDoublev(GL_MODELVIEW_MATRIX, &viewingRotation[0]); - - glCallList(m_bgstarsDlist); - /* Position light at sol. */ - vector3d lpos = Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), cam_frame); - float lightPos[4]; - lightPos[0] = lpos.x; - lightPos[1] = lpos.y; - lightPos[2] = lpos.z; - lightPos[3] = 0; - glLightfv(GL_LIGHT0, GL_POSITION, lightPos); - glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, lightCol); - glLightfv(GL_LIGHT0, GL_SPECULAR, lightCol); - - Space::Render(cam_frame); - L3D::player->DrawHUD(cam_frame); - - L3D::player->GetFrame()->RemoveChild(cam_frame); - delete cam_frame; } void WorldView::Update(void) { @@ -110,18 +110,23 @@ void WorldView::Update(void) { m_hyperspaceButton->Hide(); } /* Player control inputs. */ - L3D::player->PollControls(); + if(L3D::player) + L3D::player->PollControls(); } void WorldView::OnMouseDown(Gui::MouseButtonEvent* e) { - if(1 == e->button) { - /* Left click in view => Select target. */ + if(1 == e->button && !L3D::MouseButtonState(3)) { + /* Left click in view when RMB not pressed => Select target. */ float screenPos[2]; GetPosition(screenPos); /* Put mouse coords into screen space. */ screenPos[0] += e->x; screenPos[1] += e->y; - L3D::player->SetTarget(PickBody(screenPos[0], screenPos[1])); + Body* const target = PickBody(screenPos[0], screenPos[1]); + if(L3D::player) { + /* TODO: If in nav mode, SetNavTarget(), else SetCombatTarget(). */ + L3D::player->SetNavTarget(target); + } } }