continued the cleanup

This commit is contained in:
Magnus Auvinen 2008-01-12 17:09:00 +00:00
parent 99f0a47d6b
commit 906ece7894
24 changed files with 1768 additions and 1743 deletions

View file

@ -80,26 +80,6 @@ struct animation {
instance:sequence attach = attach instance:sequence attach = attach
} }
struct gui_box {
int x = @1
int y = @2
int w = @3
int h = @4
}
struct gui_compositebox {
instance:gui_box rect = rect
instance:gui_box center = center
}
struct gui_widgets {
array:gui_compositebox boxes = boxes.*
array:gui_box misc = misc.*
}
const array:int gui_box = gui.boxes.*
const array:int gui_misc = gui.misc.*
struct data_container { struct data_container {
array:image images = images.* array:image images = images.*
array:spriteset spritesets = sprites.* array:spriteset spritesets = sprites.*
@ -111,7 +91,6 @@ struct data_container {
array:soundset sounds = sounds.* array:soundset sounds = sounds.*
array:animation animations = animations.* array:animation animations = animations.*
instance:gui_widgets gui = gui
} }
const array:int weapon = weapons.* const array:int weapon = weapons.*

View file

@ -215,6 +215,10 @@ sounds {
images { images {
null {
filename ""
}
game { game {
filename "data/game.png" filename "data/game.png"
} }
@ -663,7 +667,7 @@ sprites {
} }
tees images.char_default 8 4 { tees images.null 8 4 {
tee_body 0 0 3 3 tee_body 0 0 3 3
tee_body_outline 3 0 3 3 tee_body_outline 3 0 3 3
tee_foot 6 1 2 1 tee_foot 6 1 2 1
@ -827,77 +831,3 @@ animations {
} }
} }
} }
gui {
boxes {
button {
rect 0 0 48 48
center 16 16 16 16
}
screen_thick {
rect 0 384 48 48
center 16 400 16 16
}
screen_transparent {
rect 48 384 48 48
center 64 400 16 16
}
screen_info {
rect 96 384 48 48
center 112 400 16 16
}
screen_textbox {
rect 144 384 48 48
center 160 400 16 16
}
screen_list {
rect 192 384 48 48
center 208 400 16 16
}
}
misc {
button_big_topleft 0 0 16 16
button_big_topmid 16 0 16 16
button_big_topright 32 0 16 16
button_big_midleft 0 16 16 16
button_big_midmid 16 16 16 16
button_big_midright 32 16 16 16
button_big_btmleft 0 32 16 16
button_big_btmmid 16 32 16 16
button_big_btmright 32 32 16 16
slider_big_horiz_begin 0 48 16 16
slider_big_horiz_mid 16 48 16 16
slider_big_horiz_end 32 48 16 16
slider_small_horiz_begin 0 96 16 16
slider_small_horiz_mid 16 96 16 16
slider_small_horiz_end 32 96 16 16
slider_small_vert_begin 48 96 16 16
radio_unchecked 64 112 32 32
radio_checked 96 112 32 32
slider_small_vert_mid 48 112 16 16
slider_small_vert_end 48 128 16 16
slider_big_vert_begin 48 48 16 16
slider_big_handle_vert 64 48 16 32
slider_big_handle_horiz 80 64 32 16
slider_small_handle_horiz 80 48 16 16
slider_big_arrow_left 0 64 16 16
slider_big_arrow_up 16 64 16 16
slider_big_arrow_right 32 64 16 16
slider_big_arrow_down 16 80 16 16
slider_small_arrow_left 0 112 16 16
slider_small_arrow_up 16 112 16 16
slider_small_arrow_right 32 112 16 16
slider_small_arrow_down 16 128 16 16
slider_small_handle_vert 96 48 16 16
slider_big_vert_mid 48 64 16 16
slider_big_vert_end 48 80 16 16
checkbox_unchecked 64 112 32 32
checkbox_checked 96 112 32 32
}
}

14
src/game/client/gc_anim.h Normal file
View file

@ -0,0 +1,14 @@
struct animstate
{
keyframe body;
keyframe back_foot;
keyframe front_foot;
keyframe attach;
};
void anim_seq_eval(sequence *seq, float time, keyframe *frame);
void anim_eval(animation *anim, float time, animstate *state);
void anim_add_keyframe(keyframe *seq, keyframe *added, float amount);
void anim_add(animstate *state, animstate *added, float amount);
void anim_eval_add(animstate *state, animation *anim, float time, float amount);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
#include <game/g_vmath.h>
#include <game/g_protocol.h>
#include <game/g_game.h>
#include <game/client/gc_render.h>
// sound channels
enum
{
CHN_GUI=0,
CHN_MUSIC,
CHN_WORLD,
CHN_GLOBAL,
};
extern struct data_container *data;
extern vec2 mouse_pos;
extern vec2 local_character_pos;
extern vec2 local_target_pos;
// snap pointers
extern const obj_player_character *local_character;
extern const obj_player_character *local_prev_character;
extern const obj_player_info *local_info;
extern const obj_flag *flags[2];
extern const obj_game *gameobj;
// predicted players
extern player_core predicted_prev_player;
extern player_core predicted_player;
// input
extern int picked_up_weapon;
extern player_input input_data;
extern int input_target_lock;
// chat
enum
{
CHATMODE_NONE=0,
CHATMODE_ALL,
CHATMODE_TEAM,
CHATMODE_CONSOLE,
CHATMODE_REMOTECONSOLE,
};
extern int chat_mode;
void chat_add_line(int client_id, int team, const char *line);
void chat_reset();
// client data
struct client_data
{
char name[64];
char skin_name[64];
int skin_id;
int skin_color;
int team;
int emoticon;
int emoticon_start;
player_core predicted;
tee_render_info skin_info; // this is what the server reports
tee_render_info render_info; // this is what we use
void update_render_info();
};
extern client_data client_datas[MAX_CLIENTS];
// kill messages
struct killmsg
{
int weapon;
int victim;
int killer;
int mode_special; // for CTF, if the guy is carrying a flag for example
int tick;
};
const int killmsg_max = 5;
extern killmsg killmsgs[killmsg_max];
extern int killmsg_current;
// 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);
void effect_air_jump(vec2 pos);

View file

@ -0,0 +1,500 @@
#include <string.h>
#include <engine/e_interface.h>
extern "C" {
#include <engine/e_config.h>
#include <engine/client/ec_font.h>
};
#include <game/generated/gc_data.h>
#include <game/g_game.h>
#include <game/g_version.h>
#include "gc_client.h"
#include "gc_skin.h"
#include "gc_render.h"
#include "gc_mapres_image.h"
#include "gc_mapres_tilemap.h"
extern unsigned char internal_data[];
extern void menu_init();
extern bool menu_active;
extern bool menu_game_active;
extern "C" void modc_init()
{
static FONT_SET default_font;
int before = gfx_memory_usage();
font_set_load(&default_font, "fonts/default_font%d.tfnt", "fonts/default_font%d.png", "fonts/default_font%d_b.png", 14, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 36);
dbg_msg("font", "gfx memory usage: %d", gfx_memory_usage()-before);
gfx_text_set_default_font(&default_font);
menu_init();
// setup sound channels
snd_set_channel(CHN_GUI, 1.0f, 0.0f);
snd_set_channel(CHN_MUSIC, 1.0f, 0.0f);
snd_set_channel(CHN_WORLD, 0.9f, 1.0f);
snd_set_channel(CHN_GLOBAL, 1.0f, 0.0f);
// load the data container
data = load_data_from_memory(internal_data);
// TODO: should be removed
snd_set_listener_pos(0.0f, 0.0f);
float total = data->num_sounds+data->num_images;
float current = 0;
// load textures
for(int i = 0; i < data->num_images; i++)
{
render_loading(current/total);
data->images[i].id = gfx_load_texture(data->images[i].filename, IMG_AUTO);
current++;
}
// load sounds
for(int s = 0; s < data->num_sounds; s++)
{
render_loading(current/total);
for(int i = 0; i < data->sounds[s].num_sounds; i++)
{
int id;
//if (strcmp(data->sounds[s].sounds[i].filename + strlen(data->sounds[s].sounds[i].filename) - 3, ".wv") == 0)
id = snd_load_wv(data->sounds[s].sounds[i].filename);
//else
// id = snd_load_wav(data->sounds[s].sounds[i].filename);
data->sounds[s].sounds[i].id = id;
}
current++;
}
skin_init();
}
extern "C" void modc_entergame()
{
}
extern "C" void modc_shutdown()
{
// shutdown the menu
}
player_core predicted_prev_player;
player_core predicted_player;
static int predicted_tick = 0;
static int last_new_predicted_tick = -1;
extern "C" void modc_predict()
{
player_core before_prev_player = predicted_prev_player;
player_core before_player = predicted_player;
// repredict player
world_core world;
int local_cid = -1;
// search for players
for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
{
SNAP_ITEM item;
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
int client_id = item.id;
if(item.type == OBJTYPE_PLAYER_CHARACTER)
{
const obj_player_character *character = (const obj_player_character *)data;
client_datas[client_id].predicted.world = &world;
world.players[client_id] = &client_datas[client_id].predicted;
client_datas[client_id].predicted.read(character);
}
else if(item.type == OBJTYPE_PLAYER_INFO)
{
const obj_player_info *info = (const obj_player_info *)data;
if(info->local)
local_cid = client_id;
}
}
// predict
for(int tick = client_tick()+1; tick <= client_predtick(); tick++)
{
// fetch the local
if(tick == client_predtick() && world.players[local_cid])
predicted_prev_player = *world.players[local_cid];
// first calculate where everyone should move
for(int c = 0; c < MAX_CLIENTS; c++)
{
if(!world.players[c])
continue;
mem_zero(&world.players[c]->input, sizeof(world.players[c]->input));
if(local_cid == c)
{
// apply player input
int *input = client_get_input(tick);
if(input)
world.players[c]->input = *((player_input*)input);
}
world.players[c]->tick();
}
// move all players and quantize their data
for(int c = 0; c < MAX_CLIENTS; c++)
{
if(!world.players[c])
continue;
// TODO: this should be moved into the g_game
// but not done to preserve the nethash
if(length(world.players[c]->vel) > 150.0f)
world.players[c]->vel = normalize(world.players[c]->vel) * 150.0f;
world.players[c]->move();
world.players[c]->quantize();
}
if(tick > last_new_predicted_tick)
{
last_new_predicted_tick = tick;
if(local_cid != -1 && world.players[local_cid])
{
vec2 pos = world.players[local_cid]->pos;
int events = world.players[local_cid]->triggered_events;
if(events&COREEVENT_GROUND_JUMP) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
if(events&COREEVENT_AIR_JUMP)
{
effect_air_jump(pos);
snd_play_random(CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos);
}
//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos);
if(events&COREEVENT_HOOK_ATTACH_GROUND) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, pos);
//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
}
/*
dbg_msg("predict", "%d %d %d", tick,
(int)world.players[c]->pos.x, (int)world.players[c]->pos.y,
(int)world.players[c]->vel.x, (int)world.players[c]->vel.y);*/
}
if(tick == client_predtick() && world.players[local_cid])
predicted_player = *world.players[local_cid];
}
if(config.debug && predicted_tick == client_predtick())
{
if(predicted_player.pos.x != before_player.pos.x ||
predicted_player.pos.y != before_player.pos.y)
{
dbg_msg("client", "prediction error, (%d %d) (%d %d)",
(int)before_player.pos.x, (int)before_player.pos.y,
(int)predicted_player.pos.x, (int)predicted_player.pos.y);
}
if(predicted_prev_player.pos.x != before_prev_player.pos.x ||
predicted_prev_player.pos.y != before_prev_player.pos.y)
{
dbg_msg("client", "prediction error, prev (%d %d) (%d %d)",
(int)before_prev_player.pos.x, (int)before_prev_player.pos.y,
(int)predicted_prev_player.pos.x, (int)predicted_prev_player.pos.y);
}
}
predicted_tick = client_predtick();
}
extern "C" void modc_newsnapshot()
{
static int snapshot_count = 0;
snapshot_count++;
process_events(SNAP_CURRENT);
if(config.dbg_stress)
{
if((client_tick()%250) == 0)
{
msg_pack_start(MSG_SAY, MSGFLAG_VITAL);
msg_pack_int(-1);
msg_pack_string("galenskap!!!!", 512);
msg_pack_end();
client_send_msg();
}
}
clear_object_pointers();
// setup world view
{
// 1. fetch local player
// 2. set him to the center
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_INFO)
{
const obj_player_info *info = (const obj_player_info *)data;
client_datas[info->clientid].team = info->team;
if(info->local)
{
local_info = info;
const void *data = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_CHARACTER, item.id);
if(data)
{
local_character = (const obj_player_character *)data;
local_character_pos = vec2(local_character->x, local_character->y);
const void *p = snap_find_item(SNAP_PREV, OBJTYPE_PLAYER_CHARACTER, item.id);
if(p)
local_prev_character = (obj_player_character *)p;
}
}
}
else if(item.type == OBJTYPE_GAME)
gameobj = (obj_game *)data;
else if(item.type == OBJTYPE_FLAG)
{
flags[item.id%2] = (const obj_flag *)data;
}
}
}
for(int i = 0; i < MAX_CLIENTS; i++)
client_datas[i].update_render_info();
}
extern "C" void modc_render()
{
// this should be moved around abit
if(client_state() == CLIENTSTATE_ONLINE)
{
render_game();
// 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)
{
menu_render();
}
//
config.cl_team = -10;
}
extern "C" int modc_snap_input(int *data)
{
picked_up_weapon = -1;
if(!input_target_lock)
{
input_data.target_x = (int)mouse_pos.x;
input_data.target_y = (int)mouse_pos.y;
if(!input_data.target_x && !input_data.target_y)
input_data.target_y = 1;
}
input_target_lock = 0;
if(chat_mode != CHATMODE_NONE)
input_data.state = STATE_CHATTING;
else if(menu_active)
input_data.state = STATE_IN_MENU;
else
{
input_data.state = STATE_PLAYING;
input_data.left = inp_key_state(config.key_move_left);
input_data.right = inp_key_state(config.key_move_right);
input_data.hook = inp_key_state(config.key_hook);
input_data.jump = inp_key_state(config.key_jump);
}
// stress testing
if(config.dbg_stress)
{
float t = client_localtime();
mem_zero(&input_data, sizeof(input_data));
input_data.left = ((int)t/2)&1;
input_data.right = ((int)t/2+1)&1;
input_data.jump = ((int)t);
input_data.fire = ((int)(t*10));
input_data.hook = ((int)(t*2))&1;
input_data.wanted_weapon = ((int)t)%NUM_WEAPONS;
input_data.target_x = (int)(sinf(t*3)*100.0f);
input_data.target_y = (int)(cosf(t*3)*100.0f);
}
// copy and return size
mem_copy(data, &input_data, sizeof(input_data));
return sizeof(input_data);
}
void menu_do_disconnected();
void menu_do_connecting();
void menu_do_connected();
extern "C" void modc_statechange(int state, int old)
{
clear_object_pointers();
if(state == CLIENTSTATE_OFFLINE)
{
menu_do_disconnected();
menu_game_active = false;
}
else if(state == CLIENTSTATE_LOADING)
menu_do_connecting();
else if(state == CLIENTSTATE_CONNECTING)
menu_do_connecting();
else if (state == CLIENTSTATE_ONLINE)
{
menu_active = false;
menu_game_active = true;
//snapshot_count = 0;
menu_do_connected();
}
}
extern "C" void modc_message(int msg)
{
if(msg == MSG_CHAT)
{
int cid = msg_unpack_int();
int team = msg_unpack_int();
const char *message = msg_unpack_string();
dbg_msg("message", "chat cid=%d team=%d msg='%s'", cid, team, message);
chat_add_line(cid, team, message);
if(cid >= 0)
snd_play(CHN_GUI, data->sounds[SOUND_CHAT_CLIENT].sounds[0].id, 0);
else
snd_play(CHN_GUI, data->sounds[SOUND_CHAT_SERVER].sounds[0].id, 0);
}
else if(msg == MSG_SETINFO)
{
int cid = msg_unpack_int();
const char *name = msg_unpack_string();
const char *skinname = msg_unpack_string();
strncpy(client_datas[cid].name, name, 64);
strncpy(client_datas[cid].skin_name, skinname, 64);
int use_custom_color = msg_unpack_int();
client_datas[cid].skin_info.color_body = skin_get_color(msg_unpack_int());
client_datas[cid].skin_info.color_feet = skin_get_color(msg_unpack_int());
client_datas[cid].skin_info.size = 64;
// find new skin
client_datas[cid].skin_id = skin_find(client_datas[cid].skin_name);
if(client_datas[cid].skin_id < 0)
client_datas[cid].skin_id = 0;
if(use_custom_color)
client_datas[cid].skin_info.texture = skin_get(client_datas[cid].skin_id)->color_texture;
else
{
client_datas[cid].skin_info.texture = skin_get(client_datas[cid].skin_id)->org_texture;
client_datas[cid].skin_info.color_body = vec4(1,1,1,1);
client_datas[cid].skin_info.color_feet = vec4(1,1,1,1);
}
client_datas[cid].update_render_info();
}
else if(msg == MSG_WEAPON_PICKUP)
{
int weapon = msg_unpack_int();
picked_up_weapon = weapon+1;
}
else if(msg == MSG_READY_TO_ENTER)
{
client_entergame();
}
else if(msg == MSG_KILLMSG)
{
killmsg_current = (killmsg_current+1)%killmsg_max;
killmsgs[killmsg_current].killer = msg_unpack_int();
killmsgs[killmsg_current].victim = msg_unpack_int();
killmsgs[killmsg_current].weapon = msg_unpack_int();
killmsgs[killmsg_current].mode_special = msg_unpack_int();
killmsgs[killmsg_current].tick = client_tick();
}
else if (msg == MSG_EMOTICON)
{
int cid = msg_unpack_int();
int emoticon = msg_unpack_int();
client_datas[cid].emoticon = emoticon;
client_datas[cid].emoticon_start = client_tick();
}
else if(msg == MSG_SOUND_GLOBAL)
{
int soundid = msg_unpack_int();
snd_play_random(CHN_GLOBAL, soundid, 1.0f, vec2(0,0));
}
}
extern "C" void modc_connected()
{
// init some stuff
col_init(32);
img_init();
tilemap_init();
chat_reset();
reset_projectile_particles();
clear_object_pointers();
last_new_predicted_tick = -1;
for(int i = 0; i < MAX_CLIENTS; i++)
{
client_datas[i].name[0] = 0;
client_datas[i].team = 0;
client_datas[i].emoticon = 0;
client_datas[i].emoticon_start = -1;
}
for(int i = 0; i < killmsg_max; i++)
killmsgs[i].tick = -100000;
send_info(true);
}
extern "C" const char *modc_net_version() { return TEEWARS_NETVERSION; }

View file

@ -5,6 +5,12 @@
#include "gc_mapres_image.h" #include "gc_mapres_image.h"
#include "../g_mapres.h" #include "../g_mapres.h"
enum
{
TILEFLAG_VFLIP=1,
TILEFLAG_HFLIP=2,
};
int tilemap_init() int tilemap_init()
{ {
return 0; return 0;

View file

@ -8,12 +8,6 @@ int tilemap_init();
// renders the tilemaps // renders the tilemaps
void tilemap_render(float scale, int fg); void tilemap_render(float scale, int fg);
enum
{
TILEFLAG_VFLIP=1,
TILEFLAG_HFLIP=2,
};
struct mapres_tilemap struct mapres_tilemap
{ {
int image; int image;

View file

@ -23,6 +23,7 @@ extern "C" {
#include "../generated/gc_data.h" #include "../generated/gc_data.h"
#include "gc_render.h" #include "gc_render.h"
#include "gc_anim.h"
#include "gc_skin.h" #include "gc_skin.h"
#include "gc_ui.h" #include "gc_ui.h"
#include <mastersrv/mastersrv.h> #include <mastersrv/mastersrv.h>
@ -73,11 +74,6 @@ enum
PAGE_SYSTEM, PAGE_SYSTEM,
}; };
extern void select_sprite(int id, int flags=0, int sx=0, int sy=0);
extern void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners);
extern void draw_round_rect(float x, float y, float w, float h, float r);
static void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding) static void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding)
{ {
gfx_texture_set(-1); gfx_texture_set(-1);
@ -259,12 +255,6 @@ int ui_do_edit_box(void *id, const RECT *rect, char *str, int str_size, bool hid
r = 1; r = 1;
} }
int box_type;
if (ui_active_item() == id || ui_hot_item() == id || ui_last_active_item() == id)
box_type = GUI_BOX_SCREEN_INFO;
else
box_type = GUI_BOX_SCREEN_TEXTBOX;
bool just_got_active = false; bool just_got_active = false;
if(ui_active_item() == id) if(ui_active_item() == id)
@ -1972,7 +1962,7 @@ int menu2_render()
return 0; return 0;
} }
void modmenu_render() void menu_render()
{ {
static int mouse_x = 0; static int mouse_x = 0;
static int mouse_y = 0; static int mouse_y = 0;

View file

@ -1,7 +1,7 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#ifndef __MENU_H #ifndef __MENU_H
#define __MENU_H #define __MENU_H
/*
void draw_image_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra); void draw_image_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
void draw_single_part_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra); void draw_single_part_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
void draw_menu_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra); void draw_menu_button(void *id, const char *text, int checked, float x, float y, float w, float h, void *extra);
@ -12,5 +12,5 @@ int ui_do_edit_box(void *id, float x, float y, float w, float h, char *str, int
int ui_do_check_box(void *id, float x, float y, float w, float h, int value); int ui_do_check_box(void *id, float x, float y, float w, float h, int value);
int do_scroll_bar_horiz(void *id, float x, float y, float width, int steps, int last_index); int do_scroll_bar_horiz(void *id, float x, float y, float width, int steps, int last_index);
int do_scroll_bar_vert(void *id, float x, float y, float height, int steps, int last_index); int do_scroll_bar_vert(void *id, float x, float y, float height, int steps, int last_index);
*/
#endif #endif

View file

@ -0,0 +1,237 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <math.h>
#include <engine/e_interface.h>
#include <engine/e_config.h>
#include "../generated/gc_data.h"
#include "../g_protocol.h"
#include "../g_math.h"
#include "gc_render.h"
#include "gc_anim.h"
#include "gc_client.h"
static float sprite_w_scale;
static float sprite_h_scale;
void select_sprite(sprite *spr, int flags, int sx, int sy)
{
int x = spr->x+sx;
int y = spr->y+sy;
int w = spr->w;
int h = spr->h;
int cx = spr->set->gridx;
int cy = spr->set->gridy;
float f = sqrtf(h*h + w*w);
sprite_w_scale = w/f;
sprite_h_scale = h/f;
float x1 = x/(float)cx;
float x2 = (x+w)/(float)cx;
float y1 = y/(float)cy;
float y2 = (y+h)/(float)cy;
float temp = 0;
if(flags&SPRITE_FLAG_FLIP_Y)
{
temp = y1;
y1 = y2;
y2 = temp;
}
if(flags&SPRITE_FLAG_FLIP_X)
{
temp = x1;
x1 = x2;
x2 = temp;
}
gfx_quads_setsubset(x1, y1, x2, y2);
}
void select_sprite(int id, int flags, int sx, int sy)
{
if(id < 0 || id > data->num_sprites)
return;
select_sprite(&data->sprites[id], flags, sx, sy);
}
void draw_sprite(float x, float y, float size)
{
gfx_quads_draw(x, y, size*sprite_w_scale, size*sprite_h_scale);
}
void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners)
{
int num = 8;
for(int i = 0; i < num; i+=2)
{
float a1 = i/(float)num * pi/2;
float a2 = (i+1)/(float)num * pi/2;
float a3 = (i+2)/(float)num * pi/2;
float ca1 = cosf(a1);
float ca2 = cosf(a2);
float ca3 = cosf(a3);
float sa1 = sinf(a1);
float sa2 = sinf(a2);
float sa3 = sinf(a3);
if(corners&1) // TL
gfx_quads_draw_freeform(
x+r, y+r,
x+(1-ca1)*r, y+(1-sa1)*r,
x+(1-ca3)*r, y+(1-sa3)*r,
x+(1-ca2)*r, y+(1-sa2)*r);
if(corners&2) // TR
gfx_quads_draw_freeform(
x+w-r, y+r,
x+w-r+ca1*r, y+(1-sa1)*r,
x+w-r+ca3*r, y+(1-sa3)*r,
x+w-r+ca2*r, y+(1-sa2)*r);
if(corners&4) // BL
gfx_quads_draw_freeform(
x+r, y+h-r,
x+(1-ca1)*r, y+h-r+sa1*r,
x+(1-ca3)*r, y+h-r+sa3*r,
x+(1-ca2)*r, y+h-r+sa2*r);
if(corners&8) // BR
gfx_quads_draw_freeform(
x+w-r, y+h-r,
x+w-r+ca1*r, y+h-r+sa1*r,
x+w-r+ca3*r, y+h-r+sa3*r,
x+w-r+ca2*r, y+h-r+sa2*r);
}
gfx_quads_drawTL(x+r, y+r, w-r*2, h-r*2); // center
gfx_quads_drawTL(x+r, y, w-r*2, r); // top
gfx_quads_drawTL(x+r, y+h-r, w-r*2, r); // bottom
gfx_quads_drawTL(x, y+r, r, h-r*2); // left
gfx_quads_drawTL(x+w-r, y+r, r, h-r*2); // right
if(!(corners&1)) gfx_quads_drawTL(x, y, r, r); // TL
if(!(corners&2)) gfx_quads_drawTL(x+w, y, -r, r); // TR
if(!(corners&4)) gfx_quads_drawTL(x, y+h, r, -r); // BL
if(!(corners&8)) gfx_quads_drawTL(x+w, y+h, -r, -r); // BR
}
void draw_round_rect(float x, float y, float w, float h, float r)
{
draw_round_rect_ext(x,y,w,h,r,0xf);
}
void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos)
{
vec2 direction = dir;
vec2 position = pos;
//gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id);
gfx_texture_set(info->texture);
gfx_quads_begin();
//gfx_quads_draw(pos.x, pos.y-128, 128, 128);
// first pass we draw the outline
// second pass we draw the filling
for(int p = 0; p < 2; p++)
{
int outline = p==0 ? 1 : 0;
for(int f = 0; f < 2; f++)
{
float animscale = info->size * 1.0f/64.0f;
float basesize = info->size;
if(f == 1)
{
gfx_quads_setrotation(anim->body.angle*pi*2);
// draw body
gfx_setcolor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a);
vec2 body_pos = position + vec2(anim->body.x, anim->body.y)*animscale;
select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0);
gfx_quads_draw(body_pos.x, body_pos.y, basesize, basesize);
// draw eyes
if(p == 1)
{
switch (emote)
{
case EMOTE_PAIN:
select_sprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0);
break;
case EMOTE_HAPPY:
select_sprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0);
break;
case EMOTE_SURPRISE:
select_sprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0);
break;
case EMOTE_ANGRY:
select_sprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0);
break;
default:
select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0);
break;
}
float eyescale = basesize*0.40f;
float h = emote == EMOTE_BLINK ? basesize*0.15f : eyescale;
float eyeseparation = (0.075f - 0.010f*fabs(direction.x))*basesize;
vec2 offset = vec2(direction.x*0.125f, -0.05f+direction.y*0.10f)*basesize;
gfx_quads_draw(body_pos.x-eyeseparation+offset.x, body_pos.y+offset.y, eyescale, h);
gfx_quads_draw(body_pos.x+eyeseparation+offset.x, body_pos.y+offset.y, -eyescale, h);
}
}
// 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);
keyframe *foot = f ? &anim->front_foot : &anim->back_foot;
float w = basesize;
float h = basesize/2;
gfx_quads_setrotation(foot->angle*pi*2);
gfx_quads_draw(position.x+foot->x*animscale, position.y+foot->y*animscale, w, h);
}
}
gfx_quads_end();
}
static void calc_screen_params(float amount, float wmax, float hmax, float aspect, float *w, float *h)
{
float f = sqrt(amount) / sqrt(aspect);
*w = f*aspect;
*h = f;
// limit the view
if(*w > wmax)
{
*w = wmax;
*h = *w/aspect;
}
if(*h > hmax)
{
*h = hmax;
*w = *h*aspect;
}
}
void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y,
float offset_x, float offset_y, float aspect, float zoom, float *points)
{
float width, height;
calc_screen_params(1300*1000, 1500, 1050, aspect, &width, &height);
center_x *= parallax_x;
center_y *= parallax_y;
width *= zoom;
height *= zoom;
points[0] = offset_x+center_x-width/2;
points[1] = offset_y+center_y-height/2;
points[2] = offset_x+center_x+width/2;
points[3] = offset_y+center_y+height/2;
}

View file

@ -1,17 +1,9 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
struct animstate #ifndef GAME_CLIENT_RENDER_H
{ #define GAME_CLIENT_RENDER_H
keyframe body;
keyframe back_foot;
keyframe front_foot;
keyframe attach;
};
void anim_seq_eval(sequence *seq, float time, keyframe *frame); #include "../g_vmath.h"
void anim_eval(animation *anim, float time, animstate *state); #include "../g_mapitems.h"
void anim_add_keyframe(keyframe *seq, keyframe *added, float amount);
void anim_add(animstate *state, animstate *added, float amount);
void anim_eval_add(animstate *state, animation *anim, float time, float amount);
struct tee_render_info struct tee_render_info
{ {
@ -21,4 +13,46 @@ struct tee_render_info
float size; float size;
}; };
void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos); // sprite renderings
enum
{
SPRITE_FLAG_FLIP_Y=1,
SPRITE_FLAG_FLIP_X=2,
};
typedef struct sprite;
void select_sprite(sprite *spr, int flags=0, int sx=0, int sy=0);
void select_sprite(int id, int flags=0, int sx=0, int sy=0);
void draw_sprite(float x, float y, float size);
// rects
void draw_round_rect(float x, float y, float w, float h, float r);
void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners);
// larger rendering methods
void menu_render();
void render_game();
void render_world(float center_x, float center_y, float zoom);
void render_loading(float percent);
// object render methods (gc_render_obj.cpp)
void render_tee(class animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos);
void render_flag(const struct obj_flag *prev, const struct obj_flag *current);
void render_powerup(const struct obj_powerup *prev, const struct obj_powerup *current);
void render_projectile(const struct obj_projectile *current, int itemid);
void render_player(
const struct obj_player_character *prev_char, const struct obj_player_character *player_char,
const struct obj_player_info *prev_info, const struct obj_player_info *player_info);
// map render methods (gc_render_map.cpp)
void render_quads(QUAD *quads, int num_quads);
void render_tilemap(TILE *tiles, int w, int h, float scale);
// helpers
void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y,
float offset_x, float offset_y, float aspect, float zoom, float *points);
#endif

View file

@ -0,0 +1,167 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <engine/e_interface.h>
#include "../g_math.h"
#include "gc_client.h"
static void rotate(POINT *center, POINT *point, float rotation)
{
int x = point->x - center->x;
int y = point->y - center->y;
point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x);
point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y);
}
void render_quads(QUAD *quads, int num_quads)
{
gfx_quads_begin();
float conv = 1/255.0f;
for(int i = 0; i < num_quads; i++)
{
QUAD *q = &quads[i];
gfx_quads_setsubset_free(
fx2f(q->texcoords[0].x), fx2f(q->texcoords[0].y),
fx2f(q->texcoords[1].x), fx2f(q->texcoords[1].y),
fx2f(q->texcoords[2].x), fx2f(q->texcoords[2].y),
fx2f(q->texcoords[3].x), fx2f(q->texcoords[3].y)
);
float r=1, g=1, b=1, a=1;
float offset_x = 0;
float offset_y = 0;
float rot = 0;
/*
// TODO: fix this
if(editor.animate)
{
if(q->pos_env >= 0 && q->pos_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->pos_env];
float t = editor.animate_time+q->pos_env_offset/1000.0f;
offset_x = e->eval(t, 0);
offset_y = e->eval(t, 1);
rot = e->eval(t, 2);
}
if(q->color_env >= 0 && q->color_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->color_env];
float t = editor.animate_time+q->color_env_offset/1000.0f;
r = e->eval(t, 0);
g = e->eval(t, 1);
b = e->eval(t, 2);
a = e->eval(t, 3);
}
}*/
gfx_setcolorvertex(0, q->colors[0].r*conv*r, q->colors[0].g*conv*g, q->colors[0].b*conv*b, q->colors[0].a*conv*a);
gfx_setcolorvertex(1, q->colors[1].r*conv*r, q->colors[1].g*conv*g, q->colors[1].b*conv*b, q->colors[1].a*conv*a);
gfx_setcolorvertex(2, q->colors[2].r*conv*r, q->colors[2].g*conv*g, q->colors[2].b*conv*b, q->colors[2].a*conv*a);
gfx_setcolorvertex(3, q->colors[3].r*conv*r, q->colors[3].g*conv*g, q->colors[3].b*conv*b, q->colors[3].a*conv*a);
POINT *points = q->points;
if(rot != 0)
{
static POINT rotated[4];
rotated[0] = q->points[0];
rotated[1] = q->points[1];
rotated[2] = q->points[2];
rotated[3] = q->points[3];
points = rotated;
rotate(&q->points[4], &rotated[0], rot);
rotate(&q->points[4], &rotated[1], rot);
rotate(&q->points[4], &rotated[2], rot);
rotate(&q->points[4], &rotated[3], rot);
}
gfx_quads_draw_freeform(
fx2f(points[0].x)+offset_x, fx2f(points[0].y)+offset_y,
fx2f(points[1].x)+offset_x, fx2f(points[1].y)+offset_y,
fx2f(points[2].x)+offset_x, fx2f(points[2].y)+offset_y,
fx2f(points[3].x)+offset_x, fx2f(points[3].y)+offset_y
);
}
gfx_quads_end();
}
void render_tilemap(TILE *tiles, int w, int h, float scale)
{
//gfx_texture_set(img_get(tmap->image));
float screen_x0, screen_y0, screen_x1, screen_y1;
gfx_getscreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
// calculate the final pixelsize for the tiles
float tile_pixelsize = 1024/32.0f;
float final_tilesize = scale/(screen_x1-screen_x0) * gfx_screenwidth();
float final_tilesize_scale = final_tilesize/tile_pixelsize;
gfx_quads_begin();
int starty = (int)(screen_y0/scale)-1;
int startx = (int)(screen_x0/scale)-1;
int endy = (int)(screen_y1/scale)+1;
int endx = (int)(screen_x1/scale)+1;
// adjust the texture shift according to mipmap level
float texsize = 1024.0f;
float frac = (1.25f/texsize) * (1/final_tilesize_scale);
float nudge = (0.5f/texsize) * (1/final_tilesize_scale);
for(int y = starty; y < endy; y++)
for(int x = startx; x < endx; x++)
{
int mx = x;
int my = y;
if(mx<0)
continue; // mx = 0;
if(mx>=w)
continue; // mx = w-1;
if(my<0)
continue; // my = 0;
if(my>=h)
continue; // my = h-1;
int c = mx + my*w;
unsigned char index = tiles[c].index;
if(index)
{
unsigned char flags = tiles[c].flags;
int tx = index%16;
int ty = index/16;
int px0 = tx*(1024/16);
int py0 = ty*(1024/16);
int px1 = (tx+1)*(1024/16)-1;
int py1 = (ty+1)*(1024/16)-1;
float u0 = nudge + px0/texsize+frac;
float v0 = nudge + py0/texsize+frac;
float u1 = nudge + px1/texsize-frac;
float v1 = nudge + py1/texsize-frac;
if(flags&TILEFLAG_VFLIP)
{
float tmp = u0;
u0 = u1;
u1 = tmp;
}
if(flags&TILEFLAG_HFLIP)
{
float tmp = v0;
v0 = v1;
v1 = tmp;
}
gfx_quads_setsubset(u0,v0,u1,v1);
gfx_quads_drawTL(x*scale, y*scale, scale, scale);
}
}
gfx_quads_end();
}

View file

@ -0,0 +1,478 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <math.h>
#include <engine/e_interface.h>
#include <engine/e_config.h>
#include "../generated/gc_data.h"
#include "../g_protocol.h"
#include "../g_math.h"
#include "gc_render.h"
#include "gc_anim.h"
#include "gc_client.h"
void render_projectile(const obj_projectile *current, int itemid)
{
/*
if(debug_firedelay)
{
debug_firedelay = time_get()-debug_firedelay;
dbg_msg("game", "firedelay=%.2f ms", debug_firedelay/(float)time_freq()*1000.0f);
debug_firedelay = 0;
}*/
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
// get positions
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);
vec2 startvel(current->vx, current->vy);
vec2 pos = calc_pos(startpos, startvel, gravity, ct);
vec2 prevpos = calc_pos(startpos, startvel, gravity, ct-0.001f);
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));
else
gfx_quads_setrotation(0);
// TODO: do this, but nice
//temp_system.new_particle(pos, vec2(0,0), 0.3f, 14.0f, 0, 0.95f);
gfx_quads_draw(pos.x, pos.y, 32, 32);
gfx_quads_setrotation(0);
gfx_quads_end();
}
void render_powerup(const obj_powerup *prev, const obj_powerup *current)
{
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
float angle = 0.0f;
float size = 64.0f;
if (current->type == POWERUP_WEAPON)
{
angle = 0; //-pi/6;//-0.25f * pi * 2.0f;
select_sprite(data->weapons[current->subtype%data->num_weapons].sprite_body);
size = data->weapons[current->subtype%data->num_weapons].visual_size;
}
else
{
const int c[] = {
SPRITE_POWERUP_HEALTH,
SPRITE_POWERUP_ARMOR,
SPRITE_POWERUP_WEAPON,
SPRITE_POWERUP_NINJA,
SPRITE_POWERUP_TIMEFIELD
};
select_sprite(c[current->type]);
if(c[current->type] == SPRITE_POWERUP_NINJA)
{
/*
proj_particles.addparticle(0, 0,
pos+vec2((frandom()-0.5f)*80.0f, (frandom()-0.5f)*20.0f),
vec2((frandom()-0.5f)*10.0f, (frandom()-0.5f)*10.0f));*/
size *= 2.0f;
pos.x += 10.0f;
}
}
gfx_quads_setrotation(angle);
float offset = pos.y/32.0f + pos.x/32.0f;
pos.x += cosf(client_localtime()*2.0f+offset)*2.5f;
pos.y += sinf(client_localtime()*2.0f+offset)*2.5f;
draw_sprite(pos.x, pos.y, size);
gfx_quads_end();
}
void render_flag(const obj_flag *prev, const obj_flag *current)
{
float angle = 0.0f;
float size = 42.0f;
gfx_blend_normal();
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
if(current->team == 0) // red team
select_sprite(SPRITE_FLAG_RED);
else
select_sprite(SPRITE_FLAG_BLUE);
gfx_quads_setrotation(angle);
vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
if(local_info && current->carried_by == local_info->clientid)
pos = local_character_pos;
//gfx_setcolor(current->team ? 0 : 1,0,current->team ? 1 : 0,1);
//draw_sprite(pos.x, pos.y, size);
gfx_quads_draw(pos.x, pos.y-size*0.75f, size, size*2);
gfx_quads_end();
}
static void render_hand(tee_render_info *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset)
{
// for drawing hand
//const skin *s = skin_get(skin_id);
float basesize = 10.0f;
//dir = normalize(hook_pos-pos);
vec2 hand_pos = center_pos + dir;
float angle = get_angle(dir);
if (dir.x < 0)
angle -= angle_offset;
else
angle += angle_offset;
vec2 dirx = dir;
vec2 diry(-dir.y,dir.x);
if (dir.x < 0)
diry = -diry;
hand_pos += dirx * post_rot_offset.x;
hand_pos += diry * post_rot_offset.y;
//gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id);
gfx_texture_set(info->texture);
gfx_quads_begin();
gfx_setcolor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a);
// two passes
for (int i = 0; i < 2; i++)
{
bool outline = i == 0;
select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0);
gfx_quads_setrotation(angle);
gfx_quads_draw(hand_pos.x, hand_pos.y, 2*basesize, 2*basesize);
}
gfx_quads_setrotation(0);
gfx_quads_end();
}
void render_player(
const obj_player_character *prev_char,
const obj_player_character *player_char,
const obj_player_info *prev_info,
const obj_player_info *player_info
)
{
obj_player_character prev;
obj_player_character player;
prev = *prev_char;
player = *player_char;
obj_player_info info = *player_info;
float intratick = client_intratick();
float ticktime = client_ticktime();
if(player.health < 0) // dont render dead players
return;
if(info.local && config.cl_predict)
{
if(!local_character || (local_character->health < 0) || (gameobj && gameobj->game_over))
{
}
else
{
// apply predicted results
predicted_player.write(&player);
predicted_prev_player.write(&prev);
intratick = client_intrapredtick();
}
}
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);
if(prev.health < 0) // Don't flicker from previous position
position = vec2(player.x, player.y);
bool stationary = player.vx < 1 && player.vx > -1;
bool inair = col_check_point(player.x, player.y+16) == 0;
// evaluate animation
float walk_time = fmod(position.x, 100.0f)/100.0f;
animstate state;
anim_eval(&data->animations[ANIM_BASE], 0, &state);
if(inair)
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
anim_eval_add(&state, &data->animations[ANIM_WALK], walk_time, 1.0f);
if (player.weapon == WEAPON_HAMMER)
{
float a = clamp((client_tick()-player.attacktick+ticktime)/10.0f, 0.0f, 1.0f);
anim_eval_add(&state, &data->animations[ANIM_HAMMER_SWING], a, 1.0f);
}
if (player.weapon == WEAPON_NINJA)
{
float a = clamp((client_tick()-player.attacktick+ticktime)/40.0f, 0.0f, 1.0f);
anim_eval_add(&state, &data->animations[ANIM_NINJA_SWING], a, 1.0f);
}
// draw hook
if (prev.hook_state>0 && player.hook_state>0)
{
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
//gfx_quads_begin();
vec2 pos = position;
vec2 hook_pos;
if(player_char->hooked_player != -1)
{
if(local_info && player_char->hooked_player == local_info->clientid)
{
hook_pos = mix(vec2(predicted_prev_player.pos.x, predicted_prev_player.pos.y),
vec2(predicted_player.pos.x, predicted_player.pos.y), client_intrapredtick());
}
else
hook_pos = mix(vec2(prev_char->hook_x, prev_char->hook_y), vec2(player_char->hook_x, player_char->hook_y), client_intratick());
}
else
hook_pos = mix(vec2(prev.hook_x, prev.hook_y), vec2(player.hook_x, player.hook_y), intratick);
float d = distance(pos, hook_pos);
vec2 dir = normalize(pos-hook_pos);
gfx_quads_setrotation(get_angle(dir)+pi);
// render head
select_sprite(SPRITE_HOOK_HEAD);
gfx_quads_draw(hook_pos.x, hook_pos.y, 24,16);
// render chain
select_sprite(SPRITE_HOOK_CHAIN);
for(float f = 24; f < d; f += 24)
{
vec2 p = hook_pos + dir*f;
gfx_quads_draw(p.x, p.y,24,16);
}
gfx_quads_setrotation(0);
gfx_quads_end();
render_hand(&client_datas[info.clientid].render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0));
}
// draw gun
{
gfx_texture_set(data->images[IMAGE_GAME].id);
gfx_quads_begin();
gfx_quads_setrotation(state.attach.angle*pi*2+angle);
// normal weapons
int iw = clamp(player.weapon, 0, NUM_WEAPONS-1);
select_sprite(data->weapons[iw].sprite_body, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
vec2 dir = direction;
float recoil = 0.0f;
vec2 p;
if (player.weapon == WEAPON_HAMMER)
{
// Static position for hammer
p = position;
p.y += data->weapons[iw].offsety;
// if attack is under way, bash stuffs
if(direction.x < 0)
{
gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
p.x -= data->weapons[iw].offsetx;
}
else
{
gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
}
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
}
else if (player.weapon == WEAPON_NINJA)
{
p = position;
p.y += data->weapons[iw].offsety;
if(direction.x < 0)
{
gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
p.x -= data->weapons[iw].offsetx;
}
else
{
gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
}
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
// HADOKEN
if ((client_tick()-player.attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons[iw].nummuzzlesprites)
{
int itex = rand() % data->weapons[iw].nummuzzlesprites;
float alpha = 1.0f;
if (alpha > 0.0f && data->weapons[iw].sprite_muzzle[itex].psprite)
{
vec2 dir = vec2(player_char->x,player_char->y) - vec2(prev_char->x, prev_char->y);
dir = normalize(dir);
float hadokenangle = get_angle(dir);
gfx_quads_setrotation(hadokenangle);
//float offsety = -data->weapons[iw].muzzleoffsety;
select_sprite(data->weapons[iw].sprite_muzzle[itex].psprite, 0);
vec2 diry(-dir.y,dir.x);
p = position;
float offsetx = data->weapons[iw].muzzleoffsetx;
p -= dir * offsetx;
draw_sprite(p.x, p.y, 160.0f);
}
}
}
else
{
// TODO: should be an animation
recoil = 0;
float a = (client_tick()-player.attacktick+intratick)/5.0f;
if(a < 1)
recoil = sinf(a*pi);
p = position + dir * data->weapons[iw].offsetx - dir*recoil*10.0f;
p.y += data->weapons[iw].offsety;
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
}
if (player.weapon == WEAPON_GUN || player.weapon == WEAPON_SHOTGUN)
{
// check if we're firing stuff
if (true)//prev.attackticks)
{
float alpha = 0.0f;
int phase1tick = (client_tick() - player.attacktick);
if (phase1tick < (data->weapons[iw].muzzleduration + 3))
{
float t = ((((float)phase1tick) + intratick)/(float)data->weapons[iw].muzzleduration);
alpha = LERP(2.0, 0.0f, min(1.0f,max(0.0f,t)));
}
int itex = rand() % data->weapons[iw].nummuzzlesprites;
if (alpha > 0.0f && data->weapons[iw].sprite_muzzle[itex].psprite)
{
float offsety = -data->weapons[iw].muzzleoffsety;
select_sprite(data->weapons[iw].sprite_muzzle[itex].psprite, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
if(direction.x < 0)
offsety = -offsety;
vec2 diry(-dir.y,dir.x);
vec2 muzzlepos = p + dir * data->weapons[iw].muzzleoffsetx + diry * offsety;
draw_sprite(muzzlepos.x, muzzlepos.y, data->weapons[iw].visual_size);
/*gfx_setcolor(1.0f,1.0f,1.0f,alpha);
vec2 diry(-dir.y,dir.x);
p += dir * muzzleparams[player.weapon].offsetx + diry * offsety;
gfx_quads_draw(p.x,p.y,muzzleparams[player.weapon].sizex, muzzleparams[player.weapon].sizey);*/
}
}
}
gfx_quads_end();
switch (player.weapon)
{
case WEAPON_GUN: render_hand(&client_datas[info.clientid].render_info, p, direction, -3*pi/4, vec2(-15, 4)); break;
case WEAPON_SHOTGUN: render_hand(&client_datas[info.clientid].render_info, p, direction, -pi/2, vec2(-5, 4)); break;
case WEAPON_ROCKET: render_hand(&client_datas[info.clientid].render_info, p, direction, -pi/2, vec2(-4, 7)); break;
}
}
// render the "shadow" tee
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;
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);
if(player.state == STATE_CHATTING)
{
gfx_texture_set(data->images[IMAGE_EMOTICONS].id);
gfx_quads_begin();
select_sprite(SPRITE_DOTDOT);
gfx_quads_draw(position.x + 24, position.y - 40, 64,64);
gfx_quads_end();
}
if (client_datas[info.clientid].emoticon_start != -1 && client_datas[info.clientid].emoticon_start + 2 * client_tickspeed() > client_tick())
{
gfx_texture_set(data->images[IMAGE_EMOTICONS].id);
gfx_quads_begin();
int since_start = client_tick() - client_datas[info.clientid].emoticon_start;
int from_end = client_datas[info.clientid].emoticon_start + 2 * client_tickspeed() - client_tick();
float a = 1;
if (from_end < client_tickspeed() / 5)
a = from_end / (client_tickspeed() / 5.0);
float h = 1;
if (since_start < client_tickspeed() / 10)
h = since_start / (client_tickspeed() / 10.0);
float wiggle = 0;
if (since_start < client_tickspeed() / 5)
wiggle = since_start / (client_tickspeed() / 5.0);
float wiggle_angle = sin(5*wiggle);
gfx_quads_setrotation(pi/6*wiggle_angle);
gfx_setcolor(1.0f,1.0f,1.0f,a);
// client_datas::emoticon is an offset from the first emoticon
select_sprite(SPRITE_OOP + client_datas[info.clientid].emoticon);
gfx_quads_draw(position.x, position.y - 23 - 32*h, 64, 64*h);
gfx_quads_end();
}
// render name plate
if(!info.local && config.cl_nameplates)
{
//gfx_text_color
float a = 1;
if(config.cl_nameplates_always == 0)
a = clamp(1-powf(distance(local_target_pos, position)/200.0f,16.0f), 0.0f, 1.0f);
const char *name = client_datas[info.clientid].name;
float tw = gfx_text_width(0, 28.0f, name, -1);
gfx_text_color(1,1,1,a);
gfx_text(0, position.x-tw/2.0f, position.y-60, 28.0f, name, -1);
gfx_text_color(1,1,1,1);
}
}

View file

@ -1,3 +1,5 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -15,8 +17,9 @@ extern "C" {
//#include "game/mapres_col.h" //#include "game/mapres_col.h"
#include <game/g_mapres.h> #include <game/g_mapres.h>
#include <game/g_game.h> #include <game/g_game.h>
#include <game/client/gc_render.h>
#include "editor.hpp" #include "ed_editor.hpp"
static int checker_texture = 0; static int checker_texture = 0;
static int background_texture = 0; static int background_texture = 0;
@ -116,9 +119,6 @@ int LAYERGROUP::swap_layers(int index0, int index1)
/******************************************************** /********************************************************
OTHER OTHER
*********************************************************/ *********************************************************/
extern void draw_round_rect_ext(float x, float y, float w, float h, float r, int corners);
extern void draw_round_rect(float x, float y, float w, float h, float r);
static void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding) static void ui_draw_rect(const RECT *r, vec4 color, int corners, float rounding)
{ {
gfx_texture_set(-1); gfx_texture_set(-1);
@ -1961,67 +1961,6 @@ void EDITOR::make_game_group(LAYERGROUP *group)
editor.game_group->name = "Game"; editor.game_group->name = "Game";
} }
typedef struct
{
int version;
int width;
int height;
int external;
int image_name;
int image_data;
} MAPITEM_IMAGE;
typedef struct
{
int version;
int offset_x;
int offset_y;
int parallax_x;
int parallax_y;
int start_layer;
int num_layers;
} MAPITEM_GROUP;
typedef struct
{
int version;
int type;
int flags;
} MAPITEM_LAYER;
typedef struct
{
MAPITEM_LAYER layer;
int version;
int width;
int height;
int flags;
COLOR color;
int color_env;
int color_env_offset;
int image;
int data;
} MAPITEM_LAYER_TILEMAP;
typedef struct
{
MAPITEM_LAYER layer;
int version;
int num_quads;
int data;
int image;
} MAPITEM_LAYER_QUADS;
typedef struct
{
int version;
} MAPITEM_VERSION;
template<typename T> template<typename T>
static int make_version(int i, const T &v) static int make_version(int i, const T &v)
{ return (i<<16)+sizeof(T); } { return (i<<16)+sizeof(T); }
@ -2411,6 +2350,7 @@ extern "C" void editor_init()
editor.show_envelope_editor = 1; editor.show_envelope_editor = 1;
#endif #endif
/*
if(1) if(1)
{ {
float w, h; float w, h;
@ -2426,7 +2366,7 @@ extern "C" void editor_init()
calc_screen_params(amount, max, max, 9.0f/16.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h); calc_screen_params(amount, max, max, 9.0f/16.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h);
calc_screen_params(amount, max, max, 16.0f/3.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h); calc_screen_params(amount, max, max, 16.0f/3.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h);
calc_screen_params(amount, max, max, 3.0f/16.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h); calc_screen_params(amount, max, max, 3.0f/16.0f, &w, &h); dbg_msg("", "%f %f %f", w, h, w*h);
} }*/
} }
extern "C" void editor_update_and_render() extern "C" void editor_update_and_render()

View file

@ -1,6 +1,9 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "array.h" #include "array.h"
#include "../g_mapitems.h"
extern "C" { extern "C" {
#include <engine/e_system.h> #include <engine/e_system.h>
@ -28,76 +31,14 @@ enum
DIALOG_NONE=0, DIALOG_NONE=0,
DIALOG_LOAD_IMAGE, DIALOG_LOAD_IMAGE,
LAYERTYPE_INVALID=0,
LAYERTYPE_GAME,
LAYERTYPE_TILES,
LAYERTYPE_QUADS,
}; };
typedef struct
{
int x, y; // 22.10 fixed point
} POINT;
// float to fixed
inline int f2fx(float v) { return (int)(v*(float)(1<<10)); }
inline float fx2f(int v) { return v*(1.0f/(1<<10)); }
typedef struct // as in file
{
int r, g, b, a;
} COLOR;
typedef struct // as in file
{
POINT points[5];
COLOR colors[4];
POINT texcoords[4];
int pos_env;
int pos_env_offset;
int color_env;
int color_env_offset;
} QUAD;
typedef struct // as in file typedef struct // as in file
{ {
POINT position; POINT position;
int type; int type;
} ENTITY; } ENTITY;
enum
{
ENTITY_NULL=0,
ENTITY_SPAWN,
ENTITY_SPAWN_RED,
ENTITY_SPAWN_BLUE,
ENTITY_FLAGSTAND_RED,
ENTITY_FLAGSTAND_BLUE,
ENTITY_ARMOR_1,
ENTITY_HEATH_1,
ENTITY_WEAPON_SHOTGUN,
ENTITY_WEAPON_ROCKET,
ENTITY_POWERUP_NINJA,
NUM_ENTITIES,
TILE_AIR=0,
TILE_SOLID,
TILE_NOHOOK,
ENTITY_OFFSET=255-16*4,
};
typedef struct // as in file
{
unsigned char index;
unsigned char flags;
unsigned char reserved1;
unsigned char reserved2;
} TILE;
enum enum
{ {
CURVETYPE_STEP=0, CURVETYPE_STEP=0,
@ -531,39 +472,3 @@ public:
virtual void render_properties(RECT *toolbox); virtual void render_properties(RECT *toolbox);
}; };
inline void calc_screen_params(float amount, float wmax, float hmax, float aspect, float *w, float *h)
{
float f = sqrt(amount) / sqrt(aspect);
*w = f*aspect;
*h = f;
// limit the view
if(*w > wmax)
{
*w = wmax;
*h = *w/aspect;
}
if(*h > hmax)
{
*h = hmax;
*w = *h*aspect;
}
}
inline void mapscreen_to_world(float center_x, float center_y, float parallax_x, float parallax_y,
float offset_x, float offset_y, float aspect, float zoom, float *points)
{
float width, height;
calc_screen_params(1300*1000, 1500, 1050, aspect, &width, &height);
center_x *= parallax_x;
center_y *= parallax_y;
width *= zoom;
height *= zoom;
points[0] = offset_x+center_x-width/2;
points[1] = offset_y+center_y-height/2;
points[2] = offset_x+center_x+width/2;
points[3] = offset_y+center_y+height/2;
}

View file

@ -1,5 +1,5 @@
#include <game/client/gc_mapres_tilemap.h> #include <game/client/gc_mapres_tilemap.h>
#include "editor.hpp" #include "ed_editor.hpp"
LAYER_GAME::LAYER_GAME(int w, int h) LAYER_GAME::LAYER_GAME(int w, int h)

View file

@ -1,5 +1,7 @@
#include "editor.hpp" #include "ed_editor.hpp"
#include <game/g_math.h> #include <game/g_math.h>
#include <game/generated/gc_data.h>
#include <game/client/gc_render.h>
LAYER_QUADS::LAYER_QUADS() LAYER_QUADS::LAYER_QUADS()
{ {
@ -12,88 +14,6 @@ LAYER_QUADS::~LAYER_QUADS()
{ {
} }
static void rotate(POINT *center, POINT *point, float rotation)
{
int x = point->x - center->x;
int y = point->y - center->y;
point->x = (int)(x * cosf(rotation) - y * sinf(rotation) + center->x);
point->y = (int)(x * sinf(rotation) + y * cosf(rotation) + center->y);
}
static void render_quads(QUAD *quads, int num_quads)
{
gfx_quads_begin();
float conv = 1/255.0f;
for(int i = 0; i < num_quads; i++)
{
QUAD *q = &quads[i];
gfx_quads_setsubset_free(
fx2f(q->texcoords[0].x), fx2f(q->texcoords[0].y),
fx2f(q->texcoords[1].x), fx2f(q->texcoords[1].y),
fx2f(q->texcoords[2].x), fx2f(q->texcoords[2].y),
fx2f(q->texcoords[3].x), fx2f(q->texcoords[3].y)
);
float r=1, g=1, b=1, a=1;
float offset_x = 0;
float offset_y = 0;
float rot = 0;
if(editor.animate)
{
if(q->pos_env >= 0 && q->pos_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->pos_env];
float t = editor.animate_time+q->pos_env_offset/1000.0f;
offset_x = e->eval(t, 0);
offset_y = e->eval(t, 1);
rot = e->eval(t, 2);
}
if(q->color_env >= 0 && q->color_env < editor.map.envelopes.len())
{
ENVELOPE *e = editor.map.envelopes[q->color_env];
float t = editor.animate_time+q->color_env_offset/1000.0f;
r = e->eval(t, 0);
g = e->eval(t, 1);
b = e->eval(t, 2);
a = e->eval(t, 3);
}
}
gfx_setcolorvertex(0, q->colors[0].r*conv*r, q->colors[0].g*conv*g, q->colors[0].b*conv*b, q->colors[0].a*conv*a);
gfx_setcolorvertex(1, q->colors[1].r*conv*r, q->colors[1].g*conv*g, q->colors[1].b*conv*b, q->colors[1].a*conv*a);
gfx_setcolorvertex(2, q->colors[2].r*conv*r, q->colors[2].g*conv*g, q->colors[2].b*conv*b, q->colors[2].a*conv*a);
gfx_setcolorvertex(3, q->colors[3].r*conv*r, q->colors[3].g*conv*g, q->colors[3].b*conv*b, q->colors[3].a*conv*a);
POINT *points = q->points;
if(rot != 0)
{
static POINT rotated[4];
rotated[0] = q->points[0];
rotated[1] = q->points[1];
rotated[2] = q->points[2];
rotated[3] = q->points[3];
points = rotated;
rotate(&q->points[4], &rotated[0], rot);
rotate(&q->points[4], &rotated[1], rot);
rotate(&q->points[4], &rotated[2], rot);
rotate(&q->points[4], &rotated[3], rot);
}
gfx_quads_draw_freeform(
fx2f(points[0].x)+offset_x, fx2f(points[0].y)+offset_y,
fx2f(points[1].x)+offset_x, fx2f(points[1].y)+offset_y,
fx2f(points[2].x)+offset_x, fx2f(points[2].y)+offset_y,
fx2f(points[3].x)+offset_x, fx2f(points[3].y)+offset_y
);
}
gfx_quads_end();
}
void LAYER_QUADS::render() void LAYER_QUADS::render()
{ {
gfx_texture_set(-1); gfx_texture_set(-1);

View file

@ -1,84 +1,8 @@
#include <game/client/gc_mapres_tilemap.h> #include <game/client/gc_mapres_tilemap.h>
#include <game/g_math.h> #include <game/g_math.h>
#include "editor.hpp" #include <game/generated/gc_data.h>
#include <game/client/gc_render.h>
static void render_tilemap(TILE *tiles, int w, int h, float scale) #include "ed_editor.hpp"
{
//gfx_texture_set(img_get(tmap->image));
float screen_x0, screen_y0, screen_x1, screen_y1;
gfx_getscreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
// calculate the final pixelsize for the tiles
float tile_pixelsize = 1024/32.0f;
float final_tilesize = scale/(screen_x1-screen_x0) * gfx_screenwidth();
float final_tilesize_scale = final_tilesize/tile_pixelsize;
gfx_quads_begin();
int starty = (int)(screen_y0/scale)-1;
int startx = (int)(screen_x0/scale)-1;
int endy = (int)(screen_y1/scale)+1;
int endx = (int)(screen_x1/scale)+1;
// adjust the texture shift according to mipmap level
float texsize = 1024.0f;
float frac = (1.25f/texsize) * (1/final_tilesize_scale);
float nudge = (0.5f/texsize) * (1/final_tilesize_scale);
for(int y = starty; y < endy; y++)
for(int x = startx; x < endx; x++)
{
int mx = x;
int my = y;
if(mx<0)
continue; // mx = 0;
if(mx>=w)
continue; // mx = w-1;
if(my<0)
continue; // my = 0;
if(my>=h)
continue; // my = h-1;
int c = mx + my*w;
unsigned char index = tiles[c].index;
if(index)
{
unsigned char flags = tiles[c].flags;
int tx = index%16;
int ty = index/16;
int px0 = tx*(1024/16);
int py0 = ty*(1024/16);
int px1 = (tx+1)*(1024/16)-1;
int py1 = (ty+1)*(1024/16)-1;
float u0 = nudge + px0/texsize+frac;
float v0 = nudge + py0/texsize+frac;
float u1 = nudge + px1/texsize-frac;
float v1 = nudge + py1/texsize-frac;
if(flags&TILEFLAG_VFLIP)
{
float tmp = u0;
u0 = u1;
u1 = tmp;
}
if(flags&TILEFLAG_HFLIP)
{
float tmp = v0;
v0 = v1;
v1 = tmp;
}
gfx_quads_setsubset(u0,v0,u1,v1);
gfx_quads_drawTL(x*scale, y*scale, scale, scale);
}
}
gfx_quads_end();
}
LAYER_TILES::LAYER_TILES(int w, int h) LAYER_TILES::LAYER_TILES(int w, int h)
{ {

View file

@ -1,4 +1,7 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#ifndef GAME_GAME_H
#define GAME_GAME_H
#include <engine/e_system.h> #include <engine/e_system.h>
#include <game/g_math.h> #include <game/g_math.h>
#include <math.h> #include <math.h>
@ -169,3 +172,5 @@ enum
ITEM_ARMOR=0x00030001, ITEM_ARMOR=0x00030001,
ITEM_NINJA=0x00040001, ITEM_NINJA=0x00040001,
}; };
#endif

138
src/game/g_mapitems.h Normal file
View file

@ -0,0 +1,138 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#ifndef GAME_MAPITEMS_H
#define GAME_MAPITEMS_H
// layer types
enum
{
LAYERTYPE_INVALID=0,
LAYERTYPE_GAME, // not used
LAYERTYPE_TILES,
LAYERTYPE_QUADS,
};
// game layer tiles
enum
{
ENTITY_NULL=0,
ENTITY_SPAWN,
ENTITY_SPAWN_RED,
ENTITY_SPAWN_BLUE,
ENTITY_FLAGSTAND_RED,
ENTITY_FLAGSTAND_BLUE,
ENTITY_ARMOR_1,
ENTITY_HEATH_1,
ENTITY_WEAPON_SHOTGUN,
ENTITY_WEAPON_ROCKET,
ENTITY_POWERUP_NINJA,
NUM_ENTITIES,
TILE_AIR=0,
TILE_SOLID,
TILE_NOHOOK,
TILEFLAG_VFLIP=1,
TILEFLAG_HFLIP=2,
ENTITY_OFFSET=255-16*4,
};
typedef struct
{
int x, y; // 22.10 fixed point
} POINT;
typedef struct
{
int r, g, b, a;
} COLOR;
typedef struct
{
POINT points[5];
COLOR colors[4];
POINT texcoords[4];
int pos_env;
int pos_env_offset;
int color_env;
int color_env_offset;
} QUAD;
typedef struct
{
unsigned char index;
unsigned char flags;
unsigned char reserved1;
unsigned char reserved2;
} TILE;
typedef struct
{
int version;
int width;
int height;
int external;
int image_name;
int image_data;
} MAPITEM_IMAGE;
typedef struct
{
int version;
int offset_x;
int offset_y;
int parallax_x;
int parallax_y;
int start_layer;
int num_layers;
} MAPITEM_GROUP;
typedef struct
{
int version;
int type;
int flags;
} MAPITEM_LAYER;
typedef struct
{
MAPITEM_LAYER layer;
int version;
int width;
int height;
int flags;
COLOR color;
int color_env;
int color_env_offset;
int image;
int data;
} MAPITEM_LAYER_TILEMAP;
typedef struct
{
MAPITEM_LAYER layer;
int version;
int num_quads;
int data;
int image;
} MAPITEM_LAYER_QUADS;
typedef struct
{
int version;
} MAPITEM_VERSION;
// float to fixed
inline int f2fx(float v) { return (int)(v*(float)(1<<10)); }
inline float fx2f(int v) { return v*(1.0f/(1<<10)); }
#endif

View file

@ -1,4 +1,8 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#ifndef GAME_MAPRES_COL_H
#define GAME_MAPRES_COL_H
#include <game/g_vmath.h> #include <game/g_vmath.h>
struct mapres_collision struct mapres_collision
@ -13,3 +17,5 @@ int col_check_point(int x, int y);
int col_width(); int col_width();
int col_height(); int col_height();
bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out); bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out);
#endif

View file

@ -2,6 +2,8 @@
#ifndef BASE_MATH_H #ifndef BASE_MATH_H
#define BASE_MATH_H #define BASE_MATH_H
#include <stdlib.h>
template <typename T> template <typename T>
inline T clamp(T val, T min, T max) inline T clamp(T val, T min, T max)
{ {
@ -22,6 +24,9 @@ inline T mix(const T a, const T b, TB amount)
{ {
return a + (b-a)*amount; return a + (b-a)*amount;
} }
inline float frandom() { return rand()/(float)(RAND_MAX); }
const float pi = 3.1415926535897932384626433f; const float pi = 3.1415926535897932384626433f;
template <typename T> inline T min(T a, T b) { return a<b?a:b; } template <typename T> inline T min(T a, T b) { return a<b?a:b; }

View file

@ -1,6 +1,9 @@
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
// NOTE: Be very careful when editing this file as it will change the network version // NOTE: Be very careful when editing this file as it will change the network version
#ifndef GAME_PROTOCOL_H
#define GAME_PROTOCOL_H
// --------- PHYSICS TWEAK! -------- // --------- PHYSICS TWEAK! --------
const float ground_control_speed = 7.0f; const float ground_control_speed = 7.0f;
const float ground_control_accel = 2.0f; const float ground_control_accel = 2.0f;
@ -213,3 +216,5 @@ struct obj_player_info
int latency; int latency;
int latency_flux; int latency_flux;
}; };
#endif