16
|
1
|
|
2 // written in the D programming language
|
|
3
|
|
4 module samples.Player;
|
|
5
|
|
6 import chipmunkd.chipmunk;
|
|
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 cpVect groundNormal;
|
|
18 cpArray *groundShapes;
|
|
19 }
|
|
20
|
|
21 PlayerStruct playerInstance;
|
|
22
|
|
23 static cpBool
|
|
24 begin(cpArbiter *arb, cpSpace *space, void *ignore)
|
|
25 {
|
|
26 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
27 PlayerStruct *player = cast(PlayerStruct *)a.data;
|
|
28
|
|
29 cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
|
|
30 if(n.y > 0.0f){
|
|
31 cpArrayPush(player.groundShapes, b);
|
|
32 }
|
|
33
|
|
34 return cpTrue;
|
|
35 }
|
|
36
|
|
37 static cpBool
|
|
38 preSolve(cpArbiter *arb, cpSpace *space, void *ignore)
|
|
39 {
|
|
40 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
41 PlayerStruct *player = cast(PlayerStruct *)a.data;
|
|
42
|
|
43 if(cpArbiterIsFirstContact(arb)){
|
|
44 a.u = player.u;
|
|
45
|
|
46 // pick the most upright jump normal each frame
|
|
47 cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
|
|
48 if(n.y >= player.groundNormal.y){
|
|
49 player.groundNormal = n;
|
|
50 }
|
|
51 }
|
|
52
|
|
53 return cpTrue;
|
|
54 }
|
|
55
|
|
56 static void
|
|
57 separate(cpArbiter *arb, cpSpace *space, void *ignore)
|
|
58 {
|
|
59 mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
|
|
60 PlayerStruct *player = cast(PlayerStruct *)a.data;
|
|
61
|
|
62 cpArrayDeleteObj(player.groundShapes, b);
|
|
63
|
|
64 if(player.groundShapes.num == 0){
|
|
65 a.u = 0.0f;
|
|
66 player.groundNormal = cpvzero;
|
|
67 }
|
|
68 }
|
|
69
|
|
70 static void
|
|
71 playerUpdateVelocity(cpBody *_body, cpVect gravity, cpFloat damping, cpFloat dt)
|
|
72 {
|
|
73 cpBodyUpdateVelocity(_body, gravity, damping, dt);
|
|
74 _body.v.y = cpfmax(_body.v.y, -700);
|
|
75 _body.v.x = cpfclamp(_body.v.x, -400, 400);
|
|
76 }
|
|
77
|
|
78
|
|
79 static void
|
|
80 update(int ticks)
|
|
81 {
|
|
82 static int lastJumpState = 0;
|
|
83 int jumpState = (arrowDirection.y > 0.0f);
|
|
84
|
|
85 cpBody *_body = playerInstance.shape._body;
|
|
86
|
|
87 cpVect groundNormal = playerInstance.groundNormal;
|
|
88 if(groundNormal.y > 0.0f){
|
|
89 playerInstance.shape.surface_v = cpvmult(cpvperp(groundNormal), 400.0f*arrowDirection.x);
|
|
90 if(arrowDirection.x) cpBodyActivate(_body);
|
|
91 } else {
|
|
92 playerInstance.shape.surface_v = cpvzero;
|
|
93 }
|
|
94
|
|
95 // apply jump
|
|
96 if(jumpState && !lastJumpState && cpvlengthsq(groundNormal)){
|
|
97 // body.v = cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.5f), 500.0f);
|
|
98 _body.v = cpvadd(_body.v, cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.75f), 500.0f));
|
|
99 cpBodyActivate(_body);
|
|
100 }
|
|
101
|
|
102 if(playerInstance.groundShapes.num == 0){
|
|
103 cpFloat air_accel = _body.v.x + arrowDirection.x*(2000.0f);
|
|
104 _body.f.x = _body.m*air_accel;
|
|
105 // body.v.x = cpflerpconst(body.v.x, 400.0f*arrowDirection.x, 2000.0f/60.0f);
|
|
106 }
|
|
107
|
|
108 enum int steps = 3;
|
|
109 enum cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
|
|
110
|
|
111 for(int i=0; i<steps; i++){
|
|
112 cpSpaceStep(space, dt);
|
|
113 }
|
|
114
|
|
115 lastJumpState = jumpState;
|
|
116 }
|
|
117
|
|
118 static cpSpace *
|
|
119 init()
|
|
120 {
|
|
121 cpResetShapeIdCounter();
|
|
122
|
|
123 space = cpSpaceNew();
|
|
124 space.iterations = 10;
|
|
125 space.gravity = cpv(0, -1500);
|
|
126
|
|
127 cpBody *_body;
|
|
128 cpBody *staticBody = &space.staticBody;
|
|
129 cpShape *shape;
|
|
130
|
|
131 // Create segments around the edge of the screen.
|
|
132 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
|
|
133 shape.e = 1.0f; shape.u = 1.0f;
|
|
134 shape.layers = NOT_GRABABLE_MASK;
|
|
135 shape.collision_type = 2;
|
|
136
|
|
137 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
|
|
138 shape.e = 1.0f; shape.u = 1.0f;
|
|
139 shape.layers = NOT_GRABABLE_MASK;
|
|
140 shape.collision_type = 2;
|
|
141
|
|
142 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
|
|
143 shape.e = 1.0f; shape.u = 1.0f;
|
|
144 shape.layers = NOT_GRABABLE_MASK;
|
|
145 shape.collision_type = 2;
|
|
146
|
|
147 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
|
|
148 shape.e = 1.0f; shape.u = 1.0f;
|
|
149 shape.layers = NOT_GRABABLE_MASK;
|
|
150 shape.collision_type = 2;
|
|
151
|
|
152 // add some other segments to play with
|
|
153 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-200), cpv(-220,240), 0.0f));
|
|
154 shape.e = 1.0f; shape.u = 1.0f;
|
|
155 shape.layers = NOT_GRABABLE_MASK;
|
|
156 shape.collision_type = 2;
|
|
157
|
|
158 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(320,-200), 0.0f));
|
|
159 shape.e = 1.0f; shape.u = 1.0f;
|
|
160 shape.layers = NOT_GRABABLE_MASK;
|
|
161 shape.collision_type = 2;
|
|
162
|
|
163 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(200,-240), cpv(320,-100), 0.0f));
|
|
164 shape.e = 1.0f; shape.u = 1.0f;
|
|
165 shape.layers = NOT_GRABABLE_MASK;
|
|
166 shape.collision_type = 2;
|
|
167
|
|
168 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-80), cpv(200,-80), 0.0f));
|
|
169 shape.e = 1.0f; shape.u = 1.0f;
|
|
170 shape.layers = NOT_GRABABLE_MASK;
|
|
171 shape.collision_type = 2;
|
|
172
|
|
173 // Set up the player
|
|
174 cpFloat radius = 15.0f;
|
|
175 _body = cpSpaceAddBody(space, cpBodyNew(10.0f, INFINITY));
|
|
176 _body.p = cpv(0, -220);
|
|
177 _body.velocity_func = &playerUpdateVelocity;
|
|
178
|
|
179 shape = cpSpaceAddShape(space, cpCircleShapeNew(_body, radius, cpvzero));
|
|
180 shape.e = 0.0f; shape.u = 2.0f;
|
|
181 shape.collision_type = 1;
|
|
182
|
|
183 playerInstance.u = shape.u;
|
|
184 playerInstance.shape = shape;
|
|
185 playerInstance.groundShapes = cpArrayNew(0);
|
|
186 shape.data = &playerInstance;
|
|
187
|
|
188 cpSpaceAddCollisionHandler(space, 1, 2, &begin, &preSolve, null, &separate, null);
|
|
189
|
|
190 return space;
|
|
191 }
|
|
192
|
|
193 static void
|
|
194 destroy()
|
|
195 {
|
|
196 cpSpaceFreeChildren(space);
|
|
197 cpSpaceFree(space);
|
|
198
|
|
199 cpArrayFree(playerInstance.groundShapes);
|
|
200 }
|
|
201
|
|
202 chipmunkDemo Player = {
|
|
203 "Player",
|
|
204 null,
|
|
205 &init,
|
|
206 &update,
|
|
207 &destroy,
|
|
208 };
|