418 lines
12 KiB
C++
418 lines
12 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->GetRoomIdx() <= 0) {
|
|
abort();
|
|
}
|
|
for (int i = 0; i < (max_grid_id_ + 1); ++i) {
|
|
GridCell& cell = cells_[i];
|
|
cell.human_list[room->GetRoomIdx()].clear();
|
|
cell.entity_list[room->GetRoomIdx()].clear();
|
|
cell.bullet_list[room->GetRoomIdx()].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->SetGridId(x/cell_width_ + (y/cell_width_) * cell_count_per_row_);
|
|
if (hum->GetGridId() == 0 || hum->GetGridId() > max_grid_id_) {
|
|
abort();
|
|
}
|
|
cells_[hum->GetGridId()].human_list[hum->room->GetRoomIdx()].insert(hum);
|
|
GetAllCells(hum->room, hum->GetGridId(), hum->GetGridList());
|
|
}
|
|
|
|
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->GetGridId()) {
|
|
std::set<GridCell*> inc_grid_list;
|
|
std::set<GridCell*> dec_grid_list;
|
|
std::set<GridCell*> old_grid_list = hum->GetGridList();
|
|
ComputeDiff(hum->room,
|
|
hum->GetGridId(),
|
|
new_grid_id,
|
|
hum->GetGridList(),
|
|
inc_grid_list,
|
|
dec_grid_list);
|
|
cells_[hum->GetGridId()].human_list[hum->room->GetRoomIdx()].erase(hum);
|
|
cells_[new_grid_id].human_list[hum->room->GetRoomIdx()].insert(hum);
|
|
hum->SetGridId(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->SetGridId(x/cell_width_ + (y/cell_width_) * cell_count_per_row_);
|
|
if (bullet->GetGridId() == 0 || bullet->GetGridId() > max_grid_id_) {
|
|
abort();
|
|
}
|
|
cells_[bullet->GetGridId()].bullet_list[bullet->room->GetRoomIdx()].insert(bullet);
|
|
GetAllCells(bullet->room, bullet->GetGridId(), bullet->GetGridList());
|
|
}
|
|
|
|
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->GetGridId()) {
|
|
std::set<GridCell*> inc_grid_list;
|
|
std::set<GridCell*> dec_grid_list;
|
|
std::set<GridCell*> old_grid_list = bullet->GetGridList();
|
|
ComputeDiff(bullet->room,
|
|
bullet->GetGridId(),
|
|
new_grid_id,
|
|
bullet->GetGridList(),
|
|
inc_grid_list,
|
|
dec_grid_list);
|
|
cells_[bullet->GetGridId()].bullet_list[bullet->room->GetRoomIdx()].erase(bullet);
|
|
cells_[new_grid_id].bullet_list[bullet->room->GetRoomIdx()].insert(bullet);
|
|
bullet->SetGridId(new_grid_id);
|
|
}
|
|
}
|
|
|
|
void GridService::DelBullet(Bullet* bullet)
|
|
{
|
|
GridCell& cell = cells_[bullet->GetGridId()];
|
|
cell.bullet_list[bullet->room->GetRoomIdx()].erase(bullet);
|
|
}
|
|
|
|
void GridService::AddRoomEntity(Room* room, Entity* entity)
|
|
{
|
|
assert(!entity->IsEntityType(ET_Player));
|
|
int x = (int)entity->GetX() + cell_width_;
|
|
int y = (int)entity->GetY() + cell_width_;
|
|
if (BroderOverFlow(x, y)) {
|
|
abort();
|
|
}
|
|
entity->SetGridId(x/cell_width_ + (y/cell_width_) * cell_count_per_row_);
|
|
if (entity->GetGridId() == 0 || entity->GetGridId() > max_grid_id_) {
|
|
abort();
|
|
}
|
|
cells_[entity->GetGridId()].entity_list[room->GetRoomIdx()].insert(entity);
|
|
}
|
|
|
|
void GridService::DelRoomEntity(Room* room, Entity* entity)
|
|
{
|
|
GridCell& cell = cells_[entity->GetGridId()];
|
|
cell.entity_list[room->GetRoomIdx()].erase(entity);
|
|
}
|
|
|
|
void GridService::AddPermanentEntity(Entity* entity)
|
|
{
|
|
assert(!entity->IsEntityType(ET_Player));
|
|
int x = (int)entity->GetX() + cell_width_;
|
|
int y = (int)entity->GetY() + cell_width_;
|
|
if (BroderOverFlow(x, y)) {
|
|
abort();
|
|
}
|
|
entity->SetGridId(x/cell_width_ + (y/cell_width_) * cell_count_per_row_);
|
|
if (entity->GetGridId() == 0 || entity->GetGridId() > max_grid_id_) {
|
|
abort();
|
|
}
|
|
cells_[entity->GetGridId()].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->GetRoomIdx()].find(hum) !=
|
|
cell->human_list[hum->room->GetRoomIdx()].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->GetRoomIdx()].find(entity) !=
|
|
cell->entity_list[room->GetRoomIdx()].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 = x/cell_width_ + (y/cell_width_) * cell_count_per_row_;
|
|
bool in_view = InView(grid_id, b_grid_id);
|
|
#ifdef DEBUG
|
|
if (in_view) {
|
|
a8::UdpLog::Instance()->Debug("InView %d %d %f %f",
|
|
{
|
|
grid_id,
|
|
b_grid_id,
|
|
x,
|
|
y
|
|
});
|
|
}
|
|
#endif
|
|
return in_view;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void GridService::TouchLayer0EntityList(std::set<GridCell*>& grid_list,
|
|
std::function<void (Entity*, bool&)> func)
|
|
{
|
|
bool stop = false;
|
|
for (auto& cell : grid_list) {
|
|
for (Entity* entity : cell->entity_list[0]) {
|
|
func(entity, stop);
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GridService::TouchLayer1EntityList(int room_idx,
|
|
std::set<GridCell*>& grid_list,
|
|
std::function<void (Entity*, bool&)> func)
|
|
{
|
|
bool stop = false;
|
|
for (auto& cell : grid_list) {
|
|
for (Entity* entity : cell->entity_list[room_idx]) {
|
|
func(entity, stop);
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GridService::TouchAllLayerEntityList(int room_idx,
|
|
std::set<GridCell*>& grid_list,
|
|
std::function<void (Entity*, bool&)> func)
|
|
{
|
|
bool stop = false;
|
|
for (auto& cell : grid_list) {
|
|
for (Entity* entity : cell->entity_list[0]) {
|
|
func(entity, stop);
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
for (Entity* entity : cell->entity_list[room_idx]) {
|
|
func(entity, stop);
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GridService::TouchAllLayerHumanList(int room_idx,
|
|
std::set<GridCell*>& grid_list,
|
|
std::function<void (Human*, bool&)> func)
|
|
{
|
|
bool stop = false;
|
|
for (auto& cell : grid_list) {
|
|
for (Human* hum : cell->human_list[room_idx]) {
|
|
func(hum, stop);
|
|
if (stop) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GridService::DeatchHuman(Human* target)
|
|
{
|
|
for (auto& cell : target->GetGridList()) {
|
|
for (Human* hum : cell->human_list[target->room->GetRoomIdx()]) {
|
|
hum->AddOutObjects(target);
|
|
}
|
|
cell->human_list[target->room->GetRoomIdx()].erase(target);
|
|
}
|
|
target->SetGridId(0);
|
|
target->GetGridList().clear();
|
|
}
|