I'm creating a 2D game in JS, and I've made the generic class that all objects in the game will be (I've decided they are all circular for now).
An object has motion
and angMotion
array
properties which contain the 0th, 1st and 2nd derivatives of the object's (angular) motion.
I've also introduced aliases for each of these derivatives (like acc
for acceleration, etc).
Upon initialization, the default for all derivatives should be 0.
I'm satisfied with how the class works as it is now as long as it remains 2 dimensional and I don't need higher derivatives of (angular) motion.
However, I feel that my code is repetitive in some places which would require changes in multiple places supposing I want to change how it works slightly.
Eg. I've considered the possibility of wanting to include higher derivatives of motion (without introducing more aliases like jerk
) or changing the dimension I'm working in (ignore angular motion in this case).
Note: I wanted the derivatives of (angular) motion to be stored in arrays so that I can loop over them to simulate Physics using Taylor's Expansion as shown below. The simulatePhysics
function works regardless of the number of derivatives or dimension.
I'm also wondering from a design point of view - would it be a better idea to put simulatePhysics
as a method of the game instead of the object?
class Game2DObject {
constructor(options) {
if (options) {
this.motion = options.motion || []
this.angMotion = options.angMotion || []
this.dis = options.dis || [0, 0]
this.vel = options.vel || [0, 0]
this.acc = options.acc || [0, 0]
this.angDis = options.angDis || 0
this.angVel = options.angVel || 0
this.angAcc = options.angAcc || 0
this.radius = options.radius || 0
this.mass = options.mass || 0
} else {
this.motion = [[0, 0], [0, 0], [0, 0]]
this.angMotion = [0, 0, 0]
this.radius = 0
this.mass = 0
}
}
//motion
get dis() {
return this.motion[0]
}
set dis(x) {
this.motion[0] = x
}
get vel() {
return this.motion[1]
}
set vel(x) {
this.motion[1] = x
}
get acc() {
return this.motion[2]
}
set acc(x) {
this.motion[2] = x
}
//angMotion
get angDis() {
return this.angMotion[0]
}
set angDis(x) {
this.angMotion[0] = x
}
get angVel() {
return this.angMotion[1]
}
set angVel(x) {
this.angMotion[1] = x
}
get angAcc() {
return this.angMotion[2]
}
set angAcc(x) {
this.angMotion[2] = x
}
simulatePhysics(dt) {
function taylor(arr) {
return arr.reduceRight((acc, cur, i) => acc * dt / (i + 1) + cur, 0)
}
for (var dim = 0; dim < this.motion[0].length; dim++) {
for (var deriv = 0; deriv < this.motion.length; deriv++) {
this.motion[deriv][dim] = taylor(this.motion.slice(deriv).map((cur) => cur[dim]))
}
}
for (var deriv = 0; deriv < this.angMotion.length; deriv++) {
this.angMotion[deriv] = taylor(this.angMotion.slice(deriv))
}
}
}
//*DEBUG
var a = new Game2DObject({acc: [-6, 0], angVel: 9})
console.log(a)
console.log(a.dis[0] = 1)
console.log(a.dis[1] = 5)
console.log(a.acc[1] = -2)
console.log(a)
a.simulatePhysics(1)
console.log(a)
a.simulatePhysics(1)
console.log(a)
a.simulatePhysics(1)
console.log(a)
Output: