aozhiwei b8362a8754 1
2019-07-15 13:16:01 +08:00

194 lines
4.4 KiB
C++

#include "precompile.h"
#include "entity.h"
#include "collider.h"
#include "room.h"
#include "building.h"
#include "human.h"
#include "app.h"
Entity::Entity()
{
}
Entity::~Entity()
{
ClearColliders();
}
void Entity::Initialize()
{
xtimer_attacher.xtimer = &room->xtimer;
}
void Entity::GetAabbBox(AabbCollider& aabb_box)
{
aabb_box.active = true;
aabb_box.owner = this;
}
void Entity::GetCircleBox(CircleCollider& circle_box)
{
circle_box.active = true;
circle_box.owner = this;
circle_box.rad = 1;
}
bool Entity::TestCollision(Entity* b)
{
App::Instance()->perf.test_times++;
if (b->dead) {
return false;
}
for (auto& a_collider : colliders) {
for (auto& b_collider : b->colliders) {
if (a_collider->Intersect(b_collider)) {
return true;
}
}
}
return false;
}
bool Entity::TestCollision(ColliderComponent* b)
{
for (auto& a_collider : colliders) {
if (a_collider->Intersect(b)) {
return true;
}
}
return false;
}
void Entity::ClearColliders()
{
for (auto& itr : colliders) {
ColliderComponent* collider = itr;
DestoryCollider(collider);
}
colliders.clear();
}
void Entity::FindLocationWithTarget(Entity* target)
{
a8::Vec2 old_pos = pos;
a8::Vec2 new_pos = pos;
AabbCollider a_collider;
GetAabbBox(a_collider);
AabbCollider target_collider;
target->GetAabbBox(target_collider);
{
bool ret = a_collider.CalcSafePoint(&target_collider, new_pos);
if (!ret) {
abort();
}
}
a8::Vec2 new_pos_dir = new_pos - old_pos;
new_pos_dir.Normalize();
float distance = (new_pos - old_pos).Norm();
for (int i = distance; i < 10000000; i += 5) {
pos = old_pos + new_pos_dir * i;
Entity* building = nullptr;
std::set<GridCell*> new_grid_list;
room->grid_service.GetAllCellsByXy(pos.x, pos.y, new_grid_list);
for (auto& grid : new_grid_list) {
for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Building:
{
if (TestCollision(entity)) {
building = entity;
}
}
break;
default:
break;
}
if (building) {
break;
}
}
if (building) {
break;
}
}
if (!building) {
bool is_collision = false;
std::set<ColliderComponent*> colliders;
room->map_service.GetColliders(pos.x, pos.y, colliders);
for (ColliderComponent* collider : colliders) {
if (TestCollision(collider)) {
is_collision = true;
break;
}
}
if (!is_collision) {
break;
}
}
}
room->grid_service.RemoveFromGridList(grid_list, this);
{
grid_list.clear();
switch (entity_type) {
case ET_Player:
{
room->grid_service.AddHuman((Human*)this);
}
break;
case ET_Bullet:
{
room->grid_service.AddBullet((Bullet*)this);
}
break;
default:
{
room->grid_service.AddEntity(this);
}
break;
}
}
}
void Entity::BroadcastFullState()
{
std::set<GridCell*> grid_list;
room->grid_service.GetAllCells(grid_id, grid_list);
for (auto& grid : grid_list) {
for (Human* hum : grid->human_list) {
hum->AddToNewObjects(this);
}
}
}
void Entity::BroadcastDeleteState()
{
std::set<GridCell*> grid_list;
room->grid_service.GetAllCells(grid_id, grid_list);
for (auto& grid : grid_list) {
for (Human* hum : grid->human_list) {
hum->RemoveObjects(this);
}
}
}
void Entity::AddCollider(ColliderComponent* collider)
{
colliders.push_back(collider);
}
void Entity::NotifyDelObject()
{
std::set<GridCell*> grid_list;
room->grid_service.GetAllCellsByXy(pos.x, pos.y, grid_list);
for (auto& grid : grid_list) {
for (Human* hum: grid->human_list) {
hum->RemoveObjects(this);
}
}
}