Compare commits
1 Commits
685b15933a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d139e77969 |
13
Game.cpp
13
Game.cpp
@@ -18,6 +18,8 @@
|
||||
#include "GUIModuleCommon.h"
|
||||
#include "AppModule.h"
|
||||
#include "GUIModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "physics.h"
|
||||
#include "sound.h"
|
||||
class App;
|
||||
class SkyRenderer : public Ogre::SceneManager::Listener {
|
||||
@@ -626,10 +628,13 @@ end:
|
||||
void setupInput()
|
||||
{
|
||||
}
|
||||
JoltPhysicsWrapper *mJolt;
|
||||
void createContent()
|
||||
{
|
||||
int i;
|
||||
sky = new SkyBoxRenderer(getSceneManager());
|
||||
mJolt = new JoltPhysicsWrapper(mScnMgr, mCameraNode);
|
||||
|
||||
sky = new SkyBoxRenderer(getSceneManager());
|
||||
bool drawFirst = true;
|
||||
uint8_t renderQueue = drawFirst ?
|
||||
Ogre::RENDER_QUEUE_SKIES_EARLY :
|
||||
@@ -651,6 +656,12 @@ end:
|
||||
ECS::setupExteriorScene(mScnMgr,
|
||||
/*mDynWorld.get(), */ mCameraNode,
|
||||
mCamera, getRenderWindow());
|
||||
|
||||
ECS::get().import <ECS::PhysicsModule>();
|
||||
ECS::Physics &ph = ECS::get().ensure<ECS::Physics>();
|
||||
ph.physics = mJolt;
|
||||
ECS::modified<ECS::Physics>();
|
||||
|
||||
ECS::get()
|
||||
.observer<ECS::App>("UpdateInputListener")
|
||||
.event(flecs::OnSet)
|
||||
|
||||
@@ -9,7 +9,89 @@
|
||||
#include "CharacterAIModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
class ActionNodeActions {
|
||||
struct ActionExec {
|
||||
struct PlanExecData {
|
||||
TownNPCs::NPCData &npc;
|
||||
Blackboard &bb;
|
||||
nlohmann::json &memory;
|
||||
};
|
||||
enum { OK = 0, BUSY, ERROR };
|
||||
TownNPCs::NPCData &npc;
|
||||
Blackboard &bb;
|
||||
nlohmann::json &memory;
|
||||
bool complete;
|
||||
bool active;
|
||||
const goap::BaseAction<Blackboard> *action;
|
||||
ActionExec(PlanExecData &data,
|
||||
const goap::BaseAction<Blackboard> *action)
|
||||
: npc(data.npc)
|
||||
, bb(data.bb)
|
||||
, memory(data.memory)
|
||||
, complete(false)
|
||||
, active(false)
|
||||
, action(action)
|
||||
{
|
||||
}
|
||||
ActionExec(const ActionExec &other)
|
||||
: npc(other.npc)
|
||||
, bb(other.bb)
|
||||
, memory(other.memory)
|
||||
, complete(other.complete)
|
||||
, active(other.active)
|
||||
, action(other.action)
|
||||
{
|
||||
}
|
||||
ActionExec &operator=(const ActionExec &other)
|
||||
{
|
||||
npc = other.npc;
|
||||
bb = other.bb;
|
||||
memory = other.memory;
|
||||
complete = other.complete;
|
||||
active = other.active;
|
||||
action = other.action;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual int update(float delta) = 0;
|
||||
virtual void finish(int result) = 0;
|
||||
virtual void activate() = 0;
|
||||
|
||||
public:
|
||||
int operator()(float delta)
|
||||
{
|
||||
if (!active)
|
||||
activate();
|
||||
int ret = update(delta);
|
||||
if (ret != BUSY)
|
||||
finish(ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
struct PlanExec {
|
||||
enum { OK = 0, BUSY, ERROR };
|
||||
std::vector<struct ActionExec *> action_exec;
|
||||
int index;
|
||||
PlanExec()
|
||||
: index(-1)
|
||||
{
|
||||
}
|
||||
int operator()(float delta)
|
||||
{
|
||||
if (index == -1)
|
||||
index = 0;
|
||||
int rc = (*action_exec[index])(delta);
|
||||
if (rc == ActionExec::ERROR)
|
||||
return ERROR;
|
||||
if (action_exec[index]->complete)
|
||||
index++;
|
||||
if (index >= action_exec.size())
|
||||
return OK;
|
||||
return BUSY;
|
||||
}
|
||||
};
|
||||
|
||||
struct ActionNodeActions {
|
||||
struct WalkToAction : public goap::BaseAction<Blackboard> {
|
||||
int node;
|
||||
WalkToAction(int node, int cost)
|
||||
@@ -98,12 +180,103 @@ out:
|
||||
std::vector<goap::BaseAction<Blackboard> *> m_actions;
|
||||
|
||||
public:
|
||||
struct ActionExecWalk : ActionExec {
|
||||
private:
|
||||
Ogre::Vector3 targetPosition;
|
||||
float radius;
|
||||
int update(float delta) override
|
||||
{
|
||||
if (npc.e.is_valid()) {
|
||||
Ogre::Vector3 position =
|
||||
npc.e.get<CharacterBase>()
|
||||
.mBodyNode
|
||||
->_getDerivedPosition();
|
||||
if (position.squaredDistance(targetPosition) >=
|
||||
radius * radius) {
|
||||
if (npc.e.is_valid())
|
||||
npc.e.get<CharacterBase>()
|
||||
.mBodyNode
|
||||
->_setDerivedPosition(
|
||||
targetPosition);
|
||||
npc.position = targetPosition;
|
||||
return BUSY;
|
||||
}
|
||||
} else {
|
||||
if (npc.position.squaredDistance(
|
||||
targetPosition) >=
|
||||
radius * radius) {
|
||||
npc.position = targetPosition;
|
||||
return BUSY;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
void finish(int rc) override
|
||||
{
|
||||
if (rc == OK)
|
||||
bb.apply(action->effects);
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
const ActionNodeActions::WalkToAction *wtaction =
|
||||
static_cast<
|
||||
const ActionNodeActions::WalkToAction *>(
|
||||
action);
|
||||
radius = ECS::get<ActionNodeList>()
|
||||
.dynamicNodes[wtaction->node]
|
||||
.radius;
|
||||
targetPosition = ECS::get<ActionNodeList>()
|
||||
.dynamicNodes[wtaction->node]
|
||||
.position;
|
||||
Ogre::Vector3 direction =
|
||||
(targetPosition - npc.position).normalisedCopy();
|
||||
targetPosition -= direction * radius;
|
||||
std::cout << action->get_name();
|
||||
}
|
||||
|
||||
public:
|
||||
ActionExecWalk(ActionExec::PlanExecData &data,
|
||||
goap::BaseAction<Blackboard> *action)
|
||||
: ActionExec(data, action)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct ActionExecUse : ActionExec {
|
||||
private:
|
||||
int update(float delta) override
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
void finish(int rc) override
|
||||
{
|
||||
if (rc == OK)
|
||||
bb.apply(action->effects);
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
std::cout << action->get_name();
|
||||
const ActionNodeActions::RunActionNode *runaction =
|
||||
static_cast<const ActionNodeActions::RunActionNode
|
||||
*>(action);
|
||||
if (runaction)
|
||||
std::cout << "Is Run" << std::endl;
|
||||
OgreAssert(false, "activate");
|
||||
}
|
||||
|
||||
public:
|
||||
ActionExecUse(ActionExec::PlanExecData &data,
|
||||
goap::BaseAction<Blackboard> *action)
|
||||
: ActionExec(data, action)
|
||||
{
|
||||
}
|
||||
};
|
||||
ActionNodeActions(int node, const Blackboard &prereq, int cost)
|
||||
{
|
||||
OgreAssert(
|
||||
node < ECS::get<ActionNodeList>().dynamicNodes.size(),
|
||||
"bad node " + Ogre::StringConverter::toString(node));
|
||||
m_actions.push_back(OGRE_NEW WalkToAction(node, 10000));
|
||||
auto paction = OGRE_NEW WalkToAction(node, 10000);
|
||||
m_actions.push_back(paction);
|
||||
nlohmann::json jactionPrereq = nlohmann::json::object();
|
||||
nlohmann::json jactionEffect = nlohmann::json::object();
|
||||
jactionPrereq["at_object"] = 1;
|
||||
@@ -176,6 +349,32 @@ public:
|
||||
return m_actions;
|
||||
}
|
||||
};
|
||||
struct ActionExecCommon : ActionExec {
|
||||
private:
|
||||
int update(float delta) override
|
||||
{
|
||||
std::cout << "running: " << action->get_name() << std::endl;
|
||||
return OK;
|
||||
}
|
||||
void finish(int rc) override
|
||||
{
|
||||
if (rc == OK)
|
||||
bb.apply(action->effects);
|
||||
std::cout << "finish: " << action->get_name() << std::endl;
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
std::cout << action->get_name();
|
||||
std::cout << "!";
|
||||
}
|
||||
|
||||
public:
|
||||
ActionExecCommon(ActionExec::PlanExecData &data,
|
||||
goap::BaseAction<Blackboard> *action)
|
||||
: ActionExec(data, action)
|
||||
{
|
||||
}
|
||||
};
|
||||
CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
{
|
||||
static std::mutex ecs_mutex;
|
||||
@@ -376,92 +575,6 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
});
|
||||
});
|
||||
});
|
||||
struct ActionExec {
|
||||
enum { OK = 0, BUSY, ERROR };
|
||||
TownNPCs::NPCData &npc;
|
||||
Blackboard &bb;
|
||||
nlohmann::json &memory;
|
||||
bool complete;
|
||||
bool active;
|
||||
const goap::BaseAction<Blackboard> *action;
|
||||
ActionExec(TownNPCs::NPCData &npc, Blackboard &bb,
|
||||
nlohmann::json &memory,
|
||||
const goap::BaseAction<Blackboard> *action)
|
||||
: npc(npc)
|
||||
, bb(bb)
|
||||
, memory(memory)
|
||||
, complete(false)
|
||||
, active(false)
|
||||
, action(action)
|
||||
{
|
||||
}
|
||||
ActionExec(const ActionExec &other)
|
||||
: npc(other.npc)
|
||||
, bb(other.bb)
|
||||
, memory(other.memory)
|
||||
, complete(other.complete)
|
||||
, active(other.active)
|
||||
, action(other.action)
|
||||
{
|
||||
}
|
||||
ActionExec &operator=(const ActionExec &other)
|
||||
{
|
||||
npc = other.npc;
|
||||
bb = other.bb;
|
||||
memory = other.memory;
|
||||
complete = other.complete;
|
||||
active = other.active;
|
||||
action = other.action;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
int update(float delta)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
void finish(int result)
|
||||
{
|
||||
}
|
||||
void activate()
|
||||
{
|
||||
std::cout << action->get_name();
|
||||
OgreAssert(false, "activate");
|
||||
}
|
||||
|
||||
public:
|
||||
int operator()(float delta)
|
||||
{
|
||||
if (!active)
|
||||
activate();
|
||||
int ret = update(delta);
|
||||
if (ret != BUSY)
|
||||
finish(ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
struct PlanExec {
|
||||
enum { OK = 0, BUSY, ERROR };
|
||||
std::vector<struct ActionExec> action_exec;
|
||||
int index;
|
||||
PlanExec()
|
||||
: index(-1)
|
||||
{
|
||||
}
|
||||
int operator()(float delta)
|
||||
{
|
||||
if (index == -1)
|
||||
index = 0;
|
||||
int rc = action_exec[index](delta);
|
||||
if (rc == ActionExec::ERROR)
|
||||
return ERROR;
|
||||
if (action_exec[index].complete)
|
||||
index++;
|
||||
if (index >= action_exec.size())
|
||||
return OK;
|
||||
return BUSY;
|
||||
}
|
||||
};
|
||||
static std::unordered_map<int, struct PlanExec> plan_exec;
|
||||
ecs.system<const EngineData, TownNPCs, TownAI>("RunPLAN")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -470,7 +583,14 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
for (const auto &plans : ai.plans) {
|
||||
if (plan_exec.find(plans.first) !=
|
||||
plan_exec.end()) {
|
||||
plan_exec[plans.first](eng.delta);
|
||||
int rc = plan_exec[plans.first](
|
||||
eng.delta);
|
||||
if (rc != PlanExec::BUSY) {
|
||||
plan_exec.erase(plans.first);
|
||||
ai.plans[plans.first].erase(
|
||||
ai.plans[plans.first]
|
||||
.begin());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::cout << "NPC: " << plans.first;
|
||||
@@ -482,14 +602,45 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
std::cout << " Goal: ";
|
||||
plan.goal->goal.dump_bits();
|
||||
for (const auto &action : plan.plan) {
|
||||
pexec.action_exec.emplace_back(
|
||||
ActionExec::PlanExecData data({
|
||||
npcs.npcs.at(
|
||||
plans.first),
|
||||
ai.blackboards.at(
|
||||
plans.first),
|
||||
ai.memory.at(
|
||||
plans.first),
|
||||
action);
|
||||
|
||||
});
|
||||
// TODO: executor factory is needed
|
||||
if (action->get_name().substr(
|
||||
0, 4) == "Walk") {
|
||||
ActionExec *e = OGRE_NEW
|
||||
ActionNodeActions::ActionExecWalk(
|
||||
data,
|
||||
action);
|
||||
pexec.action_exec
|
||||
.push_back(e);
|
||||
} else if (action->get_name()
|
||||
.substr(0,
|
||||
4) ==
|
||||
"Use(") {
|
||||
ActionExec *e = OGRE_NEW
|
||||
ActionNodeActions::ActionExecUse(
|
||||
data,
|
||||
action);
|
||||
pexec.action_exec
|
||||
.push_back(e);
|
||||
} else {
|
||||
std::cout
|
||||
<< action->get_name()
|
||||
<< " ";
|
||||
ActionExec *e = OGRE_NEW
|
||||
ActionExecCommon(
|
||||
data,
|
||||
action);
|
||||
pexec.action_exec
|
||||
.push_back(e);
|
||||
}
|
||||
std::cout << action->get_name()
|
||||
<< " ";
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "CharacterAIModule.h"
|
||||
#include "QuestModule.h"
|
||||
#include "world-build.h"
|
||||
#include "physics.h"
|
||||
|
||||
namespace ECS
|
||||
{
|
||||
@@ -50,9 +51,11 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
|
||||
Ogre::Camera *camera, Ogre::RenderWindow *window)
|
||||
{
|
||||
std::cout << "Setup GameData\n";
|
||||
setup_minimal();
|
||||
setup_minimal();
|
||||
|
||||
std::cout << "Setup Editor\n";
|
||||
ecs.component<GameState>().add(flecs::Singleton);
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <BoatModule>();
|
||||
ecs.import <PhysicsModule>();
|
||||
ecs.import <WaterModule>();
|
||||
@@ -208,9 +211,11 @@ void setupInventoryScene(Ogre::SceneManager *scnMgr,
|
||||
void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
|
||||
Ogre::Camera *camera, Ogre::RenderWindow *window)
|
||||
{
|
||||
std::cout << "Setup Editor\n";
|
||||
setup_minimal();
|
||||
ecs.component<RenderWindow>().add(flecs::Singleton);
|
||||
setup_minimal();
|
||||
Physics &ph = ECS::get().ensure<Physics>();
|
||||
ph.physics = new JoltPhysicsWrapper(scnMgr, cameraNode);
|
||||
ECS::modified<Physics>();
|
||||
ecs.component<RenderWindow>().add(flecs::Singleton);
|
||||
ecs.component<EditorSceneSwitch>().add(flecs::Singleton);
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <BoatModule>();
|
||||
|
||||
@@ -627,11 +627,6 @@ void PhysicsModule::setDebugDraw(bool enable)
|
||||
|
||||
void PhysicsModule::configurePhysics()
|
||||
{
|
||||
Physics &ph = ECS::get().ensure<Physics>();
|
||||
const EngineData &e = ECS::get<EngineData>();
|
||||
const Camera &c = ECS::get<Camera>();
|
||||
ph.physics = new JoltPhysicsWrapper(e.mScnMgr, c.mCameraNode);
|
||||
ECS::modified<Physics>();
|
||||
}
|
||||
bool WaterBody::isInWater(const JPH::BodyID &id) const
|
||||
{
|
||||
|
||||
@@ -579,9 +579,6 @@ public:
|
||||
static int instanceCount = 0;
|
||||
OgreAssert(instanceCount == 0, "Bad initialisation");
|
||||
instanceCount++;
|
||||
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
|
||||
// It is not directly used in this example but still required.
|
||||
JPH::Factory::sInstance = new JPH::Factory();
|
||||
|
||||
// Register all physics types with the factory and install their collision handlers with the CollisionDispatch class.
|
||||
// If you have your own custom shape types you probably need to register their handlers with the CollisionDispatch before calling this function.
|
||||
@@ -1530,7 +1527,11 @@ JoltPhysicsWrapper::JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
|
||||
// This needs to be done before any other Jolt function is called.
|
||||
JPH::RegisterDefaultAllocator();
|
||||
|
||||
// Install trace and assert callbacks
|
||||
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
|
||||
// It is not directly used in this example but still required.
|
||||
JPH::Factory::sInstance = new JPH::Factory();
|
||||
|
||||
// Install trace and assert callbacks
|
||||
JPH::Trace = TraceImpl;
|
||||
JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = AssertFailedImpl;)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user