# HG changeset patch # User Extrawurst # Date 1291424549 -3600 # Node ID af2f61a96318a2d8028798640372ffadbafa5ab1 # Parent df4ebc8add6612fa58c4df3c16dee98ce9432369 ported chipmunk demos diff -r df4ebc8add66 -r af2f61a96318 trunk/tests/ChipmunkDemos/drawSpace.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/tests/ChipmunkDemos/drawSpace.d Sat Dec 04 02:02:29 2010 +0100 @@ -0,0 +1,510 @@ +/* Copyright (c) 2007 Scott Lembcke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +module drawSpace; + +import derelict.opengl.gl; + +import chipmunkd.chipmunk; + +import std.math:PI; +import std.stdio; + +struct drawSpaceOptions { + int drawHash; + int drawBBs; + int drawShapes; + float collisionPointSize; + float bodyPointSize; + float lineThickness; +} + +/* + IMPORTANT - READ ME! + + This file sets up a simple interface that the individual demos can use to get + a Chipmunk space running and draw what's in it. In order to keep the Chipmunk + examples clean and simple, they contain no graphics code. All drawing is done + by accessing the Chipmunk structures at a very low level. It is NOT + recommended to write a game or application this way as it does not scale + beyond simple shape drawing and is very dependent on implementation details + about Chipmunk which may change with little to no warning. +*/ + +enum float[3] LINE_COLOR = [0,0,0]; +enum float[3] COLLISION_COLOR = [1,0,0]; +enum float[3] BODY_COLOR = [0,0,1]; + +static void +glColor_from_pointer(void *ptr) +{ + ulong val = cast(long)ptr; + + // hash the pointer up nicely + val = (val+0x7ed55d16) + (val<<12); + val = (val^0xc761c23c) ^ (val>>19); + val = (val+0x165667b1) + (val<<5); + val = (val+0xd3a2646c) ^ (val<<9); + val = (val+0xfd7046c5) + (val<<3); + val = (val^0xb55a4f09) ^ (val>>16); + +// GLfloat v = (GLfloat)val/(GLfloat)ULONG_MAX; +// v = 0.95f - v*0.15f; +// +// glColor3f(v, v, v); + + GLubyte r = (val>>0) & 0xFF; + GLubyte g = (val>>8) & 0xFF; + GLubyte b = (val>>16) & 0xFF; + + GLubyte max = r>g ? (r>b ? r : b) : (g>b ? g : b); + + const int mult = 127; + const int add = 63; + r = cast(ubyte)((r*mult)/max + add); + g = cast(ubyte)((g*mult)/max + add); + b = cast(ubyte)((b*mult)/max + add); + + glColor3ub(r, g, b); +} + +static void +glColor_for_shape(cpShape *shape, cpSpace *space) +{ + cpBody *_body = shape._body; + if(_body){ + if(_body.node.next){ + GLfloat v = 0.25f; + glColor3f(v,v,v); + return; + } else if(_body.node.idleTime > space.sleepTimeThreshold) { + GLfloat v = 0.9f; + glColor3f(v,v,v); + return; + } + } + + glColor_from_pointer(shape); +} + +enum GLfloat[] circleVAR = [ + 0.0000f, 1.0000f, + 0.2588f, 0.9659f, + 0.5000f, 0.8660f, + 0.7071f, 0.7071f, + 0.8660f, 0.5000f, + 0.9659f, 0.2588f, + 1.0000f, 0.0000f, + 0.9659f, -0.2588f, + 0.8660f, -0.5000f, + 0.7071f, -0.7071f, + 0.5000f, -0.8660f, + 0.2588f, -0.9659f, + 0.0000f, -1.0000f, + -0.2588f, -0.9659f, + -0.5000f, -0.8660f, + -0.7071f, -0.7071f, + -0.8660f, -0.5000f, + -0.9659f, -0.2588f, + -1.0000f, -0.0000f, + -0.9659f, 0.2588f, + -0.8660f, 0.5000f, + -0.7071f, 0.7071f, + -0.5000f, 0.8660f, + -0.2588f, 0.9659f, + 0.0000f, 1.0000f, + 0.0f, 0.0f, // For an extra line to see the rotation. +]; +enum int circleVAR_count = circleVAR.length / 2; + +static void +drawCircleShape(cpBody *_body, cpCircleShape *circle, cpSpace *space) +{ + glVertexPointer(2, GL_FLOAT, 0, circleVAR.ptr); + + glPushMatrix(); { + cpVect center = circle.tc; + glTranslatef(center.x, center.y, 0.0f); + glRotatef(_body.a*180.0f/PI, 0.0f, 0.0f, 1.0f); + glScalef(circle.r, circle.r, 1.0f); + + if(!circle.shape.sensor){ + glColor_for_shape(cast(cpShape *)circle, space); + glDrawArrays(GL_TRIANGLE_FAN, 0, circleVAR_count - 1); + } + + glColor3fv(LINE_COLOR.ptr); + glDrawArrays(GL_LINE_STRIP, 0, circleVAR_count); + } glPopMatrix(); +} + +enum GLfloat[] pillVAR = [ + 0.0000f, 1.0000f, 1.0f, + 0.2588f, 0.9659f, 1.0f, + 0.5000f, 0.8660f, 1.0f, + 0.7071f, 0.7071f, 1.0f, + 0.8660f, 0.5000f, 1.0f, + 0.9659f, 0.2588f, 1.0f, + 1.0000f, 0.0000f, 1.0f, + 0.9659f, -0.2588f, 1.0f, + 0.8660f, -0.5000f, 1.0f, + 0.7071f, -0.7071f, 1.0f, + 0.5000f, -0.8660f, 1.0f, + 0.2588f, -0.9659f, 1.0f, + 0.0000f, -1.0000f, 1.0f, + + 0.0000f, -1.0000f, 0.0f, + -0.2588f, -0.9659f, 0.0f, + -0.5000f, -0.8660f, 0.0f, + -0.7071f, -0.7071f, 0.0f, + -0.8660f, -0.5000f, 0.0f, + -0.9659f, -0.2588f, 0.0f, + -1.0000f, -0.0000f, 0.0f, + -0.9659f, 0.2588f, 0.0f, + -0.8660f, 0.5000f, 0.0f, + -0.7071f, 0.7071f, 0.0f, + -0.5000f, 0.8660f, 0.0f, + -0.2588f, 0.9659f, 0.0f, + 0.0000f, 1.0000f, 0.0f, +]; +enum int pillVAR_count = pillVAR.length/3; + +static void +drawSegmentShape(cpBody *_body, cpSegmentShape *seg, cpSpace *space) +{ + cpVect a = seg.ta; + cpVect b = seg.tb; + + if(seg.r){ + glVertexPointer(3, GL_FLOAT, 0, pillVAR.ptr); + glPushMatrix(); { + cpVect d = cpvsub(b, a); + cpVect r = cpvmult(d, seg.r/cpvlength(d)); + + GLfloat matrix[] = [ + r.x, r.y, 0.0f, 0.0f, + -r.y, r.x, 0.0f, 0.0f, + d.x, d.y, 0.0f, 0.0f, + a.x, a.y, 0.0f, 1.0f, + ]; + glMultMatrixf(matrix.ptr); + + if(!seg.shape.sensor){ + glColor_for_shape(cast(cpShape *)seg, space); + glDrawArrays(GL_TRIANGLE_FAN, 0, pillVAR_count); + } + + glColor3fv(LINE_COLOR.ptr); + glDrawArrays(GL_LINE_LOOP, 0, pillVAR_count); + } glPopMatrix(); + } else { + glColor3fv(LINE_COLOR.ptr); + glBegin(GL_LINES); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + } +} + +static void +drawPolyShape(cpBody *_body, cpPolyShape *poly, cpSpace *space) +{ + int count = poly.numVerts; +version(CP_USE_DOUBLES) +{ + glVertexPointer(2, GL_DOUBLE, 0, poly.tVerts); +} +else +{ + glVertexPointer(2, GL_FLOAT, 0, poly.tVerts); +} + + if(!poly.shape.sensor){ + glColor_for_shape(cast(cpShape *)poly, space); + glDrawArrays(GL_TRIANGLE_FAN, 0, count); + } + + glColor3fv(LINE_COLOR.ptr); + glDrawArrays(GL_LINE_LOOP, 0, count); +} + +static void +drawObject(cpShape *shape, cpSpace *space) +{ + cpBody *_body = shape._body; + + switch(shape.klass.type){ + case cpShapeType.CP_CIRCLE_SHAPE: + drawCircleShape(_body, cast(cpCircleShape *)shape, space); + break; + case cpShapeType.CP_SEGMENT_SHAPE: + drawSegmentShape(_body, cast(cpSegmentShape *)shape, space); + break; + case cpShapeType.CP_POLY_SHAPE: + drawPolyShape(_body, cast(cpPolyShape *)shape, space); + break; + default: + writefln("Bad enumeration in drawObject()."); + } +} + +enum GLfloat[] springVAR = [ + 0.00f, 0.0f, + 0.20f, 0.0f, + 0.25f, 3.0f, + 0.30f,-6.0f, + 0.35f, 6.0f, + 0.40f,-6.0f, + 0.45f, 6.0f, + 0.50f,-6.0f, + 0.55f, 6.0f, + 0.60f,-6.0f, + 0.65f, 6.0f, + 0.70f,-3.0f, + 0.75f, 6.0f, + 0.80f, 0.0f, + 1.00f, 0.0f, +]; +enum int springVAR_count = springVAR.length / 2; + +static void +drawSpring(cpDampedSpring *spring, cpBody *body_a, cpBody *body_b) +{ + cpVect a = cpvadd(body_a.p, cpvrotate(spring.anchr1, body_a.rot)); + cpVect b = cpvadd(body_b.p, cpvrotate(spring.anchr2, body_b.rot)); + + glPointSize(5.0f); + glBegin(GL_POINTS); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + + cpVect delta = cpvsub(b, a); + + glVertexPointer(2, GL_FLOAT, 0, springVAR.ptr); + glPushMatrix(); { + GLfloat x = a.x; + GLfloat y = a.y; + GLfloat cos = delta.x; + GLfloat sin = delta.y; + GLfloat s = 1.0f/cpvlength(delta); + + GLfloat matrix[] = [ + cos, sin, 0.0f, 0.0f, + -sin*s, cos*s, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + x, y, 0.0f, 1.0f, + ]; + + glMultMatrixf(matrix.ptr); + glDrawArrays(GL_LINE_STRIP, 0, springVAR_count); + } glPopMatrix(); +} + +static void +drawConstraint(cpConstraint *constraint) +{ + cpBody *body_a = constraint.a; + cpBody *body_b = constraint.b; + + const cpConstraintClass *klass = constraint.klass; + if(klass == cpPinJointGetClass()){ + cpPinJoint *joint = cast(cpPinJoint *)constraint; + + cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); + cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); + + glPointSize(5.0f); + glBegin(GL_POINTS); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + + glBegin(GL_LINES); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + } else if(klass == cpSlideJointGetClass()){ + cpSlideJoint *joint = cast(cpSlideJoint *)constraint; + + cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); + cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); + + glPointSize(5.0f); + glBegin(GL_POINTS); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + + glBegin(GL_LINES); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + } else if(klass == cpPivotJointGetClass()){ + cpPivotJoint *joint = cast(cpPivotJoint *)constraint; + + cpVect a = cpvadd(body_a.p, cpvrotate(joint.anchr1, body_a.rot)); + cpVect b = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); + + glPointSize(10.0f); + glBegin(GL_POINTS); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + } else if(klass == cpGrooveJointGetClass()){ + cpGrooveJoint *joint = cast(cpGrooveJoint *)constraint; + + cpVect a = cpvadd(body_a.p, cpvrotate(joint.grv_a, body_a.rot)); + cpVect b = cpvadd(body_a.p, cpvrotate(joint.grv_b, body_a.rot)); + cpVect c = cpvadd(body_b.p, cpvrotate(joint.anchr2, body_b.rot)); + + glPointSize(5.0f); + glBegin(GL_POINTS); { + glVertex2f(c.x, c.y); + } glEnd(); + + glBegin(GL_LINES); { + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + } glEnd(); + } else if(klass == cpDampedSpringGetClass()){ + drawSpring(cast(cpDampedSpring *)constraint, body_a, body_b); + } else { +// printf("Cannot draw constraint\n"); + } +} + +static void +drawBB(cpShape *shape, void *unused) +{ + glBegin(GL_LINE_LOOP); { + glVertex2f(shape.bb.l, shape.bb.b); + glVertex2f(shape.bb.l, shape.bb.t); + glVertex2f(shape.bb.r, shape.bb.t); + glVertex2f(shape.bb.r, shape.bb.b); + } glEnd(); +} + +// copied from cpSpaceHash.c +static cpHashValue +hash_func(cpHashValue x, cpHashValue y, cpHashValue n) +{ + return cast(cpHashValue)((x*1640531513uL ^ y*2654435789uL) % n); +} + +static void +drawSpatialHash(cpSpaceHash *hash) +{ + cpBB bb = cpBBNew(-320, -240, 320, 240); + + cpFloat dim = hash.celldim; + int n = hash.numcells; + + int l = cast(int)floorf(bb.l/dim); + int r = cast(int)floorf(bb.r/dim); + int b = cast(int)floorf(bb.b/dim); + int t = cast(int)floorf(bb.t/dim); + + for(int i=l; i<=r; i++){ + for(int j=b; j<=t; j++){ + int cell_count = 0; + + int index = hash_func(i,j,n); + for(cpSpaceHashBin *bin = hash.table[index]; bin; bin = bin.next) + cell_count++; + + GLfloat v = 1.0f - cast(GLfloat)cell_count/10.0f; + glColor3f(v,v,v); + glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim); + } + } +} + +void +DrawSpace(cpSpace *space, const drawSpaceOptions *options) +{ + if(options.drawHash){ + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); + drawSpatialHash(space.activeShapes); + glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE); + drawSpatialHash(space.staticShapes); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + glLineWidth(options.lineThickness); + if(options.drawShapes){ + cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&drawObject, space); + cpSpaceHashEach(space.staticShapes, cast(cpSpaceHashIterator)&drawObject, space); + } + + glLineWidth(1.0f); + if(options.drawBBs){ + glColor3f(0.3f, 0.5f, 0.3f); + cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&drawBB, null); + cpSpaceHashEach(space.staticShapes, cast(cpSpaceHashIterator)&drawBB, null); + } + + cpArray *constraints = space.constraints; + + glColor3f(0.5f, 1.0f, 0.5f); + for(int i=0, count = constraints.num; i>3) + y*image_row_length]>>(~x&0x7)) & 1; +} + +static cpSpace *space; + +static void +update(int ticks) +{ + enum int steps = 1; + enum cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps; + + for(int i=0; i 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 340){ + cpFloat x = frand()*640 - 320; + _body.p = cpv(x, 260); + } +} + +static void +update(int ticks) +{ + int steps = 1; + cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps; + + for(int i=0; i 320.0f){ + ball.v = cpvzero; + ball.p = cpv(-224.0f, 200.0f); + } + } + } +} + +static cpBody * +add_ball(cpVect pos) +{ + cpBody *_body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 30, 0, cpvzero))); + _body.p = pos; + + cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, 30, cpvzero)); + shape.e = 0.0f; shape.u = 0.5f; + + return _body; +} + +static cpSpace * +init() +{ + space = cpSpaceNew(); + space.gravity = cpv(0, -600); + + cpBody *staticBody = &space.staticBody; + cpShape *shape; + + // beveling all of the line segments slightly helps prevent things from getting stuck on cracks + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-256,300), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-192,0), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,0), cpv(-192, -64), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,-64), cpv(-128,144), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,80), cpv(-192,176), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,176), cpv(-128,240), 2.0f)); + shape.e = 0.0f; shape.u = 0.0f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,144), cpv(192,64), 2.0f)); + shape.e = 0.0f; shape.u = 0.5f; shape.layers = 1; + shape.layers = NOT_GRABABLE_MASK; + + cpVect verts[] = [ + cpv(-30,-80), + cpv(-30, 80), + cpv( 30, 64), + cpv( 30,-80), + ]; + + cpBody *plunger = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY)); + plunger.p = cpv(-160,-80); + + shape = cpSpaceAddShape(space, cpPolyShapeNew(plunger, 4, verts.ptr, cpvzero)); + shape.e = 1.0f; shape.u = 0.5f; shape.layers = 1; + + // add balls to hopper + for(int i=0; i 0.0 ? 1.0 : -1.0); + tankControlBody.v = cpvrotate(tankBody.rot, cpv(30.0f*direction, 0.0f)); + } + + cpSpaceStep(space, dt); + } +} + +static cpBody * +add_box(cpFloat size, cpFloat mass) +{ + cpVect verts[] = [ + cpv(-size,-size), + cpv(-size, size), + cpv( size, size), + cpv( size,-size), + ]; + + cpFloat radius = cpvlength(cpv(size, size)); + + cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts.ptr, cpvzero))); + _body.p = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius)); + + cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(_body, 4, verts.ptr, cpvzero)); + shape.e = 0.0f; shape.u = 0.7f; + + return _body; +} + +static cpSpace * +init() +{ + cpResetShapeIdCounter(); + + space = cpSpaceNew(); + cpSpaceResizeActiveHash(space, 30.0f, 1000); + space.iterations = 10; + space.sleepTimeThreshold = 0.5f; + + 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 = 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 = 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 = 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; + + for(int i=0; i<50; i++){ + cpBody *_body = add_box(10.0, 1.0); + + cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, _body, cpvzero, cpvzero)); + pivot.biasCoef = 0.0f; // disable joint correction + pivot.maxForce = 1000.0f; // emulate linear friction + + cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(staticBody, _body, 0.0f, 1.0f)); + gear.biasCoef = 0.0f; // disable joint correction + gear.maxForce = 5000.0f; // emulate angular friction + } + + // We joint the tank to the control _body and control the tank indirectly by modifying the control _body. + tankControlBody = cpBodyNew(INFINITY, INFINITY); + tankBody = add_box(15.0, 10.0); + + cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero)); + pivot.biasCoef = 0.0f; // disable joint correction + pivot.maxForce = 10000.0f; // emulate linear friction + + cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(tankControlBody, tankBody, 0.0f, 1.0f)); + gear.biasCoef = 1.0f; // limit angular correction rate + gear.maxBias = 1.0f; // limit angular correction rate + gear.maxForce = 500000.0f; // emulate angular friction + + return space; +} + +static void +destroy() +{ + cpBodyFree(tankControlBody); + cpSpaceFreeChildren(space); + cpSpaceFree(space); +} + +chipmunkDemo Tank = { + "Tank", + null, + &init, + &update, + &destroy, +}; diff -r df4ebc8add66 -r af2f61a96318 trunk/tests/ChipmunkDemos/samples/TheoJansen.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/tests/ChipmunkDemos/samples/TheoJansen.d Sat Dec 04 02:02:29 2010 +0100 @@ -0,0 +1,161 @@ + +// written in the D programming language + +module samples.TheoJansen; + +import chipmunkd.chipmunk; + +import samples.ChipmunkDemo; + +import gameApp; + +import std.math; + +enum M_PI = PI; +enum M_PI_2 = PI*0.5f; + +static cpSpace *space; + +static cpConstraint *motor; + +static void +update(int ticks) +{ + cpFloat coef = (2.0f + arrowDirection.y)/3.0f; + cpFloat rate = arrowDirection.x*10.0f*coef; + cpSimpleMotorSetRate(motor, rate); + motor.maxForce = (rate) ? 100000.0f : 0.0f; + + enum int steps = 3; + enum cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps; + + for(int i=0; i