2 registered members (AndrewAMD, juanex),
1,247
guests, and 6
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
a little help here?
#469597
11/23/17 23:51
11/23/17 23:51
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
Hey guys... Can anyone please, help me out here, by telling why does this happen? I'm really frustrated right now.. Spent few days working on movement code, and at the end it turns out to be like on the screen above.. Before showing my code, a little 'intro'. I used two separate models, one handles gravity and everything related to Z movement, the other one is responsible for XY movement. Also used gravity script from Superku's Tip of the Week series (it looks like the bbox size needs to be box shaped, other ways I faced some strange behaviours, can post demo if needed as well). Also, I do and I can understand, that cause of the ellipsoid shape, bbox can a bit penetrate the wall (on the both upper and lower ends of the bbox), but not like this, right? Player can simply go though the whole wall to the other side. Here is the code:
#include <acknex.h>
#include <default.c>
#include <windows.h>
#include <strio.c>
#define PRAGMA_PATH "data"
#define PRAGMA_POINTER
#define TRACE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)
#define MOVE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)
ENTITY *hero_ent;
ENTITY *hero_xy_ent;
void level_setup_world(){
sun_light = 0;
sun_angle.pan = 270;
sun_angle.tilt = -25;
vec_set(&d3d_lodfactor, vector(12.5, 25, 50));
camera->clip_near = 1;
camera->clip_far = 45000;
camera->fog_start = 1;
camera->fog_end = 40000;
fog_color = 4;
vec_set(&d3d_fogcolor4.blue, vector(128, 128, 128));
vec_set(&sky_color.blue, &d3d_fogcolor4.blue);
}
void player_xy_collider(){
proc_mode = PROC_LATE;
VECTOR input, abs_dist;
vec_fill(&input, 0);
vec_fill(&abs_dist, 0);
var movement_speed = 8.5, movement_friction = 0.85;
hero_xy_ent = my;
set(my, TRANSLUCENT);
c_setminmax(my);
while(!hero_ent){ wait(1); }
while(my){
input.x = movement_speed * (key_w - key_s);
input.y = movement_speed * (key_a - key_d);
input.z = 0;
if(vec_length(vector(input.x, input.y, 0)) > movement_speed){
var len = sqrt(input.x * input.x + input.y * input.y);
input.x *= ((movement_speed) / len);
input.y *= ((movement_speed) / len);
}
vec_rotate(&input, vector(camera->pan, 0, 0));
accelerate(&abs_dist.x, input.x * time_step, movement_friction);
accelerate(&abs_dist.y, input.y * time_step, movement_friction);
c_move(my, nullvector, vector(abs_dist.x, abs_dist.y, 0), MOVE_FLAGS | IGNORE_MODELS | GLIDE);
if(hero_ent){
hero_ent->x = my->x;
hero_ent->y = my->y;
my->z = hero_ent->z + 16;
}
camera->pan = cycle(camera->pan - mickey.x / 6.5, 0, 360);
camera->tilt = clamp(camera->tilt - mickey.y / 6.5, -90, 90);
camera->x = my->x + fcos((camera->pan), fcos(camera->tilt, -128));
camera->y = my->y + fsin((camera->pan), fcos(camera->tilt, -128));
camera->z = my->z + fsin(camera->tilt, -128);
camera->arc = 90;
wait(1);
}
}
action player_controller(){
VECTOR force;
vec_fill(&force, 0);
var foot_height = 0, soil_height = 0, soil_contact = 0;
var jump_height = 16, jump_key_off = 0;
hero_ent = my;
set(my, INVISIBLE);
my->scale_z = 0.5;
wait(1);
c_setminmax(my);
VECTOR temp;
vec_for_min(&temp, my);
foot_height = (temp.z * my->scale_z) - 0;
ent_create("bbox_npc.mdl", &my->x, player_xy_collider);
while(my){
if(force.z <= 0){
vec_set(&temp, vector(my->x, my->y, my->z - 150 + foot_height));
c_trace(&my->x, &temp, TRACE_FLAGS | IGNORE_MODELS | USE_BOX);
soil_height = temp.z - foot_height;
if(trace_hit){ soil_height = target.z - foot_height; }
}
if(my->z > soil_height + (5 + 20 * soil_contact) * time_step || force.z > 0){
soil_contact = 0;
force.z = maxv(force.z - 4 * time_step, -90);
}
else{
c_move(me, nullvector, vector(0, 0, soil_height - my->z), MOVE_FLAGS | IGNORE_MODELS);
soil_contact = 1;
force.z = 0;
if(key_space){
if(jump_key_off == 0){
jump_key_off = 1;
force.z = jump_height;
}
}
else{ jump_key_off = 0; }
}
if(force.z){
c_move(me, nullvector, vector(0, 0, maxv(force.z * time_step, soil_height - my->z)), MOVE_FLAGS | IGNORE_MODELS);
if(HIT_TARGET && normal.z < -0.5){ force.z = minv(force.z, 0); }
}
wait(1);
}
}
void main(){
video_set(800, 600, 16, 2);
doppler_factor = 0;
warn_level = 6;
fps_max = 60;
fps_min = 30;
time_smooth = 0.9;
freeze_mode = 1;
level_load("def_map.wmb");
wait(3);
freeze_mode = 0;
random_seed(0);
level_setup_world();
}
Just in order to show you that bboxes are set correct, here is a screen with both of them visible (in the first screen above only of the bbox, which is responsible for XY movement is visible): And for those who are willing even test this (I want to say big thank you in advance to those risky folks), here is a demo (in order to 'walk in', walk towards the wall and jump few times): Download link (19kb) Originally I used smaller model sizes (like 32 was the total height of the character), thought maybe it was a bad size, increased it by 2 times, yet same results... I do really hope that some of you guys could help me out here, with an advice or by sharing your experience about the topic. Thank you all in advance. Best regards.
|
|
|
Re: a little help here?
[Re: 3run]
#469604
11/24/17 11:15
11/24/17 11:15
|
Joined: Sep 2003
Posts: 6,861 Kiel (Germany)
Superku
Senior Expert
|
Senior Expert
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
|
Hm very strange. Tried to code it a little differently but still got the same result. I'm gonna paste the code here even though it does not change much, just for inspiration:
action player_controller(){
VECTOR force;
VECTOR input, abs_dist;
vec_fill(&input, 0);
vec_fill(&abs_dist, 0);
vec_fill(&force, 0);
var movement_speed = 8.5, movement_friction = 0.85;
var foot_height = 0, soil_height = 0, soil_contact = 0;
var jump_height = 16, jump_key_off = 0;
hero_ent = my;
set(my, TRANSLUCENT);
wait(1);
c_setminmax(my);
VECTOR temp;
vec_for_min(&temp, my);
foot_height = (temp.z * my->scale_z) - 2;
while(my)
{
// xy
my->min_x -= 1;
my->max_x += 1;
my->min_y -= 1;
my->max_y += 1;
input.x = movement_speed * (key_w - key_s);
input.y = movement_speed * (key_a - key_d);
input.z = 0;
if(vec_length(vector(input.x, input.y, 0)) > movement_speed){
var len = sqrt(input.x * input.x + input.y * input.y);
input.x *= ((movement_speed) / len);
input.y *= ((movement_speed) / len);
}
vec_rotate(&input.x, vector(camera->pan, 0, 0));
disable_z_glide = 1;
c_move(my, nullvector, vector(input.x*time_step, input.y*time_step, 0), MOVE_FLAGS | IGNORE_MODELS | GLIDE);
disable_z_glide = 0;
my->min_x += 1;
my->max_x -= 1;
my->min_y += 1;
my->max_y -= 1;
// gravity
var oldMaxZ = my->max_z;
my->max_z = 0.025; // flat box/ cylinder like gravity
my->min_z = -0.025;
if(force.z <= 0){
vec_set(&temp, vector(my->x, my->y, my->z - 150 + foot_height));
c_trace(&my->x, &temp, TRACE_FLAGS | IGNORE_MODELS | USE_BOX);
soil_height = temp.z - foot_height;
if(trace_hit){ soil_height = target.z - foot_height; }
}
if(my->z > soil_height + (5 + 20 * soil_contact) * time_step || force.z > 0){
soil_contact = 0;
force.z = maxv(force.z - 4 * time_step, -90);
}
else{
c_move(me, nullvector, vector(0, 0, soil_height - my->z), MOVE_FLAGS | IGNORE_MODELS);
soil_contact = 1;
force.z = 0;
if(key_space){
if(jump_key_off == 0){
jump_key_off = 1;
force.z = jump_height;
}
}
else{ jump_key_off = 0; }
}
if(force.z){
c_move(me, nullvector, vector(0, 0, maxv(force.z * time_step, soil_height - my->z)), MOVE_FLAGS | IGNORE_MODELS);
if(HIT_TARGET && normal.z < -0.5){ force.z = minv(force.z, 0); }
}
my->max_z = oldMaxZ;
my->min_z = -oldMaxZ;
camera->pan = cycle(camera->pan - mickey.x / 6.5, 0, 360);
camera->tilt = clamp(camera->tilt - mickey.y / 6.5, -90, 90);
camera->x = my->x + fcos((camera->pan), fcos(camera->tilt, -128));
camera->y = my->y + fsin((camera->pan), fcos(camera->tilt, -128));
camera->z = my->z + fsin(camera->tilt, -128);
camera->arc = 90;
wait(1);
}
}
"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual Check out my new game: Pogostuck: Rage With Your Friends
|
|
|
Re: a little help here?
[Re: jumpman]
#469614
11/24/17 23:38
11/24/17 23:38
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
Thank you for your response jumpman! Yeah, it kinda solved problem for me too, but it causes more inaccuracies in movement, f.e. jumping (when hitting the celling) etc, so I had to refuse this solution. Reason why I wanted to separate XY and Z movement, is cause of issues given by ellipsoid collision hull. Making entity responsible for gravity smaller (half size, so ellipsoid is kinda smushed and thus resulting more or less box like collisions) and placing it below the origin of the XY moving entity allows me to get more or less suitable results for jumping on block edges etc. When you make trace from the origin of the XY moving entity, it will cause player to hump on the edges at places/situations, where player shouldn't be able to jump on. Also, I made traces from that half sized entity towards the moving velocity of XY, in order to detect obstacles and push him (player) away, this helps to prevent situation I've described above as well. I'm not great at explaining such stuff in English unfortunately, sorry for that. In order to explain problems I've faced with ellipsoid hull, I could draw a picture if you want to. Right now I seems to get things working, had to unite XY and Z in one entity, a bit more tricky, but I guess I'll be able to workaround some situations by level design (also I already had this setup working, with seperated XY and Z for movement, you can find it on the forum, something related to auto jumping, also it's on my webpage, but here I used a bit another approach and it resulted in problem described in the first post of this thread). As soon as I'll have something running, I'll make a thread and post a demo, would love to see you guys giving it a try My best regards!
|
|
|
Re: a little help here?
[Re: 3run]
#469616
11/25/17 00:32
11/25/17 00:32
|
Joined: Apr 2002
Posts: 1,246 ny
jumpman
Serious User
|
Serious User
Joined: Apr 2002
Posts: 1,246
ny
|
awesome 3run!
Can you draw a picture of the reasons, if you dont mind?
Can you upload the current test level with it working? the one with the single entity?
Last edited by jumpman; 11/25/17 00:33.
|
|
|
Re: a little help here?
[Re: jumpman]
#469617
11/25/17 11:54
11/25/17 11:54
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
Sure! I'll describe the problem I'm facing (what I don't like in ellipsoid hull), then I'll try to describe solution I came up with and then the problem I've faced with my solution (it's not related to this topic, but to the main disadvantage it has). WHAT I DON'T LIKE: PROBLEM #1: You can see that cause of ellipsoid hull, player's gravity trace, will be able to 'grab' the edge of the block. That happens cause our bounding box isn't box shaped (or at least capsule), and gravity trace is stretched downwards... As soon as it will grab that edge, player will be able to walk up on it. Plus, cause of GLIDE and ellipsoid hull, player will be able to get on top of that edge any way, cause GLIDE will push him upwards. PROBLEM #2: Not a big problem, but it's also related to GLIDE, in this situation, player will be pushed downwards a little bit (at least till the bbox will hit the ground, if you have an offset from surface below). This will result in getting stuck if you will get 'pushed to floor' and will try to move sideways. PROBLEM #3: It's just another picture to show how ellipsoid will collide with the edge, and what I would like to avoid. SOLUTIONS: #1: We could push player away from the normals of the surface we are moving towards to, that's what I do now. I get player's velocity for a direction, then I use (f.e.) my->max_x and then trace (picture doesn't use my->max_x, and trace is stretched with the velocity, but that's just to show you the idea of what I've done). As soon as the trace hits anything, we disable our input towards the hit->x position ( if(hit->x < my->x){ input.x = maxv(input.x, 0); } else { input.x = minv(input.x, 0); } ) and we push player away from the normals ( input.x += normal.x * (1 - vec_dot(&normal, &input)); ). #2: First of all, we separate XY and Z movement. Entity responsible for Z is half sized and placed below the origin of the XY entity. This will make trace more 'smushed'. In addition to this, we set my->max_z and my->min_z to smaller values, like 0.1 and -0.1 right before performing gravity trace, after the gravity we restore them back again (this also helps to get more or less box like trace hull). For gravity trace, we don't use our Z entities origin position, but we add a little offset, this will also help us to avoid PROBLEM #1. Our XY movement has full bounding box size and it's responsible for all XY collisions, but there is a gap, as you may see on the picture, between our XY ellipsoid hull and gravity trace. To fix that, we need to use solutions #1 and #2 together. #3: We just add first solution to the second one, to fill the gaps and to prevent player from hopping on top of the blocks/edges as shown on PROBLEM 1. For this trace (towards the moving direction) we'll use Z entity's origin position, as shown on the picture. 'SOLUTIONS' PROBLEM However this 'solution' has main disadvantage (at least the way I setup things), there is a gap between X and Y traces, you can see at the picture. And if player will walk towards the edge of the wall, traces won't help much, player will be able to touch the wall (and that's the main thing I would like to archive in order to prevent all problems). It's probably a pretty dirty and not elegant way of handling things, but it's what I came up with anyway. For now, I use the same method, but with only one entity, which is responsible for XY. It preforms gravity trace (with Z offset for start position) and it also handles those traces towards the moving velocity. As for the demo, I can't share it right now, cause it's pretty complicated, and I'll have to spent time on ripping main parts out of it. Soon I'll post a demo of the movement itself, but it probably won't be 'open source', but compiled one. Best regards.
|
|
|
Re: a little help here?
[Re: 3run]
#469618
11/25/17 12:23
11/25/17 12:23
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
Even if you don't need a physics simulation (just a movement script, for example) I'd recommend you to use a physics engine for better collisions. The built-in physx plugin will most likely not do, though, as it's missing some important features (mostly scene-query stuff).
I'm using the unfinished physix 3 plugin someone on the forum made a while ago. It has some problems aswell (including bugs with joints, iirc) but for me it works. You could also wrap physx3 or another physics engine yourself.
POTATO-MAN saves the day! - Random
|
|
|
Re: a little help here?
[Re: Kartoffel]
#469623
11/25/17 13:22
11/25/17 13:22
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
I'm using the unfinished physix 3 plugin someone on the forum made a while ago. It has some problems aswell (including bugs with joints, iirc) but for me it works. You could also wrap physx3 or another physics engine yourself. You are probably using plugin which was made by 3dgs_snake. The first version of it, as he wanted to recreate the plugin from scratch, with the knowledge he have gained and he even started working on it. Unfortunately I don't have any of his plugins on my current PC. And yes, build-it physX won't work, cause it has already some limitations and bugs, I would love to use solid working physX 3.x plugin, but there are none and I'm not good in creating anything like that myself... Greets.
|
|
|
|