/*
A project started by Clemens Möckel (23.1.2011)
with the aim of a nice, big collection of 3dGS PhysX gimmicks...
Start now and create/add yours. Here's the How-to:
1) Program a function which creates your physics gimmick (simulation)... like the function create_chain_ball()
-try to keep it as simple as possible
-document and comment your source code and insert "[help]" at each places, you have trouble with
2) Implement a hotkey to your function in the main function.
3) You need to have a while loop
-which includes the user control (if there is one) (I)
-a draw_text command giving a short description of your gimmick (II)
-and very important: a "if (key_delete)" block, which removes your gimmick (III)
4) Add a "gimmick_is_running=1;" before the while loop and a "gimmick_is_running=0;" after that loop
5) Share it in the 3dGs forum at: [url]
-don't forget a download with the models/prefabs
-post a screenshot of your gimmick
*/
///////////////////////////////
#include <acknex.h>
#include <default.c>
#include <ackphysx.h>
///////////////////////////////
BOOL gimmick_is_running;
////////////////////////
// chain_ball v0.3 by Clemens
function create_chain_ball() {
// Create the chains, and the ball at the bottom
ENTITY* Ring1 = ent_create("chain_ring.mdl", vector(0,0,0), NULL);
ENTITY* Ring2 = ent_create("chain_ring.mdl", vector(0,0,-10), NULL);
Ring2.pan=90;
ENTITY* Ring3 = ent_create("chain_ring.mdl", vector(0,0,-20), NULL);
ENTITY* Ring4 = ent_create("chain_ring.mdl", vector(0,0,-30), NULL);
Ring4.pan=90;
ENTITY* Ring5 = ent_create("chain_ring.mdl", vector(0,0,-40), NULL);
ENTITY* Ring6 = ent_create("chain_ring.mdl", vector(0,0,-50), NULL);
Ring6.pan=90;
ENTITY* Ball = ent_create("sphere.mdl", vector(0,0,-64), NULL);
// Just for the look
// material
set(Ring1,LIGHT|CAST);set(Ring2,LIGHT|CAST);set(Ring3,LIGHT|CAST);set(Ring4,LIGHT|CAST);set(Ring5,LIGHT|CAST);set(Ring6,LIGHT|CAST);set(Ball,LIGHT|CAST);
Ring1.material=mat_metal;Ring2.material=mat_metal;Ring3.material=mat_metal;Ring4.material=mat_metal;Ring5.material=mat_metal;Ring6.material=mat_metal;Ball.material=mat_metal;
// colors
//[variante1] vec_set(Ring1.blue,vector(200,0,0));vec_set(Ring2.blue,vector(0,100,0));vec_set(Ring3.blue,vector(200,0,0));vec_set(Ring4.blue,vector(0,200,0));vec_set(Ring5.blue,vector(200,0,0));vec_set(Ring6.blue,vector(0,200,0));vec_set(Ball.blue,vector(0,0,200));
vec_set(Ring1.blue,vector(200,0,0));vec_set(Ring2.blue,vector(160,40,0));vec_set(Ring3.blue,vector(120,80,0));vec_set(Ring4.blue,vector(80,120,0));vec_set(Ring5.blue,vector(40,160,0));vec_set(Ring6.blue,vector(0,200,0));vec_set(Ball.blue,vector(0,100,100));
// casting shadows
set(Ring1,SHADOW); set(Ring2,SHADOW); set(Ring3,SHADOW); set(Ring4,SHADOW); set(Ring5,SHADOW); set(Ring6,SHADOW); set(Ball,SHADOW);
// Make them physical by define their types
pXent_settype(Ring1,PH_RIGID,PH_CONVEX);
pXent_settype(Ring2,PH_RIGID,PH_CONVEX);
pXent_settype(Ring3,PH_RIGID,PH_CONVEX);
pXent_settype(Ring4,PH_RIGID,PH_CONVEX);
pXent_settype(Ring5,PH_RIGID,PH_CONVEX);
pXent_settype(Ring6,PH_RIGID,PH_CONVEX);
pXent_settype(Ball,PH_RIGID,PH_BALL);
// group the rings so they dont affect each other related to their collision (getting important if they losing their constraints)
pXent_setgroup(Ring1,3); pXent_setgroup(Ring2,3); pXent_setgroup(Ring3,3); pXent_setgroup(Ring4,3);pXent_setgroup (Ring5,3);pXent_setgroup (Ring6,3);
//pXent_setgroup(Ball,3);
// Connect the objects!
pXcon_add ( PH_BALL, Ring1, NULL, 0 ); // PH_BALL makes it more movable...
pXcon_add ( PH_HINGE, Ring2, Ring1, 0 );
pXcon_add ( PH_HINGE, Ring3, Ring2, 0 );
pXcon_add ( PH_HINGE, Ring4, Ring3, 0 );
pXcon_add ( PH_HINGE, Ring5, Ring4, 0 );
pXcon_add ( PH_HINGE, Ring6, Ring5, 0 );
pXcon_add ( PH_HINGE, Ball, Ring6, 0 );
pXcon_setparams1(Ring1, vector(0,0,5), NULL, NULL); // anchor point at the top, like attached on the ceiling
// change the axis - otherwise the chains wouldn't keep their 90° pan relation ... (1,0,0), (0,1,0), (1,1,0) seems to make no difference (?)
pXcon_setparams1(Ring2, NULL, vector(0,1,0), NULL);
pXcon_setparams1(Ring3, NULL, vector(0,1,0), NULL);
pXcon_setparams1(Ring4, NULL, vector(0,1,0), NULL);
pXcon_setparams1(Ring5, NULL, vector(0,1,0), NULL);
pXcon_setparams1(Ring6, NULL, vector(0,1,0), NULL);
pXent_setmass(Ball, 0.01); // if the ball is to heavy it results in physical chaos
// reducing pXent_setmaxspeed can help to protect chaos, too - but then the sixth ring becomes stiff... why? [help]
//pXent_setmaxspeed(Ball, 0.1);
// second way would probably be to change parameter3 --> let it break before
pXent_setdamping (Ball, 50, 50 ); // the ball gets forced, so it as well has to be damped - otherwise doesn't stop moving
gimmick_is_running=1;
while(1) {
// (I) user control
if (key_cul) pXent_addforcecentral(Ball, vector(-0.01, 0, 0));
if (key_cur) pXent_addforcecentral(Ball, vector(0.01, 0, 0));
if (key_cuu) pXent_addforcecentral(Ball, vector(0, 0.01, 0));
if (key_cud)pXent_addforcecentral(Ball, vector(0, -0.01, 0));
// (II) info text
draw_text("chain_ball v0.3 by Clemens \n arrow keys: give the ball a force in that direction \n del key: destroy it", 10,10,vector(255,255,255));
// (III) remove gimmick... (only a part)
if (key_del) {
pXcon_remove(Ball); // backwards order important
pXcon_remove(Ring6);
pXcon_remove(Ring5);
pXcon_remove(Ring4);
pXcon_remove(Ring3);
pXcon_remove(Ring2);
pXcon_remove(Ring1);
break;
}
pX_pick();
wait(1);
}
gimmick_is_running=0;
wait(-5);
// placed the real remove routine here, because it's a nice effect, having it destroyed and lying on the door for five seconds
ent_remove(Ball);
/* "Error E1513: Script crash in physX_ent_remove: SYS" when deleting the rings -> don't know why [help]
ent_remove(Ring6);
ent_remove(Ring5);
ent_remove(Ring4);
ent_remove(Ring3);
ent_remove(Ring2);
ent_remove(Ring1);
*/
}
////////////////
// main function
function main() {
sun_angle.pan -= 80;
sun_angle.tilt = 50;
shadow_stencil = 3;
d3d_antialias = 4;
physX_open();
level_load(""); // load empty level
vec_set(camera.x,vector(0,-180,-50));
camera.pan=90;
// create ground plate (copied from physXtest.c by jcl)
ENTITY* ground = ent_create(CUBE_MDL,vector(0,0,-100),NULL);
vec_set(ground.scale_x,vector(20,20,1));
pXent_settype(ground,PH_STATIC,PH_BOX);
pXent_setfriction(ground,10);
while (1) {
if (gimmick_is_running==0) {
if (key_a) {
create_chain_ball();
wait(-1);
}
// Here you have to insert your function-hotkey
// ...
}
wait(1);
}
}