修复房间行走阻挡问题

This commit is contained in:
aozhiwei 2020-04-30 13:56:43 +08:00
parent 03099c0e7c
commit 2fe179077b
4 changed files with 117 additions and 56 deletions

View File

@ -27,6 +27,9 @@ void Building::Initialize()
void Building::RecalcSelfCollider()
{
std::vector<AabbCollider*> collider_list;
collider_list.reserve(meta->i->staticobj_size());
for (auto& obj : meta->i->staticobj()) {
AabbCollider* collider = new AabbCollider();
collider->owner = this;
@ -35,8 +38,11 @@ void Building::RecalcSelfCollider()
collider->_max = a8::Vec2(obj.x() + obj.width()/2.0 - meta->i->tilewidth()/2.0,
obj.y() + obj.height()/2.0 - meta->i->tileheight()/2.0);
AddCollider(collider);
collider_list.push_back(collider);
room->map_service.AddCollider(collider);
}
AutoAdjust(collider_list);
}
void Building::FillMFObjectPart(cs::MFObjectPart* part_data)
@ -66,3 +72,46 @@ void Building::GetAabbBox(AabbCollider& aabb_box)
aabb_box._max.x = meta->i->tilewidth()/2.0;
aabb_box._max.y = meta->i->tileheight()/2.0;
}
void Building::AutoAdjust(std::vector<AabbCollider*>& collider_list)
{
for (int dir = 0; dir < 4; ++dir) {
for (size_t i = 0; i < collider_list.size(); ++i) {
AabbCollider* a_collider = collider_list[i];
for (size_t ii = i + 1; ii < collider_list.size(); ++ii) {
AabbCollider* b_collider = collider_list[ii];
switch (dir) {
case 0:
{
if (std::fabs(a_collider->_min.x - b_collider->_min.x) < 2.0f) {
b_collider->_min.x = a_collider->_min.x;
}
}
break;
case 1:
{
if (std::fabs(a_collider->_min.y - b_collider->_min.y) < 2.0f) {
b_collider->_min.y = a_collider->_min.y;
}
}
break;
case 2:
{
if (std::fabs(a_collider->_max.x - b_collider->_max.x) < 2.0f) {
b_collider->_max.x = a_collider->_max.x;
}
}
break;
case 3:
{
if (std::fabs(a_collider->_max.y - b_collider->_max.y) < 2.0f) {
b_collider->_max.y = a_collider->_max.y;
}
}
break;
}
}
}
}
}

View File

@ -25,4 +25,7 @@ class Building : public Entity
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual void GetAabbBox(AabbCollider& aabb_box) override;
private:
void AutoAdjust(std::vector<AabbCollider*>& collider_list);
};

View File

@ -439,11 +439,22 @@ bool Human::IsCollisionInMapService()
std::set<ColliderComponent*> colliders;
room->map_service.GetColliders(GetX(), GetY(), colliders);
AabbCollider aabb_box;
GetAabbBox(aabb_box);
for (ColliderComponent* collider : colliders) {
switch (collider->owner->entity_type) {
case ET_Obstacle:
{
#if 1
if (!collider->owner->dead &&
(
(collider->type == CT_Aabb && aabb_box.Intersect((ColliderComponent*)collider)) ||
(collider->type == CT_Circle && self_collider_->Intersect((ColliderComponent*)collider))
)
) {
#else
if (!collider->owner->dead && TestCollision((ColliderComponent*)collider)) {
#endif
if (last_collision_door != collider->owner) {
Obstacle* obstacle = (Obstacle*)collider->owner;
if (!obstacle->dead &&
@ -476,7 +487,16 @@ bool Human::IsCollisionInMapService()
break;
case ET_Building:
{
#if 1
if (!collider->owner->dead &&
(
(collider->type == CT_Aabb && aabb_box.Intersect((ColliderComponent*)collider)) ||
(collider->type == CT_Circle && self_collider_->Intersect((ColliderComponent*)collider))
)
) {
#else
if (!collider->owner->dead && TestCollision((ColliderComponent*)collider)) {
#endif
if (last_collision_door != collider->owner) {
Global::last_collider = collider;
return true;
@ -572,61 +592,6 @@ void Human::FindPathInMapService()
}
}
SetPos(old_pos);
if (entity_subtype == EST_Player && last_collider && last_collider->type == CT_Aabb) {
#if 0
AabbCollider* aabb_collider = (AabbCollider*)last_collider;
#endif
if (GetPos().x > last_collider->owner->GetPos().x) {
//在右边
if (GetPos().y > last_collider->owner->GetPos().y) {
//右上
#ifdef DEBUG
a8::XPrintf("右上\n", {});
#endif
if (move_dir.Dot(a8::Vec2(1, -1)) > 0.000002f) {
SetPos(old_pos + a8::Vec2(2, 0));
} else {
SetPos(old_pos + a8::Vec2(0, 2));
}
} else {
//右下
#ifdef DEBUG
a8::XPrintf("右下\n", {});
#endif
if (move_dir.Dot(a8::Vec2(-1, 1)) > 0.000002f) {
SetPos(old_pos + a8::Vec2(2, 0));
} else {
SetPos(old_pos + a8::Vec2(0, -2));
}
}
} else {
//左边
if (GetPos().y > last_collider->owner->GetPos().y) {
//左上
#ifdef DEBUG
a8::XPrintf("左上\n", {});
#endif
if (move_dir.Dot(a8::Vec2(-1, -1)) > 0.000001f) {
SetPos(old_pos + a8::Vec2(-2, 0));
} else {
SetPos(old_pos + a8::Vec2(0, 2));
}
} else {
//左下
#ifdef DEBUG
a8::XPrintf("左下\n", {});
#endif
if (move_dir.Dot(a8::Vec2(1, -1)) > 0.000001f) {
SetPos(old_pos + a8::Vec2(-2, 0));
} else {
SetPos(old_pos + a8::Vec2(0, -2));
}
}
}
}
if (IsCollisionInMapService()) {
SetPos(old_pos);
}
}
float Human::GetRadius()
@ -2003,6 +1968,49 @@ void Human::CheckSkinTank()
void Human::_UpdateMove(int speed)
{
#if 1
float nx = move_dir.x * speed;
float ny = move_dir.y * speed;
a8::Vec2 old_pos = GetPos();
#if 1
SetPos(old_pos + a8::Vec2(nx, ny));
if (!IsCollisionInMapService()) {
room->grid_service.MoveHuman(this);
return;
} else {
if (Global::last_collider && Global::last_collider->type == CT_Circle) {
SetPos(old_pos + a8::Vec2(nx, ny));
if (self_collider_->Intersect(Global::last_collider)) {
CircleCollider* circle_collider = (CircleCollider*)Global::last_collider;
a8::Vec2 tmp_dir = GetPos() - (circle_collider->owner->GetPos() + circle_collider->pos);
float len = circle_collider->rad + self_collider_->rad + 1;
float rate = len - tmp_dir.Norm();
tmp_dir.Normalize();
a8::Vec2 new_dir = tmp_dir * rate;
SetPos(GetPos() + new_dir);
}
if (!IsCollisionInMapService()) {
room->grid_service.MoveHuman(this);
return;
}
}
}
#endif
SetPos(old_pos + a8::Vec2(nx, 0));
if (IsCollisionInMapService()) {
nx = 0;
}
SetPos(old_pos + a8::Vec2(nx, ny));
if (IsCollisionInMapService()) {
ny = 0;
}
SetPos(old_pos + a8::Vec2(nx, ny));
room->grid_service.MoveHuman(this);
#else
for (int i = 0; i < speed; ++i) {
a8::Vec2 old_pos = GetPos();
SetPos(GetPos() + move_dir);
@ -2017,6 +2025,7 @@ void Human::_UpdateMove(int speed)
}
room->grid_service.MoveHuman(this);
}
#endif
}
void Human::ClearFrameData()

@ -1 +1 @@
Subproject commit a369c484113b240f042c62cba80afd26df91e4ca
Subproject commit 62cad93ca276670dc7280425df58916bacbe20e5