diff --git a/server/gameserver/building.cc b/server/gameserver/building.cc index c80e1de..d426db2 100644 --- a/server/gameserver/building.cc +++ b/server/gameserver/building.cc @@ -27,6 +27,9 @@ void Building::Initialize() void Building::RecalcSelfCollider() { + std::vector 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& 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; + } + } + } + } +} diff --git a/server/gameserver/building.h b/server/gameserver/building.h index 42a8e68..bddd1e1 100644 --- a/server/gameserver/building.h +++ b/server/gameserver/building.h @@ -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& collider_list); }; diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 577895f..05d693f 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -439,11 +439,22 @@ bool Human::IsCollisionInMapService() std::set 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() diff --git a/third_party/a8engine b/third_party/a8engine index a369c48..62cad93 160000 --- a/third_party/a8engine +++ b/third_party/a8engine @@ -1 +1 @@ -Subproject commit a369c484113b240f042c62cba80afd26df91e4ca +Subproject commit 62cad93ca276670dc7280425df58916bacbe20e5