game2004/server/gameserver/gridservice.cc
aozhiwei 006154f6af 1
2020-05-28 10:32:13 +08:00

329 lines
9.5 KiB
C++

#include "precompile.h"
#include "gridservice.h"
#include "human.h"
#include "bullet.h"
#include "room.h"
GridCell::GridCell()
{
human_list.reserve(MAX_ROOM_IDX);
entity_list.reserve(MAX_ROOM_IDX);
bullet_list.reserve(MAX_ROOM_IDX);
for (int i = 0; i < MAX_ROOM_IDX; ++i) {
human_list.push_back(std::set<Human*>());
entity_list.push_back(std::set<Entity*>());
bullet_list.push_back(std::set<Bullet*>());
}
}
/*
1 2 3
4 5 6
7 8 9
*/
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(Room* room, 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(Room* room, 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(room, new_grid_id, grid_list);
}
bool GridService::CanAdd(float x, float y)
{
int new_x = (int)x + cell_width_;
int new_y = (int)x + cell_width_;
return !BroderOverFlow(new_x, new_y);
}
void GridService::ClearRoomData(Room* room)
{
if (room->room_idx <= 0) {
abort();
}
for (int i = 0; i < (max_grid_id_ + 1); ++i) {
GridCell& cell = cells_[i];
cell.human_list[room->room_idx].clear();
cell.entity_list[room->room_idx].clear();
cell.bullet_list[room->room_idx].clear();
}
}
void GridService::AddHuman(Human* hum)
{
int x = (int)hum->GetX() + cell_width_;
int y = (int)hum->GetY() + 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[hum->room->room_idx].insert(hum);
GetAllCells(hum->room, hum->grid_id, hum->grid_list);
}
void GridService::MoveHuman(Human* hum)
{
int new_x = (int)hum->GetX() + cell_width_;
int new_y = (int)hum->GetY() + 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->room,
hum->grid_id,
new_grid_id,
hum->grid_list,
inc_grid_list,
dec_grid_list);
cells_[hum->grid_id].human_list[hum->room->room_idx].erase(hum);
cells_[new_grid_id].human_list[hum->room->room_idx].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->GetX() + cell_width_;
int y = (int)bullet->GetY() + 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[bullet->room->room_idx].insert(bullet);
GetAllCells(bullet->room, bullet->grid_id, bullet->grid_list);
}
void GridService::MoveBullet(Bullet* bullet)
{
int new_x = (int)bullet->GetX() + cell_width_;
int new_y = (int)bullet->GetY() + 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->room,
bullet->grid_id,
new_grid_id,
bullet->grid_list,
inc_grid_list,
dec_grid_list);
cells_[bullet->grid_id].bullet_list[bullet->room->room_idx].erase(bullet);
cells_[new_grid_id].bullet_list[bullet->room->room_idx].insert(bullet);
bullet->grid_id = new_grid_id;
}
}
void GridService::DelBullet(Bullet* bullet)
{
GridCell& cell = cells_[bullet->grid_id];
cell.bullet_list[bullet->room->room_idx].erase(bullet);
}
void GridService::AddRoomEntity(Room* room, Entity* entity)
{
assert(entity->entity_type != ET_Player);
int x = (int)entity->GetX() + cell_width_;
int y = (int)entity->GetY() + 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[room->room_idx].insert(entity);
}
void GridService::DelRoomEntity(Room* room, Entity* entity)
{
GridCell& cell = cells_[entity->grid_id];
cell.entity_list[room->room_idx].erase(entity);
}
void GridService::AddPermanentEntity(Entity* entity)
{
assert(entity->entity_type != ET_Player);
int x = (int)entity->GetX() + cell_width_;
int y = (int)entity->GetY() + 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[0].insert(entity);
}
bool GridService::HumanInGridList(Human* hum, std::set<GridCell*>& grid_list)
{
for (auto& cell : grid_list) {
if (cell->human_list[hum->room->room_idx].find(hum) !=
cell->human_list[hum->room->room_idx].end()) {
return true;
}
}
return false;
}
bool GridService::EntityInGridList(Room* room, Entity* entity, std::set<GridCell*>& grid_list)
{
for (auto& cell : grid_list) {
if (cell->entity_list[0].find(entity) != cell->entity_list[0].end()) {
return true;
}
if (cell->entity_list[room->room_idx].find(entity) !=
cell->entity_list[room->room_idx].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;
}
bool GridService::InView(int grid_id, float x, float y)
{
int b_grid_id = grid_id = x/cell_width_ + (y/cell_width_) * cell_count_per_row_;
return InView(grid_id, b_grid_id);
}
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(Room* room,
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)
{
#if 1
{
std::set<GridCell*> new_grid_list;
GetAllCells(room, 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(room, new_grid_id, grid_list);
}