修复碰撞问题

This commit is contained in:
aozhiwei 2019-06-24 17:19:09 +08:00
parent 11eee3ae95
commit 4e793b075a
16 changed files with 157 additions and 209 deletions

View File

@ -56,22 +56,6 @@ void Building::FillMFObjectFull(cs::MFObjectFull* full_data)
p->set_building_id(meta->i->mapid()); p->set_building_id(meta->i->mapid());
} }
ColliderComponent* Building::GetBoxBound()
{
AabbCollider* collider = new AabbCollider();
collider->active = true;
collider->owner = this;
collider->_min = Vector2D(
-meta->i->tilewidth()/2.0,
-meta->i->tileheight()/2.0
);
collider->_max = Vector2D(
meta->i->tilewidth()/2.0,
meta->i->tileheight()/2.0
);
return collider;
}
void Building::GetAabbBox(AabbCollider& aabb_box) void Building::GetAabbBox(AabbCollider& aabb_box)
{ {
aabb_box.active = true; aabb_box.active = true;

View File

@ -24,6 +24,5 @@ class Building : public Entity
void RecalcSelfCollider(); void RecalcSelfCollider();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override; virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override; virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
virtual void GetAabbBox(AabbCollider& aabb_box) override; virtual void GetAabbBox(AabbCollider& aabb_box) override;
}; };

View File

@ -256,15 +256,6 @@ void Bullet::MapServiceUpdate()
for (ColliderComponent* collider : colliders) { for (ColliderComponent* collider : colliders) {
if (TestCollision(collider)) { if (TestCollision(collider)) {
objects.insert(collider->owner); objects.insert(collider->owner);
#if 0
a8::XPrintf("%d,%d collider:%d,%d \n",
{
pos.x,
pos.y,
collider->owner->pos.x,
collider->owner->pos.y
});
#endif
} }
} }
} }

View File

@ -107,7 +107,7 @@ bool ColliderComponent::CalcSafePoint(ColliderComponent* b, Vector2D& new_pos)
switch (b->type) { switch (b->type) {
case CT_Aabb: case CT_Aabb:
{ {
AabbCollider* b_aabb = (AabbCollider*)this; AabbCollider* b_aabb = (AabbCollider*)b;
return CalcAabbAabbSafePoint(a_aabb->owner->pos + a_aabb->_min, return CalcAabbAabbSafePoint(a_aabb->owner->pos + a_aabb->_min,
a_aabb->owner->pos + a_aabb->_max, a_aabb->owner->pos + a_aabb->_max,
b_aabb->owner->pos + b_aabb->_min, b_aabb->owner->pos + b_aabb->_min,

View File

@ -143,12 +143,34 @@ bool CalcAabbAabbSafePoint(Vector2D a_min, Vector2D a_max, Vector2D b_min, Vecto
Vector2D& new_pos) Vector2D& new_pos)
{ {
Vector2D a_pos = a_min + (a_max - a_min)/2.0f; Vector2D a_pos = a_min + (a_max - a_min)/2.0f;
float a_rad = (a_max - a_min).Norm(); new_pos = a_pos;
Vector2D b_pos = b_min + (b_max - b_min)/2.0f; bool at_left = std::abs(a_pos.x - b_min.x) < std::abs(a_pos.x - b_max.x);
float b_rad = (b_max - b_min).Norm(); bool at_down = std::abs(a_pos.y - b_min.y) < std::abs(a_pos.y - b_max.y);
Vector2D dir = (a_pos - b_pos); float x_len = at_left ? std::abs(a_pos.x - b_min.x) : std::abs(a_pos.x - b_max.x);
dir.Normalize(); float y_len = at_down ? std::abs(a_pos.y - b_min.y) : std::abs(a_pos.y - b_max.y);
new_pos = b_pos + dir*(a_rad + b_rad) + 1; if (at_left) {
if (x_len < y_len) {
//左
new_pos.x = b_min.x - (a_max.x - a_min.x)/2.0f - 1;
} else {
if (at_down) {
new_pos.y = b_min.y - (a_max.y - a_min.y)/2.0f - 1;
} else {
new_pos.y = b_max.y + (a_max.y - a_min.y)/2.0f + 1;
}
}
} else {
if (x_len < y_len) {
//右
new_pos.x = b_max.x + (a_max.x - a_min.x)/2.0f + 1;
} else {
if (at_down) {
new_pos.y = b_min.y - (a_max.y - a_min.y)/2.0f - 1;
} else {
new_pos.y = b_max.y + (a_max.y - a_min.y)/2.0f + 1;
}
}
}
return true; return true;
} }
@ -156,9 +178,33 @@ bool CalcAabbCircleSafePoint(Vector2D a_min, Vector2D a_max, Vector2D b_pos, flo
Vector2D& new_pos) Vector2D& new_pos)
{ {
Vector2D a_pos = a_min + (a_max - a_min)/2.0f; Vector2D a_pos = a_min + (a_max - a_min)/2.0f;
float a_rad = (a_max - a_min).Norm(); new_pos = a_pos;
Vector2D dir = a_pos - b_pos; bool at_left = std::abs(a_min.x - b_pos.x) < std::abs(a_max.x - b_pos.x);
dir.Normalize(); bool at_down = std::abs(a_min.y - b_pos.y) < std::abs(a_max.y - b_pos.y);
new_pos = b_pos + dir*(a_rad + b_rad) + 1; float x_len = at_left ? std::abs(a_min.x - b_pos.x) : std::abs(a_max.x - b_pos.x);
float y_len = at_down ? std::abs(a_min.y - b_pos.y) : std::abs(a_max.y - b_pos.y);
if (at_left) {
if (x_len < y_len) {
//左
new_pos.x = b_pos.x - (a_max.x - a_min.x)/2.0f - 1;
} else {
if (at_down) {
new_pos.y = b_pos.y - (a_max.y - a_min.y)/2.0f - 1;
} else {
new_pos.y = b_pos.y + (a_max.y - a_min.y)/2.0f + 1;
}
}
} else {
if (x_len < y_len) {
//右
new_pos.x = b_pos.x + (a_max.x - a_min.x)/2.0f + 1;
} else {
if (at_down) {
new_pos.y = b_pos.y - (a_max.y - a_min.y)/2.0f - 1;
} else {
new_pos.y = b_pos.y + (a_max.y - a_min.y)/2.0f + 1;
}
}
}
return true; return true;
} }

View File

@ -135,6 +135,33 @@ enum EquipAttr_e
EA_End EA_End
}; };
enum EntityType_e
{
ET_None = 0,
ET_Player = 1,
ET_Obstacle = 2,
ET_Building = 3,
//ET_LootSpawner = 4,
ET_Loot = 5,
//ET_DeadBody = 6,
//ET_Decal = 7,
//ET_Projectile = 8,
ET_Smoke = 9,
ET_Hero = 10,
ET_Bullet = 20,
ET_Android = 30,
ET_MAX
};
enum EntitySubType_e
{
EST_None = 0,
EST_Player = 1,
EST_Android = 2,
};
const char* const PROJ_NAME_FMT = "game%d_gameserver"; const char* const PROJ_NAME_FMT = "game%d_gameserver";
const char* const PROJ_ROOT_FMT = "/data/logs/%s"; const char* const PROJ_ROOT_FMT = "/data/logs/%s";
@ -172,4 +199,3 @@ const int MAX_INSTANCE_ID = 500;
const int WALK_ZONE_WIDTH = 100; const int WALK_ZONE_WIDTH = 100;
const int MAX_TEAM_NUM = 4; const int MAX_TEAM_NUM = 4;

View File

@ -22,14 +22,6 @@ void Entity::Initialize()
xtimer_attacher.xtimer = &room->xtimer; xtimer_attacher.xtimer = &room->xtimer;
} }
ColliderComponent* Entity::GetBoxBound()
{
CircleCollider* collider = new CircleCollider();
collider->active = true;
collider->owner = this;
return collider;
}
void Entity::GetAabbBox(AabbCollider& aabb_box) void Entity::GetAabbBox(AabbCollider& aabb_box)
{ {
aabb_box.active = true; aabb_box.active = true;
@ -80,45 +72,60 @@ void Entity::ClearColliders()
void Entity::FindLocationWithTarget(Entity* target) void Entity::FindLocationWithTarget(Entity* target)
{ {
ColliderComponent* a_collider = GetBoxBound();
Vector2D old_pos = pos; Vector2D old_pos = pos;
Vector2D new_pos = pos; Vector2D new_pos = pos;
ColliderComponent* target_collider = target->GetBoxBound(); AabbCollider a_collider;
GetAabbBox(a_collider);
AabbCollider target_collider;
target->GetAabbBox(target_collider);
{ {
bool ret = a_collider->CalcSafePoint(target_collider, new_pos); bool ret = a_collider.CalcSafePoint(&target_collider, new_pos);
if (!ret) { if (!ret) {
abort(); abort();
} }
} }
Vector2D new_pos_dir = new_pos - old_pos; Vector2D new_pos_dir = new_pos - old_pos;
float distance = (new_pos - old_pos).Norm();
new_pos_dir.Normalize(); new_pos_dir.Normalize();
for (float i = distance; i < 10000000; i += 5.0f) { float distance = (new_pos - old_pos).Norm();
for (int i = distance; i < 10000000; i += 5) {
pos = old_pos + new_pos_dir * i; pos = old_pos + new_pos_dir * i;
Entity* building = nullptr;
std::set<GridCell*> new_grid_list; std::set<GridCell*> new_grid_list;
room->grid_service.GetAllCellsByXy(pos.x, pos.y, new_grid_list); room->grid_service.GetAllCellsByXy(pos.x, pos.y, new_grid_list);
std::vector<Entity*> objects;
for (auto& grid : new_grid_list) { for (auto& grid : new_grid_list) {
for (Entity* entity : grid->entity_list) { for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) { switch (entity->entity_type) {
case ET_Obstacle: case ET_Building:
{ {
if (entity != this && TestCollision(entity)){ if (TestCollision(entity)) {
objects.push_back(entity); building = entity;
break;
} }
} }
break; break;
default: }
{ if (building) {
}
break; break;
} }
} }
if (building) {
break;
}
} }
if (objects.empty()) {
break; if (!building) {
bool is_collision = false;
std::set<ColliderComponent*> colliders;
room->map_service.GetColliders(pos.x, pos.y, colliders);
for (ColliderComponent* collider : colliders) {
if (TestCollision(collider)) {
is_collision = true;
break;
}
}
if (!is_collision) {
break;
}
} }
} }
@ -143,9 +150,6 @@ void Entity::FindLocationWithTarget(Entity* target)
break; break;
} }
} }
DestoryCollider(target_collider);
DestoryCollider(a_collider);
} }
void Entity::BroadcastFullState() void Entity::BroadcastFullState()

View File

@ -8,33 +8,6 @@ namespace cs
class MFObjectFull; class MFObjectFull;
} }
enum EntityType_e
{
ET_None = 0,
ET_Player = 1,
ET_Obstacle = 2,
ET_Building = 3,
//ET_LootSpawner = 4,
ET_Loot = 5,
//ET_DeadBody = 6,
//ET_Decal = 7,
//ET_Projectile = 8,
ET_Smoke = 9,
ET_Hero = 10,
ET_Bullet = 20,
ET_Android = 30,
ET_MAX
};
enum EntitySubType_e
{
EST_None = 0,
EST_Player = 1,
EST_Android = 2,
};
class Room; class Room;
class Obstacle; class Obstacle;
class ColliderComponent; class ColliderComponent;
@ -66,7 +39,6 @@ class Entity
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) {}; virtual void FillMFObjectPart(cs::MFObjectPart* part_data) {};
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) {}; virtual void FillMFObjectFull(cs::MFObjectFull* full_data) {};
virtual float GetSpeed() { return 1.0f;}; virtual float GetSpeed() { return 1.0f;};
virtual ColliderComponent* GetBoxBound();
virtual void GetAabbBox(AabbCollider& aabb_box); virtual void GetAabbBox(AabbCollider& aabb_box);
virtual void GetCircleBox(CircleCollider& circle_box); virtual void GetCircleBox(CircleCollider& circle_box);
bool TestCollision(Entity* b); bool TestCollision(Entity* b);

View File

@ -55,12 +55,3 @@ void Hero::FillMFObjectFull(cs::MFObjectFull* full_data)
weapon.ToPB(p->mutable_weapon()); weapon.ToPB(p->mutable_weapon());
p->set_energy_shield(energy_shield); p->set_energy_shield(energy_shield);
} }
ColliderComponent* Hero::GetBoxBound()
{
CircleCollider* collider = new CircleCollider();
collider->owner = this;
collider->pos = Vector2D();
collider->rad = master->GetRadius();
return collider;
}

View File

@ -28,7 +28,6 @@ class Hero : public Entity
void RecalcSelfCollider(); void RecalcSelfCollider();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override; virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override; virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
private: private:
CircleCollider* self_collider_ = nullptr; CircleCollider* self_collider_ = nullptr;

View File

@ -142,15 +142,6 @@ void Human::FillMFObjectFull(cs::MFObjectFull* full_data)
FillBodyState(p->mutable_states()); FillBodyState(p->mutable_states());
} }
ColliderComponent* Human::GetBoxBound()
{
CircleCollider* collider = new CircleCollider();
collider->owner = this;
collider->pos = Vector2D();
collider->rad = GetRadius();
return collider;
}
void Human::FillMFPlayerStats(cs::MFPlayerStats* stats_pb) void Human::FillMFPlayerStats(cs::MFPlayerStats* stats_pb)
{ {
stats_pb->set_player_id(entity_uniid); stats_pb->set_player_id(entity_uniid);
@ -180,6 +171,19 @@ void Human::FillMFPlayerStats(cs::MFPlayerStats* stats_pb)
stats_pb->set_account_id(account_id); stats_pb->set_account_id(account_id);
} }
void Human::GetAabbBox(AabbCollider& aabb_box)
{
if (!meta) {
abort();
}
aabb_box.active = true;
aabb_box.owner = this;
aabb_box._min.x = -meta->i->radius();
aabb_box._min.y = -meta->i->radius();
aabb_box._max.x = meta->i->radius();
aabb_box._max.y = meta->i->radius();
}
void Human::FillMFTeamData(cs::MFTeamData* team_data) void Human::FillMFTeamData(cs::MFTeamData* team_data)
{ {
team_data->set_player_id(entity_uniid); team_data->set_player_id(entity_uniid);
@ -1138,70 +1142,34 @@ void Human::DoSkill()
void Human::FindLocation() void Human::FindLocation()
{ {
{ Entity* target = nullptr;
std::vector<Entity*> objects; for (auto& grid : grid_list) {
room->BuildingBoxBoundCollisionDetection(this, objects); for (Entity* entity : grid->entity_list) {
if (objects.size() > 1) { switch (entity->entity_type) {
#if 0 case ET_Obstacle:
abort(); {
#endif if (!target) {
} if (TestCollision(entity)) {
if (!objects.empty()) { target = entity;
Building* building = (Building*)objects[0]; }
Vector2D b_min = Vector2D( }
building->pos.x - building->meta->i->tilewidth()/2.0, }
building->pos.y - building->meta->i->tileheight()/2.0 break;
); case ET_Building:
Vector2D b_max = Vector2D( {
building->pos.x + building->meta->i->tilewidth()/2.0, if (!target || target->entity_type != ET_Building) {
building->pos.y + building->meta->i->tileheight()/2.0 AabbCollider aabb_box;
); entity->GetAabbBox(aabb_box);
Vector2D new_pos; if (TestCollision(&aabb_box)) {
bool ret = CalcCircleAabbSafePoint( target = entity;
pos, }
GetRadius(), }
b_min, }
b_max, break;
new_pos
);
if (!ret) {
abort();
}
if (ret) {
pos = new_pos;
room->grid_service.MoveHuman(this);
return;
} }
} }
} }
{ if (target) {
std::vector<Entity*> objects;
for (auto& grid : grid_list) {
for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Obstacle:
{
if (TestCollision(entity)){
objects.push_back(entity);
}
}
break;
default:
{
}
break;
}
}
}
if (objects.empty()) {
return;
}
std::sort(objects.begin(), objects.end(),
[this] (Entity* a, Entity *b) -> bool
{
return (this->pos - a->pos).Norm() < (this->pos - b->pos).Norm();
});
Entity* target = objects[0];
FindLocationWithTarget(target); FindLocationWithTarget(target);
} }
} }

View File

@ -122,8 +122,8 @@ class Human : public Entity
virtual float GetSpeed4(); virtual float GetSpeed4();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override; virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override; virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
virtual void FillMFPlayerStats(cs::MFPlayerStats* stats); virtual void FillMFPlayerStats(cs::MFPlayerStats* stats);
virtual void GetAabbBox(AabbCollider& aabb_box);
void FillMFTeamData(cs::MFTeamData* team_data); void FillMFTeamData(cs::MFTeamData* team_data);
void Shot(Vector2D& target_dir); void Shot(Vector2D& target_dir);
void RecalcSelfCollider(); void RecalcSelfCollider();

View File

@ -132,21 +132,6 @@ void Obstacle::FillMFObjectFull(cs::MFObjectFull* full_data)
} }
} }
ColliderComponent* Obstacle::GetBoxBound()
{
if (self_collider_) {
CircleCollider* collider = new CircleCollider();
*collider = *self_collider_;
return collider;
}
if (self_collider2_) {
AabbCollider* collider = new AabbCollider();
*collider = *self_collider2_;
return collider;
}
return nullptr;
}
void Obstacle::GetAabbBox(AabbCollider& aabb_box) void Obstacle::GetAabbBox(AabbCollider& aabb_box)
{ {
if (self_collider2_) { if (self_collider2_) {

View File

@ -41,7 +41,6 @@ class Obstacle : public Entity
void RecalcSelfCollider(); void RecalcSelfCollider();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override; virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override; virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
virtual void GetAabbBox(AabbCollider& aabb_box) override; virtual void GetAabbBox(AabbCollider& aabb_box) override;
virtual void GetCircleBox(CircleCollider& circle_box) override; virtual void GetCircleBox(CircleCollider& circle_box) override;
void Explosion(Bullet* bullet); void Explosion(Bullet* bullet);

View File

@ -324,21 +324,6 @@ Human* Room::FindEnemy(Human* hum)
return !enemys.empty() ? enemys[0] : nullptr; return !enemys.empty() ? enemys[0] : nullptr;
} }
void Room::BuildingBoxBoundCollisionDetection(Entity* sender, std::vector<Entity*>& objects)
{
ColliderComponent* a_collider = sender->GetBoxBound();
for (auto& pair : uniid_hash_) {
if (pair.second->entity_type == ET_Building) {
ColliderComponent* target_collider = pair.second->GetBoxBound();
if (a_collider->Intersect(target_collider)) {
objects.push_back(pair.second);
}
DestoryCollider(target_collider);
}
}
DestoryCollider(a_collider);
}
void Room::FillSMJoinedNotify(Player* self_hum, cs::SMJoinedNotify& msg) void Room::FillSMJoinedNotify(Player* self_hum, cs::SMJoinedNotify& msg)
{ {
msg.set_team_mode(msg.team_mode()); msg.set_team_mode(msg.team_mode());
@ -873,9 +858,9 @@ void Room::UpdateGas()
{ {
if (a8::HasBitFlag(hum->status, HS_Fly)) { if (a8::HasBitFlag(hum->status, HS_Fly)) {
hum->DoJump(); hum->DoJump();
if (hum->entity_subtype == EST_Player) { }
GameLog::Instance()->GameStart((Player*)hum); if (hum->entity_subtype == EST_Player) {
} GameLog::Instance()->GameStart((Player*)hum);
} }
return true; return true;
}); });

View File

@ -62,7 +62,6 @@ public:
void AddPlayer(Player* hum); void AddPlayer(Player* hum);
Human* FindEnemy(Human* hum); Human* FindEnemy(Human* hum);
void BuildingBoxBoundCollisionDetection(Entity* sender, std::vector<Entity*>& objects);
void RemoveObjectLater(Entity* entity); void RemoveObjectLater(Entity* entity);
void FetchBuilding(Human* hum); void FetchBuilding(Human* hum);