Mercurial > projects > chipmunkd
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, +};