This commit is contained in:
aozhiwei 2019-04-25 15:56:13 +08:00
parent 7a95ca7c51
commit 07535d954f
9 changed files with 126 additions and 115 deletions

View File

@ -26,32 +26,44 @@ void Bullet::Update(int delta_time)
{ {
pos = pos + dir * gun_meta->i->bullet_speed() / 20.0f; pos = pos + dir * gun_meta->i->bullet_speed() / 20.0f;
float distance = (pos - born_pos).Norm(); float distance = (pos - born_pos).Norm();
if (meta->i->_inventory_slot() == 5 || room->grid_service.MoveBullet(this);
meta->i->_inventory_slot() == 6) { if (room->OverBorder(pos, gun_meta->i->bullet_rad())) {
std::vector<Entity*> objects; if (IsBomb()){
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) {
ProcBomb(); ProcBomb();
} else {
room->RemoveObjectLater(this);
} }
} else { } else {
std::vector<Entity*> objects; std::set<Entity*> objects;
int detection_flags = 0; for (auto& grid : grid_list) {
{ for (Entity* entity : grid->entity_list) {
a8::SetBitFlag(detection_flags, ET_Obstacle); switch (entity->entity_type) {
a8::SetBitFlag(detection_flags, ET_Player); case ET_Obstacle:
} case ET_Building:
room->CollisionDetection(this, detection_flags, objects); case ET_Player:
if (!objects.empty() || distance > gun_meta->i->range()) { {
deleted = true; if (TestCollision(entity)) {
if (!objects.empty()) { objects.insert(entity);
OnHit(objects); }
}
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(); self_collider_->rad = gun_meta->i->bullet_rad();
} }
void Bullet::OnHit(std::vector<Entity*>& objects) void Bullet::OnHit(std::set<Entity*>& objects)
{ {
for (auto& target : objects) { for (auto& target : objects) {
switch (target->entity_type) { switch (target->entity_type) {
@ -125,3 +137,9 @@ void Bullet::ProcBomb()
} }
room->RemoveObjectLater(this); room->RemoveObjectLater(this);
} }
bool Bullet::IsBomb()
{
return meta->i->_inventory_slot() == 5 ||
meta->i->_inventory_slot() == 6;
}

View File

@ -29,8 +29,9 @@ class Bullet : public Entity
private: private:
void OnHit(std::vector<Entity*>& objects); void OnHit(std::set<Entity*>& objects);
void ProcBomb(); void ProcBomb();
bool IsBomb();
private: private:
CircleCollider* self_collider_ = nullptr; CircleCollider* self_collider_ = nullptr;

View File

@ -4,6 +4,7 @@
#include "collider.h" #include "collider.h"
#include "room.h" #include "room.h"
#include "building.h" #include "building.h"
#include "human.h"
Entity::Entity() Entity::Entity()
{ {
@ -71,7 +72,9 @@ void Entity::FindLocationWithTarget(Entity* target)
{ {
a8::SetBitFlag(detection_flags, ET_Obstacle); a8::SetBitFlag(detection_flags, ET_Obstacle);
} }
#if 0
room->CollisionDetection(this, detection_flags, objects); room->CollisionDetection(this, detection_flags, objects);
#endif
if (objects.empty()) { if (objects.empty()) {
break; break;
} }
@ -83,18 +86,15 @@ void Entity::FindLocationWithTarget(Entity* target)
void Entity::BroadcastFullState() void Entity::BroadcastFullState()
{ {
#if 0 std::set<GridCell*> grid_list;
room->TouchPlayerList(a8::XParams() room->grid_service.Get123456789(grid_id, grid_list);
.SetSender(obstacle), for (auto& grid : grid_list) {
[] (Player* hum, a8::XParams& param) for (Human* hum : grid->human_list) {
{ hum->AddToNewObjects(this);
Obstacle* obstacle = (Obstacle*)param.sender.GetUserData(); }
hum->AddToNewObjects(obstacle); }
});
#endif
} }
void Entity::BroadcastDeleteState() void Entity::BroadcastDeleteState()
{ {
} }

View File

@ -2,6 +2,7 @@
#include "gridservice.h" #include "gridservice.h"
#include "human.h" #include "human.h"
#include "bullet.h"
GridService::GridService() 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<GridCell*> inc_grid_list;
std::set<GridCell*> dec_grid_list;
std::set<GridCell*> 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) void GridService::AddEntity(Entity* entity)
{ {
int x = (int)entity->pos.x + cell_width_; int x = (int)entity->pos.x + cell_width_;

View File

@ -2,11 +2,13 @@
class Entity; class Entity;
class Human; class Human;
class Bullet;
struct GridCell struct GridCell
{ {
std::set<Human*> human_list; std::set<Human*> human_list;
std::set<Entity*> entity_list; std::set<Entity*> entity_list;
std::set<Bullet*> bullet_list;
}; };
/* /*
@ -37,6 +39,9 @@ class GridService
void AddHuman(Human* hum); void AddHuman(Human* hum);
void MoveHuman(Human* hum); void MoveHuman(Human* hum);
void AddBullet(Bullet* bullet);
void MoveBullet(Bullet* bullet);
void AddEntity(Entity* entity); void AddEntity(Entity* entity);
bool HumanInGridList(Human* hum, std::set<GridCell*>& grid_list); bool HumanInGridList(Human* hum, std::set<GridCell*>& grid_list);

View File

@ -246,27 +246,8 @@ void Human::RecalcSelfCollider()
bool Human::IsCollision() bool Human::IsCollision()
{ {
//检查x轴 if (room->OverBorder(pos, meta->i->radius())){
{ return true;
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 (a8::HasBitFlag(status, HS_Jump)) { if (a8::HasBitFlag(status, HS_Jump)) {
@ -305,16 +286,6 @@ bool Human::IsCollision()
return !objects.empty(); return !objects.empty();
} }
ColliderComponent* Human::GetFirstCollision()
{
int detection_flags = 0;
a8::SetBitFlag(detection_flags, ET_Obstacle);
a8::SetBitFlag(detection_flags, ET_Building);
std::vector<Entity*> objects;
room->CollisionDetection(this, detection_flags, objects);
return objects.empty() ? *objects[0]->colliders.begin() : nullptr;
}
void Human::FindPath() void Human::FindPath()
{ {
Vector2D old_pos = pos; Vector2D old_pos = pos;
@ -669,7 +640,9 @@ void Human::FindLocation()
a8::SetBitFlag(detection_flags, ET_Obstacle); a8::SetBitFlag(detection_flags, ET_Obstacle);
a8::SetBitFlag(detection_flags, ET_Player); a8::SetBitFlag(detection_flags, ET_Player);
} }
#if 0
room->CollisionDetection(this, detection_flags, objects); room->CollisionDetection(this, detection_flags, objects);
#endif
if (objects.empty()) { if (objects.empty()) {
return; return;
} }

View File

@ -98,7 +98,6 @@ class Human : public Entity
void Shot(Vector2D& target_dir); void Shot(Vector2D& target_dir);
void RecalcSelfCollider(); void RecalcSelfCollider();
bool IsCollision(); bool IsCollision();
ColliderComponent* GetFirstCollision();
void FindPath(); void FindPath();
float GetRadius(); float GetRadius();
float GetMaxHP(); float GetMaxHP();

View File

@ -233,54 +233,6 @@ Human* Room::FindEnemy(Human* hum)
return !enemys.empty() ? enemys[0] : nullptr; return !enemys.empty() ? enemys[0] : nullptr;
} }
void Room::CollisionDetection(Entity* sender, int detection_flags, std::vector<Entity*>& 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<Entity*>& objects) void Room::BuildingBoxBoundCollisionDetection(Entity* sender, std::vector<Entity*>& objects)
{ {
ColliderComponent* a_collider = sender->GetBoxBound(); ColliderComponent* a_collider = sender->GetBoxBound();
@ -486,6 +438,7 @@ void Room::CreateBullet(Human* hum, MetaData::Equip* gun_meta,
bullet->entity_uniid = AllocUniid(); bullet->entity_uniid = AllocUniid();
bullet->Initialize(); bullet->Initialize();
AddObjectLater(bullet); AddObjectLater(bullet);
grid_service.AddBullet(bullet);
} }
void Room::RemoveObjectLater(Entity* entity) void Room::RemoveObjectLater(Entity* entity)
@ -534,6 +487,33 @@ void Room::OnHumanDie(Human* hum)
--alive_count_; --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() int Room::NewTeam()
{ {
++current_teamid; ++current_teamid;

View File

@ -57,7 +57,6 @@ public:
void AddPlayer(Player* hum); void AddPlayer(Player* hum);
Human* FindEnemy(Human* hum); Human* FindEnemy(Human* hum);
void CollisionDetection(Entity* sender, int detection_flags, std::vector<Entity*>& objects);
void BuildingBoxBoundCollisionDetection(Entity* sender, std::vector<Entity*>& objects); void BuildingBoxBoundCollisionDetection(Entity* sender, std::vector<Entity*>& objects);
void RemoveObjectLater(Entity* entity); void RemoveObjectLater(Entity* entity);
@ -80,6 +79,7 @@ public:
Vector2D pos, Vector2D dir, float fly_distance); Vector2D pos, Vector2D dir, float fly_distance);
void OnHumanDie(Human* hum); void OnHumanDie(Human* hum);
bool OverBorder(const Vector2D pos, float radius);
private: private:
unsigned short AllocUniid(); unsigned short AllocUniid();