loads of fixes, skidding, velocity ramping and other stuff

This commit is contained in:
Magnus Auvinen 2008-03-16 22:32:17 +00:00
parent 727c9a3a32
commit 4a3c2e2c8c
12 changed files with 223 additions and 74 deletions

View file

@ -119,6 +119,13 @@ sounds {
"data/audio/vo_teefault_spawn-07.wv"
}
player_skid {
"data/audio/sfx_skid-01.wv"
"data/audio/sfx_skid-02.wv"
"data/audio/sfx_skid-03.wv"
"data/audio/sfx_skid-04.wv"
}
tee_cry {
"data/audio/vo_teefault_cry-01.wv"
"data/audio/vo_teefault_cry-02.wv"

View file

@ -1373,11 +1373,15 @@ void render_game()
{
gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300);
float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y),
vec2(netobjects.local_character->x, netobjects.local_character->y));
/*float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y),
vec2(netobjects.local_character->x, netobjects.local_character->y));*/
float velspeed = length(vec2(netobjects.local_character->vx/256.0f, netobjects.local_character->vy/256.0f))*50;
float ramp = velocity_ramp(velspeed, tuning.velramp_start, tuning.velramp_range, tuning.velramp_curvature);
char buf[512];
str_format(buf, sizeof(buf), "%.2f %d", speed/2, netobj_num_corrections());
str_format(buf, sizeof(buf), "%.0f\n%.0f\n%.2f\n%d", velspeed, velspeed*ramp, ramp, netobj_num_corrections());
gfx_text(0, 150, 50, 12, buf, -1);
}
@ -1481,6 +1485,24 @@ void render_game()
count++;
}
y = y+count*6;
gfx_texture_set(-1);
gfx_blend_normal();
gfx_lines_begin();
float height = 50.0f;
float pv = 1;
for(int i = 0; i < 100; i++)
{
float speed = i/100.0f * 3000;
float ramp = velocity_ramp(speed, tuning.velramp_start, tuning.velramp_range, tuning.velramp_curvature);
float rampedspeed = (speed * ramp)/1000.0f;
gfx_lines_draw((i-1)*2, y+height-pv*height, i*2, y+height-rampedspeed*height);
//gfx_lines_draw((i-1)*2, 200, i*2, 200);
pv = rampedspeed;
}
gfx_lines_end();
}
gfx_text_color(1,1,1,1);

View file

@ -142,6 +142,7 @@ void effects_update();
void effect_bullettrail(vec2 pos);
void effect_smoketrail(vec2 pos, vec2 vel);
void effect_skidtrail(vec2 pos, vec2 vel);
void effect_explosion(vec2 pos);
void effect_air_jump(vec2 pos);
void effect_damage_indicator(vec2 pos, vec2 dir);

View file

@ -2,7 +2,8 @@
#include "gc_client.h"
#include "../generated/gc_data.h"
static bool add_trail = false;
static bool add_50hz = false;
static bool add_100hz = false;
void effect_air_jump(vec2 pos)
{
@ -27,7 +28,7 @@ void effect_air_jump(vec2 pos)
void effect_powerupshine(vec2 pos, vec2 size)
{
if(!add_trail)
if(!add_50hz)
return;
particle p;
@ -48,7 +49,7 @@ void effect_powerupshine(vec2 pos, vec2 size)
void effect_smoketrail(vec2 pos, vec2 vel)
{
if(!add_trail)
if(!add_50hz)
return;
particle p;
@ -65,9 +66,28 @@ void effect_smoketrail(vec2 pos, vec2 vel)
}
void effect_skidtrail(vec2 pos, vec2 vel)
{
if(!add_100hz)
return;
particle p;
p.set_default();
p.spr = SPRITE_PART_SMOKE;
p.pos = pos;
p.vel = vel + random_dir()*50.0f;
p.life_span = 0.5f + frandom()*0.5f;
p.start_size = 24.0f + frandom()*12;
p.end_size = 0;
p.friction = 0.7f;
p.gravity = frandom()*-500.0f;
p.color = vec4(0.75f,0.75f,0.75f,1.0f);
particle_add(PARTGROUP_GENERAL, &p);
}
void effect_bullettrail(vec2 pos)
{
if(!add_trail)
if(!add_100hz)
return;
particle p;
@ -77,7 +97,7 @@ void effect_bullettrail(vec2 pos)
p.life_span = 0.25f + frandom()*0.25f;
p.start_size = 8.0f;
p.end_size = 0;
p.friction = 0.7;
p.friction = 0.7f;
particle_add(PARTGROUP_PROJECTILE_TRAIL, &p);
}
@ -170,14 +190,26 @@ void effect_explosion(vec2 pos)
void effects_update()
{
static float last_update = 0;
if(client_localtime()-last_update > 0.02f)
static float last_update_100hz = 0;
static float last_update_50hz = 0;
if(client_localtime()-last_update_100hz > 0.01f)
{
add_trail = true;
last_update = client_localtime();
flow_update();
add_100hz = true;
last_update_100hz = client_localtime();
}
else
add_trail = false;
add_100hz = false;
if(client_localtime()-last_update_50hz > 0.02f)
{
add_50hz = true;
last_update_50hz = client_localtime();
}
else
add_50hz = false;
if(add_50hz)
flow_update();
}

View file

@ -107,6 +107,7 @@ void particle_update(float time_passed)
particles[first_free].prev_part = i;
particles[i].prev_part = -1;
particles[i].next_part = first_free;
first_free = i;
}
i = next;

View file

@ -25,15 +25,29 @@ void render_projectile(const NETOBJ_PROJECTILE *current, int itemid)
gfx_quads_begin();
// get positions
float gravity = -400;
if(current->type != WEAPON_GRENADE)
gravity = -100;
float curvature = 0;
float speed = 0;
if(current->type == WEAPON_GRENADE)
{
curvature = tuning.grenade_curvature;
speed = tuning.grenade_speed;
}
else if(current->type == WEAPON_SHOTGUN)
{
curvature = tuning.shotgun_curvature;
speed = tuning.shotgun_speed;
}
else if(current->type == WEAPON_GUN)
{
curvature = tuning.gun_curvature;
speed = tuning.gun_speed;
}
float ct = (client_tick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime()*1/(float)SERVER_TICK_SPEED;
vec2 startpos(current->x, current->y);
vec2 startvel(current->vx, current->vy);
vec2 pos = calc_pos(startpos, startvel, gravity, ct);
vec2 prevpos = calc_pos(startpos, startvel, gravity, ct-0.001f);
vec2 startvel(current->vx/100.0f, current->vy/100.0f);
vec2 pos = calc_pos(startpos, startvel, curvature, speed, ct);
vec2 prevpos = calc_pos(startpos, startvel, curvature, speed, ct-0.001f);
select_sprite(data->weapons[clamp(current->type, 0, NUM_WEAPONS-1)].sprite_proj);
vec2 vel = pos-prevpos;
@ -295,6 +309,7 @@ void render_player(
bool stationary = player.vx < 1 && player.vx > -1;
bool inair = col_check_point(player.x, player.y+16) == 0;
bool want_other_dir = (player.wanted_direction == -1 && vel.x > 0) || (player.wanted_direction == 1 && vel.x < 0);
// evaluate animation
float walk_time = fmod(position.x, 100.0f)/100.0f;
@ -305,7 +320,7 @@ void render_player(
anim_eval_add(&state, &data->animations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
else if(stationary)
anim_eval_add(&state, &data->animations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
else
else if(!want_other_dir)
anim_eval_add(&state, &data->animations[ANIM_WALK], walk_time, 1.0f);
if (player.weapon == WEAPON_HAMMER)
@ -319,6 +334,22 @@ void render_player(
anim_eval_add(&state, &data->animations[ANIM_NINJA_SWING], a, 1.0f);
}
// do skidding
if(!inair && want_other_dir && length(vec2(prev.vx/256.0f, prev.vy/256.0f)*50) > 500.0f)
{
static int64 skid_sound_time = 0;
if(time_get()-skid_sound_time > time_freq()/10)
{
snd_play_random(CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, position);
skid_sound_time = time_get();
}
effect_skidtrail(
position+vec2(-player.wanted_direction*6,12),
vec2(-player.wanted_direction*100*length(vel),-50)
);
}
// draw hook
if (prev.hook_state>0 && player.hook_state>0)
{

View file

@ -154,6 +154,17 @@ void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity)
*inout_vel = vel;
}
float hermite_basis1(float v)
{
return 2*v*v*v - 3*v*v+1;
}
float velocity_ramp(float value, float start, float range, float curvature)
{
if(value < start)
return 1.0f;
return 1.0f/pow(curvature, (value-start)/range);
}
void player_core::reset()
{
@ -405,13 +416,17 @@ void player_core::tick()
}
// clamp the velocity to something sane
if(length(vel) > world->tuning.terminal_velocity)
vel = normalize(vel) * world->tuning.terminal_velocity;
if(length(vel) > 6000)
vel = normalize(vel) * 6000;
}
void player_core::move()
{
float rampvalue = velocity_ramp(length(vel)*50, world->tuning.velramp_start, world->tuning.velramp_range, world->tuning.velramp_curvature);
vel.x = vel.x*rampvalue;
move_box(&pos, &vel, vec2(28.0f, 28.0f), 0);
vel.x = vel.x*(1.0f/rampvalue);
}
void player_core::write(NETOBJ_PLAYER_CORE *obj_core)

View file

@ -53,11 +53,12 @@ inline float get_angle(vec2 dir)
}
inline vec2 calc_pos(vec2 p, vec2 v, float gravity, float t)
inline vec2 calc_pos(vec2 p, vec2 v, float curvature, float speed, float t)
{
vec2 n;
t *= speed;
n.x = p.x + v.x*t;
n.y = p.y + v.y*t - gravity*(t*t);
n.y = p.y + v.y*t + curvature/10000*(t*t);
return n;
}
@ -88,7 +89,7 @@ inline T saturated_add(T min, T max, T current, T modifier)
void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces);
void move_box(vec2 *inout_pos, vec2 *inout_vel, vec2 size, float elasticity);
bool test_box(vec2 pos, vec2 size);
float velocity_ramp(float value, float start, float range, float curvature);
// hooking stuff
enum

View file

@ -151,14 +151,16 @@ end
object player_character extends player_core
range(0, NUM_PLAYERSTATES-1) player_state
range(-1, 1) wanted_direction
range(0, 10) health
range(0, 10) armor
range(0, 10) ammocount
range(0, 10) weaponstage
range(0, NUM_WEAPONS-1) weapon
range(0, NUM_EMOTES-1) emote
range(0, 10) weaponstage
range(0, max_int) attacktick
end

View file

@ -12,15 +12,20 @@ MACRO_TUNING_PARAM(hook_fire_speed, 45.0f)
MACRO_TUNING_PARAM(hook_drag_accel, 3.0f)
MACRO_TUNING_PARAM(hook_drag_speed, 15.0f)
MACRO_TUNING_PARAM(gravity, 0.5f)
MACRO_TUNING_PARAM(terminal_velocity, 1000.0f / ticks_per_second)
MACRO_TUNING_PARAM(velramp_start, 500)
MACRO_TUNING_PARAM(velramp_range, 2000)
MACRO_TUNING_PARAM(velramp_curvature, 1.5f)
/* weapon tuning */
MACRO_TUNING_PARAM(gun_speed, 30.0f)
MACRO_TUNING_PARAM(gun_curvature, 1.5f)
MACRO_TUNING_PARAM(gun_speed, 2200.0f)
MACRO_TUNING_PARAM(shotgun_speed_center, 40.0f)
MACRO_TUNING_PARAM(shotgun_speed_wide, 30.0f)
MACRO_TUNING_PARAM(shotgun_curvature, 1.5f)
MACRO_TUNING_PARAM(shotgun_speed, 2200.0f)
MACRO_TUNING_PARAM(grenade_speed, 15.0f)
MACRO_TUNING_PARAM(grenade_curvature, 7.0f)
MACRO_TUNING_PARAM(grenade_speed, 900.0f)
MACRO_TUNING_PARAM(laser_reach, 800.0f)
MACRO_TUNING_PARAM(laser_bounce_delay, 150)

View file

@ -188,7 +188,7 @@ public:
PROJECTILE_FLAGS_EXPLODE = 1 << 0,
};
vec2 vel;
vec2 direction;
entity *powner; // this is nasty, could be removed when client quits
int lifespan;
int owner;

View file

@ -24,6 +24,7 @@ void create_playerspawn(vec2 p);
void create_death(vec2 p);
void create_sound(vec2 pos, int sound, int mask=-1);
class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0);
class player *closest_player(vec2 pos, float radius, entity *notthis);
game_world *world;
@ -380,13 +381,13 @@ static input_count count_input(int prev, int cur)
//////////////////////////////////////////////////
// projectile
//////////////////////////////////////////////////
projectile::projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity* powner,
projectile::projectile(int type, int owner, vec2 pos, vec2 dir, int span, entity* powner,
int damage, int flags, float force, int sound_impact, int weapon)
: entity(NETOBJTYPE_PROJECTILE)
{
this->type = type;
this->pos = pos;
this->vel = vel * server_tickspeed(); // TODO: remove this
this->direction = normalize(dir);
this->lifespan = span;
this->owner = owner;
this->powner = powner;
@ -407,14 +408,28 @@ void projectile::reset()
void projectile::tick()
{
float gravity = -400;
if(type != WEAPON_GRENADE)
gravity = -100;
float curvature = 0;
float speed = 0;
if(type == WEAPON_GRENADE)
{
curvature = tuning.grenade_curvature;
speed = tuning.grenade_speed;
}
else if(type == WEAPON_SHOTGUN)
{
curvature = tuning.shotgun_curvature;
speed = tuning.shotgun_speed;
}
else if(type == WEAPON_GUN)
{
curvature = tuning.gun_curvature;
speed = tuning.gun_speed;
}
float pt = (server_tick()-start_tick-1)/(float)server_tickspeed();
float ct = (server_tick()-start_tick)/(float)server_tickspeed();
vec2 prevpos = calc_pos(pos, vel, gravity, pt);
vec2 curpos = calc_pos(pos, vel, gravity, ct);
vec2 prevpos = calc_pos(pos, direction, curvature, speed, pt);
vec2 curpos = calc_pos(pos, direction, curvature, speed, ct);
lifespan--;
@ -432,7 +447,7 @@ void projectile::tick()
create_explosion(prevpos, owner, weapon, false);
else if (targetplayer)
{
targetplayer->take_damage(normalize(vel) * max(0.001f, force), damage, owner, weapon);
targetplayer->take_damage(direction * max(0.001f, force), damage, owner, weapon);
}
world->destroy_entity(this);
@ -443,19 +458,21 @@ void projectile::fill_info(NETOBJ_PROJECTILE *proj)
{
proj->x = (int)pos.x;
proj->y = (int)pos.y;
proj->vx = (int)vel.x;
proj->vy = (int)vel.y;
proj->vx = (int)(direction.x*100.0f);
proj->vy = (int)(direction.y*100.0f);
proj->start_tick = start_tick;
proj->type = type;
}
void projectile::snap(int snapping_client)
{
float ct = (server_tick()-start_tick)/(float)server_tickspeed();
vec2 curpos = calc_pos(pos, vel, -7.5f*server_tickspeed(), ct);
/*float ct = (server_tick()-start_tick)/(float)server_tickspeed();*/
/*vec2 curpos = calc_pos(pos, vel, -7.5f*server_tickspeed(), ct);*/
if(distance(players[snapping_client].pos, curpos) > 1000.0f)
return;
/*if(distance(players[snapping_client].pos, curpos) > 1000.0f)
return;*/
/* TODO: FIX ME */
NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE));
fill_info(proj);
@ -989,7 +1006,7 @@ void player::fire_weapon()
projectile *proj = new projectile(WEAPON_GUN,
client_id,
pos+vec2(0,0),
direction*tuning.gun_speed,
direction,
server_tickspeed(),
this,
1, 0, 0, -1, WEAPON_GUN);
@ -1013,7 +1030,7 @@ void player::fire_weapon()
projectile *proj = new projectile(WEAPON_GRENADE,
client_id,
pos+vec2(0,0),
direction*tuning.grenade_speed,
direction,
100,
this,
1, projectile::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
@ -1043,13 +1060,12 @@ void player::fire_weapon()
{
float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
float a = get_angle(direction);
float v = 1.0f-fabs(i/(float)shotspread);
a += spreading[i+2];
float speed = mix((float)tuning.shotgun_speed_wide, (float)tuning.shotgun_speed_center, v);
/*float speed = mix((float)tuning.shotgun_speed_wide, (float)tuning.shotgun_speed_center, v);*/
projectile *proj = new projectile(WEAPON_SHOTGUN,
client_id,
pos+vec2(0,0),
vec2(cosf(a), sinf(a))*speed,
vec2(cosf(a), sinf(a)),
(int)(server_tickspeed()*0.25f),
this,
1, 0, 0, -1, WEAPON_SHOTGUN);
@ -1622,9 +1638,17 @@ void player::snap(int snaping_client)
character->ammocount = weapons[active_weapon].ammo;
character->health = 0;
character->armor = 0;
character->weapon = active_weapon;
character->attacktick = attack_tick;
character->wanted_direction = 0;
if(input.left && !input.right)
character->wanted_direction = -1;
else if(!input.left && input.right)
character->wanted_direction = 1;
if(client_id == snaping_client)
{
character->health = health;
@ -1696,8 +1720,7 @@ void powerup::tick()
return;
}
// Check if a player intersected us
vec2 meh;
player* pplayer = intersect_player(pos, pos + vec2(0,16), meh, 0);
player* pplayer = closest_player(pos, 20.0f, 0);
if (pplayer)
{
// player picked us up, is someone was hooking us, let them go
@ -1957,29 +1980,38 @@ player *intersect_player(vec2 pos0, vec2 pos1, vec2& new_pos, entity *notthis)
}
return closest;
}
/*
entity *ents[64];
vec2 dir = pos1 - pos0;
float radius = length(dir * 0.5f);
vec2 center = pos0 + dir * 0.5f;
const int types[] = {OBJTYPE_PLAYER_CHARACTER};
int num = world->find_entities(center, radius, ents, 64, types, 1);
for (int i = 0; i < num; i++)
player *closest_player(vec2 pos, float radius, entity *notthis)
{
// Find other players
float closest_range = radius*2;
player *closest = 0;
for(int i = 0; i < MAX_CLIENTS; i++)
{
// Check if entity is a player
if (ents[i] != notthis)
if(players[i].client_id < 0 || (entity *)&players[i] == notthis)
continue;
if(!(players[i].flags&entity::FLAG_PHYSICS))
continue;
float len = distance(pos, players[i].pos);
if(len < player::phys_size+radius)
{
new_pos = ents[i]->pos;
return (player*)ents[i];
if(len < closest_range)
{
closest_range = len;
closest = &players[i];
}
}
}
return 0;*/
return closest;
}
// TODO: should be more general
/*
@ -2281,7 +2313,7 @@ static void con_broadcast(void *result, void *user_data)
void mods_console_init()
{
MACRO_REGISTER_COMMAND("tune", "s?i", con_tune_param, 0);
MACRO_REGISTER_COMMAND("tune", "si", con_tune_param, 0);
MACRO_REGISTER_COMMAND("tune_reset", "", con_tune_reset, 0);
MACRO_REGISTER_COMMAND("tune_dump", "", con_tune_dump, 0);