about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-07 23:43:14 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-07 23:43:14 +0000
commitdf434e3163511936572a7f6e71e2abeb9738e3e7 (patch)
tree855bb93ca7bd6f69a44604191831da825721b908
parenta1e1fb01eaf7aefa9bb5254893c4395c044f6dec (diff)
downloadzcatch-df434e3163511936572a7f6e71e2abeb9738e3e7.tar.gz
zcatch-df434e3163511936572a7f6e71e2abeb9738e3e7.zip
fixed more responsive input handling
-rw-r--r--src/engine/client/inp.c88
-rw-r--r--src/engine/interface.h4
-rw-r--r--src/game/client/game_client.cpp50
-rw-r--r--src/game/game_protocol.h7
-rw-r--r--src/game/server/game_server.cpp61
5 files changed, 169 insertions, 41 deletions
diff --git a/src/engine/client/inp.c b/src/engine/client/inp.c
index 6b0ba829..fb29dc6c 100644
--- a/src/engine/client/inp.c
+++ b/src/engine/client/inp.c
@@ -1,3 +1,4 @@
+#include <string.h>
 #include <engine/external/glfw/include/GL/glfw.h>
 
 #include <engine/system.h>
@@ -7,6 +8,19 @@ static int keyboard_state[2][1024]; /* TODO: fix this!! */
 static int keyboard_current = 0;
 static int keyboard_first = 1;
 
+
+static struct
+{
+	unsigned char presses;
+	unsigned char releases;
+} input_count[2][1024] = {{{0}}, {{0}}};
+
+static unsigned char input_state[2][1024] = {{0}, {0}};
+
+/*static unsigned char input_state[2][1024] = {{0},{0}};*/
+/*static unsigned char input_state[1024] = {{0},{0}};*/
+static int input_current = 0;
+
 void inp_mouse_relative(int *x, int *y)
 {
 	static int last_x = 0, last_y = 0;
@@ -29,15 +43,55 @@ static void char_callback(int character, int action)
 
 static void key_callback(int key, int action)
 {
-    if(action == GLFW_PRESS)
-	    last_k = key;
+	if(action == GLFW_PRESS)
+		last_k = key;
+	
+	if(action == GLFW_PRESS)
+		input_count[input_current^1][key].presses++;
+	if(action == GLFW_RELEASE)
+		input_count[input_current^1][key].releases++;
+	input_state[input_current^1][key] = action;
+}
+
+static void mousebutton_callback(int button, int action)
+{
+	if(action == GLFW_PRESS)
+		input_count[input_current^1][KEY_MOUSE_FIRST+button].presses++;
+	if(action == GLFW_RELEASE)
+		input_count[input_current^1][KEY_MOUSE_FIRST+button].releases++;
+	input_state[input_current^1][KEY_MOUSE_FIRST+button] = action;
+}
+
+
+static void mousewheel_callback(int pos)
+{
+	if(pos > 0)
+	{
+		while(pos-- != 0)
+		{
+			input_count[input_current^1][KEY_MOUSE_WHEEL_UP].presses++;
+			input_count[input_current^1][KEY_MOUSE_WHEEL_UP].releases++;
+		}
+	}
+	else if(pos < 0)
+	{
+		while(pos++ != 0)
+		{
+			input_count[input_current^1][KEY_MOUSE_WHEEL_DOWN].presses++;
+			input_count[input_current^1][KEY_MOUSE_WHEEL_DOWN].releases++;
+		}	
+	}
+	glfwSetMouseWheel(0);
 }
 
+
 void inp_init()
 {
 	glfwEnable(GLFW_KEY_REPEAT);
 	glfwSetCharCallback(char_callback);
 	glfwSetKeyCallback(key_callback);
+	glfwSetMouseButtonCallback(mousebutton_callback);
+	glfwSetMouseWheelCallback(mousewheel_callback);
 }
 
 char inp_last_char()
@@ -66,6 +120,21 @@ void inp_mouse_mode_relative()
 	glfwDisable(GLFW_MOUSE_CURSOR);
 }
 
+int inp_key_presses(int key)
+{
+	return input_count[input_current][key].presses;
+}
+
+int inp_key_releases(int key)
+{
+	return input_count[input_current][key].releases;
+}
+
+int inp_key_state(int key)
+{
+	return input_state[input_current][key];
+}
+
 int inp_key_pressed(int key) { return keyboard_state[keyboard_current][key]; }
 int inp_key_was_pressed(int key) { return keyboard_state[keyboard_current^1][key]; }
 int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); }
@@ -74,6 +143,11 @@ int inp_button_pressed(int button) { return keyboard_state[keyboard_current][but
 void inp_update()
 {
     int i, v;
+    
+	/* clear and begin count on the other one */
+	mem_zero(&input_count[input_current], sizeof(input_count[input_current]));
+	memcpy(input_state[input_current], input_state[input_current^1], sizeof(input_state[input_current]));
+	input_current^=1;
 
     if(keyboard_first)
     {
@@ -93,13 +167,13 @@ void inp_update()
     }
 
 	/* handle mouse wheel */
-    i = glfwGetMouseWheel();
+	/*
+	i = glfwGetMouseWheel();
     keyboard_state[keyboard_current][KEY_MOUSE_WHEEL_UP] = 0;
     keyboard_state[keyboard_current][KEY_MOUSE_WHEEL_DOWN] = 0;
-    if(i > 0)
+    if(w > 0)
     	keyboard_state[keyboard_current][KEY_MOUSE_WHEEL_UP] = 1;
-    if(i < 0)
+    if(w < 0)
     	keyboard_state[keyboard_current][KEY_MOUSE_WHEEL_DOWN] = 1;
-    glfwSetMouseWheel(0);
-
+    glfwSetMouseWheel(0);*/
 }
diff --git a/src/engine/interface.h b/src/engine/interface.h
index 1ca692d6..94201ea0 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -766,6 +766,10 @@ void inp_init();
 void inp_mouse_mode_absolute();
 void inp_mouse_mode_relative();
 
+int inp_key_presses(int key);
+int inp_key_releases(int key);
+int inp_key_state(int key);
+
 const char *inp_key_name(int k);
 int inp_key_code(const char *key_name);
 
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp
index 332a84d9..dc135509 100644
--- a/src/game/client/game_client.cpp
+++ b/src/game/client/game_client.cpp
@@ -1786,6 +1786,14 @@ void render_world(float center_x, float center_y, float zoom)
 	damageind.render();	
 }
 
+static void do_input(int *v, int key)
+{
+	*v += inp_key_presses(key) + inp_key_releases(key);
+	if((*v&1) != inp_key_state(key))
+		(*v)++;
+	*v &= INPUT_STATE_MASK;
+}
+
 void render_game()
 {	
 	float width = 400*3.0f;
@@ -1934,12 +1942,10 @@ void render_game()
 	
 	// snap input
 	{
-		player_input input;
-		mem_zero(&input, sizeof(input));
+		static player_input input = {0};
 			
 		input.target_x = (int)mouse_pos.x;
 		input.target_y = (int)mouse_pos.y;
-		input.activeweapon = 0;
 	
 		if(chat_mode != CHATMODE_NONE)
 			input.state = STATE_CHATTING;
@@ -1948,27 +1954,36 @@ void render_game()
 		else
 		{
 			input.state = STATE_PLAYING;
-			input.left = inp_key_pressed(config.key_move_left);
-			input.right = inp_key_pressed(config.key_move_right);
-			input.jump = inp_key_pressed(config.key_jump);
-			// TODO: this is not very well done. it should check this some other way
-			input.fire = emoticon_selector_active ? 0 : inp_key_pressed(config.key_fire);
-			input.hook = inp_key_pressed(config.key_hook);
+			input.left = inp_key_state(config.key_move_left);
+			input.right = inp_key_state(config.key_move_right);
+			input.hook = inp_key_state(config.key_hook);
+			input.jump  = inp_key_state(config.key_jump);
+			
+			if(!emoticon_selector_active)
+				do_input(&input.fire, config.key_fire);
+			
+			// weapon selection
+			do_input(&input.next_weapon, config.key_next_weapon);
+			do_input(&input.prev_weapon, config.key_prev_weapon);
 			
-			// Weapon switching
-			if(inp_key_pressed(config.key_next_weapon)) input.activeweapon = -1;
-			if(inp_key_pressed(config.key_prev_weapon)) input.activeweapon = -2;
-			if(inp_key_pressed(config.key_weapon1)) input.activeweapon = 1;
-			if(inp_key_pressed(config.key_weapon2)) input.activeweapon = 2;
-			if(inp_key_pressed(config.key_weapon3)) input.activeweapon = 3;
-			if(inp_key_pressed(config.key_weapon4)) input.activeweapon = 4;
+			if(inp_key_presses(config.key_next_weapon) || inp_key_presses(config.key_prev_weapon))
+				input.wanted_weapon = 0;
+			else
+			{
+				if(inp_key_presses(config.key_weapon1)) input.wanted_weapon = 1;
+				if(inp_key_presses(config.key_weapon2)) input.wanted_weapon = 2;
+				if(inp_key_presses(config.key_weapon3)) input.wanted_weapon = 3;
+				if(inp_key_presses(config.key_weapon4)) input.wanted_weapon = 4;
+			}
 		}
 		
 		// stress testing
 		if(config.stress)
 		{
-			float t = client_localtime();
+			//float t = client_localtime();
 			mem_zero(&input, sizeof(input));
+			
+			/*
 			input.left = 1;
 			input.jump = ((int)t)&1;
 			input.fire = ((int)(t*10))&1;
@@ -1976,6 +1991,7 @@ void render_game()
 			input.activeweapon = ((int)t)%NUM_WEAPONS;
 			input.target_x = (int)(sinf(t*3)*100.0f);
 			input.target_y = (int)(cosf(t*3)*100.0f);
+			*/
 			
 			//input.target_x = (int)((rand()/(float)RAND_MAX)*64-32);
 			//input.target_y = (int)((rand()/(float)RAND_MAX)*64-32);
diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h
index 56156e24..0300c88a 100644
--- a/src/game/game_protocol.h
+++ b/src/game/game_protocol.h
@@ -60,6 +60,11 @@ enum
 
 enum
 {
+	INPUT_STATE_MASK=0x1f,
+};
+
+enum
+{
 	STATE_UNKNOWN=0,
 	STATE_PLAYING,
 	STATE_IN_MENU,
@@ -82,9 +87,9 @@ struct player_input
 	int fire;
 	int hook;
 	int blink;
-	int activeweapon;
 	int state;
 	
+	int wanted_weapon;
 	int next_weapon;
 	int prev_weapon;
 };
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index ff5dbd84..9821c87f 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -602,6 +602,30 @@ int player::handle_ninja()
 	return 0;
 }
 
+struct input_count
+{
+	int presses;
+	int releases;
+};
+
+static input_count count_input(int prev, int cur)
+{
+	input_count c = {0,0};
+	prev &= INPUT_STATE_MASK;
+	cur &= INPUT_STATE_MASK;
+	int i = prev;
+	while(i != cur)
+	{
+		i = (i+1)&INPUT_STATE_MASK;
+		if(i&1)
+			c.presses++;
+		else
+			c.releases++;
+	}
+	
+	return c;		
+}
+
 int player::handle_weapons()
 {
 	vec2 direction = normalize(vec2(input.target_x, input.target_y));
@@ -630,26 +654,30 @@ int player::handle_weapons()
 		return handle_ninja();
 	}
 
-	// switch weapon if wanted		
-	if(input.activeweapon && data->weapons[active_weapon].duration <= 0)
+	// switch weapon if wanted
+	if(data->weapons[active_weapon].duration <= 0)
 	{
 		int new_weapon = active_weapon;
-		if(input.activeweapon > 0) // straight selection
-			new_weapon = input.activeweapon-1;
-		else if(input.activeweapon == -1 && !previnput.activeweapon) // next weapon
+		int next = count_input(previnput.next_weapon, input.next_weapon).presses;
+		int prev = count_input(previnput.prev_weapon, input.prev_weapon).presses;
+		while(next) // next weapon selection
 		{
-			do
-				new_weapon = (new_weapon+1)%NUM_WEAPONS;
-			while(!weapons[new_weapon].got);
+			new_weapon = (new_weapon+1)%NUM_WEAPONS;
+			if(weapons[new_weapon].got)
+				next--;
 		}
-		else if(input.activeweapon == -2 && !previnput.activeweapon)
+
+		while(prev) // prev weapon selection
 		{
-			do
-				new_weapon = (new_weapon-1)<0?NUM_WEAPONS-1:new_weapon-1;
-			while(!weapons[new_weapon].got);
+			new_weapon = (new_weapon-1)<0?NUM_WEAPONS-1:new_weapon-1;
+			if(weapons[new_weapon].got)
+				prev--;
 		}
-			
-		if(new_weapon >= 0 && new_weapon < NUM_WEAPONS && weapons[new_weapon].got)
+		
+		if(input.wanted_weapon) // direct weapon selection
+			new_weapon = input.wanted_weapon-1;
+				
+		if(new_weapon != active_weapon && new_weapon >= 0 && new_weapon < NUM_WEAPONS && weapons[new_weapon].got)
 		{
 			if(active_weapon != new_weapon)
 				create_sound(pos, SOUND_WEAPON_SWITCH);
@@ -659,7 +687,7 @@ int player::handle_weapons()
 		}
 	}
 	
-	if(!previnput.fire && input.fire)
+	if(count_input(previnput.fire, input.fire).presses) //previnput.fire != input.fire && (input.fire&1))
 	{
 		if(reload_timer == 0)
 		{
@@ -727,6 +755,7 @@ int player::handle_weapons()
 			}
 		}
 	}
+	
 	// Update weapons
 	if (active_weapon == WEAPON_HAMMER && reload_timer > 0)
 	{
@@ -841,7 +870,7 @@ void player::tick()
 	{
 		if(server_tick()-die_tick >= server_tickspeed()*5) // auto respawn after 3 sec
 			respawn();
-		if(input.fire && server_tick()-die_tick >= server_tickspeed()/2) // auto respawn after 0.5 sec
+		if((input.fire&1) && server_tick()-die_tick >= server_tickspeed()/2) // auto respawn after 0.5 sec
 			respawn();
 		return;
 	}