6 #include "jelly/JellyPhysics.h"
7 #include "videolib/videolib.h"
10 ////////////////////////////////////////////////////////////////////////////////
11 static float scale_x
= 30.0f
;
12 static float scale_y
= 22.0f
;
13 static float center_x
= -12.0f
;
14 static float center_y
= -20.0f
;
17 static inline int x2s (float x
) { return (x
-center_x
)*scale_x
; }
18 static inline int y2s (float y
) { return SCR_WIDTH
-(y
-center_y
)*scale_y
; }
20 static inline float s2x (int x
) { return ((float)x
/scale_x
)+center_x
; }
21 static inline float s2y (int y
) { return ((float)(SCR_WIDTH
-y
)/scale_y
)+center_y
; }
24 static void dll (float x0
, float y0
, float x1
, float y1
, Uint32 clr
) {
29 draw_line(x0
, y0
, x1
, y1
, clr
);
33 ////////////////////////////////////////////////////////////////////////////////
34 using namespace JellyPhysics
;
37 ////////////////////////////////////////////////////////////////////////////////
38 // simple inherited classes, to add gravity force
39 class FallingBody
: public SpringBody
{
42 World
*w
, ClosedShape
&s
, float massPerPoint
,
43 float edgeSpringK
, float edgeSpringDamp
,
44 const Vector2
&pos
, float angle
, const Vector2
&scale
45 ) : SpringBody(w
, s
, massPerPoint
, edgeSpringK
, edgeSpringDamp
, pos
, angle
, scale
, false) {}
48 World
*w
, const ClosedShape
&shape
, float massPerPoint
,
49 float shapeSpringK
, float shapeSpringDamp
,
50 float edgeSpringK
, float edgeSpringDamp
,
51 const Vector2
&pos
, float angleinRadians
,
52 const Vector2
&scale
, bool kinematic
=false
53 ) : SpringBody(w
, shape
, massPerPoint
, shapeSpringK
, shapeSpringDamp
, edgeSpringK
, edgeSpringDamp
, pos
, angleinRadians
, scale
, kinematic
) {}
55 virtual void accumulateExternalForces () {
57 for (unsigned int i
= 0; i
< mPointMasses
.size(); ++i
) mPointMasses
[i
].Force
+= Vector2(0.0f
, -9.8f
*mPointMasses
[i
].mass());
62 class FallingPressureBody
: public PressureBody
{
65 World
*w
, const ClosedShape
&s
, float mpp
,
66 float gasPressure
, float shapeK
, float shapeD
,
67 float edgeK
, float edgeD
,
68 const Vector2
&pos
, float angleInRadians
, const Vector2
&scale
,
69 bool kinematic
) : PressureBody(w
, s
, mpp
, gasPressure
, shapeK
, shapeD
, edgeK
, edgeD
, pos
, angleInRadians
, scale
, kinematic
) {}
71 virtual void accumulateExternalForces () {
73 for (unsigned int i
= 0; i
< mPointMasses
.size(); ++i
) mPointMasses
[i
].Force
+= Vector2(0.0f
, -9.8f
*mPointMasses
[i
].mass());
78 ////////////////////////////////////////////////////////////////////////////////
82 static void createI (float x
, float y
) {
83 // this is a complex body, in the shape of a capital "I", and connected with many internal springs.
86 shape
.addVertex(Vector2(-1.5f
, 2.0f
));
87 shape
.addVertex(Vector2(-0.5f
, 2.0f
));
88 shape
.addVertex(Vector2( 0.5f
, 2.0f
));
89 shape
.addVertex(Vector2( 1.5f
, 2.0f
));
90 shape
.addVertex(Vector2( 1.5f
, 1.0f
));
91 shape
.addVertex(Vector2( 0.5f
, 1.0f
));
92 shape
.addVertex(Vector2( 0.5f
, -1.0f
));
93 shape
.addVertex(Vector2( 1.5f
, -1.0f
));
94 shape
.addVertex(Vector2( 1.5f
, -2.0f
));
95 shape
.addVertex(Vector2( 0.5f
, -2.0f
));
96 shape
.addVertex(Vector2(-0.5f
, -2.0f
));
97 shape
.addVertex(Vector2(-1.5f
, -2.0f
));
98 shape
.addVertex(Vector2(-1.5f
, -1.0f
));
99 shape
.addVertex(Vector2(-0.5f
, -1.0f
));
100 shape
.addVertex(Vector2(-0.5f
, 1.0f
));
101 shape
.addVertex(Vector2(-1.5f
, 1.0f
));
104 FallingBody
*body
= new FallingBody(mWorld
, shape
, 1.0f
, 150.0f
, 5.0f
, 300.0f
, 15.0f
, Vector2(x
, y
), 0.0f
, Vector2::One
);
105 body
->addInternalSpring(0, 14, 300.0f
, 10.0f
);
106 body
->addInternalSpring(1, 14, 300.0f
, 10.0f
);
107 body
->addInternalSpring(1, 15, 300.0f
, 10.0f
);
108 body
->addInternalSpring(1, 5, 300.0f
, 10.0f
);
109 body
->addInternalSpring(2, 14, 300.0f
, 10.0f
);
110 body
->addInternalSpring(2, 5, 300.0f
, 10.0f
);
111 body
->addInternalSpring(1, 5, 300.0f
, 10.0f
);
112 body
->addInternalSpring(14, 5, 300.0f
, 10.0f
);
113 body
->addInternalSpring(2, 4, 300.0f
, 10.0f
);
114 body
->addInternalSpring(3, 5, 300.0f
, 10.0f
);
115 body
->addInternalSpring(14, 6, 300.0f
, 10.0f
);
116 body
->addInternalSpring(5, 13, 300.0f
, 10.0f
);
117 body
->addInternalSpring(13, 6, 300.0f
, 10.0f
);
118 body
->addInternalSpring(12, 10, 300.0f
, 10.0f
);
119 body
->addInternalSpring(13, 11, 300.0f
, 10.0f
);
120 body
->addInternalSpring(13, 10, 300.0f
, 10.0f
);
121 body
->addInternalSpring(13, 9, 300.0f
, 10.0f
);
122 body
->addInternalSpring(6, 10, 300.0f
, 10.0f
);
123 body
->addInternalSpring(6, 9, 300.0f
, 10.0f
);
124 body
->addInternalSpring(6, 8, 300.0f
, 10.0f
);
125 body
->addInternalSpring(7, 9, 300.0f
, 10.0f
);
129 static void createBall (float x
, float y
) {
130 // pressure body: similar to a SpringBody, but with internal pressurized gas to help maintain shape
133 for (int i
= 0; i
< 360; i
+= 20) {
134 ball
.addVertex(Vector2(cosf(VectorTools::degToRad((float)-i
)), sinf(VectorTools::degToRad((float)-i
))));
137 new FallingPressureBody(mWorld
, ball
, 1.0f
, 40.0f
, 10.0f
, 1.0f
, 300.0f
, 20.0f
, Vector2(x
, y
), 0, Vector2::One
, false);
141 static void initialize (void) {
142 // create physics world
143 mWorld
= new World();
144 // static ground object
145 // all Closed Shape objects are assumed to be a list of lines going from point to point, with the last point
146 // connecting back to the first point to close the shape. this is a simple rectangle to represent the ground for this demo.
147 // ClosedShape objects are automatically "centered" when you call finish(), and that center becomes the center when
148 // setting the position of the object.
149 ClosedShape groundShape
;
151 groundShape
.addVertex(Vector2(-10.0f
, -2.0f
));
152 groundShape
.addVertex(Vector2(-10.0f
, 2.0f
));
153 groundShape
.addVertex(Vector2( 10.0f
, 2.0f
));
154 groundShape
.addVertex(Vector2( 10.0f
, -2.0f
));
155 groundShape
.finish();
157 // creating the body. since this is a static body, we can use the base class Body.
158 // setting the mass per point to 0.0f or INFINITY makes it immobile / static.
159 new Body(mWorld
, groundShape
, INFINITY
, Vector2(0.0f
, -5.0f
), 0.0f
, Vector2::One
, false);
163 ////////////////////////////////////////////////////////////////////////////////
164 static void update (int elapsed_ms
) {
165 sdl_frame_changed
= 1;
166 // UPDATE the physics!
167 for (int i
= 0; i
< 3; ++i
) mWorld
->update(1/200.0f
);
171 ////////////////////////////////////////////////////////////////////////////////
172 static void process_mousedown (SDL_MouseButtonEvent
*ev
) {
173 if (ev
->button
== SDL_BUTTON_LEFT
) {
174 float x
= s2x(ev
->x
);
175 float y
= s2y(ev
->y
);
176 //fprintf(stderr, "x=%.15g; y=%.15g\n", x, y);
179 shape
.addVertex(Vector2(-1.0f
, 0.0f
));
180 shape
.addVertex(Vector2( 0.0f
, 1.0f
));
181 shape
.addVertex(Vector2( 1.0f
, 0.0f
));
182 shape
.addVertex(Vector2( 0.0f
, -1.0f
));
185 FallingBody
*body
= new FallingBody(mWorld
, shape
, 1.0f
, 300.0f
, 10.0f
, Vector2(x
, y
), VectorTools::degToRad((float)rand()/RAND_MAX
*360.0f
), Vector2::One
);
186 body
->addInternalSpring(0, 2, 400.0f
, 12.0f
);
187 body
->addInternalSpring(1, 3, 400.0f
, 12.0f
);
191 if (ev
->button
== SDL_BUTTON_RIGHT
) {
192 float x
= s2x(ev
->x
);
193 float y
= s2y(ev
->y
);
198 if (ev
->button
== SDL_BUTTON_MIDDLE
) {
199 float x
= s2x(ev
->x
);
200 float y
= s2y(ev
->y
);
207 static void rebuild (void) {
208 memset(sdl_vscr
, 0, SCR_WIDTH
*SCR_HEIGHT
*sizeof(sdl_vscr
[0]));
209 for (int f
= 0; f
< mWorld
->bodyCount(); ++f
) {
210 Body
*b
= mWorld
->getBody(f
);
211 const ClosedShape
&shp
= b
->getBaseShape();
212 Vector2List vrt
= shp
.transformVertices(b
->getDerivedPosition(), b
->getDerivedAngle(), b
->getScale());
213 unsigned int pn
= vrt
.size()-1;
214 for (unsigned int vn
= 0; vn
< vrt
.size(); pn
= vn
++) {
215 //fprintf(stderr, "vn=%u; x=%d; y=%d\n", vn, x2s(vrt[vn].X), y2s(vrt[vn].Y));
216 dll(vrt
[pn
].X
, vrt
[pn
].Y
, vrt
[vn
].X
, vrt
[vn
].Y
, rgb2col(255, 255, 255));
221 static char buf
[128];
222 snprintf(buf
, sizeof(buf
), "body count: %d", mWorld
->bodyCount());
223 //draw_str_pr(1, 1, "Meow!WO-OIl!", rgb2col(255, 255, 0), rgba2col(0, 0, 200, 200));
224 draw_str(1, 1, buf
, rgb2col(255, 255, 0), mWorld
->bodyCount());
230 ////////////////////////////////////////////////////////////////////////////////
231 static void process_keydown (SDL_KeyboardEvent
*ev
) {
232 if (ev
->keysym
.sym
== SDLK_RETURN
&& (ev
->keysym
.mod
&KMOD_ALT
)) { switch_fullscreen(); return; }
233 if (ev
->keysym
.sym
== SDLK_ESCAPE
) { post_quit_message(); return; }
234 if (ev
->keysym
.sym
== SDLK_SPACE
) {
236 while (mWorld
->bodyCount() > 1) delete mWorld
->getBody(mWorld
->bodyCount()-1);
241 ////////////////////////////////////////////////////////////////////////////////
242 int main (int argc
, char *argv
[]) {
244 videolib_args(&argc
, argv
);
245 if (videolib_init("JellyPhysics Demo 00") < 0) {
246 fprintf(stderr
, "FATAL: can't initialize SDL!\n");
250 vl_rebuild
= rebuild
;
252 vl_process_keydown
= process_keydown
;
253 vl_process_mousedown
= process_mousedown
;