/
Vehicle.js
180 lines (126 loc) · 3.93 KB
/
Vehicle.js
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import { MovingEntity } from '../core/MovingEntity.js';
import { SteeringManager } from './SteeringManager.js';
import { Vector3 } from '../math/Vector3.js';
import { Smoother } from './Smoother.js';
const steeringForce = new Vector3();
const displacement = new Vector3();
const acceleration = new Vector3();
const target = new Vector3();
const velocitySmooth = new Vector3();
/**
* This type of game entity implements a special type of locomotion, the so called
* *Vehicle Model*. The class uses basic physical metrics in order to implement a
* realistic movement.
*
* @author {@link https://github.com/Mugen87|Mugen87}
* @author {@link https://github.com/robp94|robp94}
* @augments MovingEntity
*/
class Vehicle extends MovingEntity {
/**
* Constructs a new vehicle.
*/
constructor() {
super();
/**
* The mass if the vehicle in kilogram.
* @type Number
* @default 1
*/
this.mass = 1;
/**
* The maximum force this entity can produce to power itself.
* @type Number
* @default 100
*/
this.maxForce = 100;
/**
* The steering manager of this vehicle.
* @type SteeringManager
*/
this.steering = new SteeringManager( this );
/**
* An optional smoother to avoid shakiness due to conflicting steering behaviors.
* @type Smoother
* @default null
*/
this.smoother = null;
}
/**
* This method is responsible for updating the position based on the force produced
* by the internal steering manager.
*
* @param {Number} delta - The time delta.
* @return {Vehicle} A reference to this vehicle.
*/
update( delta ) {
// calculate steering force
this.steering.calculate( delta, steeringForce );
// acceleration = force / mass
acceleration.copy( steeringForce ).divideScalar( this.mass );
// update velocity
this.velocity.add( acceleration.multiplyScalar( delta ) );
// make sure vehicle does not exceed maximum speed
if ( this.getSpeedSquared() > ( this.maxSpeed * this.maxSpeed ) ) {
this.velocity.normalize();
this.velocity.multiplyScalar( this.maxSpeed );
}
// calculate displacement
displacement.copy( this.velocity ).multiplyScalar( delta );
// calculate target position
target.copy( this.position ).add( displacement );
// update the orientation if the vehicle has a non zero velocity
if ( this.updateOrientation === true && this.smoother === null && this.getSpeedSquared() > 0.00000001 ) {
this.lookAt( target );
}
// update position
this.position.copy( target );
// if smoothing is enabled, the orientation (not the position!) of the vehicle is
// changed based on a post-processed velocity vector
if ( this.updateOrientation === true && this.smoother !== null ) {
this.smoother.calculate( this.velocity, velocitySmooth );
displacement.copy( velocitySmooth ).multiplyScalar( delta );
target.copy( this.position ).add( displacement );
this.lookAt( target );
}
return this;
}
/**
* Transforms this instance into a JSON object.
*
* @return {Object} The JSON object.
*/
toJSON() {
const json = super.toJSON();
json.mass = this.mass;
json.maxForce = this.maxForce;
json.steering = this.steering.toJSON();
json.smoother = this.smoother ? this.smoother.toJSON() : null;
return json;
}
/**
* Restores this instance from the given JSON object.
*
* @param {Object} json - The JSON object.
* @return {Vehicle} A reference to this vehicle.
*/
fromJSON( json ) {
super.fromJSON( json );
this.mass = json.mass;
this.maxForce = json.maxForce;
this.steering = new SteeringManager( this ).fromJSON( json.steering );
this.smoother = json.smoother ? new Smoother().fromJSON( json.smoother ) : null;
return this;
}
/**
* Restores UUIDs with references to GameEntity objects.
*
* @param {Map} entities - Maps game entities to UUIDs.
* @return {Vehicle} A reference to this vehicle.
*/
resolveReferences( entities ) {
super.resolveReferences( entities );
this.steering.resolveReferences( entities );
}
}
export { Vehicle };