forked from jakecoffman/cp
/
tank.go
105 lines (85 loc) · 2.88 KB
/
tank.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package main
import (
"log"
"math/rand"
"time"
. "github.com/jakecoffman/cp"
"github.com/jakecoffman/cp/examples"
)
var (
tankBody, tankControlBody *Body
)
const (
width = 640
height = 480
hwidth = width / 2
hheight = height / 2
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
rand.Seed(time.Now().Unix())
space := NewSpace()
//space.Iterations = 10
space.SleepTimeThreshold = 0.5
sides := []Vector{
{-hwidth, -hheight}, {-hwidth, hheight},
{hwidth, -hheight}, {hwidth, hheight},
{-hwidth, -hheight}, {hwidth, -hheight},
{-hwidth, hheight}, {hwidth, hheight},
}
for i := 0; i < len(sides); i += 2 {
var seg *Shape
seg = space.AddShape(NewSegment(space.StaticBody, sides[i], sides[i+1], 0))
seg.SetElasticity(1)
seg.SetFriction(1)
seg.SetFilter(examples.NotGrabbableFilter)
}
for i := 0; i < 50; i++ {
body := addBox(space, 20, 1)
pivot := space.AddConstraint(NewPivotJoint2(space.StaticBody, body, Vector{}, Vector{}))
pivot.SetMaxBias(0) // disable joint correction
pivot.SetMaxForce(1000.0) // emulate linear friction
gear := space.AddConstraint(NewGearJoint(space.StaticBody, body, 0.0, 1.0))
gear.SetMaxBias(0)
gear.SetMaxForce(5000.0) // emulate angular friction
}
// We joint the tank to the control body and control the tank indirectly by modifying the control body.
tankControlBody = space.AddBody(NewKinematicBody())
tankBody = addBox(space, 30, 10)
pivot := space.AddConstraint(NewPivotJoint2(tankControlBody, tankBody, Vector{}, Vector{}))
pivot.SetMaxBias(0)
pivot.SetMaxForce(10000)
gear := space.AddConstraint(NewGearJoint(tankControlBody, tankBody, 0.0, 1.0))
gear.SetErrorBias(0) // attempt to fully correct the joint each step
gear.SetMaxBias(1.2)
gear.SetMaxForce(50000)
examples.Main(space, 1.0/60.0, update, examples.DefaultDraw)
}
func addBox(space *Space, size, mass float64) *Body {
radius := (&Vector{size, size}).Length()
body := space.AddBody(NewBody(mass, MomentForBox(mass, size, size)))
body.SetPosition(Vector{rand.Float64()*(width-2*radius) - (hwidth - radius), rand.Float64()*(height-2*radius) - (hheight - radius)})
shape := space.AddShape(NewBox(body, size, size, 0))
shape.SetElasticity(0)
shape.SetFriction(0.7)
return body
}
func update(space *Space, dt float64) {
// turn the control body based on the angle relative to the actual body
mouseDelta := examples.Mouse.Sub(tankBody.Position())
turn := tankBody.Rotation().Unrotate(mouseDelta).ToAngle()
tankControlBody.SetAngle(tankBody.Angle() - turn)
// drive the tank towards the mouse
if examples.Mouse.Near(tankBody.Position(), 30.0) {
tankControlBody.SetVelocityVector(Vector{}) // stop
} else {
var direction float64
if mouseDelta.Dot(tankBody.Rotation()) > 0.0 {
direction = 1.0
} else {
direction = -1.0
}
tankControlBody.SetVelocityVector(tankBody.Rotation().Rotate(Vector{30.0 * direction, 0.0}))
}
space.Step(dt)
}