207 lines
5.3 KiB
C++
207 lines
5.3 KiB
C++
#include "precompile.h"
|
|
|
|
#include "human.h"
|
|
#include "cs_proto.pb.h"
|
|
#include "movement.h"
|
|
#include "metamgr.h"
|
|
#include "room.h"
|
|
#include "bullet.h"
|
|
#include "collider.h"
|
|
|
|
Human::Human()
|
|
{
|
|
movement = new MovementComponent();
|
|
movement->owner = this;
|
|
}
|
|
|
|
Human::~Human()
|
|
{
|
|
delete movement;
|
|
movement = nullptr;
|
|
}
|
|
|
|
void Human::Initialize()
|
|
{
|
|
}
|
|
|
|
float Human::GetSpeed()
|
|
{
|
|
return meta->i->move_speed();
|
|
}
|
|
|
|
void Human::FillMFObjectPart(cs::MFObjectPart* part_data)
|
|
{
|
|
part_data->set_object_type(ET_Player);
|
|
cs::MFPlayerPart* p = part_data->mutable_union_obj_1();
|
|
p->set_obj_uniid(entity_uniid);
|
|
pos.ToPB(p->mutable_pos());
|
|
attack_dir.ToPB(p->mutable_dir());
|
|
}
|
|
|
|
void Human::FillMFObjectFull(cs::MFObjectFull* full_data)
|
|
{
|
|
full_data->set_object_type(ET_Player);
|
|
cs::MFPlayerFull* p = full_data->mutable_union_obj_1();
|
|
p->set_obj_uniid(entity_uniid);
|
|
pos.ToPB(p->mutable_pos());
|
|
attack_dir.ToPB(p->mutable_dir());
|
|
|
|
p->set_health(health);
|
|
p->set_dead(dead);
|
|
p->set_downed(downed);
|
|
p->set_disconnected(disconnected);
|
|
p->set_anim_type(anim_type);
|
|
p->set_anim_seq(anim_seq);
|
|
p->set_action_type(action_type);
|
|
p->set_skin(skin);
|
|
|
|
p->set_helmet(helmet);
|
|
p->set_chest(chest);
|
|
p->set_weapon(weapon);
|
|
p->set_energy_shield(energy_shield);
|
|
p->set_vip(vip);
|
|
p->set_sdmg(sdmg);
|
|
}
|
|
|
|
void Human::Shot(Vector2D& target_dir)
|
|
{
|
|
if (!weapon_meta) {
|
|
return;
|
|
}
|
|
|
|
{
|
|
cs::MFShot* shot = room->frame_data.shots.Add();
|
|
shot->set_player_id(entity_uniid);
|
|
shot->set_weapon_id(weapon_meta->i->id());
|
|
shot->set_offhand(true);
|
|
shot->set_bullskin(10001);
|
|
}
|
|
{
|
|
cs::MFBullet* bullet = room->frame_data.bullets.Add();
|
|
bullet->set_player_id(entity_uniid);
|
|
bullet->set_bullet_id(weapon_meta->i->use_bullet());
|
|
pos.ToPB(bullet->mutable_pos());
|
|
target_dir.ToPB(bullet->mutable_dir());
|
|
bullet->set_bulletskin(10001);
|
|
}
|
|
{
|
|
Bullet* bullet = new Bullet();
|
|
bullet->player = this;
|
|
bullet->room = room;
|
|
bullet->gun_meta = weapon_meta;
|
|
bullet->meta = MetaMgr::Instance()->GetEquip(weapon_meta->i->use_bullet());
|
|
bullet->pos = pos;
|
|
bullet->dir = target_dir;
|
|
bullet->born_pos = pos;
|
|
bullet->born_dir = target_dir;
|
|
bullet->entity_uniid = bullet->room->AllocUniid();
|
|
bullet->Initialize();
|
|
room->AddBullet(bullet);
|
|
}
|
|
}
|
|
|
|
void Human::RecalcSelfCollider()
|
|
{
|
|
if (!self_collider_) {
|
|
self_collider_ = new CircleCollider();
|
|
self_collider_->owner = this;
|
|
colliders.push_back(self_collider_);
|
|
}
|
|
self_collider_->pos = Vector2D();
|
|
self_collider_->rad = meta->i->radius();
|
|
}
|
|
|
|
bool Human::IsCollision()
|
|
{
|
|
//检查x轴
|
|
{
|
|
int left_x = pos.x - meta->i->radius();
|
|
if (left_x < 0.001f) {
|
|
return true;
|
|
}
|
|
int right_x = pos.x + meta->i->radius();
|
|
if (right_x > room->map_meta->i->width()) {
|
|
return true;
|
|
}
|
|
}
|
|
//检查y轴
|
|
{
|
|
int up_y = pos.y + meta->i->radius();
|
|
if (up_y > room->map_meta->i->height()) {
|
|
return true;
|
|
}
|
|
int down_y = pos.y - meta->i->radius();
|
|
if (down_y < 0.001f) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
int detection_flags = 0;
|
|
a8::SetBitFlag(detection_flags, ET_Obstacle);
|
|
a8::SetBitFlag(detection_flags, ET_Building);
|
|
std::vector<Entity*> objects;
|
|
room->CollisionDetection(this, detection_flags, objects);
|
|
return !objects.empty();
|
|
}
|
|
|
|
ColliderComponent* Human::GetFirstCollision()
|
|
{
|
|
int detection_flags = 0;
|
|
a8::SetBitFlag(detection_flags, ET_Obstacle);
|
|
a8::SetBitFlag(detection_flags, ET_Building);
|
|
std::vector<Entity*> objects;
|
|
room->CollisionDetection(this, detection_flags, objects);
|
|
return objects.empty() ? *objects[0]->colliders.begin() : nullptr;
|
|
}
|
|
|
|
void Human::FindPath()
|
|
{
|
|
ColliderComponent* first_collider = nullptr;
|
|
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 (!IsCollision()) {
|
|
return;
|
|
} else {
|
|
//向下
|
|
pos = old_pos + Vector2D::DOWN;
|
|
if (!IsCollision()) {
|
|
return;
|
|
}
|
|
}
|
|
} else if (up_dot > 0.001f) { //基本相同
|
|
pos = old_pos + (at_left_side ? Vector2D::LEFT : Vector2D::RIGHT);
|
|
if (!IsCollision()) {
|
|
return;
|
|
} else {
|
|
//向上
|
|
pos = old_pos + Vector2D::UP;
|
|
if (!IsCollision()) {
|
|
return;
|
|
}
|
|
}
|
|
} else if (up_dot < 0.001f) { //基本相反
|
|
pos = old_pos + (at_left_side ? Vector2D::LEFT : Vector2D::RIGHT);
|
|
if (!IsCollision()) {
|
|
return;
|
|
} else {
|
|
//向下
|
|
pos = old_pos + Vector2D::DOWN;
|
|
if (!IsCollision()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pos = old_pos;
|
|
}
|
|
|
|
float Human::GetRadius()
|
|
{
|
|
return meta->i->radius();
|
|
}
|