Skip to content

Commit e6dd466

Browse files
committed
quick and dirty projectile hit detection
1 parent a4d757d commit e6dd466

10 files changed

Lines changed: 153 additions & 66 deletions

src/GameCheatsWindow.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,6 @@ void GameCheatsWindow::DoUI(ImGuiIO& imguiContext)
9393
ImGui::Text("state: %s", cxx::enum_to_string(pedestrian->GetCurrentStateID()));
9494
ImGui::HorzSpacing();
9595

96-
// get block location
97-
glm::ivec3 blockPosition = Convert::MetersToMapUnits(pedPosition);
98-
99-
BlockStyle* currBlock = gGameMap.GetBlockClamp(blockPosition.x, blockPosition.z, blockPosition.y);
100-
101-
ImGui::Text("b ground: %s", cxx::enum_to_string(currBlock->mGroundType));
102-
ImGui::Text("b slope: %d", currBlock->mSlopeType);
103-
ImGui::Text("b directions: %d, %d, %d, %d", currBlock->mUpDirection, currBlock->mRightDirection,
104-
currBlock->mDownDirection, currBlock->mLeftDirection);
105-
106-
ImGui::HorzSpacing();
10796
ImGui::SliderInt("ped remap", &pedestrian->mRemapIndex, -1, MAX_PED_REMAPS - 1);
10897

10998
if (pedestrian->IsCarPassenger())

src/GameDefs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ enum eProjectileType
800800
{
801801
eProjectileType_Bullet, // pistol, machinegun
802802
eProjectileType_Flame, // flamethrower
803-
eProjectileType_Rocket, // rocket launcher, tank rocket
803+
eProjectileType_Missile, // rocket launcher, tank rocket
804804
eProjectileType_COUNT
805805
};
806806
decl_enum_strings(eProjectileType);

src/GameObjectDefs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ decl_enum_as_flags(eGameObjectFlags);
4242
// game object type indices
4343
enum
4444
{
45-
//GameObjectIndex_
46-
47-
45+
GameObjectType_Null = 0,
46+
// todo...
4847
GameObjectType_MAX = 102
4948
};

src/PhysicsComponents.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,7 @@ ProjectilePhysicsBody::ProjectilePhysicsBody(b2World* physicsWorld, Projectile*
705705

706706
b2FixtureDef fixtureDef;
707707
fixtureDef.shape = &shapeDef;
708-
fixtureDef.isSensor = true;
709-
fixtureDef.filter.categoryBits = PHYSICS_OBJCAT_PROJECTILE_SENSOR;
708+
fixtureDef.filter.categoryBits = PHYSICS_OBJCAT_PROJECTILE;
710709
fixtureDef.filter.maskBits = PHYSICS_OBJCAT_PED | PHYSICS_OBJCAT_CAR | PHYSICS_OBJCAT_OBSTACLE | PHYSICS_OBJCAT_MAP_SOLID_BLOCK;
711710

712711
b2Fixture* b2fixture = mPhysicsBody->CreateFixture(&fixtureDef);
@@ -719,6 +718,9 @@ ProjectilePhysicsBody::~ProjectilePhysicsBody()
719718

720719
void ProjectilePhysicsBody::SimulationStep()
721720
{
721+
if (mReferenceProjectile->IsContactDetected() || mReferenceProjectile->IsMarkedForDeletion())
722+
return;
723+
722724
// setup physics
723725
glm::vec2 velocity = GetSignVector();
724726
SetLinearVelocity(velocity * mReferenceProjectile->mProjectileStyle->mSpeed);
@@ -728,12 +730,14 @@ void ProjectilePhysicsBody::SimulationStep()
728730

729731
if (glm::distance(startPosition, currPosition) >= mReferenceProjectile->mProjectileStyle->mBaseDistance)
730732
{
731-
mReferenceProjectile->mDead = true;
732733
mReferenceProjectile->MarkForDeletion();
733734
}
734735
}
735736

736737
bool ProjectilePhysicsBody::ShouldContactWith(unsigned int objCatBits) const
737738
{
738-
return true; // todo
739+
if (mReferenceProjectile->IsContactDetected() || mReferenceProjectile->IsMarkedForDeletion())
740+
return false;
741+
742+
return true;
739743
}

src/PhysicsDefs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ enum
1212
PHYSICS_OBJCAT_PED = BIT(2),
1313
PHYSICS_OBJCAT_CAR = BIT(3),
1414
PHYSICS_OBJCAT_OBSTACLE = BIT(4),
15-
15+
PHYSICS_OBJCAT_PROJECTILE = BIT(5),
1616
// sensors
17-
PHYSICS_OBJCAT_PED_SENSOR = BIT(5),
18-
PHYSICS_OBJCAT_PROJECTILE_SENSOR = BIT(6),
17+
PHYSICS_OBJCAT_PED_SENSOR = BIT(6),
1918
};
2019

2120
const int MaxPhysicsQueryElements = 32;

src/PhysicsManager.cpp

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,45 @@ void PhysicsManager::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
339339
b2Fixture* fixtureMapSolidBlock = FilterFixture(fixtureA, fixtureB, PHYSICS_OBJCAT_MAP_SOLID_BLOCK);
340340
b2Fixture* fixturePed = FilterFixture(fixtureA, fixtureB, PHYSICS_OBJCAT_PED);
341341
b2Fixture* fixtureCar = FilterFixture(fixtureA, fixtureB, PHYSICS_OBJCAT_CAR);
342+
b2Fixture* fixtureProjectile = FilterFixture(fixtureA, fixtureB, PHYSICS_OBJCAT_PROJECTILE);
342343

343-
if (fixturePed)
344+
if (fixtureProjectile)
345+
{
346+
hasCollision = false; // projectiles doesnt collide
347+
348+
ProjectilePhysicsBody* projectileObject = CastBodyData<ProjectilePhysicsBody>(fixtureProjectile->GetBody());
349+
350+
// projectile vs map solid block
351+
if (fixtureMapSolidBlock)
352+
{
353+
b2FixtureData_map fxdata = fixtureMapSolidBlock->GetUserData();
354+
if (projectileObject->ShouldContactWith(PHYSICS_OBJCAT_MAP_SOLID_BLOCK))
355+
{
356+
ProcessProjectileVsMap(contact, projectileObject, fxdata.mX, fxdata.mZ);
357+
}
358+
}
359+
// projectile vs car
360+
else if (fixtureCar)
361+
{
362+
CarPhysicsBody* carPhysicsObject = CastBodyData<CarPhysicsBody>(fixtureCar->GetBody());
363+
if (projectileObject->ShouldContactWith(PHYSICS_OBJCAT_CAR))
364+
{
365+
ProcessProjectileVsCar(contact, projectileObject, carPhysicsObject);
366+
}
367+
}
368+
// projectile vs ped
369+
else if (fixturePed)
370+
{
371+
PedPhysicsBody* pedPhysicsObject = CastBodyData<PedPhysicsBody>(fixturePed->GetBody());
372+
if (projectileObject->ShouldContactWith(PHYSICS_OBJCAT_PED))
373+
{
374+
ProcessProjectileVsPed(contact, projectileObject, pedPhysicsObject);
375+
}
376+
}
377+
}
378+
else if (fixturePed)
344379
{
345380
PedPhysicsBody* pedPhysicsObject = CastBodyData<PedPhysicsBody>(fixturePed->GetBody());
346-
debug_assert(pedPhysicsObject);
347381

348382
// ped vs map solid block
349383
if (fixtureMapSolidBlock)
@@ -570,7 +604,6 @@ bool PhysicsManager::ProcessSensorContact(b2Contact* contact, bool onBegin)
570604

571605
b2Fixture* pedFixture = FilterFixture(contact->GetFixtureA(), contact->GetFixtureB(), PHYSICS_OBJCAT_PED | PHYSICS_OBJCAT_PED_SENSOR);
572606
b2Fixture* carFixture = FilterFixture(contact->GetFixtureA(), contact->GetFixtureB(), PHYSICS_OBJCAT_CAR);
573-
b2Fixture* projectileFixture = FilterFixture(contact->GetFixtureA(), contact->GetFixtureB(), PHYSICS_OBJCAT_PROJECTILE_SENSOR);
574607
b2Fixture* mapSolidBlockFixture = FilterFixture(contact->GetFixtureA(), contact->GetFixtureB(), PHYSICS_OBJCAT_MAP_SOLID_BLOCK);
575608
if (pedFixture && carFixture)
576609
{
@@ -586,31 +619,6 @@ bool PhysicsManager::ProcessSensorContact(b2Contact* contact, bool onBegin)
586619
}
587620
return true;
588621
}
589-
590-
if (projectileFixture)
591-
{
592-
ProjectilePhysicsBody* projectileObject = CastBodyData<ProjectilePhysicsBody>(projectileFixture->GetBody());
593-
if (projectileObject->mReferenceProjectile->mDead)
594-
return false;
595-
596-
if (pedFixture)
597-
{
598-
PedPhysicsBody* pedObject = CastBodyData<PedPhysicsBody>(pedFixture->GetBody());
599-
return ProcessSensorProjectileVsPed(contact, projectileObject, pedObject);
600-
}
601-
602-
if (carFixture)
603-
{
604-
CarPhysicsBody* carObject = CastBodyData<CarPhysicsBody>(carFixture->GetBody());
605-
return ProcessSensorProjectileVsCar(contact, projectileObject, carObject);
606-
}
607-
608-
if (mapSolidBlockFixture)
609-
{
610-
b2FixtureData_map fxdata = mapSolidBlockFixture->GetUserData();
611-
return ProcessSensorProjectileVsMap(contact, projectileObject, fxdata.mX, fxdata.mZ);
612-
}
613-
}
614622
return false;
615623
}
616624

@@ -714,29 +722,82 @@ void PhysicsManager::HandleContactPedVsCar(b2Contact* contact, float impulse, Pe
714722
ped->mReferencePed->ReceiveHitByCar(car->mReferenceCar, impulse);
715723
}
716724

717-
bool PhysicsManager::ProcessSensorProjectileVsMap(b2Contact* contact, ProjectilePhysicsBody* projectile, int mapx, int mapy) const
725+
bool PhysicsManager::ProcessProjectileVsMap(b2Contact* contact, ProjectilePhysicsBody* projectile, int mapx, int mapy) const
718726
{
719727
// check same height
728+
int layer = (int) (Convert::MetersToMapUnits(projectile->mHeight) + 0.5f);
729+
730+
BlockStyle* mapBlock = gGameMap.GetBlockClamp(mapx, mapy, layer);
731+
if (mapBlock->mGroundType != eGroundType_Building)
732+
return false;
733+
734+
// get collision point
735+
b2WorldManifold wmanifold;
736+
contact->GetWorldManifold(&wmanifold);
720737

738+
int pointsCount = contact->GetManifold()->pointCount;
739+
if (pointsCount > 0)
740+
{
741+
glm::vec3 contactPoint(
742+
wmanifold.points[0].x, projectile->mHeight,
743+
wmanifold.points[0].y );
721744

745+
projectile->mReferenceProjectile->SetContactDetected(contactPoint, nullptr);
746+
return true;
747+
}
722748
return false;
723749
}
724750

725-
bool PhysicsManager::ProcessSensorProjectileVsCar(b2Contact* contact, ProjectilePhysicsBody* projectile, CarPhysicsBody* car) const
751+
bool PhysicsManager::ProcessProjectileVsCar(b2Contact* contact, ProjectilePhysicsBody* projectile, CarPhysicsBody* car) const
726752
{
753+
// check car bounds height
754+
// todo: get car height!
755+
bool hasContact = ((projectile->mHeight >= car->mHeight) &&
756+
(projectile->mHeight <= (car->mHeight + 2.0f)));
727757

758+
if (!hasContact)
759+
return false;
728760

729-
// check same height
761+
// get collision point
762+
b2WorldManifold wmanifold;
763+
contact->GetWorldManifold(&wmanifold);
730764

765+
int pointsCount = contact->GetManifold()->pointCount;
766+
if (pointsCount > 0)
767+
{
768+
glm::vec3 contactPoint(
769+
wmanifold.points[0].x, projectile->mHeight,
770+
wmanifold.points[0].y );
771+
772+
projectile->mReferenceProjectile->SetContactDetected(contactPoint, car->mReferenceCar);
773+
return true;
774+
}
731775
return false;
732776
}
733777

734-
bool PhysicsManager::ProcessSensorProjectileVsPed(b2Contact* contact, ProjectilePhysicsBody* projectile, PedPhysicsBody* ped) const
778+
bool PhysicsManager::ProcessProjectileVsPed(b2Contact* contact, ProjectilePhysicsBody* projectile, PedPhysicsBody* ped) const
735779
{
736-
if (!ped->ShouldContactWith(PHYSICS_OBJCAT_PROJECTILE_SENSOR))
780+
// check ped bounds height
781+
// todo: get car height!
782+
bool hasContact = ((projectile->mHeight >= ped->mHeight) &&
783+
(projectile->mHeight <= (ped->mHeight + 2.0f)));
784+
785+
if (!hasContact)
737786
return false;
738787

739-
// check same height
788+
// get collision point
789+
b2WorldManifold wmanifold;
790+
contact->GetWorldManifold(&wmanifold);
791+
792+
int pointsCount = contact->GetManifold()->pointCount;
793+
if (pointsCount > 0)
794+
{
795+
glm::vec3 contactPoint(
796+
wmanifold.points[0].x, projectile->mHeight,
797+
wmanifold.points[0].y );
740798

799+
projectile->mReferenceProjectile->SetContactDetected(contactPoint, ped->mReferencePed);
800+
return true;
801+
}
741802
return false;
742803
}

src/PhysicsManager.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,15 @@ class PhysicsManager final: private b2ContactListener
7272
bool HasCollisionCarVsMap(b2Contact* contact, b2Fixture* fixtureCar, int mapx, int mapy) const;
7373
bool HasCollisionPedVsCar(b2Contact* contact, PedPhysicsBody* ped, CarPhysicsBody* car) const;
7474

75+
bool ProcessProjectileVsMap(b2Contact* contact, ProjectilePhysicsBody* projectile, int mapx, int mapy) const;
76+
bool ProcessProjectileVsCar(b2Contact* contact, ProjectilePhysicsBody* projectile, CarPhysicsBody* car) const;
77+
bool ProcessProjectileVsPed(b2Contact* contact, ProjectilePhysicsBody* projectile, PedPhysicsBody* ped) const;
78+
7579
// post solve collisions
7680
void HandleContactPedVsCar(b2Contact* contact, float impulse, PedPhysicsBody* ped, CarPhysicsBody* car);
7781

7882
// sensors
7983
bool ProcessSensorContact(b2Contact* contact, bool onBegin);
80-
bool ProcessSensorProjectileVsMap(b2Contact* contact, ProjectilePhysicsBody* projectile, int mapx, int mapy) const;
81-
bool ProcessSensorProjectileVsCar(b2Contact* contact, ProjectilePhysicsBody* projectile, CarPhysicsBody* car) const;
82-
bool ProcessSensorProjectileVsPed(b2Contact* contact, ProjectilePhysicsBody* projectile, PedPhysicsBody* ped) const;
8384

8485
private:
8586
b2Body* mMapCollisionShape;

src/Projectile.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
#include "GameMapManager.h"
66
#include "TimeManager.h"
77
#include "DebugRenderer.h"
8+
#include "GameObjectsManager.h"
89

910
Projectile::Projectile(ProjectileStyle* style)
1011
: GameObject(eGameObjectClass_Projectile, GAMEOBJECT_ID_NULL)
1112
, mProjectileStyle(style)
12-
, mDrawHeight()
1313
, mStartPosition()
1414
{
1515
debug_assert(style);
@@ -28,7 +28,7 @@ void Projectile::Spawn(const glm::vec3& startPosition, cxx::angle_t startRotatio
2828
debug_assert(mProjectileStyle);
2929

3030
mStartPosition = startPosition;
31-
mDead = false;
31+
mContactDetected = false;
3232
if (mPhysicsBody == nullptr)
3333
{
3434
mPhysicsBody = gPhysics.CreatePhysicsBody(this, startPosition, startRotation);
@@ -56,6 +56,13 @@ void Projectile::UpdateFrame()
5656
{
5757
float deltaTime = gTimeManager.mGameFrameDelta;
5858
mAnimationState.AdvanceAnimation(deltaTime);
59+
60+
if (IsContactDetected())
61+
{
62+
MarkForDeletion();
63+
64+
Explosion* explosion = gGameObjectsManager.CreateExplosion(mContactPoint);
65+
}
5966
}
6067

6168
void Projectile::PreDrawFrame()
@@ -67,7 +74,6 @@ void Projectile::PreDrawFrame()
6774
ComputeDrawHeight(position);
6875

6976
mDrawSprite.mPosition = glm::vec2(position.x, position.z);
70-
mDrawSprite.mHeight = mDrawHeight;
7177
mDrawSprite.SetOriginToCenter();
7278
}
7379

@@ -92,5 +98,26 @@ void Projectile::ComputeDrawHeight(const glm::vec3& position)
9298
}
9399
}
94100

95-
mDrawHeight = maxHeight + 0.1f; // todo: magic numbers
101+
mDrawSprite.mHeight = maxHeight + 0.1f; // todo: magic numbers
102+
}
103+
104+
void Projectile::SetContactDetected(const glm::vec3& position, GameObject* gameObject)
105+
{
106+
mContactDetected = true;
107+
mContactObject = gameObject;
108+
mContactPoint = position;
109+
110+
if (gameObject == nullptr)
111+
{
112+
mContactPoint.y += Convert::MapUnitsToMeters(1.0f); // todo: magic numbers
113+
}
114+
else
115+
{
116+
mContactPoint.y += 0.1f; // todo: magic numbers
117+
}
118+
}
119+
120+
bool Projectile::IsContactDetected() const
121+
{
122+
return mContactDetected;
96123
}

src/Projectile.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ class Projectile final: public GameObject
1414
// readonly
1515
ProjectileStyle* mProjectileStyle = nullptr;
1616
ProjectilePhysicsBody* mPhysicsBody = nullptr;
17-
float mDrawHeight;
1817

19-
bool mDead; // whether projectile should be removed from map
2018
glm::vec3 mStartPosition;
2119

2220
public:
@@ -31,9 +29,18 @@ class Projectile final: public GameObject
3129
// Setup initial state when spawned or respawned on level
3230
void Spawn(const glm::vec3& startPosition, cxx::angle_t startRotation);
3331

32+
// @param gameObject: null if contacting with map
33+
void SetContactDetected(const glm::vec3& position, GameObject* gameObject);
34+
bool IsContactDetected() const;
35+
3436
private:
3537
void ComputeDrawHeight(const glm::vec3& position);
3638

3739
private:
3840
SpriteAnimation mAnimationState;
41+
42+
// collision contact info
43+
glm::vec3 mContactPoint;
44+
GameObject* mContactObject = nullptr;
45+
bool mContactDetected = false;
3946
};

src/enums_impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl_enum_strings(eProjectileType)
551551
{
552552
{eProjectileType_Bullet, "bullet"},
553553
{eProjectileType_Flame, "flame"},
554-
{eProjectileType_Rocket, "missile"},
554+
{eProjectileType_Missile, "missile"},
555555
};
556556

557557
impl_enum_strings(eWeaponFireType)

0 commit comments

Comments
 (0)