WIP on master: 3474689 1

This commit is contained in:
aozhiwei 2019-06-28 14:31:23 +08:00
commit 725e992797
6 changed files with 257 additions and 13 deletions

View File

@ -97,6 +97,71 @@ bool ColliderComponent::Intersect(ColliderComponent* b)
return false;
}
bool ColliderComponent::IntersectEx(const a8::Vec2& pos, ColliderComponent* b)
{
switch (type) {
case CT_None:
break;
case CT_Aabb:
{
AabbCollider* a_aabb = (AabbCollider*)this;
switch (b->type) {
case CT_None:
break;
case CT_Aabb:
{
AabbCollider* b_aabb = (AabbCollider*)b;
return a8::IntersectAabbAabb(a_aabb->owner->pos + a_aabb->_min,
a_aabb->owner->pos + a_aabb->_max,
pos + b_aabb->_min,
pos + b_aabb->_max
);
}
break;
case CT_Circle:
{
CircleCollider* b_circle = (CircleCollider*)b;
return a8::IntersectAabbCircle(a_aabb->owner->pos + a_aabb->_min,
a_aabb->owner->pos + a_aabb->_max,
pos + b_circle->pos,
b_circle->rad);
}
break;
}
};
break;
case CT_Circle:
{
CircleCollider* a_circle = (CircleCollider*)this;
switch (b->type) {
case CT_None:
break;
case CT_Aabb:
{
AabbCollider* b_aabb = (AabbCollider*)b;
return a8::IntersectAabbCircle(pos + b_aabb->_min,
pos + b_aabb->_max,
a_circle->owner->pos + a_circle->pos,
a_circle->rad);
}
break;
case CT_Circle:
{
CircleCollider* b_circle = (CircleCollider*)b;
return a8::IntersectCircleCircle(
a_circle->owner->pos + a_circle->pos,
a_circle->rad,
pos + b_circle->pos,
b_circle->rad);
}
break;
}
}
break;
}
return false;
}
bool ColliderComponent::CalcSafePoint(ColliderComponent* b, a8::Vec2& new_pos)
{
switch (type) {
@ -164,6 +229,73 @@ bool ColliderComponent::CalcSafePoint(ColliderComponent* b, a8::Vec2& new_pos)
return false;
}
bool ColliderComponent::CalcSafePointEx(const a8::Vec2& a_pos, ColliderComponent* b, a8::Vec2& new_pos)
{
switch (type) {
case CT_None:
break;
case CT_Aabb:
{
AabbCollider* a_aabb = (AabbCollider*)this;
switch (b->type) {
case CT_Aabb:
{
AabbCollider* b_aabb = (AabbCollider*)b;
return a8::CalcAabbAabbSafePoint(a_pos + a_aabb->_min,
a_pos + a_aabb->_max,
b_aabb->owner->pos + b_aabb->_min,
b_aabb->owner->pos + b_aabb->_max,
new_pos);
}
break;
case CT_Circle:
{
CircleCollider* b_circle = (CircleCollider*)b;
return a8::CalcAabbAabbSafePoint(a_pos + a_aabb->_min,
a_pos + a_aabb->_max,
b_circle->owner->pos + b_circle->pos,
b_circle->rad,
new_pos);
}
break;
}
}
break;
case CT_Circle:
{
CircleCollider* a_circle = (CircleCollider*)this;
switch (b->type) {
case CT_Aabb:
{
AabbCollider* b_aabb = (AabbCollider*)b;
return a8::CalcCircleAabbSafePoint(
a_pos + a_circle->pos,
a_circle->rad,
b_aabb->owner->pos + b_aabb->_min,
b_aabb->owner->pos + b_aabb->_max,
new_pos);
}
break;
case CT_Circle:
{
CircleCollider* b_circle = (CircleCollider*)b;
return a8::CalcCircleCircleSafePoint(
a_pos + a_circle->pos,
a_circle->rad,
b_circle->owner->pos + b_circle->pos,
b_circle->rad,
new_pos);
}
break;
}
}
break;
default:
break;
}
return false;
}
void DestoryCollider(ColliderComponent* collider)
{
switch (collider->type) {

View File

@ -16,8 +16,10 @@ class ColliderComponent
bool active = true;
bool Intersect(ColliderComponent* b);
bool IntersectEx(const a8::Vec2& pos, ColliderComponent* b);
bool IntersectSegment(a8::Vec2& p0, a8::Vec2& p1);
bool CalcSafePoint(ColliderComponent* b, a8::Vec2& new_pos);
bool CalcSafePointEx(const a8::Vec2& a_pos, ColliderComponent* b, a8::Vec2& new_pos);
};
class AabbCollider : public ColliderComponent

View File

@ -61,6 +61,16 @@ bool Entity::TestCollision(ColliderComponent* b)
return false;
}
bool Entity::TestCollisionEx(const a8::Vec2& aabb_pos, AabbCollider& aabb_box)
{
for (auto& a_collider : colliders) {
if (a_collider->IntersectEx(aabb_pos, &aabb_box)) {
return true;
}
}
return false;
}
void Entity::ClearColliders()
{
for (auto& itr : colliders) {

View File

@ -43,6 +43,7 @@ class Entity
virtual void GetCircleBox(CircleCollider& circle_box);
bool TestCollision(Entity* b);
bool TestCollision(ColliderComponent* b);
bool TestCollisionEx(const a8::Vec2& aabb_pos, AabbCollider& aabb_box);
void FindLocationWithTarget(Entity* target);
void BroadcastFullState();
void BroadcastDeleteState();

View File

@ -333,17 +333,6 @@ void Room::FillSMJoinedNotify(Player* self_hum, cs::SMJoinedNotify& msg)
msg.set_player_id(self_hum->entity_uniid);
msg.set_started(false);
msg.set_room_uuid(a8::XValue(room_uuid).GetString());
#if 0
for (auto& pair : uniid_hash_) {
if (pair.second->entity_type == ET_Player) {
Human* hum = (Human*)pair.second;
cs::MFPlayerInfo* info = msg.add_player_infos();
info->set_player_id(hum->entity_uniid);
info->set_team_id(hum->team_id);
info->set_name(hum->name);
}
}
#endif
}
void Room::ScatterDrop(a8::Vec2 center, int drop_id)
@ -735,6 +724,99 @@ void Room::OnPlayerOffline(Player* hum)
}
}
Entity* Room::FindFirstCollisonEntity(const a8::Vec2& aabb_pos, AabbCollider& aabb_box)
{
Entity* target = nullptr;
std::set<GridCell*> grid_list;
grid_service.GetAllCellsByXy(aabb_pos.x, aabb_pos.y, grid_list);
for (auto& grid : grid_list) {
for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Obstacle:
{
if (!target) {
if (entity->TestCollisionEx(aabb_pos, aabb_box)) {
target = entity;
}
}
}
break;
case ET_Building:
{
if (!target || target->entity_type != ET_Building) {
AabbCollider building_aabb_box;
entity->GetAabbBox(building_aabb_box);
if (building_aabb_box.IntersectEx(aabb_pos, &aabb_box)) {
target = entity;
}
}
}
break;
}
}
}
return target;
}
void Room::FindLocationWithAabb(Entity* target, const a8::Vec2& aabb_pos, AabbCollider* aabb_box,
float& new_x, float& new_y)
{
a8::Vec2 old_pos = aabb_pos;
a8::Vec2 new_pos = aabb_pos;
AabbCollider target_collider;
target->GetAabbBox(target_collider);
{
bool ret = aabb_box->CalcSafePointEx(aabb_pos, &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) {
a8::Vec2 pos = old_pos + new_pos_dir * i;
Entity* building = nullptr;
std::set<GridCell*> new_grid_list;
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 (entity->TestCollisionEx(pos, *aabb_box)) {
building = entity;
}
}
break;
}
if (building) {
break;
}
}
if (building) {
break;
}
}
if (!building) {
bool is_collision = false;
std::set<ColliderComponent*> colliders;
map_service.GetColliders(pos.x, pos.y, colliders);
for (ColliderComponent* collider : colliders) {
if (collider->IntersectEx(pos, &target_collider)) {
is_collision = true;
break;
}
}
if (!is_collision) {
break;
}
}
}
}
std::set<Human*>* Room::GetAliveTeam()
{
for (auto& pair : team_hash_) {
@ -1116,7 +1198,6 @@ void Room::AirDrop(int appear_time, int box_id)
a8::Vec2 dir = a8::Vec2::UP;
dir.Rotate(a8::RandAngle());
a8::Vec2 box_pos = gas_data.pos_new + dir * (500 + rand() % 300);
#if 1
if (box_pos.x < 1.0f) {
box_pos.x = 1.0f;
}
@ -1129,7 +1210,21 @@ void Room::AirDrop(int appear_time, int box_id)
if (box_pos.y >= MAP_HEIGHT) {
box_pos.y = MAP_HEIGHT - 1;
}
#endif
AabbCollider air_drop_aabb_box;
{
air_drop_aabb_box._min.x = box_pos.x - thing_meta->i->width()/2.0f;
air_drop_aabb_box._min.y = box_pos.y - thing_meta->i->height()/2.0f;
air_drop_aabb_box._max.x = box_pos.x + thing_meta->i->width()/2.0f;
air_drop_aabb_box._max.y = box_pos.y + thing_meta->i->height()/2.0f;
}
Entity* target = FindFirstCollisonEntity(box_pos, air_drop_aabb_box);
if (target) {
float new_x = box_pos.x;
float new_y = box_pos.y;
FindLocationWithAabb(target, box_pos, &air_drop_aabb_box, new_x, new_y);
box_pos.x = new_x;
box_pos.y = new_y;
}
frame_event.AddAirDrop(appear_time, box_id, box_pos);
xtimer.AddDeadLineTimerAndAttach(SERVER_FRAME_RATE * appear_time / 1000.f,
a8::XParams()

View File

@ -30,6 +30,7 @@ class Human;
class Player;
class Building;
class Hero;
class AabbCollider;
class Room
{
public:
@ -93,6 +94,9 @@ public:
std::set<Human*>* GetAliveTeam();
bool CanJoin(const std::string& accountid);
void OnPlayerOffline(Player* hum);
Entity* FindFirstCollisonEntity(const a8::Vec2& aabb_pos, AabbCollider& aabb_box);
void FindLocationWithAabb(Entity* target, const a8::Vec2& aabb_pos, AabbCollider* aabb_box,
float& new_x, float& new_y);
private:
int AllocUniid();