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;
float distance = (pos - born_pos).Norm();
if (meta->i->_inventory_slot() == 5 ||
meta->i->_inventory_slot() == 6) {
std::vector<Entity*> 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<Entity*> 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<Entity*> 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<Entity*>& objects)
void Bullet::OnHit(std::set<Entity*>& 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;
}

View File

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

View File

@ -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<GridCell*> 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()
{
}

View File

@ -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<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)
{
int x = (int)entity->pos.x + cell_width_;

View File

@ -2,11 +2,13 @@
class Entity;
class Human;
class Bullet;
struct GridCell
{
std::set<Human*> human_list;
std::set<Entity*> entity_list;
std::set<Bullet*> 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<GridCell*>& grid_list);

View File

@ -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<Entity*> 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;
}

View File

@ -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();

View File

@ -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<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)
{
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;

View File

@ -57,7 +57,6 @@ public:
void AddPlayer(Player* 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 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();