Attachable entities, no physics characters, basic vehicle drivers
This commit is contained in:
parent
fd3f981ec0
commit
bbf2788627
@ -1,25 +1,13 @@
|
|||||||
#include "character.hpp"
|
#include "character.hpp"
|
||||||
#include "world.hpp"
|
|
||||||
#include "net/utils.hpp"
|
|
||||||
#include "assets/cache.hpp"
|
#include "assets/cache.hpp"
|
||||||
|
#include "net/utils.hpp"
|
||||||
#include "utils/math.hpp"
|
#include "utils/math.hpp"
|
||||||
|
#include "world.hpp"
|
||||||
|
|
||||||
game::Character::Character(World& world, const CharacterInfo& info)
|
game::Character::Character(World& world, const CharacterInfo& info)
|
||||||
: Super(world, net::ET_CHARACTER), shape_(info.shape), bt_shape_(shape_.radius, shape_.height),
|
: Super(world, net::ET_CHARACTER), shape_(info.shape), bt_shape_(shape_.radius, shape_.height)
|
||||||
bt_character_(&bt_ghost_, &bt_shape_, 0.3f, btVector3(0, 0, 1))
|
|
||||||
{
|
{
|
||||||
btTransform start_transform;
|
z_offset_ = shape_.height * 0.5f + shape_.radius - 0.05f;
|
||||||
start_transform.setIdentity();
|
|
||||||
bt_ghost_.setWorldTransform(start_transform);
|
|
||||||
bt_ghost_.setCollisionShape(&bt_shape_);
|
|
||||||
bt_ghost_.setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
|
|
||||||
|
|
||||||
|
|
||||||
btDynamicsWorld& bt_world = world_.GetBtWorld();
|
|
||||||
bt_world.addCollisionObject(&bt_ghost_, btBroadphaseProxy::CharacterFilter,
|
|
||||||
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
|
|
||||||
// bt_world.addCollisionObject(&bt_ghost_);
|
|
||||||
bt_world.addAction(&bt_character_);
|
|
||||||
|
|
||||||
sk_ = SkeletonInstance(assets::CacheManager::GetSkeleton("data/human.sk"), &root_);
|
sk_ = SkeletonInstance(assets::CacheManager::GetSkeleton("data/human.sk"), &root_);
|
||||||
animstate_.idle_anim_idx = GetAnim("idle");
|
animstate_.idle_anim_idx = GetAnim("idle");
|
||||||
@ -50,9 +38,8 @@ void game::Character::Update()
|
|||||||
{
|
{
|
||||||
Super::Update();
|
Super::Update();
|
||||||
|
|
||||||
auto bt_trans = bt_ghost_.getWorldTransform();
|
SyncTransformFromController();
|
||||||
root_.local.SetBtTransform(bt_trans);
|
root_.UpdateMatrix();
|
||||||
root_.local.position.z -= shape_.height * 0.5f + shape_.radius - 0.05f; // foot pos
|
|
||||||
|
|
||||||
UpdateMovement();
|
UpdateMovement();
|
||||||
|
|
||||||
@ -80,6 +67,19 @@ void game::Character::SendInitData(Player& player, net::OutMessage& msg) const
|
|||||||
msg.WriteAt(fields_pos, fields);
|
msg.WriteAt(fields_pos, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Character::EnablePhysics(bool enable)
|
||||||
|
{
|
||||||
|
if (enable && !controller_)
|
||||||
|
{
|
||||||
|
controller_ = std::make_unique<CharacterPhysicsController>(world_.GetBtWorld(), bt_shape_);
|
||||||
|
SyncControllerTransform();
|
||||||
|
}
|
||||||
|
else if (!enable && controller_)
|
||||||
|
{
|
||||||
|
controller_.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void game::Character::SetInput(CharacterInputType type, bool enable)
|
void game::Character::SetInput(CharacterInputType type, bool enable)
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
@ -116,9 +116,8 @@ void game::Character::SetInput(CharacterInputType type, bool enable)
|
|||||||
|
|
||||||
void game::Character::SetPosition(const glm::vec3& position)
|
void game::Character::SetPosition(const glm::vec3& position)
|
||||||
{
|
{
|
||||||
auto trans = bt_ghost_.getWorldTransform();
|
root_.local.position = position;
|
||||||
trans.setOrigin(btVector3(position.x, position.y, position.z));
|
SyncControllerTransform();
|
||||||
bt_ghost_.setWorldTransform(trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Character::AddClothes(std::string name, const glm::vec3& color)
|
void game::Character::AddClothes(std::string name, const glm::vec3& color)
|
||||||
@ -126,11 +125,31 @@ void game::Character::AddClothes(std::string name, const glm::vec3& color)
|
|||||||
clothes_.emplace_back(std::move(name), color);
|
clothes_.emplace_back(std::move(name), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
game::Character::~Character()
|
void game::Character::SetMainAnim(const std::string& anim_name)
|
||||||
{
|
{
|
||||||
btDynamicsWorld& bt_world = world_.GetBtWorld();
|
animstate_.idle_anim_idx = GetAnim(anim_name);
|
||||||
bt_world.removeAction(&bt_character_);
|
}
|
||||||
bt_world.removeCollisionObject(&bt_ghost_);
|
|
||||||
|
void game::Character::SyncControllerTransform()
|
||||||
|
{
|
||||||
|
if (!controller_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& position = root_.local.position;
|
||||||
|
auto& bt_ghost = controller_->GetBtGhost();
|
||||||
|
auto trans = bt_ghost.getWorldTransform();
|
||||||
|
trans.setOrigin(btVector3(position.x, position.y, position.z + z_offset_));
|
||||||
|
bt_ghost.setWorldTransform(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Character::SyncTransformFromController()
|
||||||
|
{
|
||||||
|
if (!controller_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto bt_trans = controller_->GetBtGhost().getWorldTransform();
|
||||||
|
root_.local.SetBtTransform(bt_trans);
|
||||||
|
root_.local.position.z -= z_offset_; // foot pos
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Character::UpdateMovement()
|
void game::Character::UpdateMovement()
|
||||||
@ -163,11 +182,15 @@ void game::Character::UpdateMovement()
|
|||||||
walkdir = forward_dir * walk_speed_ * dt;
|
walkdir = forward_dir * walk_speed_ * dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_character_.setWalkDirection(btVector3(walkdir.x, walkdir.y, walkdir.z));
|
if (controller_)
|
||||||
|
|
||||||
if (in_ & (1 << CIN_JUMP) && bt_character_.canJump())
|
|
||||||
{
|
{
|
||||||
bt_character_.jump(btVector3(0.0f, 0.0f, 10.0f));
|
auto& bt_character = controller_->GetBtController();
|
||||||
|
bt_character.setWalkDirection(btVector3(walkdir.x, walkdir.y, walkdir.z));
|
||||||
|
|
||||||
|
if (in_ & (1 << CIN_JUMP) && bt_character.canJump())
|
||||||
|
{
|
||||||
|
bt_character.jump(btVector3(0.0f, 0.0f, 10.0f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update anim
|
// update anim
|
||||||
@ -193,8 +216,6 @@ void game::Character::UpdateSyncState()
|
|||||||
state.run_anim = animstate_.run_anim_idx;
|
state.run_anim = animstate_.run_anim_idx;
|
||||||
state.loco_phase.Encode(animstate_.loco_phase);
|
state.loco_phase.Encode(animstate_.loco_phase);
|
||||||
state.loco_blend.Encode(animstate_.loco_blend);
|
state.loco_blend.Encode(animstate_.loco_blend);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Character::SendUpdateMsg()
|
void game::Character::SendUpdateMsg()
|
||||||
@ -300,3 +321,24 @@ assets::AnimIdx game::Character::GetAnim(const std::string& name) const
|
|||||||
{
|
{
|
||||||
return sk_.GetSkeleton()->GetAnimationIdx(name);
|
return sk_.GetSkeleton()->GetAnimationIdx(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
game::CharacterPhysicsController::CharacterPhysicsController(btDynamicsWorld& bt_world, btCapsuleShapeZ& bt_shape)
|
||||||
|
: bt_world_(bt_world), bt_character_(&bt_ghost_, &bt_shape, 0.3f, btVector3(0, 0, 1))
|
||||||
|
{
|
||||||
|
btTransform start_transform;
|
||||||
|
start_transform.setIdentity();
|
||||||
|
bt_ghost_.setWorldTransform(start_transform);
|
||||||
|
bt_ghost_.setCollisionShape(&bt_shape);
|
||||||
|
bt_ghost_.setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
|
||||||
|
|
||||||
|
bt_world_.addCollisionObject(&bt_ghost_, btBroadphaseProxy::CharacterFilter,
|
||||||
|
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
|
||||||
|
// bt_world.addCollisionObject(&bt_ghost_);
|
||||||
|
bt_world_.addAction(&bt_character_);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::CharacterPhysicsController::~CharacterPhysicsController()
|
||||||
|
{
|
||||||
|
bt_world_.removeAction(&bt_character_);
|
||||||
|
bt_world_.removeCollisionObject(&bt_ghost_);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "entity.hpp"
|
#include <btBulletDynamicsCommon.h>
|
||||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||||
#include "BulletDynamics/Character/btKinematicCharacterController.h"
|
#include <BulletDynamics/Character/btKinematicCharacterController.h>
|
||||||
#include "character_anim_state.hpp"
|
#include "character_anim_state.hpp"
|
||||||
#include "character_sync.hpp"
|
#include "character_sync.hpp"
|
||||||
|
#include "entity.hpp"
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
@ -39,6 +40,25 @@ struct CharacterClothes
|
|||||||
glm::vec3 color;
|
glm::vec3 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CharacterPhysicsController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CharacterPhysicsController(btDynamicsWorld& bt_world, btCapsuleShapeZ& bt_shape);
|
||||||
|
DELETE_COPY_MOVE(CharacterPhysicsController)
|
||||||
|
|
||||||
|
btKinematicCharacterController& GetBtController() { return bt_character_; }
|
||||||
|
const btKinematicCharacterController& GetBtController() const { return bt_character_; }
|
||||||
|
btGhostObject& GetBtGhost() { return bt_ghost_; }
|
||||||
|
const btGhostObject& GetBtGhost() const { return bt_ghost_; }
|
||||||
|
|
||||||
|
~CharacterPhysicsController();
|
||||||
|
|
||||||
|
private:
|
||||||
|
btDynamicsWorld& bt_world_;
|
||||||
|
btPairCachingGhostObject bt_ghost_;
|
||||||
|
btKinematicCharacterController bt_character_;
|
||||||
|
};
|
||||||
|
|
||||||
class Character : public Entity
|
class Character : public Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -49,18 +69,26 @@ public:
|
|||||||
virtual void Update() override;
|
virtual void Update() override;
|
||||||
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
virtual void SendInitData(Player& player, net::OutMessage& msg) const override;
|
||||||
|
|
||||||
|
void EnablePhysics(bool enable);
|
||||||
|
|
||||||
void SetInput(CharacterInputType type, bool enable);
|
void SetInput(CharacterInputType type, bool enable);
|
||||||
void SetInputs(CharacterInputFlags inputs) { in_ = inputs; }
|
void SetInputs(CharacterInputFlags inputs) { in_ = inputs; }
|
||||||
|
|
||||||
void SetForwardYaw(float yaw) { forward_yaw_ = yaw; }
|
void SetForwardYaw(float yaw) { forward_yaw_ = yaw; }
|
||||||
|
void SetYaw(float yaw) { yaw_ = yaw; }
|
||||||
|
|
||||||
void SetPosition(const glm::vec3& position);
|
void SetPosition(const glm::vec3& position);
|
||||||
|
|
||||||
void AddClothes(std::string name, const glm::vec3& color);
|
void AddClothes(std::string name, const glm::vec3& color);
|
||||||
|
|
||||||
~Character() override;
|
void SetMainAnim(const std::string& anim_name);
|
||||||
|
|
||||||
|
~Character() override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SyncControllerTransform();
|
||||||
|
void SyncTransformFromController();
|
||||||
|
|
||||||
void UpdateMovement();
|
void UpdateMovement();
|
||||||
void UpdateSyncState();
|
void UpdateSyncState();
|
||||||
void SendUpdateMsg();
|
void SendUpdateMsg();
|
||||||
@ -79,9 +107,8 @@ private:
|
|||||||
CharacterInputFlags in_ = 0;
|
CharacterInputFlags in_ = 0;
|
||||||
|
|
||||||
btCapsuleShapeZ bt_shape_;
|
btCapsuleShapeZ bt_shape_;
|
||||||
btPairCachingGhostObject bt_ghost_;
|
float z_offset_ = 0.0f; // offset of controller from root
|
||||||
|
std::unique_ptr<CharacterPhysicsController> controller_;
|
||||||
btKinematicCharacterController bt_character_;
|
|
||||||
|
|
||||||
float yaw_ = 0.0f;
|
float yaw_ = 0.0f;
|
||||||
float forward_yaw_ = 0.0f;
|
float forward_yaw_ = 0.0f;
|
||||||
|
|||||||
@ -4,15 +4,40 @@
|
|||||||
|
|
||||||
game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype) {}
|
game::Entity::Entity(World& world, net::EntType viewtype) : Scheduler(world.GetTime()), world_(world), entnum_(world.GetNewEntnum()), viewtype_(viewtype) {}
|
||||||
|
|
||||||
void game::Entity::Update()
|
|
||||||
{
|
|
||||||
ResetMsg();
|
|
||||||
RunTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void game::Entity::SendInitData(Player& player, net::OutMessage& msg) const
|
void game::Entity::SendInitData(Player& player, net::OutMessage& msg) const
|
||||||
{
|
{
|
||||||
WriteNametag(msg);
|
WriteNametag(msg);
|
||||||
|
WriteAttach(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Entity::Update()
|
||||||
|
{
|
||||||
|
ResetMsg();
|
||||||
|
|
||||||
|
upd_time_ = world_.GetTime();
|
||||||
|
|
||||||
|
// ensure parent is updated
|
||||||
|
parent_ = nullptr;
|
||||||
|
if (parentnum_)
|
||||||
|
{
|
||||||
|
parent_ = world_.GetEntity(parentnum_);
|
||||||
|
parent_->TryUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update transform parent
|
||||||
|
root_.parent = parent_ ? &parent_->GetRoot() : nullptr;
|
||||||
|
|
||||||
|
RunTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool game::Entity::TryUpdate()
|
||||||
|
{
|
||||||
|
int64_t time = world_.GetTime();
|
||||||
|
if (time == upd_time_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Update();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::Entity::SetNametag(const std::string& nametag)
|
void game::Entity::SetNametag(const std::string& nametag)
|
||||||
@ -21,6 +46,12 @@ void game::Entity::SetNametag(const std::string& nametag)
|
|||||||
SendNametagMsg(); // notify viewers
|
SendNametagMsg(); // notify viewers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Entity::Attach(net::EntNum parentnum)
|
||||||
|
{
|
||||||
|
parentnum_ = parentnum;
|
||||||
|
SendAttachMsg();
|
||||||
|
}
|
||||||
|
|
||||||
void game::Entity::WriteNametag(net::OutMessage& msg) const
|
void game::Entity::WriteNametag(net::OutMessage& msg) const
|
||||||
{
|
{
|
||||||
msg.Write(net::NameTag{nametag_});
|
msg.Write(net::NameTag{nametag_});
|
||||||
@ -32,6 +63,17 @@ void game::Entity::SendNametagMsg()
|
|||||||
WriteNametag(msg);
|
WriteNametag(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game::Entity::WriteAttach(net::OutMessage& msg) const
|
||||||
|
{
|
||||||
|
msg.Write(parentnum_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game::Entity::SendAttachMsg()
|
||||||
|
{
|
||||||
|
auto msg = BeginEntMsg(net::EMSG_ATTACH);
|
||||||
|
WriteAttach(msg);
|
||||||
|
}
|
||||||
|
|
||||||
net::OutMessage game::Entity::BeginEntMsg(net::EntMsgType type)
|
net::OutMessage game::Entity::BeginEntMsg(net::EntMsgType type)
|
||||||
{
|
{
|
||||||
auto msg = BeginMsg(net::MSG_ENTMSG);
|
auto msg = BeginMsg(net::MSG_ENTMSG);
|
||||||
|
|||||||
@ -22,14 +22,21 @@ public:
|
|||||||
net::EntNum GetEntNum() const { return entnum_; }
|
net::EntNum GetEntNum() const { return entnum_; }
|
||||||
net::EntType GetViewType() const { return viewtype_; }
|
net::EntType GetViewType() const { return viewtype_; }
|
||||||
|
|
||||||
virtual void Update();
|
|
||||||
virtual void SendInitData(Player& player, net::OutMessage& msg) const;
|
virtual void SendInitData(Player& player, net::OutMessage& msg) const;
|
||||||
|
|
||||||
|
virtual void Update();
|
||||||
|
bool TryUpdate(); // if not already updated
|
||||||
|
int64_t GetUpdateTime() const { return upd_time_; }
|
||||||
|
|
||||||
void SetNametag(const std::string& nametag);
|
void SetNametag(const std::string& nametag);
|
||||||
|
|
||||||
|
void Attach(net::EntNum parentnum);
|
||||||
|
net::EntNum GetParentNum() const { return parentnum_; }
|
||||||
|
|
||||||
void Remove() { removed_ = true; }
|
void Remove() { removed_ = true; }
|
||||||
bool IsRemoved() const { return removed_; }
|
bool IsRemoved() const { return removed_; }
|
||||||
|
|
||||||
|
const TransformNode& GetRoot() const { return root_; }
|
||||||
const Transform& GetRootTransform() const { return root_.local; }
|
const Transform& GetRootTransform() const { return root_.local; }
|
||||||
float GetMaxDistance() const { return max_distance_; }
|
float GetMaxDistance() const { return max_distance_; }
|
||||||
|
|
||||||
@ -37,9 +44,11 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void WriteNametag(net::OutMessage& msg) const;
|
void WriteNametag(net::OutMessage& msg) const;
|
||||||
|
|
||||||
void SendNametagMsg();
|
void SendNametagMsg();
|
||||||
|
|
||||||
|
void WriteAttach(net::OutMessage& msg) const;
|
||||||
|
void SendAttachMsg();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
net::OutMessage BeginEntMsg(net::EntMsgType type);
|
net::OutMessage BeginEntMsg(net::EntMsgType type);
|
||||||
|
|
||||||
@ -49,13 +58,16 @@ protected:
|
|||||||
const net::EntType viewtype_;
|
const net::EntType viewtype_;
|
||||||
|
|
||||||
TransformNode root_;
|
TransformNode root_;
|
||||||
|
Entity* parent_ = nullptr;
|
||||||
|
|
||||||
float max_distance_ = 700.0f;
|
float max_distance_ = 700.0f;
|
||||||
std::string nametag_;
|
|
||||||
|
|
||||||
|
|
||||||
bool removed_ = false;
|
bool removed_ = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t upd_time_ = -1;
|
||||||
|
std::string nametag_;
|
||||||
|
net::EntNum parentnum_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -247,19 +247,28 @@ static glm::vec3 GetRandomColor()
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::OpenWorld::SpawnCharacter(Player& player)
|
game::Character& game::OpenWorld::SpawnRandomCharacter()
|
||||||
{
|
{
|
||||||
RemoveCharacter(player);
|
|
||||||
|
|
||||||
CharacterInfo cinfo;
|
CharacterInfo cinfo;
|
||||||
auto& character = Spawn<Character>(cinfo);
|
auto& character = Spawn<Character>(cinfo);
|
||||||
character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")");
|
|
||||||
character.SetPosition({ 100.0f, 100.0f, 5.0f });
|
|
||||||
|
|
||||||
// add clothes
|
// add clothes
|
||||||
character.AddClothes("tshirt", GetRandomColor());
|
character.AddClothes("tshirt", GetRandomColor());
|
||||||
character.AddClothes("shorts", GetRandomColor());
|
character.AddClothes("shorts", GetRandomColor());
|
||||||
|
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void game::OpenWorld::SpawnCharacter(Player& player)
|
||||||
|
{
|
||||||
|
RemoveCharacter(player);
|
||||||
|
|
||||||
|
auto& character = SpawnRandomCharacter();
|
||||||
|
character.SetNametag("player (" + std::to_string(character.GetEntNum()) + ")");
|
||||||
|
character.SetPosition({ 100.0f, 100.0f, 5.0f });
|
||||||
|
character.EnablePhysics(true);
|
||||||
|
|
||||||
player.SetCamera(character.GetEntNum());
|
player.SetCamera(character.GetEntNum());
|
||||||
|
|
||||||
player_characters_[&player] = &character;
|
player_characters_[&player] = &character;
|
||||||
@ -572,6 +581,13 @@ void game::OpenWorld::SpawnBot()
|
|||||||
vehicle.Schedule(rand() % 500, [think_state]() {
|
vehicle.Schedule(rand() % 500, [think_state]() {
|
||||||
//BotNametagThink(think_state);
|
//BotNametagThink(think_state);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// spawn driver
|
||||||
|
auto& driver = SpawnRandomCharacter();
|
||||||
|
driver.Attach(vehicle.GetEntNum());
|
||||||
|
driver.SetPosition(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
driver.SetMainAnim("vehicle_drive");
|
||||||
|
driver.SetYaw(0.5f * glm::pi<float>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::OpenWorld::SpawnVehicle(Player& player)
|
void game::OpenWorld::SpawnVehicle(Player& player)
|
||||||
|
|||||||
@ -23,6 +23,8 @@ private:
|
|||||||
void SpawnVehicle(Player& player);
|
void SpawnVehicle(Player& player);
|
||||||
void RemoveVehicle(Player& player);
|
void RemoveVehicle(Player& player);
|
||||||
|
|
||||||
|
Character& SpawnRandomCharacter();
|
||||||
|
|
||||||
void SpawnCharacter(Player& player);
|
void SpawnCharacter(Player& player);
|
||||||
void RemoveCharacter(Player& player);
|
void RemoveCharacter(Player& player);
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ void game::Player::Update()
|
|||||||
auto cam_ent = world_->GetEntity(cam_ent_);
|
auto cam_ent = world_->GetEntity(cam_ent_);
|
||||||
if (cam_ent)
|
if (cam_ent)
|
||||||
{
|
{
|
||||||
cull_pos_ = cam_ent->GetRootTransform().position;
|
cull_pos_ = cam_ent->GetRoot().GetGlobalPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ bool game::Player::ShouldSeeEntity(const Entity& entity) const
|
|||||||
{
|
{
|
||||||
// max distance check
|
// max distance check
|
||||||
float max_dist = entity.GetMaxDistance();
|
float max_dist = entity.GetMaxDistance();
|
||||||
if (glm::distance2(entity.GetRootTransform().position, cull_pos_) > (max_dist * max_dist))
|
if (glm::distance2(entity.GetRoot().GetGlobalPosition(), cull_pos_) > (max_dist * max_dist))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO: custom callback
|
// TODO: custom callback
|
||||||
|
|||||||
@ -24,6 +24,11 @@ namespace game
|
|||||||
matrix = parent->matrix * matrix;
|
matrix = parent->matrix * matrix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 GetGlobalPosition() const
|
||||||
|
{
|
||||||
|
return matrix[3];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -97,6 +97,8 @@ void game::Vehicle::Update()
|
|||||||
{
|
{
|
||||||
Super::Update();
|
Super::Update();
|
||||||
|
|
||||||
|
root_.UpdateMatrix();
|
||||||
|
|
||||||
flags_ = 0;
|
flags_ = 0;
|
||||||
ProcessInput();
|
ProcessInput();
|
||||||
UpdateWheels();
|
UpdateWheels();
|
||||||
|
|||||||
@ -41,7 +41,7 @@ void game::World::Update(int64_t delta_time)
|
|||||||
// update entities
|
// update entities
|
||||||
for (auto it = ents_.begin(); it != ents_.end();)
|
for (auto it = ents_.begin(); it != ents_.end();)
|
||||||
{
|
{
|
||||||
it->second->Update();
|
it->second->TryUpdate();
|
||||||
|
|
||||||
if (it->second->IsRemoved())
|
if (it->second->IsRemoved())
|
||||||
it = ents_.erase(it);
|
it = ents_.erase(it);
|
||||||
|
|||||||
@ -53,6 +53,8 @@ bool game::view::CharacterView::ProcessMsg(net::EntMsgType type, net::InMessage&
|
|||||||
|
|
||||||
void game::view::CharacterView::Update(const UpdateInfo& info)
|
void game::view::CharacterView::Update(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
|
Super::Update(info);
|
||||||
|
|
||||||
// interpolate states
|
// interpolate states
|
||||||
float tps = 25.0f;
|
float tps = 25.0f;
|
||||||
float t = (info.time - update_time_) * tps * 0.8f; // assume some jitter, interpolate for longer
|
float t = (info.time - update_time_) * tps * 0.8f; // assume some jitter, interpolate for longer
|
||||||
|
|||||||
@ -10,7 +10,8 @@ game::view::EntityView::EntityView(WorldView& world, net::InMessage& msg) :
|
|||||||
audioplayer_(world_.GetAudioMaster()),
|
audioplayer_(world_.GetAudioMaster()),
|
||||||
nametag_text_(assets::CacheManager::GetFont("data/comic32.font"), 0xFFFFFFFF)
|
nametag_text_(assets::CacheManager::GetFont("data/comic32.font"), 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
if (!ReadNametag(msg))
|
// read nametag and attachment info
|
||||||
|
if (!ReadNametag(msg) || !ReadAttach(msg))
|
||||||
throw EntityInitError();
|
throw EntityInitError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,13 +21,38 @@ bool game::view::EntityView::ProcessMsg(net::EntMsgType type, net::InMessage& ms
|
|||||||
{
|
{
|
||||||
case net::EMSG_NAMETAG:
|
case net::EMSG_NAMETAG:
|
||||||
return ReadNametag(msg);
|
return ReadNametag(msg);
|
||||||
|
case net::EMSG_ATTACH:
|
||||||
|
return ReadAttach(msg);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
bool game::view::EntityView::TryUpdate(const UpdateInfo& info)
|
||||||
|
{
|
||||||
|
float time = world_.GetTime();
|
||||||
|
if (time == upd_time_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Update(info);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::view::EntityView::Update(const UpdateInfo& info)
|
void game::view::EntityView::Update(const UpdateInfo& info)
|
||||||
{
|
{
|
||||||
|
upd_time_ = world_.GetTime();
|
||||||
|
|
||||||
|
// ensure parent is updated
|
||||||
|
parent_ = nullptr;
|
||||||
|
if (parentnum_)
|
||||||
|
{
|
||||||
|
parent_ = world_.GetEntity(parentnum_);
|
||||||
|
parent_->TryUpdate(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update transform parent
|
||||||
|
root_.parent = parent_ ? &parent_->GetRoot() : nullptr;
|
||||||
|
|
||||||
audioplayer_.Update();
|
audioplayer_.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +75,11 @@ bool game::view::EntityView::ReadNametag(net::InMessage& msg)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::view::EntityView::ReadAttach(net::InMessage& msg)
|
||||||
|
{
|
||||||
|
return msg.Read(parentnum_);
|
||||||
|
}
|
||||||
|
|
||||||
void game::view::EntityView::DrawNametag(const DrawArgs& args)
|
void game::view::EntityView::DrawNametag(const DrawArgs& args)
|
||||||
{
|
{
|
||||||
if (nametag_.empty())
|
if (nametag_.empty())
|
||||||
|
|||||||
@ -36,17 +36,20 @@ public:
|
|||||||
DELETE_COPY_MOVE(EntityView)
|
DELETE_COPY_MOVE(EntityView)
|
||||||
|
|
||||||
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg);
|
virtual bool ProcessMsg(net::EntMsgType type, net::InMessage& msg);
|
||||||
|
|
||||||
|
bool TryUpdate(const UpdateInfo& info); // if not updated already
|
||||||
virtual void Update(const UpdateInfo& info);
|
virtual void Update(const UpdateInfo& info);
|
||||||
|
|
||||||
virtual void Draw(const DrawArgs& args);
|
virtual void Draw(const DrawArgs& args);
|
||||||
|
|
||||||
Sphere GetBoundingSphere() const { return Sphere{root_.local.position, radius_}; }
|
Sphere GetBoundingSphere() const { return Sphere{root_.GetGlobalPosition(), radius_}; }
|
||||||
|
|
||||||
const TransformNode& GetRoot() const { return root_; }
|
const TransformNode& GetRoot() const { return root_; }
|
||||||
|
|
||||||
virtual ~EntityView() = default;
|
virtual ~EntityView() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadNametag(net::InMessage& msg);
|
bool ReadNametag(net::InMessage& msg);
|
||||||
|
bool ReadAttach(net::InMessage& msg);
|
||||||
|
|
||||||
void DrawNametag(const DrawArgs& args);
|
void DrawNametag(const DrawArgs& args);
|
||||||
void DrawAxes(const DrawArgs& args);
|
void DrawAxes(const DrawArgs& args);
|
||||||
@ -55,13 +58,20 @@ protected:
|
|||||||
WorldView& world_;
|
WorldView& world_;
|
||||||
|
|
||||||
TransformNode root_;
|
TransformNode root_;
|
||||||
|
|
||||||
|
EntityView* parent_ = nullptr;
|
||||||
|
|
||||||
float radius_ = 1.0f;
|
float radius_ = 1.0f;
|
||||||
|
|
||||||
audio::Player audioplayer_;
|
audio::Player audioplayer_;
|
||||||
|
|
||||||
|
private:
|
||||||
std::string nametag_;
|
std::string nametag_;
|
||||||
gfx::Text nametag_text_;
|
gfx::Text nametag_text_;
|
||||||
gfx::HudPosition nametag_pos_;
|
gfx::HudPosition nametag_pos_;
|
||||||
|
|
||||||
|
net::EntNum parentnum_ = 0;
|
||||||
|
float upd_time_ = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game::view
|
} // namespace game::view
|
||||||
@ -38,7 +38,7 @@ void game::view::WorldView::Update(const UpdateInfo& info)
|
|||||||
|
|
||||||
for (const auto& [entnum, ent] : ents_)
|
for (const auto& [entnum, ent] : ents_)
|
||||||
{
|
{
|
||||||
ent->Update(info);
|
ent->TryUpdate(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,6 +75,7 @@ enum EntMsgType : uint8_t
|
|||||||
EMSG_NONE,
|
EMSG_NONE,
|
||||||
|
|
||||||
EMSG_NAMETAG,
|
EMSG_NAMETAG,
|
||||||
|
EMSG_ATTACH,
|
||||||
EMSG_UPDATE,
|
EMSG_UPDATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user