#include <acknex.h>
#include <default.c>
#include <ackphysX.h>
#define PRAGMA_POINTER
#define RIGID_GROUP 3
#define PLAYER_GROUP 4
// make sure that skill50 isn't already used in your project!
// if it is, then you need to change this skill50 to not used skill
#define OBJ_MOVING_SPEED skill50
void ph_body_event()
{
if(event_type == EVENT_PUSH)
{
VECTOR speed_vec;
vec_diff(&speed_vec, vector(my->x, my->y, 0), vector(you->x, you->y, 0));
speed_vec.z = 0; // we ignore Z pushes, because they are not really needed in this demo
// also as CharacterControl.cpp from the physX source code says:
/*
We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates
useless stress on the solver.
*/
// player's OBJ_MOVING_SPEED is affecting the pushing force
// if you want to ignore player's moving speed and want to have constant pushing strength
// then remove you->OBJ_MOVING_SPEED and play around with 10.0
var coeff = you->OBJ_MOVING_SPEED * 10.0;
vec_normalize(&speed_vec, coeff);
pXent_addvelcentral(my, &speed_vec);
}
}
function create_body(ENTITY *ent, var type)
{
set(ent, LIGHT | UNLIT | CAST | SHADOW);
ent->group = RIGID_GROUP;
ent->push = RIGID_GROUP;
ent->emask |= ENABLE_PUSH;
ent->event = ph_body_event;
vec_fill(&ent->scale_x, 0.6 + random(0.4));
pXent_settype(ent, PH_RIGID, type);
pXent_setelasticity(ent, 90);
pXent_addvelcentral(ent, vector(2 - random(4), 2 - random(4), 0));
var lifetime = 16; // after 16 seconds the body get's removed
while(ent)
{
lifetime -= time_frame / 16;
if(lifetime <= 0)
{
break;
}
wait(1);
}
ptr_remove(ent);
}
void ph_ball()
{
vec_set(&my->blue, vector(0, random(100), 150 + random(100)));
create_body(my, PH_SPHERE);
}
void ph_cube()
{
vec_set(&my->blue, vector(150 + random(100), random(100), 0));
create_body(my, PH_BOX);
}
void main()
{
video_mode = 8;
fps_max = 60;
warn_level = 6;
shadow_stencil = 2;
sun_light = 5;
physX_open();
pX_setunit(0.05);
pX_setgravity(vector(0, 0, -9.81));
level_load("");
ENTITY *ground_ent = ent_create(CUBE_MDL, nullvector, NULL);
vec_set(&ground_ent->scale_x, vector(100, 100, 0.01));
c_setminmax(ground_ent);
set(ground_ent, LIGHT | UNLIT);
vec_set(&ground_ent->blue, COLOR_GREEN);
pXent_settype(ground_ent, PH_STATIC, PH_POLY);
ENTITY *player_ent = ent_create(CUBE_MDL, vector(-128, -128, 16), NULL);
vec_set(&player_ent->scale_x, vector(1, 1, 1.9)); // we set Z to 1.9 so player doesn't touch the ground ent
c_setminmax(player_ent);
set(player_ent, LIGHT | UNLIT | SHADOW | CAST);
vec_set(&player_ent->blue, COLOR_WHITE);
player_ent->group = PLAYER_GROUP;
player_ent->push = PLAYER_GROUP;
var movement_speed = 5, gnd_fric = 0.5;
VECTOR input, speed;
vec_fill(&input, 0);
vec_fill(&speed, 0);
var cam_dist = 256, cam_focus = 0, cam_mouse_sensitivity = 1.0;
var spawn_counter = 0, spawn_time = 0.075;
// rotate camera by default at center of the map
vec_to_angle(&camera->pan, vec_diff(NULL, nullvector, &player_ent->x));
camera->tilt = -25;
camera->arc = 90;
while(player_ent)
{
// spawn rigid bodies
spawn_counter += time_frame / 16;
if(spawn_counter > spawn_time)
{
ent_create(SPHERE_MDL, vector(random(20), random(20), 150), ph_ball);
if(random(100) > 70)
{
ent_create(CUBE_MDL, vector(random(20), random(20), 170), ph_cube);
}
spawn_counter -= spawn_time;
}
fps_max = 60;
if(key_space)
{
fps_max = 20;
}
// input and acceleration
input.x = movement_speed * (key_w - key_s);
input.y = movement_speed * (key_a - key_d);
input.z = 0;
// running
if(key_shift)
{
input.x *= 2;
input.y *= 2;
}
vec_rotate(&input, vector(camera->pan, 0, 0));
accelerate(&speed.x, input.x * time_step, gnd_fric);
accelerate(&speed.y, input.y * time_step, gnd_fric);
// since player's group/push is set to 4 (PLAYER_GROUP) and c_move has IGNORE_PUSH set on
// player will ignore all entities with the same or smaller group/push values (rigid bodies group/push set to RIGID_GROUP which is 3)
// and will also trigger their ENABLE_PUSH/EVENT_PUSH events, where we will push them away
// check out ph_body_event for more info
var dist = c_move(player_ent, nullvector, &speed, IGNORE_PUSH | IGNORE_PASSABLE | GLIDE);
player_ent->OBJ_MOVING_SPEED = dist / time_step;
// fix player's Z position
// so he doesn't move up or down on collisions
player_ent->z = 16;
// simple 3d camera with zoom in/out
camera->pan = cycle(camera->pan - mickey.x / 6.5 * cam_mouse_sensitivity, 0, 360);
camera->tilt = clamp(camera->tilt - mickey.y / 6.5 * cam_mouse_sensitivity, -90, 90);
cam_dist -= 0.3 * mickey.z;
cam_dist = clamp(cam_dist, 64, 512);
cam_focus = fcos(camera->tilt, -cam_dist);
camera->x = player_ent->x + fcos((camera->pan), cam_focus);
camera->y = player_ent->y + fsin((camera->pan), cam_focus);
camera->z = player_ent->z + 16 + fsin(camera->tilt, -cam_dist);
wait(1);
}
}