Well, here is an ugly and bad first step to achieve an antigravity-gun.
The code is mainly copy/paste of other examples so maybe is not too clear right now.
Anyway i have noticed a big problem.
When we attach 2 objects we really are attaching 2 elements, so we create a new big object. That behaviour doesn't looks like the regular one in FPS games.
In half life2, for example, you can grab a box, move to a small door and you will pass but the box won't (and eventually the joint will break).
I think this can not be done with the current system of joints.
Am i wrong?
GIF with a graphical explanation of the problem.
And here the code:
Code:
/*
Raydium - CQFD Corp.
http://raydium.org/
License: GPL - GNU General Public License, see "gpl.txt" file.
*/
/* This howto attemp to show how to create a gravity-like-gun
It's importat to read how_to_point_an_object.c
By one side we are putting here the most code of how_to_point_an_object.c and a bit of test6.c
From tes6 we are going to put a moveable character.
From how_to_point_an_object.c we are creating a pair of objects and the code for pointing.
Also we will take account of rrp_play.c for the code to link an object to another on the fly.
*/
#include "raydium/index.c"
int object1, object2; /*variables for the 2 objects used in the demo*/
int a; /* main character */
dReal cam_angle_h=0;
dReal cam_angle_v=90;
#define DEFAULT_RAND_DEC raydium_random_f(-3,3)
#define DEFAULT_DEC DEFAULT_RAND_DEC,DEFAULT_RAND_DEC,0
int debug=1;
//attaching variables. This could be done by an external function
signed char attached=0; // is camera attached to something ?
int attached_id; // if yes, which element is it ?
dReal attached_pos[3]; // and where the camera is ? (relative to this element)
dReal attached_lookat[3]; // and what are we looking at ? (relative, too)
/*function to create a pair of objects in the scene, near 0,0,0*/
void create_objects(void)
{
object1=raydium_ode_object_find("OBJ1");
object1=raydium_ode_object_create ("OBJ1");
raydium_ode_object_box_add("element1",object1,0.1,RAYDIUM_ODE_AUTODETECT,0,0,RAYDIUM_ODE_STANDARD,0,"crate.tri");
/*Fix to prevent quite sligth movements betwen objects caused by a non-enough friction force*/
/*Usually this won't be necesary, but usefull in the case you are showing numeric values*/
raydium_ode_element_slip_name("element1",0);
object2=raydium_ode_object_find("OBJ2");
object2=raydium_ode_object_create ("OBJ2");
raydium_ode_object_box_add("element2",object2,0.3,RAYDIUM_ODE_AUTODETECT,0,0,RAYDIUM_ODE_STANDARD,0,"crate.tri");
raydium_ode_object_move_3f (object2,2,0,0);
/*Fix to prevent quite sligth movements betwen objects caused by a non-enough friction force*/
/*Usually this won't be necesary, but usefull in the case you are showing numeric values*/
raydium_ode_element_slip_name("element2",0);
}
/*function to create our character.
As it is a FPS main character it will use a particular subset of funtions focussed to FPS
*/
void create_character(void){
// float reload_time=RELOAD_TIME;
raydium_ode_object_delete_name("PLAYER");
a=raydium_ode_object_create("PLAYER");
raydium_ode_object_sphere_add("player",a,1,RAYDIUM_ODE_AUTODETECT,RAYDIUM_ODE_STANDARD,0,"lego.tri");
raydium_ode_element_material_name("player",RAYDIUM_ODE_MATERIAL_SOFT2);
raydium_ode_element_player_set_name("player",1);
raydium_ode_motor_create("player_react",a,RAYDIUM_ODE_MOTOR_ROCKET);
raydium_ode_motor_rocket_set_name("player_react","player",0,0,0);
raydium_ode_motor_rocket_playermovement_name("player_react",1);
raydium_ode_element_slip_name("ground",RAYDIUM_ODE_SLIP_ICE/2.f);
//raydium_ode_element_OnBlow_name("player",blow_touched);
raydium_ode_element_move_name_3f("player",3,3,1);
#define DEFAULT_RAND_DEC raydium_random_f(-3,3)
#define DEFAULT_DEC DEFAULT_RAND_DEC,DEFAULT_RAND_DEC,0
//raydium_ode_object_move_name_3f("BUGGY", DEFAULT_DEC);
raydium_ode_object_move_name_3f("PLAYER",DEFAULT_DEC);
//raydium_ode_object_move_name_3f("PLAYER",2,0,0);
}
/* usual callback funtion "display" */
void display(void)
{
/*3 variables for the pointing */
dReal pos[3]; /*position of the pointed point */
dReal dist; /*distance of the pointed point from de point of view*/
dReal weapon_range;
int id_pointed; /*id of the pointed object */
weapon_range=101;
raydium_joy_key_emul();
if(raydium_key_last==1027)
exit(0);
if(raydium_key_last==1000+'d')debug=debug?0:1;
/* code to move the player */
int dir=5;
float speed=0.2;
float ptmp=0;
// directions indices:
// 1 2 3
// ^
// 4 <- 5 -> 6
// v
// 7 8 9
if(raydium_key[GLUT_KEY_LEFT]) dir=4;
if(raydium_key[GLUT_KEY_RIGHT]) dir=6;
if(raydium_key[GLUT_KEY_UP]) dir=2;
if(raydium_key[GLUT_KEY_DOWN]) dir=8;
if(raydium_key[GLUT_KEY_LEFT] && raydium_key[GLUT_KEY_UP]) dir=1;
if(raydium_key[GLUT_KEY_RIGHT] && raydium_key[GLUT_KEY_UP]) dir=3;
if(raydium_key[GLUT_KEY_LEFT] && raydium_key[GLUT_KEY_DOWN]) dir=7;
if(raydium_key[GLUT_KEY_RIGHT] && raydium_key[GLUT_KEY_DOWN]) dir=9;
switch(dir)
{
case 1:
ptmp=-45;
break;
case 2:
ptmp=0;
break;
case 3:
ptmp=45;
break;
case 4:
ptmp=-90;
break;
case 5:
speed=0; // stops player
break;
case 6:
ptmp=90;
break;
case 7:
ptmp=-135;
break;
case 8:
ptmp=180;
break;
case 9:
ptmp=135;
break;
}
raydium_ode_motor_speed_name("player_react",speed);
raydium_ode_motor_rocket_orientation_name("player_react",0,90,ptmp);
/*Till here the code to move the player */
/*checking the id of the object pointed, at a maximum of 101 units of distance */
id_pointed = raydium_ode_mouse_pick(weapon_range,pos,&dist);
raydium_osd_printf((100.0f*raydium_mouse_x)/raydium_window_tx,100-(100.0f*raydium_mouse_y)/raydium_window_ty,16,0.5,"font2.tga","+ %d %.3f %.3f %.3f %.3f",id_pointed,pos[0],pos[1],pos[2],dist);
if (raydium_mouse_button[0] && id_pointed>0 ){
if (raydium_ode_element[id_pointed].state == RAYDIUM_ODE_STANDARD){
pos[1]=pos[0]=0;
pos[2]=5;
//raydium_ode_element_addforce(id_pointed,pos);
//now the object has to be linked to the character
if(!attached)
{
raydium_log("Linking the object to the character");
int id;
dReal pos[3];
dReal cam[3];
dReal dist;
id = raydium_ode_mouse_pick(100,pos,&dist);
if(id>=0)
{
// attached_pos (camera pos to element's space)
cam[0]=raydium_camera_x;
cam[1]=raydium_camera_y;
cam[2]=raydium_camera_z;
raydium_ode_element_world2rel(id,cam,attached_pos);
// attached_lookat (impact pos to element's space)
raydium_ode_element_world2rel(id,pos,attached_lookat);
attached_id=id;
attached=1;
raydium_ode_joint_attach_hinge("hang_joint",3,id_pointed,cam[0],cam[1],cam[2],RAYDIUM_ODE_JOINT_AXE_X);
}
}
else // is alread attached
{
//raydium_ode_joint_break_name("hang_joint");
raydium_ode_joint_delete_name("hang_joint");
attached=0;
}
}
}
raydium_clear_frame();
/* [ place your camera here ] */
/*raydium_camera_look_at(10,-2,2,0,0,0);*/
float sensivity=1;
float delta_x;
float delta_y;
float zoomfact=1;
zoomfact=raydium_projection_fov/70;
delta_x = (raydium_mouse_x - (raydium_window_tx/2.f))*sensivity*zoomfact;
delta_y = (raydium_mouse_y - (raydium_window_ty/2.f))*sensivity*zoomfact;
cam_angle_h += (delta_x*0.008f); // rads
cam_angle_v += (delta_y*0.458f); // degs
raydium_mouse_move(raydium_window_tx/2, raydium_window_ty/2);
raydium_ode_element_player_angle_name("player",cam_angle_h);
if(cam_angle_v<1) cam_angle_v=1;
if(cam_angle_v>179) cam_angle_v=179;
raydium_ode_element_camera_inboard_name("player",-0.3,-0.3,0.25, raydium_trigo_sin(cam_angle_v),0,raydium_trigo_cos(cam_angle_v));
/* [ draw here ] */
raydium_ode_draw_all(RAYDIUM_ODE_DRAW_NORMAL);
raydium_ode_draw_all(RAYDIUM_ODE_DRAW_RAY);
if(debug)
{
raydium_ode_draw_all(RAYDIUM_ODE_DRAW_DEBUG);
raydium_ode_draw_all(RAYDIUM_ODE_DRAW_AABB);
}
/* we put the info on the screen each frame */
raydium_osd_printf(2,98,18,0.5,"font2.tga","HOW TO antigravity-gun",id_pointed);
raydium_osd_printf(2,95,18,0.5,"font2.tga","Id of object:%d",id_pointed);
raydium_osd_printf(2,92,18,0.5,"font2.tga","Position of the pointed point: (%f, %f, %f)",pos[0],pos[1],pos[2]);
raydium_osd_printf(2,89,18,0.5,"font2.tga","Distance to the pointed point: %f (raydium)units.",dist);
raydium_osd_printf(2,86,18,0.5,"font2.tga","Press d to toogle debug drawing.");
raydium_osd_printf(2,83,18,0.5,"font2.tga","Click on a box to grab it. Click again to release it. It's a bit tricky.");
raydium_rendering_finish();
}
int main(int argc, char **argv)
{
raydium_init_args(argc,argv);
raydium_window_create(640,480,RAYDIUM_RENDERING_WINDOW,"My app");
raydium_texture_filter_change(RAYDIUM_TEXTURE_FILTER_TRILINEAR);
raydium_window_view_perspective(60,0.01,2500); // fov 60 + near and far planes
raydium_fog_disable();
raydium_light_enable();
raydium_light_on(0);
raydium_light_conf_7f(0,50,150,200,1000000,1,0.9,0.7); // id, pos, intensity and color (RGB)
raydium_background_color_change(1,0.9,0.7,1);
raydium_sky_box_cache();
/* [ place base scene here ] */ raydium_ode_ground_set_name("cocorobix.tri");
/* create a pair of objects to have something to point to */
create_objects();
create_character();
/*forcing the render of a cursor in the mouse position*/
raydium_osd_cursor_set("BOXcursor.tga",4,4);
raydium_callback(&display);
return(0);
}
// EOF