This commit is contained in:
aozhiwei 2019-06-13 11:44:33 +08:00
parent b0013b1852
commit 2decdfd641
2 changed files with 85 additions and 10 deletions

View File

@ -1,5 +1,6 @@
#include "precompile.h" #include "precompile.h"
#include <math.h>
#include <memory.h> #include <memory.h>
#include "mapservice.h" #include "mapservice.h"
@ -13,6 +14,18 @@ MapService::MapService()
MapService::~MapService() MapService::~MapService()
{ {
for (auto pair : node_hash_) {
CellNode* node = pair.second;
while (node) {
CellNode* pdelnode = node;
node = node->next;
list_del_init(&pdelnode->entry);
delete pdelnode;
}
}
node_hash_.clear();
if (map_cells_) { if (map_cells_) {
free(map_cells_); free(map_cells_);
map_cells_ = nullptr; map_cells_ = nullptr;
@ -41,24 +54,85 @@ void MapService::UnInit()
void MapService::AddCollider(ColliderComponent* collider) void MapService::AddCollider(ColliderComponent* collider)
{ {
int grid_id = GetGridId(collider->owner->pos.x, collider->owner->pos.y); CellNode* top_node = nullptr;
CellNode* bot_node = nullptr;
switch (collider->type) { switch (collider->type) {
case CT_Aabb: case CT_Aabb:
{
}
break;
case CT_Circle: case CT_Circle:
{ {
AabbCollider aabb;
if (collider->type == CT_Aabb) {
aabb = *((AabbCollider*)collider);
} else if (collider->type == CT_Circle) {
CircleCollider* circle_box = (CircleCollider*)collider;
aabb.owner = circle_box->owner;
aabb._min.x = circle_box->owner->pos.x - circle_box->rad;
aabb._min.y = circle_box->owner->pos.y - circle_box->rad;
aabb._max.x = circle_box->owner->pos.x + circle_box->rad;
aabb._max.y = circle_box->owner->pos.y + circle_box->rad;
} else {
return;
}
float min_x = (collider->owner->pos + aabb._min).x - 2;
float min_y = (collider->owner->pos + aabb._min).y - 2;
float max_x = (collider->owner->pos + aabb._max).x + 2;
float max_y = (collider->owner->pos + aabb._max).y + 2;
int min_grid_x = ceil(min_x / cell_width_);
int min_grid_y = ceil(min_y / cell_width_);
int max_grid_x = ceil(max_x / cell_width_);
int max_grid_y = ceil(max_y / cell_width_);
if (!(min_grid_x >= 0 && max_grid_x < map_width_)) {
abort();
}
if (!(min_grid_y >= 0 && max_grid_y < map_height_)) {
abort();
}
for (int x = min_grid_x; x < max_grid_x; ++x) {
for (int y = min_grid_y; y < max_grid_y; ++y) {
int grid_id = x + y * map_width_;
list_head* head = &map_cells_[grid_id];
if (head->next == nullptr && head->prev == nullptr) {
INIT_LIST_HEAD(head);
}
CellNode* node = new CellNode();
node->collider = collider;
list_add_tail(&node->entry, head);
node->next = top_node;
top_node = node;
if (!bot_node) {
bot_node = node;
}
}
}
} }
break; break;
} }
if (top_node) {
auto pair = node_hash_.find(collider);
if (pair != node_hash_.end()) {
bot_node->next = pair->second;
pair->second = top_node;
} else {
node_hash_[collider] = top_node;
}
}
} }
void MapService::RemoveCollider(ColliderComponent* collider) void MapService::RemoveCollider(ColliderComponent* collider)
{ {
auto pair = node_hash_.find(collider);
if (pair != node_hash_.end()) {
CellNode* node = pair->second;
while (node) {
CellNode* pdelnode = node;
node = node->next;
list_del_init(&pdelnode->entry);
delete pdelnode;
}
node_hash_.erase(pair);
}
} }
bool MapService::Walkable(float world_x, float world_y) bool MapService::Walkable(float world_x, float world_y)
@ -68,10 +142,11 @@ bool MapService::Walkable(float world_x, float world_y)
return false; return false;
} }
list_head& node = map_cells_[grid_id]; list_head& node = map_cells_[grid_id];
return node.next == nullptr && node.prev == nullptr; return (node.next == nullptr && node.prev == nullptr) ||
list_empty(&node);
} }
void MapService::TouhcAroundCell(float world_x, float world_y, void MapService::TouchAroundCell(float world_x, float world_y,
std::function<bool (ColliderComponent*)> callback) std::function<bool (ColliderComponent*)> callback)
{ {

View File

@ -5,7 +5,7 @@ class ColliderComponent;
struct CellNode struct CellNode
{ {
ColliderComponent* collider; ColliderComponent* collider;
list_head entity; list_head entry;
CellNode* next = nullptr; CellNode* next = nullptr;
}; };
@ -21,7 +21,7 @@ class MapService
void AddCollider(ColliderComponent* collider); void AddCollider(ColliderComponent* collider);
void RemoveCollider(ColliderComponent* collider); void RemoveCollider(ColliderComponent* collider);
bool Walkable(float world_x, float world_y); bool Walkable(float world_x, float world_y);
void TouhcAroundCell(float world_x, float world_y, void TouchAroundCell(float world_x, float world_y,
std::function<bool (ColliderComponent*)> callback); std::function<bool (ColliderComponent*)> callback);
private: private:
@ -34,6 +34,6 @@ class MapService
int cell_width_ = 0; int cell_width_ = 0;
int max_grid_id_ = 0; int max_grid_id_ = 0;
int grid_offset_arr_[9] = {0}; int grid_offset_arr_[9] = {0};
std::map<ColliderComponent*, CellNode> node_hash_; std::map<ColliderComponent*, CellNode*> node_hash_;
}; };