-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcollision.go
132 lines (112 loc) · 4.28 KB
/
collision.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
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
package engoBox2dSystem
import (
"github.com/ByteArena/box2d"
"github.com/EngoEngine/ecs"
"github.com/EngoEngine/engo"
"github.com/EngoEngine/engo/common"
)
// CollisionStartMessage is sent out for the box2d collision callback
// CollisionStart
type CollisionStartMessage struct {
Contact box2d.B2ContactInterface
}
// Type implements the engo.Message interface
func (CollisionStartMessage) Type() string { return "CollisionStartMessage" }
// CollisionEndMessage is sent out for the box2d collision callback
// CollisionEnd
type CollisionEndMessage struct {
Contact box2d.B2ContactInterface
}
// Type implements the engo.Message interface
func (CollisionEndMessage) Type() string { return "CollisionEndMessage" }
// PreSolveMessage is sent out before a step of the physics engine
type PreSolveMessage struct {
Contact box2d.B2ContactInterface
OldManifold box2d.B2Manifold
}
// Type implements the engo.Message interface
func (PreSolveMessage) Type() string { return "PreSolveMessage" }
// PostSolveMessage is sent out after a step of the physics engine
type PostSolveMessage struct {
Contact box2d.B2ContactInterface
Impulse *box2d.B2ContactImpulse
}
// Type implements the engo.Message interface
func (PostSolveMessage) Type() string { return "PostSolveMessage" }
type collisionEntity struct {
*ecs.BasicEntity
*common.SpaceComponent
*Box2dComponent
}
// CollisionSystem is a system that handles the callbacks for box2d's
// collision system. This system does not require the physics system, but a
// they do need box2d bodies.
type CollisionSystem struct {
entities []collisionEntity
}
// New sets the system to the contact listener for box2d, which allows the collision
// messages to be sent out.
func (c *CollisionSystem) New(w *ecs.World) {
World.SetContactListener(c)
}
// Add adds the entity to the collision system.
// It also adds the body's user data to the BasicEntity's ID, which makes it
// easy to figure out which entities are which when comparing in the messages / callbacks
func (c *CollisionSystem) Add(basic *ecs.BasicEntity, space *common.SpaceComponent, box *Box2dComponent) {
box.Body.SetUserData(basic.ID())
c.entities = append(c.entities, collisionEntity{basic, space, box})
}
// AddByInterface adds the entity to the collision system if it implements the Collisionable interface
func (c *CollisionSystem) AddByInterface(o Collisionable) {
c.Add(o.GetBasicEntity(), o.GetSpaceComponent(), o.GetBox2dComponent())
}
// Remove removes the entity from the system
func (c *CollisionSystem) Remove(basic ecs.BasicEntity) {
delete := -1
for index, e := range c.entities {
if e.BasicEntity.ID() == basic.ID() {
delete = index
break
}
}
if delete >= 0 {
c.entities = append(c.entities[:delete], c.entities[delete+1:]...)
}
}
// Update doesn't do anything, since the physics engine handles passing out the
// callbacks.
func (c *CollisionSystem) Update(dt float32) {}
// BeginContact implements the B2ContactListener interface.
// when a BeginContact callback is made by box2d, it sends a message containing
// the information from the callback.
func (c *CollisionSystem) BeginContact(contact box2d.B2ContactInterface) {
engo.Mailbox.Dispatch(CollisionStartMessage{
Contact: contact,
})
}
// EndContact implements the B2ContactListener interface.
// when a EndContact callback is made by box2d, it sends a message containing
// the information from the callback.
func (c *CollisionSystem) EndContact(contact box2d.B2ContactInterface) {
engo.Mailbox.Dispatch(CollisionEndMessage{
Contact: contact,
})
}
// PreSolve implements the B2ContactListener interface.
// this is called after a contact is updated but before it goes to the solver.
// When it is called, a message is sent containing the information from the callback
func (c *CollisionSystem) PreSolve(contact box2d.B2ContactInterface, oldManifold box2d.B2Manifold) {
engo.Mailbox.Dispatch(PreSolveMessage{
Contact: contact,
OldManifold: oldManifold,
})
}
// PostSolve implements the B2ContactListener interface.
// this is called after the solver is finished.
// When it is called, a message is sent containing the information from the callback
func (c *CollisionSystem) PostSolve(contact box2d.B2ContactInterface, impulse *box2d.B2ContactImpulse) {
engo.Mailbox.Dispatch(PostSolveMessage{
Contact: contact,
Impulse: impulse,
})
}