merge master

This commit is contained in:
aozhiwei 2019-06-11 12:00:59 +08:00
commit 4a3ece88f7
11 changed files with 236 additions and 13 deletions

View File

@ -33,7 +33,7 @@ void Building::RecalcSelfCollider()
obj.y() - obj.height()/2.0 - meta->i->tileheight()/2.0); obj.y() - obj.height()/2.0 - meta->i->tileheight()/2.0);
collider->_max = Vector2D(obj.x() + obj.width()/2.0 - meta->i->tilewidth()/2.0, collider->_max = Vector2D(obj.x() + obj.width()/2.0 - meta->i->tilewidth()/2.0,
obj.y() + obj.height()/2.0 - meta->i->tileheight()/2.0); obj.y() + obj.height()/2.0 - meta->i->tileheight()/2.0);
colliders.push_back(collider); AddCollider(collider);
} }
} }

View File

@ -44,7 +44,7 @@ void Bullet::RecalcSelfCollider()
if (!self_collider_) { if (!self_collider_) {
self_collider_ = new CircleCollider(); self_collider_ = new CircleCollider();
self_collider_->owner = this; self_collider_->owner = this;
colliders.push_back(self_collider_); AddCollider(self_collider_);
} }
self_collider_->pos = Vector2D(); self_collider_->pos = Vector2D();
self_collider_->rad = gun_meta->i->bullet_rad(); self_collider_->rad = gun_meta->i->bullet_rad();
@ -99,7 +99,6 @@ void Bullet::OnHit(std::set<Entity*>& objects)
obstacle->meta->i->damage() > 0.01f) { obstacle->meta->i->damage() > 0.01f) {
obstacle->Explosion(this); obstacle->Explosion(this);
} }
obstacle->ClearColliders();
room->ScatterDrop(obstacle->pos, obstacle->meta->i->drop()); room->ScatterDrop(obstacle->pos, obstacle->meta->i->drop());
} }
obstacle->BroadcastFullState(); obstacle->BroadcastFullState();

View File

@ -165,3 +165,5 @@ const int FIGHTING_MODE_BULLET_NUM = 10000 * 10000;
const int MAX_NODE_ID = 8; const int MAX_NODE_ID = 8;
const int MAX_INSTANCE_ID = 500; const int MAX_INSTANCE_ID = 500;
const int WALK_ZONE_WIDTH = 100;

View File

@ -46,6 +46,9 @@ void Entity::GetCircleBox(CircleCollider& circle_box)
bool Entity::TestCollision(Entity* b) bool Entity::TestCollision(Entity* b)
{ {
App::Instance()->perf.test_times++; App::Instance()->perf.test_times++;
if (b->dead) {
return false;
}
for (auto& a_collider : colliders) { for (auto& a_collider : colliders) {
for (auto& b_collider : b->colliders) { for (auto& b_collider : b->colliders) {
if (a_collider->Intersect(b_collider)) { if (a_collider->Intersect(b_collider)) {
@ -156,3 +159,8 @@ void Entity::BroadcastDeleteState()
} }
} }
} }
void Entity::AddCollider(ColliderComponent* collider)
{
colliders.push_back(collider);
}

View File

@ -50,9 +50,10 @@ class Entity
Room* room = nullptr; Room* room = nullptr;
Vector2D pos; Vector2D pos;
int updated_times = 0; int updated_times = 0;
std::list<ColliderComponent*> colliders;
bool deleted = false; bool deleted = false;
a8::XTimerAttacher xtimer_attacher; a8::XTimerAttacher xtimer_attacher;
bool dead = false;
long long dead_frameno = 0;
int grid_id = 0; int grid_id = 0;
std::set<GridCell*> grid_list; std::set<GridCell*> grid_list;
@ -69,9 +70,13 @@ class Entity
virtual void GetAabbBox(AabbCollider& aabb_box); virtual void GetAabbBox(AabbCollider& aabb_box);
virtual void GetCircleBox(CircleCollider& circle_box); virtual void GetCircleBox(CircleCollider& circle_box);
bool TestCollision(Entity* b); bool TestCollision(Entity* b);
void ClearColliders();
void FindLocationWithTarget(Entity* target); void FindLocationWithTarget(Entity* target);
void BroadcastFullState(); void BroadcastFullState();
void BroadcastDeleteState(); void BroadcastDeleteState();
void AddCollider(ColliderComponent* collider);
private:
std::list<ColliderComponent*> colliders;
void ClearColliders();
}; };

View File

@ -25,7 +25,7 @@ void Hero::RecalcSelfCollider()
if (!self_collider_) { if (!self_collider_) {
self_collider_ = new CircleCollider(); self_collider_ = new CircleCollider();
self_collider_->owner = this; self_collider_->owner = this;
colliders.push_back(self_collider_); AddCollider(self_collider_);
} }
self_collider_->pos = Vector2D(); self_collider_->pos = Vector2D();
self_collider_->rad = master->GetRadius(); self_collider_->rad = master->GetRadius();

View File

@ -47,12 +47,19 @@ Human::Human():Entity()
inventory_[IS_12GAUGE] = FIGHTING_MODE_BULLET_NUM; inventory_[IS_12GAUGE] = FIGHTING_MODE_BULLET_NUM;
inventory_[IS_RPG] = FIGHTING_MODE_BULLET_NUM; inventory_[IS_RPG] = FIGHTING_MODE_BULLET_NUM;
} }
walk_zone = new AabbCollider();
walk_zone->_min.x = -(WALK_ZONE_WIDTH / 2.0f);
walk_zone->_min.y = -(WALK_ZONE_WIDTH / 2.0f);
walk_zone->_max.x = WALK_ZONE_WIDTH / 2.0f;
walk_zone->_max.y = WALK_ZONE_WIDTH / 2.0f;
} }
Human::~Human() Human::~Human()
{ {
delete movement ; delete movement ;
movement = nullptr; movement = nullptr;
delete walk_zone;
walk_zone = nullptr;
} }
void Human::Initialize() void Human::Initialize()
@ -279,7 +286,7 @@ void Human::RecalcSelfCollider()
if (!self_collider_) { if (!self_collider_) {
self_collider_ = new CircleCollider(); self_collider_ = new CircleCollider();
self_collider_->owner = this; self_collider_->owner = this;
colliders.push_back(self_collider_); AddCollider(self_collider_);
} }
self_collider_->pos = Vector2D(); self_collider_->pos = Vector2D();
self_collider_->rad = meta->i->radius(); self_collider_->rad = meta->i->radius();
@ -327,6 +334,43 @@ bool Human::IsCollision()
return !objects.empty(); return !objects.empty();
} }
bool Human::IsCollisionInWalkZone()
{
if (room->OverBorder(pos, meta->i->radius())){
return true;
}
if (a8::HasBitFlag(status, HS_Jump)) {
return false;
}
if (last_collider && !last_collider->owner->dead) {
CircleCollider circle_box;
GetCircleBox(circle_box);
if (circle_box.Intersect(last_collider)) {
if (last_collision_door != last_collider->owner) {
return true;
}
}
}
for (Entity* entity : seen_objects) {
switch (entity->entity_type) {
case ET_Obstacle:
case ET_Building:
{
if (!entity->dead && TestCollision(entity)) {
if (last_collision_door != entity) {
return true;
}
}
}
break;
}
}
return false;
}
void Human::FindPath() void Human::FindPath()
{ {
Vector2D old_pos = pos; Vector2D old_pos = pos;
@ -372,6 +416,51 @@ void Human::FindPath()
pos = old_pos; pos = old_pos;
} }
void Human::FindPathInWalkZone()
{
Vector2D old_pos = pos;
{
float up_dot = Vector2D::UP.Dot(move_dir);
bool at_left_side = Vector2D::LEFT.Dot(move_dir) > 0.0001f;
if (std::abs(up_dot) <= 0.001f) { //相互垂直
//向上
pos = old_pos + Vector2D::UP;
if (!IsCollisionInWalkZone()) {
return;
} else {
//向下
pos = old_pos + Vector2D::DOWN;
if (!IsCollisionInWalkZone()) {
return;
}
}
} else if (up_dot > 0.001f) { //基本相同
pos = old_pos + (at_left_side ? Vector2D::LEFT : Vector2D::RIGHT);
if (!IsCollisionInWalkZone()) {
return;
} else {
//向上
pos = old_pos + Vector2D::UP;
if (!IsCollisionInWalkZone()) {
return;
}
}
} else if (up_dot < 0.001f) { //基本相反
pos = old_pos + (at_left_side ? Vector2D::LEFT : Vector2D::RIGHT);
if (!IsCollisionInWalkZone()) {
return;
} else {
//向下
pos = old_pos + Vector2D::DOWN;
if (!IsCollisionInWalkZone()) {
return;
}
}
}
}
pos = old_pos;
}
float Human::GetRadius() float Human::GetRadius()
{ {
return meta->i->radius(); return meta->i->radius();
@ -1719,6 +1808,104 @@ int Human::GetSkinConfigLv(int skin_id)
return itr != skin_configs.end() ? itr->second : 0; return itr != skin_configs.end() ? itr->second : 0;
} }
void Human::GenerateWalkZone()
{
in_walk_zone = true;
walk_zone_center = pos;
seen_colliders.clear();
seen_objects.clear();
last_collider = nullptr;
for (auto& grid : grid_list) {
for (Entity* entity : grid->entity_list) {
switch (entity->entity_type) {
case ET_Obstacle:
case ET_Building:
{
if (
(last_collision_door == nullptr || last_collision_door != entity)
){
AabbCollider aabb_box;
entity->GetAabbBox(aabb_box);
if (IntersectAabbAabb(walk_zone_center + walk_zone->_min,
walk_zone_center + walk_zone->_max,
aabb_box.owner->pos + aabb_box._min,
aabb_box.owner->pos + aabb_box._max)
) {
seen_objects.insert(entity);
}
}
}
break;
default:
{
}
break;
}
}
}//end for
}
bool Human::InWalkZone()
{
float delta = 10.0f;
if (pos.x - meta->i->radius() < walk_zone_center.x + walk_zone->_min.x - delta) {
return false;
}
if (pos.x + meta->i->radius() > walk_zone_center.x + walk_zone->_max.x - delta) {
return false;
}
if (pos.y - meta->i->radius() < walk_zone_center.y + walk_zone->_min.y - delta) {
return false;
}
if (pos.y + meta->i->radius() > walk_zone_center.y + walk_zone->_max.y - delta) {
return false;
}
return false;
}
void Human::ClearWalkZone()
{
in_walk_zone = false;
}
void Human::UpdateMoveInWalkZone(int speed)
{
for (int i = 0; i < speed; ++i) {
Vector2D old_pos = pos;
pos = pos + move_dir;
if (InWalkZone()) {
if (IsCollisionInWalkZone()) {
pos = old_pos;
FindPathInWalkZone();
if (rand() % 3 == 0) {
i += 1;
}
}
} else {
ClearWalkZone();
pos = old_pos;
UpdateMoveInMap(speed - i);
return;
}
room->grid_service.MoveHuman(this);
}
}
void Human::UpdateMoveInMap(int speed)
{
for (int i = 0; i < speed; ++i) {
Vector2D old_pos = pos;
pos = pos + move_dir;
if (IsCollision()) {
pos = old_pos;
GenerateWalkZone();
UpdateMoveInWalkZone(speed - i);
return;
}
room->grid_service.MoveHuman(this);
}
}
void Human::ClearFrameData() void Human::ClearFrameData()
{ {
if (!new_objects.empty()) { if (!new_objects.empty()) {

View File

@ -29,6 +29,7 @@ enum HumanStatus
struct xtimer_list; struct xtimer_list;
class CircleCollider; class CircleCollider;
class AabbCollider;
class Obstacle; class Obstacle;
class MovementComponent; class MovementComponent;
class Human : public Entity class Human : public Entity
@ -123,7 +124,9 @@ class Human : public Entity
void Shot(Vector2D& target_dir); void Shot(Vector2D& target_dir);
void RecalcSelfCollider(); void RecalcSelfCollider();
bool IsCollision(); bool IsCollision();
bool IsCollisionInWalkZone();
void FindPath(); void FindPath();
void FindPathInWalkZone();
float GetRadius(); float GetRadius();
float GetMaxHP(); float GetMaxHP();
void UpdatePoisoning(); void UpdatePoisoning();
@ -186,6 +189,13 @@ class Human : public Entity
int GetWeaponConfigLv(int weapon_id); int GetWeaponConfigLv(int weapon_id);
int GetSkinConfigLv(int skin_id); int GetSkinConfigLv(int skin_id);
protected:
void GenerateWalkZone();
bool InWalkZone();
void ClearWalkZone();
void UpdateMoveInWalkZone(int speed);
void UpdateMoveInMap(int speed);
private: private:
void ClearFrameData(); void ClearFrameData();
void GenBattleReportData(a8::MutableXObject* params); void GenBattleReportData(a8::MutableXObject* params);
@ -222,6 +232,13 @@ protected:
bool follow_synced_active_player = false; bool follow_synced_active_player = false;
MovementComponent* movement = nullptr; MovementComponent* movement = nullptr;
bool in_walk_zone = false;
Vector2D walk_zone_center;
AabbCollider* walk_zone = nullptr;
std::set<ColliderComponent*> seen_colliders;
std::set<Entity*> seen_objects;
ColliderComponent* last_collider = nullptr;
private: private:
CircleCollider* self_collider_ = nullptr; CircleCollider* self_collider_ = nullptr;
long long last_sync_gas_frameno = 0; long long last_sync_gas_frameno = 0;

View File

@ -33,7 +33,7 @@ void Obstacle::RecalcSelfCollider()
if (!self_collider2_) { if (!self_collider2_) {
self_collider2_ = new AabbCollider(); self_collider2_ = new AabbCollider();
self_collider2_->owner = this; self_collider2_->owner = this;
colliders.push_back(self_collider2_); AddCollider(self_collider2_);
} }
if (door_state == DoorStateClose) { if (door_state == DoorStateClose) {
self_collider2_->_min = Vector2D(0.0f - door_state0->width() / 2.0f, self_collider2_->_min = Vector2D(0.0f - door_state0->width() / 2.0f,
@ -51,7 +51,7 @@ void Obstacle::RecalcSelfCollider()
if (!self_collider_) { if (!self_collider_) {
self_collider_ = new CircleCollider(); self_collider_ = new CircleCollider();
self_collider_->owner = this; self_collider_->owner = this;
colliders.push_back(self_collider_); AddCollider(self_collider_);
} }
self_collider_->pos = Vector2D(); self_collider_->pos = Vector2D();
self_collider_->rad = meta->i->height() / 2.0; self_collider_->rad = meta->i->height() / 2.0;
@ -62,7 +62,7 @@ void Obstacle::RecalcSelfCollider()
if (!self_collider2_) { if (!self_collider2_) {
self_collider2_ = new AabbCollider(); self_collider2_ = new AabbCollider();
self_collider2_->owner = this; self_collider2_->owner = this;
colliders.push_back(self_collider2_); AddCollider(self_collider2_);
} }
self_collider2_->_min = Vector2D(meta->i->width() / -2.0f, meta->i->height() / -2.0f); self_collider2_->_min = Vector2D(meta->i->width() / -2.0f, meta->i->height() / -2.0f);
self_collider2_->_max = Vector2D(meta->i->width() / 2.0f, meta->i->height() / 2.0f); self_collider2_->_max = Vector2D(meta->i->width() / 2.0f, meta->i->height() / 2.0f);
@ -216,7 +216,6 @@ void Obstacle::Explosion(Bullet* bullet)
obstacle->dead = obstacle->health <= 0.01f; obstacle->dead = obstacle->health <= 0.01f;
obstacle->dead_frameno = room->frame_no; obstacle->dead_frameno = room->frame_no;
if (obstacle->dead) { if (obstacle->dead) {
obstacle->ClearColliders();
room->ScatterDrop(obstacle->pos, obstacle->meta->i->drop()); room->ScatterDrop(obstacle->pos, obstacle->meta->i->drop());
} }
obstacle->BroadcastFullState(); obstacle->BroadcastFullState();

View File

@ -25,8 +25,6 @@ class Obstacle : public Entity
public: public:
MetaData::MapThing* meta = nullptr; MetaData::MapThing* meta = nullptr;
float health = 0.0f; float health = 0.0f;
bool dead = false;
long long dead_frameno = 0;
bool is_door = false; bool is_door = false;
int door_id = 0; int door_id = 0;

View File

@ -13,6 +13,7 @@
#include "loot.h" #include "loot.h"
#include "app.h" #include "app.h"
#include "movement.h" #include "movement.h"
#include "collider.h"
Player::Player():Human() Player::Player():Human()
{ {
@ -121,6 +122,7 @@ void Player::UpdateMove()
#endif #endif
return; return;
} }
#if 0
int speed = std::max(1, (int)GetSpeed()); int speed = std::max(1, (int)GetSpeed());
#ifdef RAY_DETECTION #ifdef RAY_DETECTION
for (int i = 0; i < speed; ++i) { for (int i = 0; i < speed; ++i) {
@ -162,6 +164,12 @@ void Player::UpdateMove()
room->grid_service.MoveHuman(this); room->grid_service.MoveHuman(this);
} }
#endif #endif
#endif
if (in_walk_zone) {
UpdateMoveInWalkZone(std::max(1, (int)GetSpeed()));
} else {
UpdateMoveInMap(std::max(1, (int)GetSpeed()));
}
if (last_collision_door && !TestCollision(last_collision_door)) { if (last_collision_door && !TestCollision(last_collision_door)) {
last_collision_door = nullptr; last_collision_door = nullptr;
} }