Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "simulation2/system/Component.h"
21 : #include "ICmpMotion.h"
22 :
23 : #include "ICmpPosition.h"
24 : #include "simulation2/MessageTypes.h"
25 :
26 : #include "graphics/Terrain.h"
27 :
28 0 : class CCmpMotionBall final : public ICmpMotion
29 : {
30 : public:
31 116 : static void ClassInit(CComponentManager& componentManager)
32 : {
33 116 : componentManager.SubscribeToMessageType(MT_Update);
34 116 : }
35 :
36 0 : DEFAULT_COMPONENT_ALLOCATOR(MotionBall)
37 :
38 : // Current speed in metres per second
39 : float m_SpeedX, m_SpeedZ;
40 :
41 116 : static std::string GetSchema()
42 : {
43 116 : return "<a:component type='test'/><ref name='anything'/>";
44 : }
45 :
46 0 : void Init(const CParamNode& UNUSED(paramNode)) override
47 : {
48 0 : m_SpeedX = 0;
49 0 : m_SpeedZ = 0;
50 0 : }
51 :
52 0 : void Deinit() override
53 : {
54 0 : }
55 :
56 0 : void Serialize(ISerializer& serialize) override
57 : {
58 0 : serialize.NumberFloat_Unbounded("speed x", m_SpeedX);
59 0 : serialize.NumberFloat_Unbounded("speed z", m_SpeedZ);
60 0 : }
61 :
62 0 : void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) override
63 : {
64 0 : Init(paramNode);
65 0 : deserialize.NumberFloat_Unbounded("speed x", m_SpeedX);
66 0 : deserialize.NumberFloat_Unbounded("speed z", m_SpeedZ);
67 0 : }
68 :
69 0 : void HandleMessage(const CMessage& msg, bool UNUSED(global)) override
70 : {
71 0 : switch (msg.GetType())
72 : {
73 0 : case MT_Update:
74 : {
75 0 : fixed dt = static_cast<const CMessageUpdate&> (msg).turnLength;
76 0 : Move(dt);
77 0 : break;
78 : }
79 : }
80 0 : }
81 :
82 : void Move(fixed dt);
83 : };
84 :
85 0 : void CCmpMotionBall::Move(fixed dt)
86 : {
87 0 : CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
88 0 : if (!cmpPosition)
89 0 : return;
90 :
91 : // TODO: this is all FP-unsafe
92 :
93 0 : CFixedVector3D pos = cmpPosition->GetPosition();
94 0 : float x = pos.X.ToFloat();
95 0 : float z = pos.Z.ToFloat();
96 :
97 0 : CVector3D normal = GetSimContext().GetTerrain().CalcExactNormal(x, z);
98 : // Flatten the vector, to get the downhill force
99 0 : float g = 10.f;
100 0 : CVector3D force(g * normal.X, 0.f, g * normal.Z);
101 :
102 0 : m_SpeedX += force.X;
103 0 : m_SpeedZ += force.Z;
104 :
105 0 : float drag = 0.5f; // fractional decay per second
106 :
107 0 : float dt_ = dt.ToFloat();
108 :
109 0 : m_SpeedX *= powf(drag, dt_);
110 0 : m_SpeedZ *= powf(drag, dt_);
111 :
112 0 : cmpPosition->MoveTo(entity_pos_t::FromFloat(x + m_SpeedX * dt_), entity_pos_t::FromFloat(z + m_SpeedZ * dt_));
113 : }
114 :
115 119 : REGISTER_COMPONENT_TYPE(MotionBall)
|