diff trunk/tests/ChipmunkDemos/samples/Player.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/Player.d	Sat Dec 04 02:02:29 2010 +0100
@@ -0,0 +1,208 @@
+
+// written in the D programming language
+
+module samples.Player;
+
+import chipmunkd.chipmunk;
+
+import samples.ChipmunkDemo;
+
+import gameApp;
+
+static cpSpace *space;
+
+struct PlayerStruct {
+	cpFloat u;
+	cpShape *shape;
+	cpVect groundNormal;
+	cpArray *groundShapes;
+}
+
+PlayerStruct playerInstance;
+
+static cpBool
+begin(cpArbiter *arb, cpSpace *space, void *ignore)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	PlayerStruct *player = cast(PlayerStruct *)a.data;
+	
+	cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
+	if(n.y > 0.0f){
+		cpArrayPush(player.groundShapes, b);
+	}
+	
+	return cpTrue;
+}
+
+static cpBool
+preSolve(cpArbiter *arb, cpSpace *space, void *ignore)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	PlayerStruct *player = cast(PlayerStruct *)a.data;
+	
+	if(cpArbiterIsFirstContact(arb)){
+		a.u = player.u;
+		
+		// pick the most upright jump normal each frame
+		cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
+		if(n.y >= player.groundNormal.y){
+			player.groundNormal = n;
+		}
+	}
+	
+	return cpTrue;
+}
+
+static void
+separate(cpArbiter *arb, cpSpace *space, void *ignore)
+{
+	mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
+	PlayerStruct *player = cast(PlayerStruct *)a.data;
+	
+	cpArrayDeleteObj(player.groundShapes, b);
+	
+	if(player.groundShapes.num == 0){
+		a.u = 0.0f;
+		player.groundNormal = cpvzero;
+	}
+}
+
+static void
+playerUpdateVelocity(cpBody *_body, cpVect gravity, cpFloat damping, cpFloat dt)
+{
+	cpBodyUpdateVelocity(_body, gravity, damping, dt);
+	_body.v.y = cpfmax(_body.v.y, -700);
+	_body.v.x = cpfclamp(_body.v.x, -400, 400);
+}
+
+
+static void
+update(int ticks)
+{
+	static int lastJumpState = 0;
+	int jumpState = (arrowDirection.y > 0.0f);
+	
+	cpBody *_body = playerInstance.shape._body;
+	
+	cpVect groundNormal = playerInstance.groundNormal;
+	if(groundNormal.y > 0.0f){
+		playerInstance.shape.surface_v = cpvmult(cpvperp(groundNormal), 400.0f*arrowDirection.x);
+		if(arrowDirection.x) cpBodyActivate(_body);
+	} else {
+		playerInstance.shape.surface_v = cpvzero;
+	}
+	
+	// apply jump
+	if(jumpState && !lastJumpState && cpvlengthsq(groundNormal)){
+//		body.v = cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.5f), 500.0f);
+		_body.v = cpvadd(_body.v, cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.75f), 500.0f));
+		cpBodyActivate(_body);
+	}
+	
+	if(playerInstance.groundShapes.num == 0){
+		cpFloat air_accel = _body.v.x + arrowDirection.x*(2000.0f);
+		_body.f.x = _body.m*air_accel;
+//		body.v.x = cpflerpconst(body.v.x, 400.0f*arrowDirection.x, 2000.0f/60.0f);
+	}
+	
+	enum int steps = 3;
+	enum cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
+	
+	for(int i=0; i<steps; i++){
+		cpSpaceStep(space, dt);
+	}
+	
+	lastJumpState = jumpState;
+}
+
+static cpSpace *
+init()
+{
+	cpResetShapeIdCounter();
+	
+	space = cpSpaceNew();
+	space.iterations = 10;
+	space.gravity = cpv(0, -1500);
+
+	cpBody *_body;
+	cpBody *staticBody = &space.staticBody;
+	cpShape *shape;
+	
+	// Create segments around the edge of the screen.
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+	
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+	
+	// add some other segments to play with
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-200), cpv(-220,240), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(320,-200), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(200,-240), cpv(320,-100), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+
+	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-80), cpv(200,-80), 0.0f));
+	shape.e = 1.0f; shape.u = 1.0f;
+	shape.layers = NOT_GRABABLE_MASK;
+	shape.collision_type = 2;
+	
+	// Set up the player
+	cpFloat radius = 15.0f;
+	_body = cpSpaceAddBody(space, cpBodyNew(10.0f, INFINITY));
+	_body.p = cpv(0, -220);
+	_body.velocity_func = &playerUpdateVelocity;
+
+	shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, radius, cpvzero));
+	shape.e = 0.0f; shape.u = 2.0f;
+	shape.collision_type = 1;
+	
+	playerInstance.u = shape.u;
+	playerInstance.shape = shape;
+	playerInstance.groundShapes = cpArrayNew(0);
+	shape.data = &playerInstance;
+	
+	cpSpaceAddCollisionHandler(space, 1, 2, &begin, &preSolve, null, &separate, null);
+	
+	return space;
+}
+
+static void
+destroy()
+{
+	cpSpaceFreeChildren(space);
+	cpSpaceFree(space);
+	
+	cpArrayFree(playerInstance.groundShapes);
+}
+
+chipmunkDemo Player = {
+	"Player",
+	null,
+	&init,
+	&update,
+	&destroy,
+};