diff --git a/server/gameserver/bullet.cc b/server/gameserver/bullet.cc index e9ffb0d..097431d 100644 --- a/server/gameserver/bullet.cc +++ b/server/gameserver/bullet.cc @@ -26,32 +26,44 @@ void Bullet::Update(int delta_time) { pos = pos + dir * gun_meta->i->bullet_speed() / 20.0f; float distance = (pos - born_pos).Norm(); - if (meta->i->_inventory_slot() == 5 || - meta->i->_inventory_slot() == 6) { - std::vector objects; - int detection_flags = 0; - { - a8::SetBitFlag(detection_flags, ET_Obstacle); - a8::SetBitFlag(detection_flags, ET_Building); - } - room->CollisionDetection(this, detection_flags, objects); - if (!objects.empty() || distance >= fly_distance) { + room->grid_service.MoveBullet(this); + if (room->OverBorder(pos, gun_meta->i->bullet_rad())) { + if (IsBomb()){ ProcBomb(); + } else { + room->RemoveObjectLater(this); } } else { - std::vector objects; - int detection_flags = 0; - { - a8::SetBitFlag(detection_flags, ET_Obstacle); - a8::SetBitFlag(detection_flags, ET_Player); - } - room->CollisionDetection(this, detection_flags, objects); - if (!objects.empty() || distance > gun_meta->i->range()) { - deleted = true; - if (!objects.empty()) { - OnHit(objects); + std::set objects; + for (auto& grid : grid_list) { + for (Entity* entity : grid->entity_list) { + switch (entity->entity_type) { + case ET_Obstacle: + case ET_Building: + case ET_Player: + { + if (TestCollision(entity)) { + objects.insert(entity); + } + } + break; + default: + { + } + break; + } + } + }//end for + if (!objects.empty() || distance > gun_meta->i->range()) { + if (IsBomb()) { + ProcBomb(); + } else { + deleted = true; + if (!objects.empty()) { + OnHit(objects); + } + room->RemoveObjectLater(this); } - room->RemoveObjectLater(this); } } } @@ -67,7 +79,7 @@ void Bullet::RecalcSelfCollider() self_collider_->rad = gun_meta->i->bullet_rad(); } -void Bullet::OnHit(std::vector& objects) +void Bullet::OnHit(std::set& objects) { for (auto& target : objects) { switch (target->entity_type) { @@ -125,3 +137,9 @@ void Bullet::ProcBomb() } room->RemoveObjectLater(this); } + +bool Bullet::IsBomb() +{ + return meta->i->_inventory_slot() == 5 || + meta->i->_inventory_slot() == 6; +} diff --git a/server/gameserver/bullet.h b/server/gameserver/bullet.h index 850e5d9..7718002 100644 --- a/server/gameserver/bullet.h +++ b/server/gameserver/bullet.h @@ -29,8 +29,9 @@ class Bullet : public Entity private: - void OnHit(std::vector& objects); + void OnHit(std::set& objects); void ProcBomb(); + bool IsBomb(); private: CircleCollider* self_collider_ = nullptr; diff --git a/server/gameserver/entity.cc b/server/gameserver/entity.cc index c2cebdb..32ac995 100644 --- a/server/gameserver/entity.cc +++ b/server/gameserver/entity.cc @@ -4,6 +4,7 @@ #include "collider.h" #include "room.h" #include "building.h" +#include "human.h" Entity::Entity() { @@ -71,7 +72,9 @@ void Entity::FindLocationWithTarget(Entity* target) { a8::SetBitFlag(detection_flags, ET_Obstacle); } + #if 0 room->CollisionDetection(this, detection_flags, objects); + #endif if (objects.empty()) { break; } @@ -83,18 +86,15 @@ void Entity::FindLocationWithTarget(Entity* target) void Entity::BroadcastFullState() { -#if 0 - room->TouchPlayerList(a8::XParams() - .SetSender(obstacle), - [] (Player* hum, a8::XParams& param) - { - Obstacle* obstacle = (Obstacle*)param.sender.GetUserData(); - hum->AddToNewObjects(obstacle); - }); -#endif + std::set grid_list; + room->grid_service.Get123456789(grid_id, grid_list); + for (auto& grid : grid_list) { + for (Human* hum : grid->human_list) { + hum->AddToNewObjects(this); + } + } } void Entity::BroadcastDeleteState() { - } diff --git a/server/gameserver/gridservice.cc b/server/gameserver/gridservice.cc index 7674a5a..fc9b192 100644 --- a/server/gameserver/gridservice.cc +++ b/server/gameserver/gridservice.cc @@ -2,6 +2,7 @@ #include "gridservice.h" #include "human.h" +#include "bullet.h" GridService::GridService() { @@ -139,6 +140,40 @@ void GridService::MoveHuman(Human* hum) } } +void GridService::AddBullet(Bullet* bullet) +{ + int x = (int)bullet->pos.x + cell_width_; + int y = (int)bullet->pos.y + cell_width_; + if (BroderOverFlow(x, y)) { + abort(); + } + bullet->grid_id = x/cell_width_ + (y/cell_width_) * cell_count_per_row_; + if (bullet->grid_id == 0 || bullet->grid_id > max_grid_id_) { + abort(); + } + cells_[bullet->grid_id].bullet_list.insert(bullet); + Get123456789(bullet->grid_id, bullet->grid_list); +} + +void GridService::MoveBullet(Bullet* bullet) +{ + int new_x = (int)bullet->pos.x + cell_width_; + int new_y = (int)bullet->pos.y + cell_width_; + int new_grid_id = new_x/cell_width_ + (new_y/cell_width_) * cell_count_per_row_; + if (new_grid_id != bullet->grid_id) { + std::set inc_grid_list; + std::set dec_grid_list; + std::set old_grid_list = bullet->grid_list; + ComputeDiff(bullet->grid_id, new_grid_id, + bullet->grid_list, + inc_grid_list, + dec_grid_list); + cells_[bullet->grid_id].bullet_list.erase(bullet); + cells_[new_grid_id].bullet_list.insert(bullet); + bullet->grid_id = new_grid_id; + } +} + void GridService::AddEntity(Entity* entity) { int x = (int)entity->pos.x + cell_width_; diff --git a/server/gameserver/gridservice.h b/server/gameserver/gridservice.h index 5d892b6..14fd45c 100644 --- a/server/gameserver/gridservice.h +++ b/server/gameserver/gridservice.h @@ -2,11 +2,13 @@ class Entity; class Human; +class Bullet; struct GridCell { std::set human_list; std::set entity_list; + std::set bullet_list; }; /* @@ -37,6 +39,9 @@ class GridService void AddHuman(Human* hum); void MoveHuman(Human* hum); + void AddBullet(Bullet* bullet); + void MoveBullet(Bullet* bullet); + void AddEntity(Entity* entity); bool HumanInGridList(Human* hum, std::set& grid_list); diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 23620af..e293438 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -246,27 +246,8 @@ void Human::RecalcSelfCollider() bool Human::IsCollision() { - //检查x轴 - { - int left_x = pos.x - meta->i->radius(); - if (left_x < 0.001f) { - return true; - } - int right_x = pos.x + meta->i->radius(); - if (right_x > MAP_WIDTH) { - return true; - } - } - //检查y轴 - { - int up_y = pos.y + meta->i->radius(); - if (up_y > MAP_HEIGHT) { - return true; - } - int down_y = pos.y - meta->i->radius(); - if (down_y < 0.001f) { - return true; - } + if (room->OverBorder(pos, meta->i->radius())){ + return true; } if (a8::HasBitFlag(status, HS_Jump)) { @@ -305,16 +286,6 @@ bool Human::IsCollision() return !objects.empty(); } -ColliderComponent* Human::GetFirstCollision() -{ - int detection_flags = 0; - a8::SetBitFlag(detection_flags, ET_Obstacle); - a8::SetBitFlag(detection_flags, ET_Building); - std::vector objects; - room->CollisionDetection(this, detection_flags, objects); - return objects.empty() ? *objects[0]->colliders.begin() : nullptr; -} - void Human::FindPath() { Vector2D old_pos = pos; @@ -669,7 +640,9 @@ void Human::FindLocation() a8::SetBitFlag(detection_flags, ET_Obstacle); a8::SetBitFlag(detection_flags, ET_Player); } + #if 0 room->CollisionDetection(this, detection_flags, objects); + #endif if (objects.empty()) { return; } diff --git a/server/gameserver/human.h b/server/gameserver/human.h index b51a903..242c04b 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -98,7 +98,6 @@ class Human : public Entity void Shot(Vector2D& target_dir); void RecalcSelfCollider(); bool IsCollision(); - ColliderComponent* GetFirstCollision(); void FindPath(); float GetRadius(); float GetMaxHP(); diff --git a/server/gameserver/room.cc b/server/gameserver/room.cc index c37c556..2a02d20 100644 --- a/server/gameserver/room.cc +++ b/server/gameserver/room.cc @@ -233,54 +233,6 @@ Human* Room::FindEnemy(Human* hum) return !enemys.empty() ? enemys[0] : nullptr; } -void Room::CollisionDetection(Entity* sender, int detection_flags, std::vector& objects) -{ - assert(uniid_hash_.size() < 2000); - for (auto& pair : uniid_hash_) { - if (sender == pair.second) { - continue; - } - #if 1 - if (std::abs(sender->pos.x - pair.second->pos.x) > 1000 || - std::abs(sender->pos.y - pair.second->pos.y) > 1000){ - continue; - } - #endif - if (a8::HasBitFlag(detection_flags, ET_Player) && pair.second->entity_type == ET_Player) { - if (sender->entity_type == ET_Bullet) { - Bullet* bullet = (Bullet*)sender; - Human* hum = (Human*)pair.second; -#if 1 - if (hum != bullet->player) { -#else - if (hum != bullet->player && - (hum->team_id == 0 || bullet->player->team_id != hum->team_id)) { -#endif - if (bullet->TestCollision(hum)) { - objects.push_back(hum); - } - } - } - } - if (a8::HasBitFlag(detection_flags, ET_Obstacle) && pair.second->entity_type == ET_Obstacle) { - if (sender->entity_type == ET_Bullet || sender->entity_type == ET_Player) { - if (pair.second != sender && - (sender->last_collision_door == nullptr || sender->last_collision_door != pair.second) && - sender->TestCollision(pair.second)) { - objects.push_back(pair.second); - } - } - } - if (a8::HasBitFlag(detection_flags, ET_Building) && pair.second->entity_type == ET_Building) { - if (sender->entity_type == ET_Bullet || sender->entity_type == ET_Player) { - if (pair.second != sender && sender->TestCollision(pair.second)) { - objects.push_back(pair.second); - } - } - } - } -} - void Room::BuildingBoxBoundCollisionDetection(Entity* sender, std::vector& objects) { ColliderComponent* a_collider = sender->GetBoxBound(); @@ -486,6 +438,7 @@ void Room::CreateBullet(Human* hum, MetaData::Equip* gun_meta, bullet->entity_uniid = AllocUniid(); bullet->Initialize(); AddObjectLater(bullet); + grid_service.AddBullet(bullet); } void Room::RemoveObjectLater(Entity* entity) @@ -534,6 +487,33 @@ void Room::OnHumanDie(Human* hum) --alive_count_; } +bool Room::OverBorder(const Vector2D pos, float radius) +{ + //检查x轴 + { + int left_x = pos.x - radius; + if (left_x < 0.001f) { + return true; + } + int right_x = pos.x + radius; + if (right_x > MAP_WIDTH) { + return true; + } + } + //检查y轴 + { + int up_y = pos.y + radius; + if (up_y > MAP_HEIGHT) { + return true; + } + int down_y = pos.y - radius; + if (down_y < 0.001f) { + return true; + } + } + return false; +} + int Room::NewTeam() { ++current_teamid; diff --git a/server/gameserver/room.h b/server/gameserver/room.h index fc53683..449c67f 100644 --- a/server/gameserver/room.h +++ b/server/gameserver/room.h @@ -57,7 +57,6 @@ public: void AddPlayer(Player* hum); Human* FindEnemy(Human* hum); - void CollisionDetection(Entity* sender, int detection_flags, std::vector& objects); void BuildingBoxBoundCollisionDetection(Entity* sender, std::vector& objects); void RemoveObjectLater(Entity* entity); @@ -80,6 +79,7 @@ public: Vector2D pos, Vector2D dir, float fly_distance); void OnHumanDie(Human* hum); + bool OverBorder(const Vector2D pos, float radius); private: unsigned short AllocUniid();