diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-01-29 21:39:41 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-01-29 21:39:41 +0000 |
| commit | 7bc733dc10f3d01985021b7b5d6ae140dd5af6f1 (patch) | |
| tree | c9b0fcd8d128ec9abd40c10dfe4fcf245650a870 | |
| parent | 0dab7db963e2706182ea120c98f746f5e265c14c (diff) | |
| download | zcatch-7bc733dc10f3d01985021b7b5d6ae140dd5af6f1.tar.gz zcatch-7bc733dc10f3d01985021b7b5d6ae140dd5af6f1.zip | |
large update. cleaned up some code. added new effects for almost everything
27 files changed, 715 insertions, 552 deletions
diff --git a/data/particles.png b/data/particles.png new file mode 100644 index 00000000..94d0d166 --- /dev/null +++ b/data/particles.png Binary files differdiff --git a/datasrc/client.dts b/datasrc/client.dts index eec61fa4..edded536 100644 --- a/datasrc/client.dts +++ b/datasrc/client.dts @@ -27,25 +27,10 @@ struct soundset { array:sound sounds = * } -struct particleinfo { - ptr:sprite spr = sprite@1 - float color_r = color@1 - float color_g = color@2 - float color_b = color@3 - float color_a = color@4 - int lifemod = life@1 -} - struct spriteptr { ptr:sprite psprite = @0 } -struct projectileparticles { - int particlespersecond = particlespersecond@1 - float particlesize = particlesize@1 - float particlelife = particlelife@1 -} - struct weapon { ptr:sprite sprite_body = sprite_body@1 ptr:sprite sprite_cursor = sprite_cursor@1 @@ -85,12 +70,9 @@ struct data_container { array:spriteset spritesets = sprites.* array:sprite sprites = sprites.*.* array:weapon weapons = weapons.* - array:particleinfo particles = particles.* - array:projectileparticles projectileinfo = projectileparticles.* array:soundset sounds = sounds.* array:animation animations = animations.* - } const array:int weapon = weapons.* diff --git a/datasrc/teewars.ds b/datasrc/teewars.ds index 1265dde0..d9e250a9 100644 --- a/datasrc/teewars.ds +++ b/datasrc/teewars.ds @@ -223,6 +223,10 @@ images { filename "data/game.png" } + particles { + filename "data/particles.png" + } + cursor { filename "data/gui_cursor.png" } @@ -240,62 +244,6 @@ images { } } -particles { - part1 { - sprite sprites.game.part1 - color 0.7 0.7 0.7 1.0 - life 50 - } - - part2 { - sprite sprites.game.part2 - color 1.0 1.0 1.0 1.0 - life 50 - } - - part3 { - sprite sprites.game.part3 - color 0.8 0.8 0.8 1.0 - life 50 - } - - part4 { - sprite sprites.game.part4 - color 0.98 0.1 0.16 1.0 - life 70 - } - - part5 { - sprite sprites.game.part5 - color 1.0 1.0 1.0 1.0 - life 70 - } - - part6 { - sprite sprites.game.part6 - color 0.6 0.6 0.6 1.0 - life 100 - } - - part7 { - sprite sprites.game.part7 - color 1.0 1.0 1.0 1.0 - life 100 - } - - part8 { - sprite sprites.game.part8 - color 0.7 0.7 0.7 1.0 - life 150 - } - - part9 { - sprite sprites.game.part9 - color 1.0 1.0 1.0 1.0 - life 40 - } -} - powerups { health { amount 1 @@ -319,44 +267,6 @@ powerups { } } -projectileparticles { - gun { - particlespersecond 200 - particlesize 16.0 - particlelife 0.5 - } - rocket { - particlespersecond 100 - particlesize 22.0 - particlelife 1.3 - } - shotgun { - particlespersecond 100 - particlesize 16.0 - particlelife 0.8 - } - empty1 { - particlespersecond 300 - particlesize 8.0 - particlelife 0.8 - } - empty2 { - particlespersecond 300 - particlesize 8.0 - particlelife 0.8 - } - empty3 { - particlespersecond 300 - particlesize 8.0 - particlelife 0.8 - } - sniper { - particlespersecond 300 - particlesize 8.0 - particlelife 0.8 - } -} - weapons { hammer { sprite_body sprites.game.weapon_hammer_body @@ -507,37 +417,6 @@ weapons { overchargetime 10.0 } - bomb { - sprite_body sprites.game.weapon_rocket_body - sprite_cursor sprites.game.weapon_rocket_cursor - sprite_proj sprites.game.weapon_rocket_proj - sprite_muzzles { - sprites.game.weapon_shotgun_muzzle1 - sprites.game.weapon_shotgun_muzzle2 - sprites.game.weapon_shotgun_muzzle3 - } - - nummuzzlesprites 3 - muzzleoffsetx 0.0 - muzzleoffsety 0.0 - maxammo 10 - costammo 1 - recoil 10 - firedelay 800 - muzzleduration 0 - visual_size 128 - offsetx 24.0 - offsety -2.0 - meleedamage 0 - meleereach 0 - ammoregentime 0 - duration -1 - movetime 0 - velocity 0 - chargetime 1.0 - overchargetime 10.0 - } - ninja { sprite_body sprites.game.weapon_ninja_body sprite_cursor sprites.game.weapon_ninja_cursor @@ -572,6 +451,20 @@ weapons { } sprites { + + particles images.particles 8 8 { + part_slice 0 0 1 1 + part_ball 1 0 1 1 + part_splat01 2 0 1 1 + part_splat02 3 0 1 1 + part_splat03 4 0 1 1 + + part_smoke 0 1 1 1 + part_shell 0 2 2 2 + part_expl01 0 4 4 4 + part_airjump 2 2 2 2 + } + game images.game 32 16 { health_full 21 0 2 2 diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c index 101b0279..1e4378d2 100644 --- a/src/engine/client/ec_gfx.c +++ b/src/engine/client/ec_gfx.c @@ -163,7 +163,7 @@ int gfx_init() /* open window */ if(config.gfx_fullscreen) { - int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 24, 0, GLFW_FULLSCREEN); + int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 8, 24, 8, GLFW_FULLSCREEN); if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); @@ -172,19 +172,22 @@ int gfx_init() } else { - int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 24, 0, GLFW_WINDOW); + int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW); if(result != GL_TRUE) { dbg_msg("game", "failed to create gl context"); return 0; } } - glfwSetWindowSizeCallback(screen_resize); + glGetIntegerv(GL_ALPHA_BITS, &i); + dbg_msg("gfx", "alphabits = %d", i); glGetIntegerv(GL_DEPTH_BITS, &i); dbg_msg("gfx", "depthbits = %d", i); + glGetIntegerv(GL_STENCIL_BITS, &i); + dbg_msg("gfx", "stencilbits = %d", i); glfwSetWindowTitle("Teewars"); @@ -212,6 +215,10 @@ int gfx_init() glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); +/* glAlphaFunc(GL_GREATER, 0); + glEnable(GL_ALPHA_TEST);*/ + + gfx_mask_op(MASK_NONE, 0); /* Set all z to -5.0f */ @@ -325,6 +332,8 @@ void gfx_set_vsync(int val) int gfx_unload_texture(int index) { + if(index < 0) + return 0; glDeleteTextures(1, &textures[index].tex); textures[index].next = first_free_texture; memory_usage -= textures[index].memsize; diff --git a/src/engine/e_system.h b/src/engine/e_system.h index 4802111f..72a4ff7b 100644 --- a/src/engine/e_system.h +++ b/src/engine/e_system.h @@ -524,6 +524,9 @@ void mem_debug_dump(); int mem_allocated(); void swap_endian(void *data, unsigned elem_size, unsigned num); + +/* #define cache_prefetch(addr) __builtin_prefetch(addr) */ + #ifdef __cplusplus } #endif diff --git a/src/game/client/gc_client.cpp b/src/game/client/gc_client.cpp index 8df0e698..4cc8ba29 100644 --- a/src/game/client/gc_client.cpp +++ b/src/game/client/gc_client.cpp @@ -13,6 +13,7 @@ extern "C" { #include "../g_game.h" #include "../g_version.h" #include "../g_layers.h" +#include "../g_math.h" #include "gc_map_image.h" #include "../generated/gc_data.h" #include "gc_menu.h" @@ -23,6 +24,8 @@ extern "C" { #include "gc_anim.h" #include "gc_console.h" +#include <GL/gl.h> + struct data_container *data = 0; static int64 debug_firedelay = 0; @@ -87,6 +90,15 @@ void snd_play_random(int chn, int setid, float vol, vec2 pos) set->last = id; } + +void send_switch_team(int team) +{ + msg_pack_start(MSG_SETTEAM, MSGFLAG_VITAL); + msg_pack_int(team); + msg_pack_end(); + client_send_msg(); +} + class damage_indicators { public: @@ -179,159 +191,6 @@ void render_damage_indicators() dmgind.render(); } -class particle_system -{ -public: - struct particle - { - vec2 pos; - vec2 vel; - float life; - float max_life; - float size; - - float rot; - float rotspeed; - - float gravity; - float friction; - int iparticle; - - vec4 color; - }; - - enum - { - MAX_PARTICLES=1024, - }; - - particle particles[MAX_PARTICLES]; - int num_particles; - - particle_system() - { - num_particles = 0; - } - - void new_particle(vec2 pos, vec2 vel, float life, float size, float gravity, float friction, vec4 color=vec4(1,1,1,1)) - { - if (num_particles >= MAX_PARTICLES) - return; - - particles[num_particles].iparticle = rand() % data->num_particles; - particles[num_particles].pos = pos; - particles[num_particles].vel = vel; - particles[num_particles].life = life - (data->particles[particles[num_particles].iparticle].lifemod/100.0f) * life; - particles[num_particles].size = size; - particles[num_particles].max_life = life; - particles[num_particles].gravity = gravity; - particles[num_particles].friction = friction; - particles[num_particles].rot = frandom()*pi*2; - particles[num_particles].rotspeed = frandom() * 10.0f; - particles[num_particles].color = color; - num_particles++; - } - - void update(float time_passed) - { - for(int i = 0; i < num_particles; i++) - { - particles[i].vel.y += particles[i].gravity*time_passed; - particles[i].vel *= particles[i].friction; - vec2 vel = particles[i].vel*time_passed; - move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom(), NULL); - particles[i].vel = vel* (1.0f/time_passed); - particles[i].life += time_passed; - particles[i].rot += time_passed * particles[i].rotspeed; - - // check particle death - if(particles[i].life > particles[i].max_life) - { - num_particles--; - particles[i] = particles[num_particles]; - i--; - } - } - } - - void render() - { - gfx_blend_additive(); - gfx_texture_set(data->images[IMAGE_GAME].id); - gfx_quads_begin(); - - for(int i = 0; i < num_particles; i++) - { - int type = particles[i].iparticle; - select_sprite(data->particles[type].spr); - float a = 1 - particles[i].life / particles[i].max_life; - vec2 p = particles[i].pos; - - gfx_quads_setrotation(particles[i].rot); - - gfx_setcolor( - data->particles[type].color_r * particles[i].color.r, - data->particles[type].color_g * particles[i].color.g, - data->particles[type].color_b * particles[i].color.b, - pow(a, 0.75f) * particles[i].color.a); - - gfx_quads_draw(p.x, p.y,particles[i].size,particles[i].size); - } - gfx_quads_end(); - gfx_blend_normal(); - } -}; - -static particle_system temp_system; - -class projectile_particles -{ -public: - enum - { - LISTSIZE = 1000, - }; - // meh, just use size % - int lastadd[LISTSIZE]; - projectile_particles() - { - reset(); - } - - void reset() - { - for (int i = 0; i < LISTSIZE; i++) - lastadd[i] = -1000; - } - - void addparticle(int projectiletype, int projectileid, vec2 pos, vec2 vel) - { - int particlespersecond = data->projectileinfo[projectiletype].particlespersecond; - int lastaddtick = lastadd[projectileid % LISTSIZE]; - - if(!particlespersecond) - return; - - if ((client_tick() - lastaddtick) > (client_tickspeed() / particlespersecond)) - { - lastadd[projectileid % LISTSIZE] = client_tick(); - float life = data->projectileinfo[projectiletype].particlelife; - float size = data->projectileinfo[projectiletype].particlesize; - vec2 v = vel * 0.2f + normalize(vec2(frandom()-0.5f, -frandom()))*(32.0f+frandom()*32.0f); - - // add the particle (from projectiletype later on, but meh...) - temp_system.new_particle(pos, v, life, size, 0, 0.95f); - } - } -}; - -static projectile_particles proj_particles; - -void reset_projectile_particles() // TODO: remove -{ - proj_particles.reset(); -} - static char chat_input[512]; static unsigned chat_input_len; static const int chat_max_lines = 10; @@ -391,16 +250,7 @@ void chat_add_line(int client_id, int team, const char *line) killmsg killmsgs[killmsg_max]; int killmsg_current = 0; -void effect_air_jump(vec2 pos) -{ - const int count = 12; - for(int i = 0; i <= count; i++) - { - float a = i/(float)count; - vec2 v = vec2((a-0.5f)*512.0f, 0); - temp_system.new_particle(pos+vec2(0,28), v, 0.4f, 16.0f, 0, 0.985f, vec4(0.25f,0.4f,1,1)); - } -} +//bool add_trail = false; extern int render_popup(const char *caption, const char *text, const char *button_text); @@ -425,107 +275,22 @@ void process_events(int snaptype) else if(item.type == EVENT_EXPLOSION) { ev_explosion *ev = (ev_explosion *)data; - vec2 p(ev->x, ev->y); - - // center explosion - temp_system.new_particle(p, vec2(0,0), 0.3f, 96.0f, 0, 0.95f); - temp_system.new_particle(p, vec2(0,0), 0.3f, 64.0f, 0, 0.95f); - temp_system.new_particle(p, vec2(0,0), 0.3f, 32.0f, 0, 0.95f); - temp_system.new_particle(p, vec2(0,0), 0.3f, 16.0f, 0, 0.95f); - - for(int i = 0; i < 16; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 0.2f+0.25f*frandom(), 16.0f, 0, 0.985f); - } - - for(int i = 0; i < 16; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(256.0f+frandom()*512.0f); - temp_system.new_particle(p, v, 0.2f+0.25f*frandom(), 16.0f, 128.0f, 0.985f); - } - - for(int i = 0; i < 64; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(frandom()*256.0f); - temp_system.new_particle(p, v, 0.2f+0.25f*frandom(), 24.0f, 128.0f, 0.985f); - } + effect_explosion(vec2(ev->x, ev->y)); } else if(item.type == EVENT_SMOKE) { ev_explosion *ev = (ev_explosion *)data; vec2 p(ev->x, ev->y); - - // center explosion - vec2 v = normalize(vec2(frandom()-0.5f, -frandom()))*(32.0f+frandom()*32.0f); - temp_system.new_particle(p, v, 1.2f, 64.0f, 0, 0.95f); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 32.0f, 0, 0.95f); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 16.0f, 0, 0.95f); - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(64.0f+frandom()*64.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 0, 0.985f); - } - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(128.0f+frandom()*256.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f); - } } - else if(item.type == EVENT_SPAWN) + else if(item.type == EVENT_PLAYERSPAWN) { ev_explosion *ev = (ev_explosion *)data; - vec2 p(ev->x, ev->y); - - // center explosion - vec2 v = normalize(vec2(frandom()-0.5f, -frandom()))*(32.0f+frandom()*32.0f); - temp_system.new_particle(p, v, 1.2f, 64.0f, 0, 0.95f); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 32.0f, 0, 0.95f); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 16.0f, 0, 0.95f); - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(64.0f+frandom()*64.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 0, 0.985f); - } - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(128.0f+frandom()*256.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f); - } + effect_playerspawn(vec2(ev->x, ev->y)); } else if(item.type == EVENT_DEATH) { ev_explosion *ev = (ev_explosion *)data; - vec2 p(ev->x, ev->y); - vec4 c(0.5f, 0.1f, 0.1f, 1.0f); - - // center explosion - vec2 v = normalize(vec2(frandom()-0.5f, -frandom()))*(32.0f+frandom()*32.0f); - temp_system.new_particle(p, v, 1.2f, 64.0f, 0, 0.95f, c); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 32.0f, 0, 0.95f, c); - v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f); - temp_system.new_particle(p, v, 1.2f, 16.0f, 0, 0.95f, c); - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(64.0f+frandom()*64.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 0, 0.985f, c); - } - - for(int i = 0; i < 8; i++) - { - vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(128.0f+frandom()*256.0f); - temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f, c); - } + effect_playerdeath(vec2(ev->x, ev->y)); } else if(item.type == EVENT_SOUND_WORLD) { @@ -964,6 +729,11 @@ static int do_input(int *v, int key) void render_game() { + // update the effects + effects_update(); + particle_update(client_frametime()); + + float width = 400*3.0f*gfx_screenaspect(); float height = 400*3.0f; @@ -1195,12 +965,16 @@ void render_game() } // render the world + float zoom = 1.0f; + if(inp_key_pressed('E')) + zoom = 0.5f; + gfx_clear(0.65f,0.78f,0.9f); if(spectate) - render_world(mouse_pos.x, mouse_pos.y, 1.0f); + render_world(mouse_pos.x, mouse_pos.y, zoom); else { - render_world(local_character_pos.x+offx, local_character_pos.y+offy, 1.0f); + render_world(local_character_pos.x+offx, local_character_pos.y+offy, zoom); // draw screen box if(0) @@ -1683,7 +1457,7 @@ void render_game() vec2(local_character->x, local_character->y)); char buf[512]; - sprintf(buf, "%.2f", speed); + sprintf(buf, "%.2f", speed/2); gfx_text(0, 150, 50, 12, buf, -1); } diff --git a/src/game/client/gc_client.h b/src/game/client/gc_client.h index f1ff02b1..def3cad8 100644 --- a/src/game/client/gc_client.h +++ b/src/game/client/gc_client.h @@ -83,12 +83,89 @@ const int killmsg_max = 5; extern killmsg killmsgs[killmsg_max]; extern int killmsg_current; +// +void send_switch_team(int team); + // various helpers void snd_play_random(int chn, int setid, float vol, vec2 pos); void process_events(int snaptype); void clear_object_pointers(); void reset_projectile_particles(); void send_info(bool start); +inline vec2 random_dir() { return normalize(vec2(frandom()-0.5f, frandom()-0.5f)); } + + +// effects +void effects_update(); +void effect_bullettrail(vec2 pos); +void effect_smoketrail(vec2 pos, vec2 vel); +void effect_explosion(vec2 pos); void effect_air_jump(vec2 pos); void effect_damage_indicator(vec2 pos, vec2 dir); +void effect_playerspawn(vec2 pos); +void effect_playerdeath(vec2 pos); + +// particles +struct particle +{ + void set_default() + { + vel = vec2(0,0); + life_span = 0; + start_size = 32; + end_size = 32; + rot = 0; + rotspeed = 0; + gravity = 0; + friction = 0; + flow_affected = 1.0f; + color = vec4(1,1,1,1); + } + + vec2 pos; + vec2 vel; + + int spr; + + float flow_affected; + + float life_span; + + float start_size; + float end_size; + + float rot; + float rotspeed; + + float gravity; + float friction; + + vec4 color; + + // set by the particle system + float life; + int prev_part; + int next_part; +}; + +enum +{ + PARTGROUP_PROJECTILE_TRAIL=0, + PARTGROUP_EXPLOSIONS, + PARTGROUP_GENERAL, + NUM_PARTGROUPS +}; + +void particle_add(int group, particle *part); +void particle_render(int group); +void particle_update(float time_passed); +void particle_reset(); + +// flow grid +vec2 flow_get(vec2 pos); +void flow_add(vec2 pos, vec2 vel, float size); +void flow_dbg_render(); +void flow_init(); +void flow_update(); + diff --git a/src/game/client/gc_console.cpp b/src/game/client/gc_console.cpp index 9cf417e2..0a4bb3d6 100644 --- a/src/game/client/gc_console.cpp +++ b/src/game/client/gc_console.cpp @@ -12,6 +12,7 @@ extern "C" { #include <cstdio> #include "gc_ui.h" +#include "gc_client.h" static unsigned int console_input_len = 0; static char console_input[256] = {0}; @@ -57,12 +58,20 @@ static void quit_command(struct lexer_result *result, void *user_data) client_quit(); } +static void con_team(struct lexer_result *result, void *user_data) +{ + int new_team; + extract_result_int(result, 1, &new_team); + send_switch_team(new_team); +} + void client_console_init() { console_register_print_callback(client_console_print); MACRO_REGISTER_COMMAND("quit", "", quit_command, 0x0); MACRO_REGISTER_COMMAND("connect", "s", connect_command, 0x0); MACRO_REGISTER_COMMAND("disconnect", "", disconnect_command, 0x0); + MACRO_REGISTER_COMMAND("team", "i", con_team, 0x0); } void console_handle_input() diff --git a/src/game/client/gc_effects.cpp b/src/game/client/gc_effects.cpp new file mode 100644 index 00000000..6394075e --- /dev/null +++ b/src/game/client/gc_effects.cpp @@ -0,0 +1,162 @@ +#include <engine/e_client_interface.h> +#include "gc_client.h" +#include "../generated/gc_data.h" + +static bool add_trail = false; + +void effect_air_jump(vec2 pos) +{ + particle p; + p.set_default(); + p.spr = SPRITE_PART_AIRJUMP; + p.pos = pos + vec2(-6.0f, 16.0f); + p.vel = vec2(0, -200); + p.life_span = 0.5f; + p.start_size = 48.0f; + p.end_size = 0; + p.rot = frandom()*pi*2; + p.rotspeed = pi*2; + p.gravity = 500; + p.friction = 0.7f; + p.flow_affected = 0.0f; + particle_add(PARTGROUP_GENERAL, &p); + + p.pos = pos + vec2(6.0f, 16.0f); + particle_add(PARTGROUP_GENERAL, &p); +} + +void effect_smoketrail(vec2 pos, vec2 vel) +{ + if(!add_trail) + 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 = 12.0f + frandom()*8; + p.end_size = 0; + p.friction = 0.7; + p.gravity = frandom()*-500.0f; + particle_add(PARTGROUP_PROJECTILE_TRAIL, &p); +} + + +void effect_bullettrail(vec2 pos) +{ + if(!add_trail) + return; + + particle p; + p.set_default(); + p.spr = SPRITE_PART_BALL; + p.pos = pos; + p.life_span = 0.25f + frandom()*0.25f; + p.start_size = 8.0f; + p.end_size = 0; + p.friction = 0.7; + particle_add(PARTGROUP_PROJECTILE_TRAIL, &p); +} + +void effect_playerspawn(vec2 pos) +{ + for(int i = 0; i < 32; i++) + { + particle p; + p.set_default(); + p.spr = SPRITE_PART_SHELL; + p.pos = pos; + p.vel = random_dir() * (pow(frandom(), 3)*600.0f); + p.life_span = 0.3f + frandom()*0.3f; + p.start_size = 64.0f + frandom()*32; + p.end_size = 0; + p.rot = frandom()*pi*2; + p.rotspeed = frandom(); + p.gravity = frandom()*-400.0f; + p.friction = 0.7f; + p.color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f); + particle_add(PARTGROUP_GENERAL, &p); + + } +} + +void effect_playerdeath(vec2 pos) +{ + for(int i = 0; i < 64; i++) + { + particle p; + p.set_default(); + p.spr = SPRITE_PART_SPLAT01 + (rand()%3); + p.pos = pos; + p.vel = random_dir() * ((frandom()+0.1f)*900.0f); + p.life_span = 0.3f + frandom()*0.3f; + p.start_size = 24.0f + frandom()*16; + p.end_size = 0; + p.rot = frandom()*pi*2; + p.rotspeed = (frandom()-0.5f) * pi; + p.gravity = 800.0f; + p.friction = 0.8f; + p.color = mix(vec4(0.75f,0.2f,0.2f,0.75f), vec4(0.5f,0.1f,0.1f,0.75f), frandom()); + particle_add(PARTGROUP_GENERAL, &p); + + } +} + + +void effect_explosion(vec2 pos) +{ + // add to flow + for(int y = -8; y <= 8; y++) + for(int x = -8; x <= 8; x++) + { + if(x == 0 && y == 0) + continue; + + float a = 1 - (length(vec2(x,y)) / length(vec2(8,8))); + flow_add(pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f); + } + + // add the explosion + particle p; + p.set_default(); + p.spr = SPRITE_PART_EXPL01; + p.pos = pos; + p.life_span = 0.4f; + p.start_size = 150.0f; + p.end_size = 0; + p.rot = frandom()*pi*2; + particle_add(PARTGROUP_EXPLOSIONS, &p); + + // add the smoke + for(int i = 0; i < 24; i++) + { + particle p; + p.set_default(); + p.spr = SPRITE_PART_SMOKE; + p.pos = pos; + p.vel = random_dir() * ((1.0f + frandom()*0.2f) * 1000.0f); + p.life_span = 0.5f + frandom()*0.4f; + p.start_size = 32.0f + frandom()*8; + p.end_size = 0; + p.gravity = frandom()*-800.0f; + p.friction = 0.4f; + p.color = mix(vec4(0.75f,0.75f,0.75f,1.0f), vec4(0.5f,0.5f,0.5f,1.0f), frandom()); + particle_add(PARTGROUP_GENERAL, &p); + } +} + +void effects_update() +{ + static float last_update = 0; + if(client_localtime()-last_update > 0.02f) + { + add_trail = true; + last_update = client_localtime(); + flow_update(); + } + else + add_trail = false; + +} diff --git a/src/game/client/gc_flow.cpp b/src/game/client/gc_flow.cpp new file mode 100644 index 00000000..aac35058 --- /dev/null +++ b/src/game/client/gc_flow.cpp @@ -0,0 +1,87 @@ +#include <engine/e_client_interface.h> +#include <engine/e_config.h> +#include "gc_client.h" +#include "../g_layers.h" + +struct FLOWCELL +{ + vec2 vel; +}; + +static FLOWCELL *cells = 0; +static int height = 0; +static int width = 0; +static int spacing = 16; + +void flow_init() +{ + if(cells) + { + mem_free(cells); + cells = 0; + } + + MAPITEM_LAYER_TILEMAP *tilemap = layers_game_layer(); + width = tilemap->width*32/spacing; + height = tilemap->height*32/spacing; + + // allocate and clear + cells = (FLOWCELL *)mem_alloc(sizeof(FLOWCELL)*width*height, 1); + for(int y = 0; y < height; y++) + for(int x = 0; x < width; x++) + cells[y*width+x].vel = vec2(0.0f, 0.0f); +} + +void flow_update() +{ + if(!config.cl_flow) + return; + + for(int y = 0; y < height; y++) + for(int x = 0; x < width; x++) + cells[y*width+x].vel *= 0.85f; +} + +void flow_dbg_render() +{ + if(!config.cl_flow) + return; + + gfx_texture_set(-1); + gfx_lines_begin(); + for(int y = 0; y < height; y++) + for(int x = 0; x < width; x++) + { + vec2 pos(x*spacing, y*spacing); + vec2 vel = cells[y*width+x].vel * 0.01f; + gfx_lines_draw(pos.x, pos.y, pos.x+vel.x, pos.y+vel.y); + } + + gfx_lines_end(); +} + +void flow_add(vec2 pos, vec2 vel, float size) +{ + if(!config.cl_flow) + return; + + int x = (int)(pos.x / spacing); + int y = (int)(pos.y / spacing); + if(x < 0 || y < 0 || x >= width || y >= height) + return; + + cells[y*width+x].vel += vel; +} + +vec2 flow_get(vec2 pos) +{ + if(!config.cl_flow) + return vec2(0,0); + + int x = (int)(pos.x / spacing); + int y = (int)(pos.y / spacing); + if(x < 0 || y < 0 || x >= width || y >= height) + return vec2(0,0); + + return cells[y*width+x].vel; +} diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp index ca425059..c16923b8 100644 --- a/src/game/client/gc_hooks.cpp +++ b/src/game/client/gc_hooks.cpp @@ -40,6 +40,7 @@ extern "C" void modc_init() gfx_text_set_default_font(&default_font); + particle_reset(); menu_init(); // setup sound channels @@ -300,13 +301,11 @@ extern "C" void modc_render() // handle team switching // TODO: FUGLY!!! + /* if(config.cl_team != -10) { - msg_pack_start(MSG_SETTEAM, MSGFLAG_VITAL); - msg_pack_int(config.cl_team); - msg_pack_end(); - client_send_msg(); - } + + }*/ } else // if (client_state() != CLIENTSTATE_CONNECTING && client_state() != CLIENTSTATE_LOADING) { @@ -317,7 +316,7 @@ extern "C" void modc_render() } // - config.cl_team = -10; + //config.cl_team = -10; } @@ -492,11 +491,12 @@ extern "C" void modc_connected() layers_init(); col_init(); img_init(); + flow_init(); //tilemap_init(); chat_reset(); - reset_projectile_particles(); + particle_reset(); clear_object_pointers(); last_new_predicted_tick = -1; diff --git a/src/game/client/gc_menu.cpp b/src/game/client/gc_menu.cpp index 9b72d4b5..6b982c37 100644 --- a/src/game/client/gc_menu.cpp +++ b/src/game/client/gc_menu.cpp @@ -22,6 +22,7 @@ extern "C" { #include "gc_anim.h" #include "gc_skin.h" #include "gc_ui.h" +#include "gc_client.h" #include <mastersrv/mastersrv.h> extern data_container *data; @@ -1623,7 +1624,7 @@ static void menu2_render_game(RECT main_view) static int spectate_button = 0; if(ui_do_button(&spectate_button, "Spectate", 0, &button, ui_draw_menu_button, 0)) { - config.cl_team = -1; + send_switch_team(-1); menu_active = false; } } @@ -1637,7 +1638,7 @@ static void menu2_render_game(RECT main_view) static int spectate_button = 0; if(ui_do_button(&spectate_button, "Join Game", 0, &button, ui_draw_menu_button, 0)) { - config.cl_team = 0; + send_switch_team(0); menu_active = false; } } @@ -1651,7 +1652,7 @@ static void menu2_render_game(RECT main_view) static int spectate_button = 0; if(ui_do_button(&spectate_button, "Join Red", 0, &button, ui_draw_menu_button, 0)) { - config.cl_team = 0; + send_switch_team(0); menu_active = false; } } @@ -1663,7 +1664,7 @@ static void menu2_render_game(RECT main_view) static int spectate_button = 0; if(ui_do_button(&spectate_button, "Join Blue", 0, &button, ui_draw_menu_button, 0)) { - config.cl_team = 1; + send_switch_team(1); menu_active = false; } } diff --git a/src/game/client/gc_particles.cpp b/src/game/client/gc_particles.cpp new file mode 100644 index 00000000..bdeb26fd --- /dev/null +++ b/src/game/client/gc_particles.cpp @@ -0,0 +1,146 @@ +#include <engine/e_client_interface.h> +#include "gc_client.h" +#include "../generated/gc_data.h" + +// NOTE: the way the particle system works isn't very cache friendly + +enum +{ + MAX_PARTICLES=1024*8, +}; + +static particle particles[MAX_PARTICLES]; +static int first_free = -1; +static int first_part[NUM_PARTGROUPS] = {-1}; + +void particle_reset() +{ + // reset particles + for(int i = 0; i < MAX_PARTICLES; i++) + { + particles[i].prev_part = i-1; + particles[i].next_part = i+1; + } + + particles[0].prev_part = 0; + particles[MAX_PARTICLES-1].next_part = -1; + first_free = 0; + + for(int i = 0; i < NUM_PARTGROUPS; i++) + first_part[i] = -1; +} + + +void particle_add(int group, particle *part) +{ + if (first_free == -1) + return; + + // remove from the free list + int id = first_free; + first_free = particles[id].next_part; + particles[first_free].prev_part = -1; + + // copy data + particles[id] = *part; + + // insert to the group list + particles[id].prev_part = -1; + particles[id].next_part = first_part[group]; + if(first_part[group] != -1) + particles[first_part[group]].prev_part = id; + first_part[group] = id; + + // set some parameters + particles[id].life = 0; +} + +void particle_update(float time_passed) +{ + static float friction_fraction = 0; + friction_fraction += time_passed; + + if(friction_fraction > 2.0f) // safty messure + friction_fraction = 0; + + int friction_count = 0; + while(friction_fraction > 0.05f) + { + friction_count++; + friction_fraction -= 0.05f; + } + + for(int g = 0; g < NUM_PARTGROUPS; g++) + { + int i = first_part[g]; + while(i != -1) + { + int next = particles[i].next_part; + particles[i].vel += flow_get(particles[i].pos)*time_passed * particles[i].flow_affected; + particles[i].vel.y += particles[i].gravity*time_passed; + + for(int f = 0; f < friction_count; f++) // apply friction + particles[i].vel *= particles[i].friction; + + // move the point + vec2 vel = particles[i].vel*time_passed; + move_point(&particles[i].pos, &vel, 0.1f+0.9f*frandom(), NULL); + particles[i].vel = vel* (1.0f/time_passed); + + particles[i].life += time_passed; + particles[i].rot += time_passed * particles[i].rotspeed; + + // check particle death + if(particles[i].life > particles[i].life_span) + { + // remove it from the group list + if(particles[i].prev_part != -1) + particles[particles[i].prev_part].next_part = particles[i].next_part; + else + first_part[g] = particles[i].next_part; + + if(particles[i].next_part != -1) + particles[particles[i].next_part].prev_part = particles[i].prev_part; + + // insert to the free list + if(first_free != -1) + particles[first_free].prev_part = i; + particles[i].prev_part = -1; + particles[i].next_part = first_free; + } + + i = next; + } + } +} + +void particle_render(int group) +{ + gfx_blend_normal(); + //gfx_blend_additive(); + gfx_texture_set(data->images[IMAGE_PARTICLES].id); + gfx_quads_begin(); + + int i = first_part[group]; + while(i != -1) + { + select_sprite(particles[i].spr); + float a = particles[i].life / particles[i].life_span; + vec2 p = particles[i].pos; + float size = mix(particles[i].start_size, particles[i].end_size, a); + + gfx_quads_setrotation(particles[i].rot); + + gfx_setcolor( + particles[i].color.r, + particles[i].color.g, + particles[i].color.b, + particles[i].color.a); // pow(a, 0.75f) * + + gfx_quads_draw(p.x, p.y, size, size); + + i = particles[i].next_part; + } + gfx_quads_end(); + gfx_blend_normal(); +} diff --git a/src/game/client/gc_render.cpp b/src/game/client/gc_render.cpp index 91ae5662..6297fc9c 100644 --- a/src/game/client/gc_render.cpp +++ b/src/game/client/gc_render.cpp @@ -197,7 +197,7 @@ void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec // draw feet gfx_setcolor(info->color_feet.r, info->color_feet.g, info->color_feet.b, info->color_feet.a); - select_sprite(outline?SPRITE_TEE_FOOT_OUTLINE:SPRITE_TEE_FOOT, 0, 0, 0); + select_sprite((outline||!info->got_airjump)?SPRITE_TEE_FOOT_OUTLINE:SPRITE_TEE_FOOT, 0, 0, 0); keyframe *foot = f ? &anim->front_foot : &anim->back_foot; @@ -278,7 +278,7 @@ void render_layers(float center_x, float center_y, int pass) bool render = false; bool is_game_layer = false; - if(layer == (MAPITEM_LAYER*)layers_game()) + if(layer == (MAPITEM_LAYER*)layers_game_layer()) { is_game_layer = true; passed_gamelayer = 1; @@ -306,7 +306,7 @@ void render_layers(float center_x, float center_y, int pass) else gfx_texture_set(img_get(tmap->image)); TILE *tiles = (TILE *)map_get_data(tmap->data); - render_tilemap(tiles, tmap->width, tmap->height, 32.0f, 1); + render_tilemap(tiles, tmap->width, tmap->height, 32.0f, vec4(1,1,1,1), 1); } else if(layer->type == LAYERTYPE_QUADS) { @@ -323,71 +323,82 @@ void render_layers(float center_x, float center_y, int pass) } } -// renders the complete game world -void render_world(float center_x, float center_y, float zoom) +static void render_items() { - // render background layers - render_layers(center_x, center_y, 0); - - // render items + int num = snap_num_items(SNAP_CURRENT); + for(int i = 0; i < num; i++) { - int num = snap_num_items(SNAP_CURRENT); - for(int i = 0; i < num; i++) - { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + SNAP_ITEM item; + const void *data = snap_get_item(SNAP_CURRENT, i, &item); - if(item.type == OBJTYPE_PROJECTILE) - { - //const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - //if(prev) - render_projectile((const obj_projectile *)data, item.id); - } - else if(item.type == OBJTYPE_POWERUP) - { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if(prev) - render_powerup((const obj_powerup *)prev, (const obj_powerup *)data); - } - else if(item.type == OBJTYPE_FLAG) - { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - if (prev) - render_flag((const obj_flag *)prev, (const obj_flag *)data); - } + if(item.type == OBJTYPE_PROJECTILE) + { + render_projectile((const obj_projectile *)data, item.id); + } + else if(item.type == OBJTYPE_POWERUP) + { + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if(prev) + render_powerup((const obj_powerup *)prev, (const obj_powerup *)data); + } + else if(item.type == OBJTYPE_FLAG) + { + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + if (prev) + render_flag((const obj_flag *)prev, (const obj_flag *)data); } } +} - // render players above all + +static void render_players() +{ + int num = snap_num_items(SNAP_CURRENT); + for(int i = 0; i < num; i++) { - int num = snap_num_items(SNAP_CURRENT); - for(int i = 0; i < num; i++) + SNAP_ITEM item; + const void *data = snap_get_item(SNAP_CURRENT, i, &item); + + if(item.type == OBJTYPE_PLAYER_CHARACTER) { - SNAP_ITEM item; - const void *data = snap_get_item(SNAP_CURRENT, i, &item); + const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); + const void *prev_info = snap_find_item(SNAP_PREV, OBJTYPE_PLAYER_INFO, item.id); + const void *info = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_INFO, item.id); - if(item.type == OBJTYPE_PLAYER_CHARACTER) + if(prev && prev_info && info) { - const void *prev = snap_find_item(SNAP_PREV, item.type, item.id); - const void *prev_info = snap_find_item(SNAP_PREV, OBJTYPE_PLAYER_INFO, item.id); - const void *info = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_INFO, item.id); - - if(prev && prev_info && info) - { - render_player( - (const obj_player_character *)prev, - (const obj_player_character *)data, - (const obj_player_info *)prev_info, - (const obj_player_info *)info - ); - } + render_player( + (const obj_player_character *)prev, + (const obj_player_character *)data, + (const obj_player_info *)prev_info, + (const obj_player_info *)info + ); } } } +} + +// renders the complete game world +void render_world(float center_x, float center_y, float zoom) +{ + // render background layers + render_layers(center_x, center_y, 0); + + // render trails + particle_render(PARTGROUP_PROJECTILE_TRAIL); + + // render items + render_items(); + + // render players above all + render_players(); // render particles - //temp_system.update(client_frametime()); - //temp_system.render(); + particle_render(PARTGROUP_EXPLOSIONS); + particle_render(PARTGROUP_GENERAL); + + if(config.dbg_flow) + flow_dbg_render(); // render foreground layers render_layers(center_x, center_y, 1); diff --git a/src/game/client/gc_render.h b/src/game/client/gc_render.h index 5294b89e..d7adeada 100644 --- a/src/game/client/gc_render.h +++ b/src/game/client/gc_render.h @@ -8,10 +8,20 @@ struct tee_render_info { + tee_render_info() + { + texture = -1; + color_body = vec4(1,1,1,1); + color_feet = vec4(1,1,1,1); + size = 1.0f; + got_airjump = 1; + }; + int texture; vec4 color_body; vec4 color_feet; float size; + int got_airjump; }; // sprite renderings @@ -40,6 +50,7 @@ void render_world(float center_x, float center_y, float zoom); void render_loading(float percent); void render_damage_indicators(); +void render_particles(); // object render methods (gc_render_obj.cpp) void render_tee(class animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos); @@ -53,7 +64,7 @@ void render_player( // map render methods (gc_render_map.cpp) void render_eval_envelope(ENVPOINT *points, int num_points, int channels, float time, float *result); void render_quads(QUAD *quads, int num_quads, void (*eval)(float time_offset, int env, float *channels)); -void render_tilemap(TILE *tiles, int w, int h, float scale, int flags); +void render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int flags); // helpers void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y, diff --git a/src/game/client/gc_render_map.cpp b/src/game/client/gc_render_map.cpp index ec96f583..4728f771 100644 --- a/src/game/client/gc_render_map.cpp +++ b/src/game/client/gc_render_map.cpp @@ -148,7 +148,7 @@ void render_quads(QUAD *quads, int num_quads, void (*eval)(float time_offset, in } -void render_tilemap(TILE *tiles, int w, int h, float scale, int flags) +void render_tilemap(TILE *tiles, int w, int h, float scale, vec4 color, int flags) { //gfx_texture_set(img_get(tmap->image)); float screen_x0, screen_y0, screen_x1, screen_y1; @@ -160,6 +160,7 @@ void render_tilemap(TILE *tiles, int w, int h, float scale, int flags) float final_tilesize_scale = final_tilesize/tile_pixelsize; gfx_quads_begin(); + gfx_setcolor(color.r, color.g, color.b, color.a); int starty = (int)(screen_y0/scale)-1; int startx = (int)(screen_x0/scale)-1; diff --git a/src/game/client/gc_render_obj.cpp b/src/game/client/gc_render_obj.cpp index bdb4cfac..3ee1704d 100644 --- a/src/game/client/gc_render_obj.cpp +++ b/src/game/client/gc_render_obj.cpp @@ -1,5 +1,6 @@ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ #include <math.h> +#include <stdio.h> #include <engine/e_client_interface.h> #include <engine/e_config.h> #include "../generated/gc_data.h" @@ -27,8 +28,6 @@ void render_projectile(const obj_projectile *current, int itemid) float gravity = -400; if(current->type != WEAPON_ROCKET) gravity = -100; - if(current->type == WEAPON_BOMB) - gravity = 0; float ct = (client_tick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime()*1/(float)SERVER_TICK_SPEED; vec2 startpos(current->x, current->y); @@ -39,17 +38,26 @@ void render_projectile(const obj_projectile *current, int itemid) select_sprite(data->weapons[current->type%data->num_weapons].sprite_proj); vec2 vel = pos-prevpos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); + // add particle for this projectile - //proj_particles.addparticle(current->type, itemid, pos, vel); - - if(length(vel) > 0.00001f) - gfx_quads_setrotation(get_angle(vel)); + if(current->type == WEAPON_ROCKET) + { + effect_smoketrail(pos, vel*-1); + flow_add(pos, vel*1000*client_frametime(), 10.0f); + gfx_quads_setrotation(client_localtime()*pi*2*2 + itemid); + } else - gfx_quads_setrotation(0); + { + effect_bullettrail(pos); + flow_add(pos, vel*1000*client_frametime(), 10.0f); - // TODO: do this, but nice - //temp_system.new_particle(pos, vec2(0,0), 0.3f, 14.0f, 0, 0.95f); + if(length(vel) > 0.00001f) + gfx_quads_setrotation(get_angle(vel)); + else + gfx_quads_setrotation(0); + + } gfx_quads_draw(pos.x, pos.y, 32, 32); gfx_quads_setrotation(0); @@ -185,6 +193,7 @@ void render_player( player = *player_char; obj_player_info info = *player_info; + tee_render_info render_info = client_datas[info.clientid].render_info; float intratick = client_intratick(); float ticktime = client_ticktime(); @@ -209,6 +218,11 @@ void render_player( vec2 direction = get_direction(player.angle); float angle = player.angle/256.0f; vec2 position = mix(vec2(prev.x, prev.y), vec2(player.x, player.y), intratick); + vec2 vel = vec2(player.x, player.y)-vec2(prev.x, prev.y); + + flow_add(position, vel*100.0f, 10.0f); + + render_info.got_airjump = player.jumped&2?0:1; if(prev.health < 0) // Don't flicker from previous position position = vec2(player.x, player.y); @@ -411,14 +425,14 @@ void render_player( if(info.local && config.debug) { vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick()); - tee_render_info ghost = client_datas[info.clientid].render_info; + tee_render_info ghost = render_info; ghost.color_body.a = 0.5f; ghost.color_feet.a = 0.5f; render_tee(&state, &ghost, player.emote, direction, ghost_position); // render ghost } // render the tee - render_tee(&state, &client_datas[info.clientid].render_info, player.emote, direction, position); + render_tee(&state, &render_info, player.emote, direction, position); if(player.state == STATE_CHATTING) { diff --git a/src/game/editor/ed_editor.hpp b/src/game/editor/ed_editor.hpp index df3a1fc1..80ca42d5 100644 --- a/src/game/editor/ed_editor.hpp +++ b/src/game/editor/ed_editor.hpp @@ -221,6 +221,11 @@ public: format = 0; } + ~IMAGE() + { + gfx_unload_texture(tex_id); + } + int tex_id; int external; char name[128]; diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp index d0f04cbc..f6a5dfe9 100644 --- a/src/game/editor/ed_layer_tiles.cpp +++ b/src/game/editor/ed_layer_tiles.cpp @@ -34,7 +34,7 @@ void LAYER_TILES::render() if(image >= 0 && image < editor.map.images.len()) tex_id = editor.map.images[image]->tex_id; gfx_texture_set(tex_id); - render_tilemap(tiles, width, height, 32.0f, 0); + render_tilemap(tiles, width, height, 32.0f, vec4(1,1,1,1), 0); } int LAYER_TILES::convert_x(float x) const { return (int)(x/32.0f); } diff --git a/src/game/g_collision.cpp b/src/game/g_collision.cpp index b15af913..6c50064b 100644 --- a/src/game/g_collision.cpp +++ b/src/game/g_collision.cpp @@ -16,9 +16,9 @@ int col_height() { return height; } int col_init() { - width = layers_game()->width; - height = layers_game()->height; - tiles = (TILE *)map_get_data(layers_game()->data); + width = layers_game_layer()->width; + height = layers_game_layer()->height; + tiles = (TILE *)map_get_data(layers_game_layer()->data); return 1; } diff --git a/src/game/g_game.cpp b/src/game/g_game.cpp index 66da6295..98ae8c47 100644 --- a/src/game/g_game.cpp +++ b/src/game/g_game.cpp @@ -284,7 +284,7 @@ void player_core::tick() hookvel.x *= 0.75f; vec2 new_vel = vel+hookvel; - + // check if we are under the legal limit for the hook if(length(new_vel) < hook_drag_speed || length(new_vel) < length(vel)) vel = new_vel; // no problem. apply @@ -348,8 +348,8 @@ void player_core::tick() } // clamp the velocity to something sane - if(length(vel) > 100.0f) - vel = normalize(vel) * 100.0f; + if(length(vel) > terminal_velocity) + vel = normalize(vel) * terminal_velocity; } void player_core::move() diff --git a/src/game/g_layers.cpp b/src/game/g_layers.cpp index 1e46168c..1595e266 100644 --- a/src/game/g_layers.cpp +++ b/src/game/g_layers.cpp @@ -1,7 +1,8 @@ #include <engine/e_common_interface.h> #include "g_layers.h" -static MAPITEM_LAYER_TILEMAP *game_layer; +static MAPITEM_LAYER_TILEMAP *game_layer = 0; +static MAPITEM_GROUP *game_group = 0; static int groups_start = 0; static int groups_num = 0; @@ -13,6 +14,7 @@ void layers_init() map_get_type(MAPITEMTYPE_GROUP, &groups_start, &groups_num); { + int p = 0; map_get_type(MAPITEMTYPE_LAYER, &layers_start, &layers_num); for(int i = 0; i < layers_num; i++) @@ -21,11 +23,23 @@ void layers_init() if(layer->type == LAYERTYPE_TILES) { MAPITEM_LAYER_TILEMAP *tilemap = (MAPITEM_LAYER_TILEMAP *)layer; + + if(p) + { + p--; + if(p == 0) + tilemap->flags |= 2; + } + if(tilemap->flags&1) + { + dbg_msg("layers", "game"); game_layer = tilemap; + p = 2; + } } + dbg_msg("layers", "%d %d", i, layer->type); } - } } @@ -40,8 +54,13 @@ MAPITEM_LAYER *layers_get_layer(int index) return (MAPITEM_LAYER *)map_get_item(layers_start+index, 0, 0); } -MAPITEM_LAYER_TILEMAP *layers_game() +MAPITEM_LAYER_TILEMAP *layers_game_layer() { return game_layer; } +MAPITEM_GROUP *layers_game_group() +{ + return game_group; +} + diff --git a/src/game/g_layers.h b/src/game/g_layers.h index 455b74a8..3ece897f 100644 --- a/src/game/g_layers.h +++ b/src/game/g_layers.h @@ -2,7 +2,8 @@ void layers_init(); -MAPITEM_LAYER_TILEMAP *layers_game(); +MAPITEM_LAYER_TILEMAP *layers_game_layer(); +MAPITEM_GROUP *layers_game_group(); int layers_num_groups(); MAPITEM_GROUP *layers_get_group(int index); diff --git a/src/game/g_protocol.h b/src/game/g_protocol.h index 9ae7b170..32ddb971 100644 --- a/src/game/g_protocol.h +++ b/src/game/g_protocol.h @@ -5,12 +5,13 @@ #define GAME_PROTOCOL_H // --------- PHYSICS TWEAK! -------- -const float ground_control_speed = 7.0f; -const float ground_control_accel = 2.0f; +const float ticks_per_second = 50.0f; +const float ground_control_speed = 350.0f / ticks_per_second; +const float ground_control_accel = 100.0f / ticks_per_second; const float ground_friction = 0.5f; const float ground_jump_speed = 12.6f; const float ground_air_speed = 11.5f; -const float air_control_speed = 5.0f; +const float air_control_speed = 250.0f / ticks_per_second; const float air_control_accel = 1.5f; const float air_friction = 0.95f; const float hook_length = 34*10.0f; @@ -18,6 +19,8 @@ const float hook_fire_speed = 45.0f; const float hook_drag_accel = 3.0f; const float hook_drag_speed = 15.0f; const float gravity = 0.5f; +const float terminal_velocity = 20.0f; + const float wall_friction = 0.80f; const float wall_jump_speed_up = ground_jump_speed*0.8f; const float wall_jump_speed_out = ground_jump_speed*0.8f; @@ -36,7 +39,7 @@ enum EVENT_DAMAGEINDICATION, EVENT_SOUND_WORLD, EVENT_SMOKE, - EVENT_SPAWN, + EVENT_PLAYERSPAWN, EVENT_DEATH, EVENT_AIR_JUMP, diff --git a/src/game/g_variables.h b/src/game/g_variables.h index 08abe313..9e4d1c7c 100644 --- a/src/game/g_variables.h +++ b/src/game/g_variables.h @@ -25,16 +25,17 @@ MACRO_CONFIG_INT(key_remoteconsole, 256+3, 32, 512) MACRO_CONFIG_INT(key_toggleconsole, 256+4, 32, 512) -MACRO_CONFIG_INT(dbg_bots, 0, 0, 11) MACRO_CONFIG_INT(cl_predict, 1, 0, 1) MACRO_CONFIG_INT(cl_nameplates, 0, 0, 1) MACRO_CONFIG_INT(cl_nameplates_always, 0, 0, 1) MACRO_CONFIG_INT(cl_dynamic_camera, 1, 0, 1) -MACRO_CONFIG_INT(cl_team, -10, -1, 0) MACRO_CONFIG_INT(cl_autoswitch_weapons, 0, 0, 1) MACRO_CONFIG_INT(cl_show_player_ids, 0, 0, 1) + +MACRO_CONFIG_INT(cl_flow, 0, 0, 1) + MACRO_CONFIG_INT(cl_show_welcome, 1, 0, 1) MACRO_CONFIG_INT(player_use_custom_color, 0, 0, 1) @@ -42,7 +43,9 @@ MACRO_CONFIG_INT(player_color_body, 65408, 0, 0) MACRO_CONFIG_INT(player_color_feet, 65408, 0, 0) MACRO_CONFIG_STR(player_skin, 64, "default") +MACRO_CONFIG_INT(dbg_bots, 0, 0, 11) MACRO_CONFIG_INT(dbg_firedelay, 0, 0, 1) +MACRO_CONFIG_INT(dbg_flow, 0, 0, 1) MACRO_CONFIG_INT(ui_page, 1, 0, 5) MACRO_CONFIG_STR(ui_server_address, 128, "localhost:8303") diff --git a/src/game/server/gs_common.h b/src/game/server/gs_common.h index b91e777e..2c7b7920 100644 --- a/src/game/server/gs_common.h +++ b/src/game/server/gs_common.h @@ -248,8 +248,6 @@ public: int attack_tick; int sniper_chargetick; - - int bomb_firetick; int damage_taken; diff --git a/src/game/server/gs_server.cpp b/src/game/server/gs_server.cpp index 914fd8e1..8e123043 100644 --- a/src/game/server/gs_server.cpp +++ b/src/game/server/gs_server.cpp @@ -18,7 +18,7 @@ class player* get_player(int index); void create_damageind(vec2 p, float angle_mod, int amount); void create_explosion(vec2 p, int owner, int weapon, bool bnodamage); void create_smoke(vec2 p); -void create_spawn(vec2 p); +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); @@ -396,8 +396,6 @@ void projectile::tick() float gravity = -400; if(type != WEAPON_ROCKET) gravity = -100; - if(type == WEAPON_BOMB) - gravity = 0; float pt = (server_tick()-start_tick-1)/(float)server_tickspeed(); float ct = (server_tick()-start_tick)/(float)server_tickspeed(); @@ -410,17 +408,10 @@ void projectile::tick() vec2 new_pos; entity *targetplayer = (entity*)intersect_player(prevpos, curpos, new_pos, powner); - player *p = (player*) powner; - if(targetplayer || collide || lifespan < 0 || (type == WEAPON_BOMB && count_input(p->previnput.fire, p->input.fire).releases)) + if(targetplayer || collide || lifespan < 0) { - if(type == WEAPON_BOMB) - { - p->bomb_firetick = -1; - p->reload_timer = data->weapons[WEAPON_BOMB].firedelay * server_tickspeed() / 1000; - } - - if (lifespan >= 0 || weapon == WEAPON_ROCKET || weapon == WEAPON_BOMB) + if (lifespan >= 0 || weapon == WEAPON_ROCKET) create_sound(pos, sound_impact); if (flags & PROJECTILE_FLAGS_EXPLODE) @@ -504,7 +495,6 @@ void player::reset() numobjectshit = 0; ninja_activationtick = 0; sniper_chargetick = -1; - bomb_firetick = -1; currentmovetime = 0; active_weapon = WEAPON_GUN; @@ -718,8 +708,6 @@ void player::try_respawn() //weapons[WEAPON_SNIPER].got = true; //weapons[WEAPON_SNIPER].ammo = data->weapons[WEAPON_SNIPER].maxammo; - weapons[WEAPON_BOMB].got = true; - weapons[WEAPON_BOMB].ammo = data->weapons[WEAPON_BOMB].maxammo; active_weapon = WEAPON_GUN; last_weapon = WEAPON_HAMMER; wanted_weapon = WEAPON_GUN; @@ -728,7 +716,7 @@ void player::try_respawn() // Create sound and spawn effects create_sound(pos, SOUND_PLAYER_SPAWN); - create_spawn(pos); + create_playerspawn(pos); gameobj->on_player_spawn(this); } @@ -941,32 +929,6 @@ int player::handle_sniper() return 0; } -int player::handle_bomb() -{ - struct input_count button = count_input(previnput.fire, input.fire); - - if(button.releases) - { - } - else if(input.fire & 1 && bomb_firetick == -1 && reload_timer == 0) - { - vec2 direction = normalize(vec2(input.target_x, input.target_y)); - new projectile(WEAPON_BOMB, - client_id, - pos+vec2(0,0), - direction*7.0f, - 100, - this, - 1, projectile::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_ROCKET_EXPLODE, WEAPON_ROCKET); - create_sound(pos, SOUND_ROCKET_FIRE); - bomb_firetick = server_tick(); - attack_tick = server_tick(); - weapons[active_weapon].ammo--; - } - - return 0; -} - int player::handle_weapons() { vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); @@ -1043,8 +1005,6 @@ int player::handle_weapons() if (active_weapon == WEAPON_SNIPER) return handle_sniper(); */ - if (active_weapon == WEAPON_BOMB) - return handle_bomb(); if(reload_timer == 0) { @@ -1073,7 +1033,7 @@ int player::handle_weapons() client_id, pos+vec2(0,0), direction*30.0f, - 100, + server_tickspeed(), this, 1, 0, 0, -1, WEAPON_GUN); create_sound(pos, SOUND_GUN_FIRE); @@ -1105,7 +1065,7 @@ int player::handle_weapons() pos+vec2(0,0), vec2(cosf(a), sinf(a))*(28.0f + 12.0f*v), //vec2(cosf(a), sinf(a))*20.0f, - (int)(server_tickspeed()*0.3f), + (int)(server_tickspeed()*0.25f), this, 1, 0, 0, -1, WEAPON_SHOTGUN); } @@ -1723,12 +1683,6 @@ void create_explosion(vec2 p, int owner, int weapon, bool bnodamage) float radius = 128.0f; float innerradius = 42.0f; - if(weapon == WEAPON_BOMB) - { - radius = 256.0f; - innerradius = 64.0f; - } - int num = world->find_entities(p, radius, ents, 64); for(int i = 0; i < num; i++) { @@ -1756,10 +1710,10 @@ void create_smoke(vec2 p) } } -void create_spawn(vec2 p) +void create_playerspawn(vec2 p) { // create the event - ev_spawn *ev = (ev_spawn *)events.create(EVENT_SPAWN, sizeof(ev_spawn)); + ev_spawn *ev = (ev_spawn *)events.create(EVENT_PLAYERSPAWN, sizeof(ev_spawn)); if(ev) { ev->x = (int)p.x; @@ -2062,7 +2016,7 @@ void mods_init() players[i].core.world = &world->core; // create all entities from the game layer - MAPITEM_LAYER_TILEMAP *tmap = layers_game(); + MAPITEM_LAYER_TILEMAP *tmap = layers_game_layer(); TILE *tiles = (TILE *)map_get_data(tmap->data); num_spawn_points[0] = 0; |