1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace Brains.Framework.Locomotion
{
/// <summary>
/// Need to rename this class.
/// </summary>
public class LocomotionController
{
private float _speed=0;
private Vector2 _velocity=Vector2.Zero;
/// <summary>
/// Gets or sets the maximum speed the agent can travel at
/// </summary>
public float MaxSpeed
{
get; set;
}
/// <summary>
/// Gets or sets the maximum amount an Agent can rotate per second
/// </summary>
/// <remarks>Value is in radians</remarks>
public float MaxRotation
{
get; set;
}
/// <summary>
/// Gets or sets the owning Agent
/// </summary>
public Agent Owner
{
get; set;
}
/// <summary>
/// Gets the current speed of the Agent
/// </summary>
public float Speed
{
get { return _speed; }
}
/// <summary>
/// Gets the velocity as a Vector2 of the Agent
/// </summary>
public Vector2 Velocity
{
get { return _velocity; }
}
/// <summary>
/// Gets or sets the value of wether the Agent will move
/// </summary>
public bool Stationary
{
get; set;
}
/// <summary>
/// Initializes a new instance of LocomotionController
/// </summary>
public LocomotionController()
{
}
/// <summary>
/// The Update method is called every update of an Agent.
/// </summary>
/// <param name="gameTime"></param>
public virtual void Update(GameTime gameTime)
{
if (Stationary)
return;
float desiredChangeRaw = Vector2.Dot(Owner.Orientation, Owner.DesiredOrientation);
float desiredChange = (float)Math.Acos(desiredChangeRaw);
float timeFactor = gameTime.GetElapsed();
if (timeFactor == 0.0f)
return;
if (desiredChange > MaxRotation * timeFactor)
{
// determine if we rotating clock or counter-clock wise,
// then aply maxRotation only
//create vector perpendicular to the desired direction;
Vector3 _perpendicular = new Vector3();
Vector3 _up = new Vector3(0, 0, 1);
Vector3 _des = Owner.DesiredOrientation.ToVector3();
if (_des != Vector3.Zero)
_des.Normalize();
Vector3.Cross(ref _des, ref _up, out _perpendicular);
bool clockWise = (Vector3.Dot(Owner.Orientation.ToVector3(), _perpendicular) >= 0.0f);
Matrix rotation = Matrix.Identity;
if (clockWise)
Matrix.CreateRotationZ(MaxRotation * timeFactor, out rotation);
else
Matrix.CreateRotationZ(-MaxRotation * timeFactor, out rotation);
_des = Vector3.Transform(Owner.Orientation.ToVector3(), rotation);
if (_des != Vector3.Zero)
_des.Normalize();
Owner.Orientation = _des.ToVector2();
}
else
{
Owner.Orientation = Owner.DesiredOrientation;
}
if (desiredChangeRaw < 0.0f)
desiredChangeRaw = 0.0f;
if (MaxSpeed > 0)
{
_speed = (1 + desiredChangeRaw) * 0.5f * MaxSpeed;
_velocity = Owner.Orientation * _speed;
Owner.Position += _velocity * timeFactor;
}
else
_speed = MaxSpeed;
}
}
} |