This commit is contained in:
aozhiwei 2021-07-01 17:55:30 +08:00
parent 2a688b5906
commit d7e1777e1e
7 changed files with 117 additions and 15 deletions

View File

@ -103,6 +103,7 @@ void Bullet::ProcBomb()
switch (entity->GetEntityType()) { switch (entity->GetEntityType()) {
case ET_Obstacle: case ET_Obstacle:
case ET_Building: case ET_Building:
case ET_Dummy:
{ {
if (TestCollision(room, entity)) { if (TestCollision(room, entity)) {
objects.insert(entity); objects.insert(entity);

View File

@ -1625,17 +1625,24 @@ void Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos)
} }
bool Creature::CollisonDetection() bool Creature::CollisonDetection()
{
ColliderComponent* pickup_collider = nullptr;
return CollisonDetectionAndGetCollider(&pickup_collider);
}
bool Creature::CollisonDetectionAndGetCollider(ColliderComponent** pickup_collider)
{ {
bool through_wall = HasBuffEffect(kBET_ThroughWall) || bool through_wall = HasBuffEffect(kBET_ThroughWall) ||
HasBuffEffect(kBET_Fly); HasBuffEffect(kBET_Fly);
AabbCollider aabb_box; AabbCollider aabb_box;
GetAabbBox(aabb_box); GetAabbBox(aabb_box);
return room->map_service->CollisionDetection return room->map_service->CollisionDetectionAndGetCollider
( (
room, room,
through_wall, through_wall,
GetPos(), GetPos(),
&aabb_box &aabb_box,
pickup_collider
); );
} }
@ -1949,18 +1956,25 @@ void Creature::SetInfiniteBulletMode()
inventory_[IS_RPG].num = FIGHTING_MODE_BULLET_NUM; inventory_[IS_RPG].num = FIGHTING_MODE_BULLET_NUM;
} }
void Creature::FindLocationWithTarget(Entity* target) void Creature::FindLocationWithTarget(Entity* target, ColliderComponent* target_collider)
{ {
a8::Vec2 old_pos = GetPos(); a8::Vec2 old_pos = GetPos();
a8::Vec2 new_pos = GetPos(); a8::Vec2 new_pos = GetPos();
AabbCollider a_collider; AabbCollider a_collider;
GetAabbBox(a_collider); GetAabbBox(a_collider);
AabbCollider target_collider;
target->GetAabbBox(target_collider);
{ {
bool ret = a_collider.CalcSafePoint(&target_collider, new_pos); if (target_collider) {
if (!ret) { bool ret = a_collider.CalcSafePoint(target_collider, new_pos);
abort(); if (!ret) {
abort();
}
} else {
AabbCollider aabb_collider;
target->GetAabbBox(aabb_collider);
bool ret = a_collider.CalcSafePoint(&aabb_collider, new_pos);
if (!ret) {
abort();
}
} }
} }
a8::Vec2 new_pos_dir = new_pos - old_pos; a8::Vec2 new_pos_dir = new_pos - old_pos;
@ -2014,16 +2028,20 @@ void Creature::FindLocationWithTarget(Entity* target)
void Creature::FindLocation() void Creature::FindLocation()
{ {
Entity* target = nullptr; Entity* target = nullptr;
ColliderComponent* target_collider = nullptr;
TraverseAllLayerEntityList TraverseAllLayerEntityList
( (
[this, &target] (Entity* entity, bool& stop) [this, &target, &target_collider] (Entity* entity, bool& stop)
{ {
ColliderComponent* collider = nullptr;
switch (entity->GetEntityType()) { switch (entity->GetEntityType()) {
case ET_Obstacle: case ET_Obstacle:
{ {
if (!target) { if (!target) {
if (TestCollision(room, entity)) { collider = TestCollisionAndGetCollider(room, entity);
if (collider) {
target = entity; target = entity;
target_collider = collider;
} }
} }
} }
@ -2033,15 +2051,23 @@ void Creature::FindLocation()
if (!target || !target->IsEntityType(ET_Building)) { if (!target || !target->IsEntityType(ET_Building)) {
AabbCollider aabb_box; AabbCollider aabb_box;
entity->GetAabbBox(aabb_box); entity->GetAabbBox(aabb_box);
if (TestCollision(room, &aabb_box)) { collider = TestCollisionAndGetCollider(room, &aabb_box);
if (collider) {
target = entity; target = entity;
target_collider = nullptr;
} }
} }
} }
break; break;
case ET_Dummy: case ET_Dummy:
{ {
if (!target) {
collider = TestCollisionAndGetCollider(room, entity);
if (collider) {
target = entity;
target_collider = collider;
}
}
} }
break; break;
default: default:
@ -2051,7 +2077,7 @@ void Creature::FindLocation()
} }
}); });
if (target) { if (target) {
FindLocationWithTarget(target); FindLocationWithTarget(target, target_collider);
} }
} }
@ -2128,6 +2154,17 @@ bool Creature::CheckCollision()
} }
} }
break; break;
case ET_Dummy:
{
if (
(collider->type == CT_Aabb && aabb_box.Intersect(collider)) ||
(collider->type == CT_Circle && self_collider_->Intersect(collider))
) {
Global::last_collider = collider;
return true;
}
}
break;
default: default:
{ {
} }

View File

@ -170,6 +170,7 @@ class Creature : public MoveableEntity
void CheckSpecObject(); void CheckSpecObject();
bool CollisonDetection(); bool CollisonDetection();
bool CollisonDetectionAndGetCollider(ColliderComponent** pickup_collider);
void SummonObstacle(Buff* buff, int id, const a8::Vec2& pos); void SummonObstacle(Buff* buff, int id, const a8::Vec2& pos);
void SummonHero(Buff* buff, const a8::Vec2& pos, const a8::Vec2& dir); void SummonHero(Buff* buff, const a8::Vec2& pos, const a8::Vec2& dir);
void FillSkillCasterState(SkillCasterState* caster_state); void FillSkillCasterState(SkillCasterState* caster_state);
@ -192,7 +193,7 @@ class Creature : public MoveableEntity
bool TryMove(const a8::Vec2& target_pos, a8::Vec2& out_pos); bool TryMove(const a8::Vec2& target_pos, a8::Vec2& out_pos);
void SetInfiniteBulletMode(); void SetInfiniteBulletMode();
void FindLocation(); void FindLocation();
void FindLocationWithTarget(Entity* target); void FindLocationWithTarget(Entity* target, ColliderComponent* target_collider);
Entity* GetLastCollisionDoor() { return last_collision_door_; } Entity* GetLastCollisionDoor() { return last_collision_door_; }
void SetLastCollisionDoor(Entity* door) { last_collision_door_ = door; } void SetLastCollisionDoor(Entity* door) { last_collision_door_ = door; }
bool CheckCollision(); bool CheckCollision();

View File

@ -53,7 +53,25 @@ bool Entity::TestCollision(Room* room, Entity* b)
return false; return false;
} }
bool Entity::TestCollision(Room* room,ColliderComponent* b) ColliderComponent* Entity::TestCollisionAndGetCollider(Room* room, Entity* b)
{
PerfMonitor::Instance()->test_times++;
if (b->IsDead(room)) {
return nullptr;
}
OnPreCollision(room);
b->OnPreCollision(room);
for (auto& a_collider : colliders_) {
for (auto& b_collider : b->colliders_) {
if (a_collider->Intersect(b_collider)) {
return b_collider;
}
}
}
return nullptr;
}
bool Entity::TestCollision(Room* room, ColliderComponent* b)
{ {
if (b->owner->IsDead(room)) { if (b->owner->IsDead(room)) {
return false; return false;
@ -68,6 +86,21 @@ bool Entity::TestCollision(Room* room,ColliderComponent* b)
return false; return false;
} }
ColliderComponent* Entity::TestCollisionAndGetCollider(Room* room, ColliderComponent* b)
{
if (b->owner->IsDead(room)) {
return nullptr;
}
OnPreCollision(room);
b->owner->OnPreCollision(room);
for (auto& a_collider : colliders_) {
if (a_collider->Intersect(b)) {
return a_collider;
}
}
return nullptr;
}
bool Entity::TestCollisionEx(Room* room, const a8::Vec2& aabb_pos, AabbCollider& aabb_box) bool Entity::TestCollisionEx(Room* room, const a8::Vec2& aabb_pos, AabbCollider& aabb_box)
{ {
OnPreCollision(room); OnPreCollision(room);

View File

@ -48,7 +48,9 @@ class Entity
{ return subtype == entity_subtype_;} { return subtype == entity_subtype_;}
int GetGridId() const { return grid_id_; } int GetGridId() const { return grid_id_; }
bool TestCollision(Room* room, Entity* b); bool TestCollision(Room* room, Entity* b);
ColliderComponent* TestCollisionAndGetCollider(Room* room, Entity* b);
bool TestCollision(Room* room, ColliderComponent* b); bool TestCollision(Room* room, ColliderComponent* b);
ColliderComponent* TestCollisionAndGetCollider(Room* room, ColliderComponent* b);
bool TestCollisionEx(Room* room, const a8::Vec2& aabb_pos, AabbCollider& aabb_box); bool TestCollisionEx(Room* room, const a8::Vec2& aabb_pos, AabbCollider& aabb_box);
void BroadcastFullState(Room* room); void BroadcastFullState(Room* room);
void BroadcastDeleteState(Room* room); void BroadcastDeleteState(Room* room);

View File

@ -72,6 +72,7 @@ void MapService::UnInit()
void MapService::AddCollider(ColliderComponent* collider) void MapService::AddCollider(ColliderComponent* collider)
{ {
if (!(collider->owner->IsEntityType(ET_Obstacle) || if (!(collider->owner->IsEntityType(ET_Obstacle) ||
collider->owner->IsEntityType(ET_Dummy) ||
collider->owner->IsEntityType(ET_Building))) { collider->owner->IsEntityType(ET_Building))) {
abort(); abort();
} }
@ -221,6 +222,7 @@ void MapService::GetColliders(Room* room,
} }
break; break;
case ET_Building: case ET_Building:
case ET_Dummy:
{ {
colliders.insert(node->collider); colliders.insert(node->collider);
} }
@ -292,6 +294,24 @@ bool MapService::CollisionDetection(Room* room,
const a8::Vec2& pos, const a8::Vec2& pos,
ColliderComponent* a_collider) ColliderComponent* a_collider)
{ {
ColliderComponent* pickup_collider = nullptr;
return CollisionDetectionAndGetCollider
(
room,
through_wall,
pos,
a_collider,
&pickup_collider
);
}
bool MapService::CollisionDetectionAndGetCollider(Room* room,
bool through_wall,
const a8::Vec2& pos,
ColliderComponent* a_collider,
ColliderComponent** pickup_collider)
{
*pickup_collider = nullptr;
if (room->OverBorder(pos, a_collider)){ if (room->OverBorder(pos, a_collider)){
return true; return true;
} }
@ -309,14 +329,17 @@ bool MapService::CollisionDetection(Room* room,
Obstacle* obstacle = (Obstacle*)collider->owner; Obstacle* obstacle = (Obstacle*)collider->owner;
if (obstacle->meta->i->collision_hit() != kCollisionHitPass) { if (obstacle->meta->i->collision_hit() != kCollisionHitPass) {
if (!obstacle->IsDead(room) && collider->IntersectEx(pos, a_collider)) { if (!obstacle->IsDead(room) && collider->IntersectEx(pos, a_collider)) {
*pickup_collider = collider;
return true; return true;
} }
} }
} }
break; break;
case ET_Building: case ET_Building:
case ET_Dummy:
{ {
if (collider->IntersectEx(pos, a_collider)) { if (collider->IntersectEx(pos, a_collider)) {
*pickup_collider = collider;
return true; return true;
} }
} }

View File

@ -58,6 +58,11 @@ class MapService
bool through_wall, bool through_wall,
const a8::Vec2& pos, const a8::Vec2& pos,
ColliderComponent* collider); ColliderComponent* collider);
bool CollisionDetectionAndGetCollider(Room* room,
bool through_wall,
const a8::Vec2& pos,
ColliderComponent* collider,
ColliderComponent** pickup_collider);
private: private:
int GetGridId(float world_x, float world_y); int GetGridId(float world_x, float world_y);