forked from oakmound/oak
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathforce.go
86 lines (72 loc) · 2.1 KB
/
force.go
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
package physics
import (
"github.com/oakmound/oak/v4/oakerr"
)
const frozen = -64
// ForceVector is a vector that has some force and can operate on entites with mass
type ForceVector struct {
Vector
Force *float64
}
// NewForceVector returns a force vector
func NewForceVector(direction Vector, force float64) ForceVector {
return ForceVector{Vector: direction, Force: &force}
}
// DefaultForceVector returns a force vector that converts the mass given
// into a force float
func DefaultForceVector(delta Vector, mass float64) ForceVector {
return NewForceVector(delta, delta.Magnitude()*mass)
}
// GetForce is a self-returning call
func (f ForceVector) GetForce() ForceVector {
return f
}
// GetForce on a non-force vector returns a zero-value for force
func (v Vector) GetForce() ForceVector {
return ForceVector{v, new(float64)}
}
// A Mass can have forces applied against it
type Mass struct {
mass float64
}
// SetMass of an object
func (m *Mass) SetMass(inMass float64) error {
if inMass > 0 {
m.mass = inMass
return nil
}
return oakerr.InvalidInput{InputName: "inMass"}
}
//GetMass returns the mass of an object
func (m *Mass) GetMass() float64 {
return m.mass
}
// Freeze changes a pushables mass such that it can no longer be pushed.
func (m *Mass) Freeze() {
m.mass = frozen
}
// Pushable is implemented by anything that has mass and directional movement,
// and therefore can be pushed.
type Pushable interface {
GetDelta() Vector
GetMass() float64
}
// A Pushes can push Pushable things through its associated ForceVector, or
// how hard the Pushable should move in a given direction
type Pushes interface {
GetForce() ForceVector
}
// Push applies the force from the pushing object its target
func Push(a Pushes, b Pushable) error {
if b.GetMass() <= 0 {
if b.GetMass() != frozen {
return oakerr.InsufficientInputs{InputName: "Mass", AtLeast: 0}
}
return nil
}
//Copy a's force so that we dont change the original when we scale it later
fdirection := a.GetForce().Copy()
totalF := *a.GetForce().Force / b.GetMass()
b.GetDelta().Add(fdirection.Normalize().Scale(totalF))
return nil
}