16
|
1
|
|
2 // written in the D programming language
|
|
3
|
|
4 module samples.Sensors;
|
|
5
|
|
6 import chipmunkd.chipmunk;
|
|
7
|
|
8 import samples.ChipmunkDemo;
|
|
9
|
|
10 static cpSpace *space;
|
|
11
|
|
12 enum CollisionTypes {
|
|
13 BALL_TYPE,
|
|
14 BLOCKING_SENSOR_TYPE,
|
|
15 CATCH_SENSOR_TYPE,
|
|
16 };
|
|
17
|
|
18 struct Emitter {
|
|
19 int queue;
|
|
20 int blocked;
|
|
21 cpVect position;
|
|
22 }
|
|
23
|
|
24 static Emitter emitterInstance;
|
|
25
|
|
26 static cpBool
|
|
27 blockerBegin(cpArbiter *arb, cpSpace *space, void *unused)
|
|
28 {
|
|
29 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
30 Emitter *emitter = cast(Emitter *) a.data;
|
|
31
|
|
32 emitter.blocked++;
|
|
33
|
|
34 return cpFalse; // Return values from sensors callbacks are ignored,
|
|
35 }
|
|
36
|
|
37 static void
|
|
38 blockerSeparate(cpArbiter *arb, cpSpace *space, void *unused)
|
|
39 {
|
|
40 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
41 Emitter *emitter = cast(Emitter *)a.data;
|
|
42
|
|
43 emitter.blocked--;
|
|
44 }
|
|
45
|
|
46 static void
|
|
47 postStepRemove(cpSpace *space, cpShape *shape, void *unused)
|
|
48 {
|
|
49 cpSpaceRemoveBody(space, shape._body);
|
|
50 cpSpaceRemoveShape(space, shape);
|
|
51
|
|
52 cpBodyFree(shape._body);
|
|
53 cpShapeFree(shape);
|
|
54 }
|
|
55
|
|
56 static cpBool
|
|
57 catcherBarBegin(cpArbiter *arb, cpSpace *space, void *unused)
|
|
58 {
|
|
59 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
60 Emitter *emitter = cast(Emitter *) a.data;
|
|
61
|
|
62 emitter.queue++;
|
|
63 cpSpaceAddPostStepCallback(space, cast(cpPostStepFunc)&postStepRemove, b, null);
|
|
64
|
|
65 return cpFalse;
|
|
66 }
|
|
67
|
|
68 static cpFloat frand_unit(){return 2.0f*(frand()) - 1.0f;}
|
|
69
|
|
70 static void
|
|
71 update(int ticks)
|
|
72 {
|
|
73 int steps = 1;
|
|
74 cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
|
|
75
|
|
76 if(!emitterInstance.blocked && emitterInstance.queue){
|
|
77 emitterInstance.queue--;
|
|
78
|
|
79 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 15.0f, 0.0f, cpvzero)));
|
|
80 _body.p = emitterInstance.position;
|
|
81 _body.v = cpvmult(cpv(frand_unit(), frand_unit()), 100.0f);
|
|
82
|
|
83 cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, 15.0f, cpvzero));
|
|
84 shape.collision_type = CollisionTypes.BALL_TYPE;
|
|
85 }
|
|
86
|
|
87 for(int i=0; i<steps; i++){
|
|
88 cpSpaceStep(space, dt);
|
|
89 }
|
|
90 }
|
|
91
|
|
92 static cpSpace *
|
|
93 init()
|
|
94 {
|
|
95 cpResetShapeIdCounter();
|
|
96
|
|
97 space = cpSpaceNew();
|
|
98 space.iterations = 10;
|
|
99 space.gravity = cpv(0, -100);
|
|
100
|
|
101 cpBody *staticBody = &space.staticBody;
|
|
102 cpShape *shape;
|
|
103
|
|
104 // Data structure for our ball emitter
|
|
105 // We'll use two sensors for it, one to see if the emitter is blocked
|
|
106 // a second to catch the balls and add them back to the emitter
|
|
107 emitterInstance.queue = 5;
|
|
108 emitterInstance.blocked = 0;
|
|
109 emitterInstance.position = cpv(0, 150);
|
|
110
|
|
111 // Create our blocking sensor, so we know when the emitter is clear to emit another ball
|
|
112 shape = cpSpaceAddShape(space, cpCircleShapeNew(staticBody, 15.0f, emitterInstance.position));
|
|
113 shape.sensor = 1;
|
|
114 shape.collision_type = CollisionTypes.BLOCKING_SENSOR_TYPE;
|
|
115 shape.data = &emitterInstance;
|
|
116
|
|
117 // Create our catch sensor to requeue the balls when they reach the bottom of the screen
|
|
118 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-2000, -200), cpv(2000, -200), 15.0f));
|
|
119 shape.sensor = 1;
|
|
120 shape.collision_type = CollisionTypes.CATCH_SENSOR_TYPE;
|
|
121 shape.data = &emitterInstance;
|
|
122
|
|
123 cpSpaceAddCollisionHandler(space, CollisionTypes.BLOCKING_SENSOR_TYPE, CollisionTypes.BALL_TYPE, &blockerBegin, null, null, &blockerSeparate, null);
|
|
124 cpSpaceAddCollisionHandler(space, CollisionTypes.CATCH_SENSOR_TYPE, CollisionTypes.BALL_TYPE, &catcherBarBegin, null, null, null, null);
|
|
125
|
|
126 return space;
|
|
127 }
|
|
128
|
|
129 static void
|
|
130 destroy()
|
|
131 {
|
|
132 cpSpaceFreeChildren(space);
|
|
133 cpSpaceFree(space);
|
|
134 }
|
|
135
|
|
136 chipmunkDemo Sensors = {
|
|
137 "Sensors",
|
|
138 null,
|
|
139 &init,
|
|
140 &update,
|
|
141 &destroy,
|
|
142 };
|