修复碰撞问题

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());
}
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)
{
aabb_box.active = true;

View File

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

View File

@ -256,15 +256,6 @@ void Bullet::MapServiceUpdate()
for (ColliderComponent* collider : colliders) {
if (TestCollision(collider)) {
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) {
case CT_Aabb:
{
AabbCollider* b_aabb = (AabbCollider*)this;
AabbCollider* b_aabb = (AabbCollider*)b;
return CalcAabbAabbSafePoint(a_aabb->owner->pos + a_aabb->_min,
a_aabb->owner->pos + a_aabb->_max,
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 a_pos = a_min + (a_max - a_min)/2.0f;
float a_rad = (a_max - a_min).Norm();
Vector2D b_pos = b_min + (b_max - b_min)/2.0f;
float b_rad = (b_max - b_min).Norm();
Vector2D dir = (a_pos - b_pos);
dir.Normalize();
new_pos = b_pos + dir*(a_rad + b_rad) + 1;
new_pos = a_pos;
bool at_left = std::abs(a_pos.x - b_min.x) < std::abs(a_pos.x - b_max.x);
bool at_down = std::abs(a_pos.y - b_min.y) < std::abs(a_pos.y - b_max.y);
float x_len = at_left ? std::abs(a_pos.x - b_min.x) : std::abs(a_pos.x - b_max.x);
float y_len = at_down ? std::abs(a_pos.y - b_min.y) : std::abs(a_pos.y - b_max.y);
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;
}
@ -156,9 +178,33 @@ bool CalcAabbCircleSafePoint(Vector2D a_min, Vector2D a_max, Vector2D b_pos, flo
Vector2D& new_pos)
{
Vector2D a_pos = a_min + (a_max - a_min)/2.0f;
float a_rad = (a_max - a_min).Norm();
Vector2D dir = a_pos - b_pos;
dir.Normalize();
new_pos = b_pos + dir*(a_rad + b_rad) + 1;
new_pos = a_pos;
bool at_left = std::abs(a_min.x - b_pos.x) < std::abs(a_max.x - b_pos.x);
bool at_down = std::abs(a_min.y - b_pos.y) < std::abs(a_max.y - b_pos.y);
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;
}

View File

@ -135,6 +135,33 @@ enum EquipAttr_e
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_ROOT_FMT = "/data/logs/%s";
@ -172,4 +199,3 @@ const int MAX_INSTANCE_ID = 500;
const int WALK_ZONE_WIDTH = 100;
const int MAX_TEAM_NUM = 4;

View File

@ -22,14 +22,6 @@ void Entity::Initialize()
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)
{
aabb_box.active = true;
@ -80,45 +72,60 @@ void Entity::ClearColliders()
void Entity::FindLocationWithTarget(Entity* target)
{
ColliderComponent* a_collider = GetBoxBound();
Vector2D old_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) {
abort();
}
}
Vector2D new_pos_dir = new_pos - old_pos;
float distance = (new_pos - old_pos).Norm();
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;
Entity* building = nullptr;
std::set<GridCell*> 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 (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Obstacle:
case ET_Building:
{
if (entity != this && TestCollision(entity)){
objects.push_back(entity);
break;
if (TestCollision(entity)) {
building = entity;
}
}
break;
default:
{
}
}
if (building) {
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;
}
}
DestoryCollider(target_collider);
DestoryCollider(a_collider);
}
void Entity::BroadcastFullState()

View File

@ -8,33 +8,6 @@ namespace cs
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 Obstacle;
class ColliderComponent;
@ -66,7 +39,6 @@ class Entity
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) {};
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) {};
virtual float GetSpeed() { return 1.0f;};
virtual ColliderComponent* GetBoxBound();
virtual void GetAabbBox(AabbCollider& aabb_box);
virtual void GetCircleBox(CircleCollider& circle_box);
bool TestCollision(Entity* b);

View File

@ -55,12 +55,3 @@ void Hero::FillMFObjectFull(cs::MFObjectFull* full_data)
weapon.ToPB(p->mutable_weapon());
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();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
private:
CircleCollider* self_collider_ = nullptr;

View File

@ -142,15 +142,6 @@ void Human::FillMFObjectFull(cs::MFObjectFull* full_data)
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)
{
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);
}
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)
{
team_data->set_player_id(entity_uniid);
@ -1138,70 +1142,34 @@ void Human::DoSkill()
void Human::FindLocation()
{
{
std::vector<Entity*> objects;
room->BuildingBoxBoundCollisionDetection(this, objects);
if (objects.size() > 1) {
#if 0
abort();
#endif
}
if (!objects.empty()) {
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
);
Vector2D b_max = Vector2D(
building->pos.x + building->meta->i->tilewidth()/2.0,
building->pos.y + building->meta->i->tileheight()/2.0
);
Vector2D new_pos;
bool ret = CalcCircleAabbSafePoint(
pos,
GetRadius(),
b_min,
b_max,
new_pos
);
if (!ret) {
abort();
}
if (ret) {
pos = new_pos;
room->grid_service.MoveHuman(this);
return;
Entity* target = nullptr;
for (auto& grid : grid_list) {
for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Obstacle:
{
if (!target) {
if (TestCollision(entity)) {
target = entity;
}
}
}
break;
case ET_Building:
{
if (!target || target->entity_type != ET_Building) {
AabbCollider aabb_box;
entity->GetAabbBox(aabb_box);
if (TestCollision(&aabb_box)) {
target = entity;
}
}
}
break;
}
}
}
{
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];
if (target) {
FindLocationWithTarget(target);
}
}

View File

@ -122,8 +122,8 @@ class Human : public Entity
virtual float GetSpeed4();
virtual void FillMFObjectPart(cs::MFObjectPart* part_data) override;
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) override;
virtual ColliderComponent* GetBoxBound() override;
virtual void FillMFPlayerStats(cs::MFPlayerStats* stats);
virtual void GetAabbBox(AabbCollider& aabb_box);
void FillMFTeamData(cs::MFTeamData* team_data);
void Shot(Vector2D& target_dir);
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)
{
if (self_collider2_) {

View File

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

View File

@ -324,21 +324,6 @@ Human* Room::FindEnemy(Human* hum)
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)
{
msg.set_team_mode(msg.team_mode());
@ -873,9 +858,9 @@ void Room::UpdateGas()
{
if (a8::HasBitFlag(hum->status, HS_Fly)) {
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;
});

View File

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