Skip to content

Commit 52e97eb

Browse files
committed
Chapter 14 initial copy
1 parent a0fe2af commit 52e97eb

137 files changed

Lines changed: 190647 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Chapter14/Actor.cpp

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// ----------------------------------------------------------------
2+
// From Game Programming in C++ by Sanjay Madhav
3+
// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
4+
//
5+
// Released under the BSD License
6+
// See LICENSE.txt for full details.
7+
// ----------------------------------------------------------------
8+
9+
#include "Actor.h"
10+
#include "Game.h"
11+
#include "Component.h"
12+
#include <algorithm>
13+
#include "LevelLoader.h"
14+
15+
const char* Actor::TypeNames[NUM_ACTOR_TYPES] = {
16+
"Actor",
17+
"BallActor",
18+
"FollowActor",
19+
"PlaneActor",
20+
"TargetActor",
21+
};
22+
23+
Actor::Actor(Game* game)
24+
:mState(EActive)
25+
,mPosition(Vector3::Zero)
26+
,mRotation(Quaternion::Identity)
27+
,mScale(1.0f)
28+
,mGame(game)
29+
,mRecomputeTransform(true)
30+
{
31+
mGame->AddActor(this);
32+
}
33+
34+
Actor::~Actor()
35+
{
36+
mGame->RemoveActor(this);
37+
// Need to delete components
38+
// Because ~Component calls RemoveComponent, need a different style loop
39+
while (!mComponents.empty())
40+
{
41+
delete mComponents.back();
42+
}
43+
}
44+
45+
void Actor::Update(float deltaTime)
46+
{
47+
if (mState == EActive)
48+
{
49+
if (mRecomputeTransform)
50+
{
51+
ComputeWorldTransform();
52+
}
53+
UpdateComponents(deltaTime);
54+
UpdateActor(deltaTime);
55+
}
56+
}
57+
58+
void Actor::UpdateComponents(float deltaTime)
59+
{
60+
for (auto comp : mComponents)
61+
{
62+
comp->Update(deltaTime);
63+
}
64+
}
65+
66+
void Actor::UpdateActor(float deltaTime)
67+
{
68+
}
69+
70+
void Actor::ComputeWorldTransform()
71+
{
72+
mRecomputeTransform = false;
73+
// Scale, then rotate, then translate
74+
mWorldTransform = Matrix4::CreateScale(mScale);
75+
mWorldTransform *= Matrix4::CreateFromQuaternion(mRotation);
76+
mWorldTransform *= Matrix4::CreateTranslation(mPosition);
77+
78+
// Inform components world transform updated
79+
for (auto comp : mComponents)
80+
{
81+
comp->OnUpdateWorldTransform();
82+
}
83+
}
84+
85+
void Actor::RotateToNewForward(const Vector3& forward)
86+
{
87+
// Figure out difference between original (unit x) and new
88+
float dot = Vector3::Dot(Vector3::UnitX, forward);
89+
float angle = Math::Acos(dot);
90+
// Facing down X
91+
if (dot > 0.9999f)
92+
{
93+
SetRotation(Quaternion::Identity);
94+
}
95+
// Facing down -X
96+
else if (dot < -0.9999f)
97+
{
98+
SetRotation(Quaternion(Vector3::UnitZ, Math::Pi));
99+
}
100+
else
101+
{
102+
// Rotate about axis from cross product
103+
Vector3 axis = Vector3::Cross(Vector3::UnitX, forward);
104+
axis.Normalize();
105+
SetRotation(Quaternion(axis, angle));
106+
}
107+
}
108+
109+
void Actor::AddComponent(Component* component)
110+
{
111+
mComponents.emplace_back(component);
112+
std::sort(mComponents.begin(), mComponents.end(), [](Component* a, Component* b) {
113+
return a->GetUpdateOrder() < b->GetUpdateOrder();
114+
});
115+
}
116+
117+
void Actor::RemoveComponent(Component* component)
118+
{
119+
auto iter = std::find(mComponents.begin(), mComponents.end(), component);
120+
if (iter != mComponents.end())
121+
{
122+
mComponents.erase(iter);
123+
}
124+
}
125+
126+
void Actor::LoadProperties(const rapidjson::Value& inObj)
127+
{
128+
// Use strings for different states
129+
std::string state;
130+
if (JsonHelper::GetString(inObj, "state", state))
131+
{
132+
if (state == "active")
133+
{
134+
SetState(EActive);
135+
}
136+
else if (state == "paused")
137+
{
138+
SetState(EPaused);
139+
}
140+
else if (state == "dead")
141+
{
142+
SetState(EDead);
143+
}
144+
}
145+
146+
// Load position, rotation, and scale, and compute transform
147+
JsonHelper::GetVector3(inObj, "position", mPosition);
148+
JsonHelper::GetQuaternion(inObj, "rotation", mRotation);
149+
JsonHelper::GetFloat(inObj, "scale", mScale);
150+
ComputeWorldTransform();
151+
}
152+
153+
void Actor::SaveProperties(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& inObj) const
154+
{
155+
std::string state = "active";
156+
if (mState == EPaused)
157+
{
158+
state = "paused";
159+
}
160+
else if (mState == EDead)
161+
{
162+
state = "dead";
163+
}
164+
165+
JsonHelper::AddString(alloc, inObj, "state", state);
166+
JsonHelper::AddVector3(alloc, inObj, "position", mPosition);
167+
JsonHelper::AddQuaternion(alloc, inObj, "rotation", mRotation);
168+
JsonHelper::AddFloat(alloc, inObj, "scale", mScale);
169+
}

Chapter14/Actor.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// ----------------------------------------------------------------
2+
// From Game Programming in C++ by Sanjay Madhav
3+
// Copyright (C) 2017 Sanjay Madhav. All rights reserved.
4+
//
5+
// Released under the BSD License
6+
// See LICENSE.txt for full details.
7+
// ----------------------------------------------------------------
8+
9+
#pragma once
10+
#include <vector>
11+
#include "Math.h"
12+
#include <rapidjson/document.h>
13+
#include "Component.h"
14+
15+
class Actor
16+
{
17+
public:
18+
enum TypeID
19+
{
20+
TActor = 0,
21+
TBallActor,
22+
TFollowActor,
23+
TPlaneActor,
24+
TTargetActor,
25+
26+
NUM_ACTOR_TYPES
27+
};
28+
29+
static const char* TypeNames[NUM_ACTOR_TYPES];
30+
31+
enum State
32+
{
33+
EActive,
34+
EPaused,
35+
EDead
36+
};
37+
38+
Actor(class Game* game);
39+
virtual ~Actor();
40+
41+
// Update function called from Game (not overridable)
42+
void Update(float deltaTime);
43+
// Updates all the components attached to the actor (not overridable)
44+
void UpdateComponents(float deltaTime);
45+
// Any actor-specific update code (overridable)
46+
virtual void UpdateActor(float deltaTime);
47+
// Any actor-specific input code (overridable)
48+
virtual void ProcessInput(const uint8_t* keys) { }
49+
50+
// Getters/setters
51+
const Vector3& GetPosition() const { return mPosition; }
52+
void SetPosition(const Vector3& pos) { mPosition = pos; mRecomputeTransform = true; }
53+
float GetScale() const { return mScale; }
54+
void SetScale(float scale) { mScale = scale; mRecomputeTransform = true; }
55+
const Quaternion& GetRotation() const { return mRotation; }
56+
void SetRotation(const Quaternion& rotation) { mRotation = rotation; mRecomputeTransform = true; }
57+
58+
void ComputeWorldTransform();
59+
const Matrix4& GetWorldTransform() const { return mWorldTransform; }
60+
61+
Vector3 GetForward() const { return Vector3::Transform(Vector3::UnitX, mRotation); }
62+
Vector3 GetRight() const { return Vector3::Transform(Vector3::UnitY, mRotation); }
63+
64+
void RotateToNewForward(const Vector3& forward);
65+
66+
State GetState() const { return mState; }
67+
void SetState(State state) { mState = state; }
68+
69+
class Game* GetGame() { return mGame; }
70+
71+
72+
// Add/remove components
73+
void AddComponent(class Component* component);
74+
void RemoveComponent(class Component* component);
75+
76+
// Load/Save
77+
virtual void LoadProperties(const rapidjson::Value& inObj);
78+
virtual void SaveProperties(rapidjson::Document::AllocatorType& alloc,
79+
rapidjson::Value& inObj) const;
80+
81+
// Create an actor with specified properties
82+
template <typename T>
83+
static Actor* Create(class Game* game, const rapidjson::Value& inObj)
84+
{
85+
// Dynamically allocate actor of type T
86+
T* t = new T(game);
87+
// Call LoadProperties on new actor
88+
t->LoadProperties(inObj);
89+
return t;
90+
}
91+
92+
// Search throuch component vector for one of type
93+
Component* GetComponentOfType(Component::TypeID type)
94+
{
95+
Component* comp = nullptr;
96+
for (Component* c : mComponents)
97+
{
98+
if (c->GetType() == type)
99+
{
100+
comp = c;
101+
break;
102+
}
103+
}
104+
return comp;
105+
}
106+
107+
virtual TypeID GetType() const { return TActor; }
108+
109+
const std::vector<Component*>& GetComponents() const { return mComponents; }
110+
private:
111+
// Actor's state
112+
State mState;
113+
114+
// Transform
115+
Matrix4 mWorldTransform;
116+
Vector3 mPosition;
117+
Quaternion mRotation;
118+
float mScale;
119+
bool mRecomputeTransform;
120+
121+
std::vector<Component*> mComponents;
122+
class Game* mGame;
123+
};

0 commit comments

Comments
 (0)