添加碰撞检测walkzone
This commit is contained in:
parent
5669d2d156
commit
6cf6ab0d20
@ -164,3 +164,5 @@ const int FIGHTING_MODE_BULLET_NUM = 10000 * 10000;
|
||||
|
||||
const int MAX_NODE_ID = 8;
|
||||
const int MAX_INSTANCE_ID = 500;
|
||||
|
||||
const int WALK_ZONE_WIDTH = 100;
|
||||
|
@ -29,6 +29,16 @@ ColliderComponent* Entity::GetBoxBound()
|
||||
return collider;
|
||||
}
|
||||
|
||||
void Entity::GetAabbBox(AabbCollider& aabb_box)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Entity::GetCircleBox(CircleCollider& circle_box)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Entity::TestCollision(Entity* b)
|
||||
{
|
||||
if (b->dead) {
|
||||
|
@ -38,6 +38,8 @@ enum EntitySubType_e
|
||||
class Room;
|
||||
class Obstacle;
|
||||
class ColliderComponent;
|
||||
class AabbCollider;
|
||||
class CircleCollider;
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
@ -65,6 +67,8 @@ class Entity
|
||||
virtual void FillMFObjectFull(cs::MFObjectFull* full_data) {};
|
||||
virtual float GetSpeed() { return 1.0f;};
|
||||
virtual ColliderComponent* GetBoxBound();
|
||||
virtual void GetAabbBox(AabbCollider& aabb_box);
|
||||
virtual void GetCircleBox(CircleCollider& circle_box);
|
||||
bool TestCollision(Entity* b);
|
||||
void FindLocationWithTarget(Entity* target);
|
||||
void BroadcastFullState();
|
||||
|
@ -46,10 +46,17 @@ Human::Human():Entity()
|
||||
inventory_[IS_12GAUGE] = 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()
|
||||
{
|
||||
delete walk_zone;
|
||||
walk_zone = nullptr;
|
||||
}
|
||||
|
||||
void Human::Initialize()
|
||||
@ -322,6 +329,43 @@ bool Human::IsCollision()
|
||||
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()
|
||||
{
|
||||
Vector2D old_pos = pos;
|
||||
@ -367,6 +411,51 @@ void Human::FindPath()
|
||||
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()
|
||||
{
|
||||
return meta->i->radius();
|
||||
@ -1714,6 +1803,104 @@ int Human::GetSkinConfigLv(int skin_id)
|
||||
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()
|
||||
{
|
||||
if (!new_objects.empty()) {
|
||||
|
@ -123,7 +123,9 @@ class Human : public Entity
|
||||
void Shot(Vector2D& target_dir);
|
||||
void RecalcSelfCollider();
|
||||
bool IsCollision();
|
||||
bool IsCollisionInWalkZone();
|
||||
void FindPath();
|
||||
void FindPathInWalkZone();
|
||||
float GetRadius();
|
||||
float GetMaxHP();
|
||||
void UpdatePoisoning();
|
||||
@ -186,6 +188,13 @@ class Human : public Entity
|
||||
int GetWeaponConfigLv(int weapon_id);
|
||||
int GetSkinConfigLv(int skin_id);
|
||||
|
||||
protected:
|
||||
void GenerateWalkZone();
|
||||
bool InWalkZone();
|
||||
void ClearWalkZone();
|
||||
void UpdateMoveInWalkZone(int speed);
|
||||
void UpdateMoveInMap(int speed);
|
||||
|
||||
private:
|
||||
void ClearFrameData();
|
||||
void GenBattleReportData(a8::MutableXObject* params);
|
||||
@ -220,8 +229,12 @@ protected:
|
||||
std::set<Human*> observers_;
|
||||
Human* follow_target_ = nullptr;
|
||||
bool follow_synced_active_player = false;
|
||||
|
||||
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:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "building.h"
|
||||
#include "loot.h"
|
||||
#include "app.h"
|
||||
#include "collider.h"
|
||||
|
||||
Player::Player():Human()
|
||||
{
|
||||
@ -114,18 +115,10 @@ void Player::UpdateMove()
|
||||
moved_frames = 0;
|
||||
return;
|
||||
}
|
||||
int speed = std::max(1, (int)GetSpeed());
|
||||
for (int i = 0; i < speed; ++i) {
|
||||
Vector2D old_pos = pos;
|
||||
pos = pos + move_dir;
|
||||
if (IsCollision()) {
|
||||
pos = old_pos;
|
||||
FindPath();
|
||||
if (rand() % 3 == 0) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
room->grid_service.MoveHuman(this);
|
||||
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)) {
|
||||
last_collision_door = nullptr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user