game2001/server/gameserver/gridservice.cc
2019-05-05 11:45:26 +08:00

383 lines
11 KiB
C++

#include "precompile.h"
#include "gridservice.h"
#include "human.h"
#include "bullet.h"
GridService::GridService()
{
}
GridService::~GridService()
{
}
void GridService::Init(int width, int height, int cell_width)
{
map_width_ = width;
map_height_ = height;
cell_width_ = cell_width;
cell_count_per_row_ = (map_height_ / cell_width + 1) + 2;
cell_count_per_col_ = (map_width_ / cell_width + 1) + 2;
max_grid_id_ = cell_count_per_row_ * cell_count_per_col_;
cells_ = new GridCell[max_grid_id_ + 1];
grid_offset_arr_[0] = -(cell_count_per_row_ - 1);
grid_offset_arr_[1] = -cell_count_per_row_;
grid_offset_arr_[2] = -(cell_count_per_row_ + 1);
grid_offset_arr_[3] = -1;
grid_offset_arr_[4] = 0;
grid_offset_arr_[5] = 1;
grid_offset_arr_[6] = cell_count_per_row_ - 1;
grid_offset_arr_[7] = cell_count_per_row_;
grid_offset_arr_[8] = cell_count_per_row_ + 1;
min_x_ = cell_width_ * 1;
min_y_ = cell_width_ * 1;
max_x_ = cell_width_ * (cell_count_per_row_ - 1);
max_y_ = cell_width_ * (cell_count_per_col_ - 1);
}
void GridService::UnInit()
{
if (cells_) {
delete[] cells_;
cells_ = nullptr;
}
}
bool GridService::BroderOverFlow(int x, int y)
{
return x <= min_x_ || x >= max_x_ || y <= min_y_ || y >= max_y_;
}
void GridService::GetAllCells(int grid_id, std::set<GridCell*>& grid_list)
{
for (size_t i = 1; i <= 9; ++i) {
GetGridList(grid_id, i, grid_list);
}
}
void GridService::GetAllCellsByXy(int x, int y, std::set<GridCell*>& grid_list)
{
int new_x = x + cell_width_;
int new_y = y + cell_width_;
int new_grid_id = new_x/cell_width_ + (new_y/cell_width_) * cell_count_per_row_;
if (BroderOverFlow(new_x, new_y)) {
abort();
}
GetAllCells(new_grid_id, grid_list);
}
void GridService::Get123(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 1, grid_list);
GetGridList(grid_id, 2, grid_list);
GetGridList(grid_id, 3, grid_list);
}
void GridService::Get456(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 4, grid_list);
GetGridList(grid_id, 5, grid_list);
GetGridList(grid_id, 6, grid_list);
}
void GridService::Get789(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 7, grid_list);
GetGridList(grid_id, 8, grid_list);
GetGridList(grid_id, 9, grid_list);
}
void GridService::Get147(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 1, grid_list);
GetGridList(grid_id, 4, grid_list);
GetGridList(grid_id, 7, grid_list);
}
void GridService::Get258(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 2, grid_list);
GetGridList(grid_id, 5, grid_list);
GetGridList(grid_id, 8, grid_list);
}
void GridService::Get369(int grid_id, std::set<GridCell*>& grid_list)
{
GetGridList(grid_id, 3, grid_list);
GetGridList(grid_id, 6, grid_list);
GetGridList(grid_id, 9, grid_list);
}
void GridService::AddHuman(Human* hum)
{
int x = (int)hum->pos.x + cell_width_;
int y = (int)hum->pos.y + cell_width_;
if (BroderOverFlow(x, y)) {
abort();
}
hum->grid_id = x/cell_width_ + (y/cell_width_) * cell_count_per_row_;
if (hum->grid_id == 0 || hum->grid_id > max_grid_id_) {
abort();
}
cells_[hum->grid_id].human_list.insert(hum);
GetAllCells(hum->grid_id, hum->grid_list);
}
void GridService::MoveHuman(Human* hum)
{
int new_x = (int)hum->pos.x + cell_width_;
int new_y = (int)hum->pos.y + cell_width_;
int new_grid_id = new_x/cell_width_ + (new_y/cell_width_) * cell_count_per_row_;
if (BroderOverFlow(new_x, new_y)) {
abort();
}
if (new_grid_id == 0 || new_grid_id > max_grid_id_) {
abort();
}
if (new_grid_id != hum->grid_id) {
std::set<GridCell*> inc_grid_list;
std::set<GridCell*> dec_grid_list;
std::set<GridCell*> old_grid_list = hum->grid_list;
ComputeDiff(hum->grid_id, new_grid_id,
hum->grid_list,
inc_grid_list,
dec_grid_list);
cells_[hum->grid_id].human_list.erase(hum);
cells_[new_grid_id].human_list.insert(hum);
hum->grid_id = new_grid_id;
hum->OnGridListChange(old_grid_list, inc_grid_list, dec_grid_list);
}
}
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);
GetAllCells(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 (BroderOverFlow(new_x, new_y)) {
abort();
}
if (new_grid_id == 0 || new_grid_id > max_grid_id_) {
abort();
}
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::DelBullet(Bullet* bullet)
{
GridCell& cell = cells_[bullet->grid_id];
cell.bullet_list.erase(bullet);
}
void GridService::AddEntity(Entity* entity)
{
assert(entity->entity_type != ET_Player);
int x = (int)entity->pos.x + cell_width_;
int y = (int)entity->pos.y + cell_width_;
if (BroderOverFlow(x, y)) {
abort();
}
entity->grid_id = x/cell_width_ + (y/cell_width_) * cell_count_per_row_;
if (entity->grid_id == 0 || entity->grid_id > max_grid_id_) {
abort();
}
cells_[entity->grid_id].entity_list.insert(entity);
}
void GridService::DelEntity(Entity* entity)
{
GridCell& cell = cells_[entity->grid_id];
cell.entity_list.erase(entity);
}
bool GridService::HumanInGridList(Human* hum, std::set<GridCell*>& grid_list)
{
for (auto& cell : grid_list) {
if (cell->human_list.find(hum) != cell->human_list.end()) {
return true;
}
}
return false;
}
bool GridService::EntityInGridList(Entity* entity, std::set<GridCell*>& grid_list)
{
for (auto& cell : grid_list) {
if (cell->entity_list.find(entity) != cell->entity_list.end()) {
return true;
}
}
return false;
}
bool GridService::InView(int a_grid, int b_grid)
{
return a_grid + grid_offset_arr_[0] == b_grid ||
a_grid + grid_offset_arr_[1] == b_grid ||
a_grid + grid_offset_arr_[2] == b_grid ||
a_grid + grid_offset_arr_[3] == b_grid ||
a_grid + grid_offset_arr_[4] == b_grid ||
a_grid + grid_offset_arr_[5] == b_grid ||
a_grid + grid_offset_arr_[6] == b_grid ||
a_grid + grid_offset_arr_[7] == b_grid ||
a_grid + grid_offset_arr_[8] == b_grid;
}
void GridService::RemoveFromGridList(std::set<GridCell*>& grid_list, Entity* entity)
{
for (auto& grid : grid_list) {
switch (entity->entity_type) {
case ET_Player:
{
grid->human_list.erase((Human*)entity);
}
break;
case ET_Bullet:
{
grid->bullet_list.erase((Bullet*)entity);
}
break;
default:
{
grid->entity_list.erase(entity);
}
break;
}
}
}
void GridService::GetGridList(int grid_id, int offset,
std::set<GridCell*>& grid_list)
{
if (offset <1 || offset > 9) {
abort();
}
if (grid_id <= 0 || grid_id >= max_grid_id_) {
return;
}
int tmp_grid_id = grid_id + grid_offset_arr_[offset - 1];
if (tmp_grid_id > 0) {
grid_list.insert(&cells_[tmp_grid_id]);
}
}
void GridService::ComputeDiff(int old_grid_id, int new_grid_id,
std::set<GridCell*>& grid_list,
std::set<GridCell*>& inc_grid_list,
std::set<GridCell*>& dec_grid_list)
{
int diff_grid = new_grid_id - old_grid_id;
#if 1
{
std::set<GridCell*> new_grid_list;
GetAllCells(new_grid_id, new_grid_list);
for (auto& cell : new_grid_list) {
if (grid_list.find(cell) == grid_list.end()) {
inc_grid_list.insert(cell);
}
}
for (auto& cell : grid_list) {
if (new_grid_list.find(cell) == new_grid_list.end()) {
dec_grid_list.insert(cell);
}
}
}
#else
if (diff_grid == 1) {
Get369(new_grid_id, inc_grid_list);
Get147(old_grid_id, dec_grid_list);
} else if (diff_grid == -1) {
Get147(new_grid_id, inc_grid_list);
Get369(old_grid_id, dec_grid_list);
} else if (diff_grid == cell_count_per_row_) {
Get789(new_grid_id, inc_grid_list);
Get123(old_grid_id, dec_grid_list);
} else if (diff_grid + cell_count_per_row_ == 0) {
Get123(new_grid_id, inc_grid_list);
Get789(old_grid_id, dec_grid_list);
} else if (diff_grid + cell_count_per_row_ == 1) {
Get123(new_grid_id, inc_grid_list);
GetGridList(new_grid_id, 6, inc_grid_list);
GetGridList(new_grid_id, 9, inc_grid_list);
GetGridList(old_grid_id, 1, dec_grid_list);
GetGridList(old_grid_id, 4, dec_grid_list);
Get789(old_grid_id, dec_grid_list);
} else if (diff_grid + cell_count_per_row_ == -1) {
Get123(new_grid_id, inc_grid_list);
GetGridList(new_grid_id, 4, inc_grid_list);
GetGridList(new_grid_id, 7, inc_grid_list);
GetGridList(old_grid_id, 6, dec_grid_list);
GetGridList(old_grid_id, 9, dec_grid_list);
Get789(old_grid_id, dec_grid_list);
} else if (diff_grid == cell_count_per_row_ + 1) {
Get789(new_grid_id, inc_grid_list);
GetGridList(new_grid_id, 3, inc_grid_list);
GetGridList(new_grid_id, 6, inc_grid_list);
GetGridList(old_grid_id, 4, dec_grid_list);
GetGridList(old_grid_id, 7, dec_grid_list);
Get123(old_grid_id, dec_grid_list);
} else if (diff_grid == cell_count_per_row_ - 1) {
Get789(new_grid_id, inc_grid_list);
GetGridList(new_grid_id, 1, inc_grid_list);
GetGridList(new_grid_id, 4, inc_grid_list);
GetGridList(old_grid_id, 6, dec_grid_list);
GetGridList(old_grid_id, 9, dec_grid_list);
Get123(old_grid_id, dec_grid_list);
} else {
std::set<GridCell*> new_grid_list;
GetAllCells(new_grid_id, new_grid_list);
for (auto& cell : new_grid_list) {
if (grid_list.find(cell) == grid_list.end()) {
inc_grid_list.insert(cell);
}
}
for (auto& cell : grid_list) {
if (new_grid_list.find(cell) == new_grid_list.end()) {
dec_grid_list.insert(cell);
}
}
}
#endif
grid_list.clear();
GetAllCells(new_grid_id, grid_list);
}