comparison trunk/tests/ChipmunkDemos/samples/Sensors.d @ 16:af2f61a96318

ported chipmunk demos
author Extrawurst
date Sat, 04 Dec 2010 02:02:29 +0100
parents
children
comparison
equal deleted inserted replaced
15:df4ebc8add66 16:af2f61a96318
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 };