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

ported chipmunk demos
author Extrawurst
date Sat, 04 Dec 2010 02:02:29 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/tests/ChipmunkDemos/samples/Sensors.d	Sat Dec 04 02:02:29 2010 +0100
@@ -0,0 +1,142 @@
+
+// written in the D programming language
+
+module samples.Sensors;
+
+import chipmunkd.chipmunk;
+
+import samples.ChipmunkDemo;
+
+static cpSpace *space;
+
+enum CollisionTypes {
+	BALL_TYPE,
+	BLOCKING_SENSOR_TYPE,
+	CATCH_SENSOR_TYPE,
+};
+
+struct Emitter {
+	int queue;
+	int blocked;
+	cpVect position;
+}
+
+static Emitter emitterInstance;
+
+static cpBool
+blockerBegin(cpArbiter *arb, cpSpace *space, void *unused)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	Emitter *emitter = cast(Emitter *) a.data;
+	
+	emitter.blocked++;
+	
+	return cpFalse; // Return values from sensors callbacks are ignored,
+}
+
+static void
+blockerSeparate(cpArbiter *arb, cpSpace *space, void *unused)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	Emitter *emitter = cast(Emitter *)a.data;
+	
+	emitter.blocked--;
+}
+
+static void
+postStepRemove(cpSpace *space, cpShape *shape, void *unused)
+{
+	cpSpaceRemoveBody(space, shape._body);
+	cpSpaceRemoveShape(space, shape);
+	
+	cpBodyFree(shape._body);
+	cpShapeFree(shape);
+}
+
+static cpBool
+catcherBarBegin(cpArbiter *arb, cpSpace *space, void *unused)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	Emitter *emitter = cast(Emitter *) a.data;
+	
+	emitter.queue++;
+	cpSpaceAddPostStepCallback(space, cast(cpPostStepFunc)&postStepRemove, b, null);
+	
+	return cpFalse;
+}
+
+static cpFloat frand_unit(){return 2.0f*(frand()) - 1.0f;}
+
+static void
+update(int ticks)
+{
+	int steps = 1;
+	cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
+	
+	if(!emitterInstance.blocked && emitterInstance.queue){
+		emitterInstance.queue--;
+		
+		cpBody *_body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 15.0f, 0.0f, cpvzero)));
+		_body.p = emitterInstance.position;
+		_body.v = cpvmult(cpv(frand_unit(), frand_unit()), 100.0f);
+		
+		cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, 15.0f, cpvzero));
+		shape.collision_type = CollisionTypes.BALL_TYPE;
+	}
+	
+	for(int i=0; i<steps; i++){
+		cpSpaceStep(space, dt);
+	}
+}
+
+static cpSpace *
+init()
+{
+	cpResetShapeIdCounter();
+	
+	space = cpSpaceNew();
+	space.iterations = 10;
+	space.gravity = cpv(0, -100);
+	
+	cpBody *staticBody = &space.staticBody;
+	cpShape *shape;
+	
+	// Data structure for our ball emitter
+	// We'll use two sensors for it, one to see if the emitter is blocked
+	// a second to catch the balls and add them back to the emitter
+	emitterInstance.queue = 5;
+	emitterInstance.blocked = 0;
+	emitterInstance.position = cpv(0, 150);
+	
+	// Create our blocking sensor, so we know when the emitter is clear to emit another ball
+	shape = cpSpaceAddShape(space, cpCircleShapeNew(staticBody, 15.0f, emitterInstance.position));
+	shape.sensor = 1;
+	shape.collision_type = CollisionTypes.BLOCKING_SENSOR_TYPE;
+	shape.data = &emitterInstance;
+	
+	// Create our catch sensor to requeue the balls when they reach the bottom of the screen
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-2000, -200), cpv(2000, -200), 15.0f));
+	shape.sensor = 1;
+	shape.collision_type = CollisionTypes.CATCH_SENSOR_TYPE;
+	shape.data = &emitterInstance;
+	
+	cpSpaceAddCollisionHandler(space, CollisionTypes.BLOCKING_SENSOR_TYPE, CollisionTypes.BALL_TYPE, &blockerBegin, null, null, &blockerSeparate, null);
+	cpSpaceAddCollisionHandler(space, CollisionTypes.CATCH_SENSOR_TYPE, CollisionTypes.BALL_TYPE, &catcherBarBegin, null, null, null, null);
+	
+	return space;
+}
+
+static void
+destroy()
+{
+	cpSpaceFreeChildren(space);
+	cpSpaceFree(space);
+}
+
+chipmunkDemo Sensors = {
+	"Sensors",
+	null,
+	&init,
+	&update,
+	&destroy,
+};