[Add] Body death and associated cleanup. Space::KillBody() to kill a

body.
This commit is contained in:
Allanis 2017-11-19 14:42:30 +00:00
parent 4595e1f643
commit 84530e9771
11 changed files with 133 additions and 55 deletions

View File

@ -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. */

View File

@ -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;
};

View File

@ -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()) {
void Player::DrawTargetSquares(void) {
glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT);
glColor3f(0.0f, 1.0f, 0.0f);
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();
}
}

View File

@ -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;

View File

@ -25,7 +25,8 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() {
m_wheelTransition = 0;
m_wheelState = 0;
m_dockedWith = 0;
m_target = 0;
m_navTarget = 0;
m_combatTarget = 0;
m_shipType = shipType;
m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0;
m_laserCollisionObj.owner = this;
@ -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];
}

View File

@ -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;
};

View File

@ -15,6 +15,7 @@ dWorldID Space::world;
std::list<Body*> Space::bodies;
Frame* Space::rootFrame;
static dJointGroupID _contactgroup;
std::list<Body*> 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<Body*>::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 {

View File

@ -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<Frame*> rootFrames;
static std::list<Body*> corpses;
};

View File

@ -30,7 +30,7 @@ SpaceStation::SpaceStation(void) : StaticRigidBody() {
}
SpaceStation::~SpaceStation(void) {
dGeomDestroy(m_geom);
}
bool SpaceStation::OnCollision(Body* b) {

View File

@ -19,6 +19,7 @@ StaticRigidBody::~StaticRigidBody(void) {
free(sbreCollMesh->pFlag);
free(sbreCollMesh);
}
GetFrame()->RemoveGeom(m_geom);
dGeomDestroy(m_geom);
}

View File

@ -67,26 +67,26 @@ void WorldView::Draw3D(void) {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(L3D::player) {
/* Make temporary camera frame at player. */
Frame* cam_frame = new Frame(L3D::player->GetFrame(), "", Frame::TEMP_VIEWING);
Frame cam_frame(L3D::player->GetFrame(), "", Frame::TEMP_VIEWING);
if(L3D::GetCamType() == L3D::CAM_FRONT) {
cam_frame->SetPosition(L3D::player->GetPosition());
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());
cam_frame.SetPosition(L3D::player->GetPosition());
} else { /* CAM_EXTERNAL */
cam_frame->SetPosition(L3D::player->GetPosition() + L3D::player->GetExternalViewTranslation());
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);
vector3d lpos = Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), &cam_frame);
float lightPos[4];
lightPos[0] = lpos.x;
lightPos[1] = lpos.y;
@ -96,11 +96,11 @@ void WorldView::Draw3D(void) {
glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, lightCol);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightCol);
Space::Render(cam_frame);
L3D::player->DrawHUD(cam_frame);
Space::Render(&cam_frame);
L3D::player->DrawHUD(&cam_frame);
L3D::player->GetFrame()->RemoveChild(cam_frame);
delete cam_frame;
L3D::player->GetFrame()->RemoveChild(&cam_frame);
}
}
void WorldView::Update(void) {
@ -110,18 +110,23 @@ void WorldView::Update(void) {
m_hyperspaceButton->Hide();
}
/* Player control inputs. */
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);
}
}
}