1 
2 // written in the D programming language
3 
4 module samples.Player;
5 
6 import dchip.all;
7 
8 import samples.ChipmunkDemo;
9 
10 import gameApp;
11 
12 static cpSpace *space;
13 
14 struct PlayerStruct {
15     cpFloat u;
16     cpShape *shape;
17 }
18 
19 PlayerStruct playerInstance;
20 
21 static void
22 playerUpdateVelocity(cpBody *body_, cpVect gravity, cpFloat damping, cpFloat dt)
23 {
24     cpBodyUpdateVelocity(body_, gravity, damping, dt);
25     body_.v.y = cpfmax(body_.v.y, -700);
26     body_.v.x = cpfclamp(body_.v.x, -400, 400);
27 }
28 
29 static void
30 SelectPlayerGroundNormal(cpBody *body_, cpArbiter *arb, cpVect *groundNormal){
31     cpVect n = cpArbiterGetNormal(arb, 0);
32 
33     if(n.y > groundNormal.y){
34         *groundNormal = n;
35     }
36 }
37 
38 static void
39 update(int ticks)
40 {
41     static int lastJumpState = 0;
42     int jumpState = (arrowDirection.y > 0.0f);
43 
44     cpBody *body_ = playerInstance.shape.body_;
45 
46     cpVect groundNormal = cpvzero;
47     cpBodyEachArbiter(body_, cast(cpBodyArbiterIteratorFunc)&SelectPlayerGroundNormal, &groundNormal);
48 
49     if(groundNormal.y > 0.0f){
50         playerInstance.shape.surface_v = cpv(400.0f*arrowDirection.x, 0.0f);//cpvmult(cpvperp(groundNormal), 400.0f*arrowDirection.x);
51         if(arrowDirection.x) cpBodyActivate(body_);
52     } else {
53         playerInstance.shape.surface_v = cpvzero;
54     }
55 
56     // apply jump
57     if(jumpState && !lastJumpState && cpvlengthsq(groundNormal)){
58         //		body.v = cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.5f), 500.0f);
59         body_.v = cpvadd(body_.v, cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.75f), 500.0f));
60         cpBodyActivate(body_);
61     }
62 
63     if(cpvlengthsq(groundNormal)){
64         cpFloat air_accel = body_.v.x + arrowDirection.x*(2000.0f);
65         body_.f.x = body_.m*air_accel;
66         //		body.v.x = cpflerpconst(body.v.x, 400.0f*arrowDirection.x, 2000.0f/60.0f);
67     }
68 
69     int steps = 3;
70     cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
71 
72     for(int i=0; i<steps; i++){
73         cpSpaceStep(space, dt);
74     }
75 
76     lastJumpState = jumpState;
77 }
78 
79 
80 static cpSpace *
81 init()
82 {
83     cpResetShapeIdCounter();
84 
85     space = cpSpaceNew();
86     space.iterations = 10;
87     space.gravity = cpv(0, -1500);
88     space.sleepTimeThreshold = 9999999;
89 
90     cpBody *body_;
91     cpBody *staticBody = space.staticBody;
92     cpShape *shape;
93 
94     // Create segments around the edge of the screen.
95     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
96     shape.e = 1.0f; shape.u = 1.0f;
97     shape.layers = NOT_GRABABLE_MASK;
98     shape.collision_type = 2;
99 
100     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
101     shape.e = 1.0f; shape.u = 1.0f;
102     shape.layers = NOT_GRABABLE_MASK;
103     shape.collision_type = 2;
104 
105     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
106     shape.e = 1.0f; shape.u = 1.0f;
107     shape.layers = NOT_GRABABLE_MASK;
108     shape.collision_type = 2;
109 
110     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
111     shape.e = 1.0f; shape.u = 1.0f;
112     shape.layers = NOT_GRABABLE_MASK;
113     shape.collision_type = 2;
114 
115     // add some other segments to play with
116     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-200), cpv(-220,240), 0.0f));
117     shape.e = 1.0f; shape.u = 1.0f;
118     shape.layers = NOT_GRABABLE_MASK;
119     shape.collision_type = 2;
120 
121     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(320,-200), 0.0f));
122     shape.e = 1.0f; shape.u = 1.0f;
123     shape.layers = NOT_GRABABLE_MASK;
124     shape.collision_type = 2;
125 
126     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(200,-240), cpv(320,-100), 0.0f));
127     shape.e = 1.0f; shape.u = 1.0f;
128     shape.layers = NOT_GRABABLE_MASK;
129     shape.collision_type = 2;
130 
131     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-80), cpv(200,-80), 0.0f));
132     shape.e = 1.0f; shape.u = 1.0f;
133     shape.layers = NOT_GRABABLE_MASK;
134     shape.collision_type = 2;
135 
136     // Set up the player
137     cpFloat radius = 15.0f;
138     body_ = cpSpaceAddBody(space, cpBodyNew(10.0f, INFINITY));
139     body_.p = cpv(0, -220);
140     body_.velocity_func = &playerUpdateVelocity;
141 
142     shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
143     shape.e = 0.0f; shape.u = 2.0f;
144     shape.collision_type = 1;
145 
146     playerInstance.u = shape.u;
147     playerInstance.shape = shape;
148     shape.data = &playerInstance;
149 
150     return space;
151 }
152 
153 static void
154 destroy()
155 {
156     ChipmunkDemoFreeSpaceChildren(space);
157     cpSpaceFree(space);
158 }
159 
160 chipmunkDemo Player = {
161     "Player",
162     null,
163     &init,
164     &update,
165     &destroy,
166 };