about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-01-13 11:15:32 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-01-13 11:15:32 +0000
commitea245b969d1864441b41d25c7631beccfb39d874 (patch)
tree68fb62ef99cdd90f5dd4ec8edf11e7bb54b7f953
parent906ece7894927983b8ac69e37dd3cb82cfe7aad1 (diff)
downloadzcatch-ea245b969d1864441b41d25c7631beccfb39d874.tar.gz
zcatch-ea245b969d1864441b41d25c7631beccfb39d874.zip
new mapformat in place. continued the cleanup. some effects are gone, gonna be redone so no biggie. CTF isn't working now.
-rw-r--r--data/maps/ctf1_old.map (renamed from data/maps/ctf1.map)bin143516 -> 143516 bytes
-rw-r--r--data/maps/ctf2_old.map (renamed from data/maps/ctf2.map)bin321777 -> 321777 bytes
-rw-r--r--data/maps/dm1_old.map (renamed from data/maps/dm1.map)bin143922 -> 143922 bytes
-rw-r--r--data/maps/dm2_old.map (renamed from data/maps/dm2.map)bin165150 -> 165150 bytes
-rw-r--r--data/maps/dm6_old.map (renamed from data/maps/dm6.map)bin145407 -> 145407 bytes
-rw-r--r--src/engine/client/ec_client.c67
-rw-r--r--src/engine/client/ec_gfx.c36
-rw-r--r--src/engine/e_config_variables.h1
-rw-r--r--src/engine/e_engine.c3
-rw-r--r--src/engine/e_interface.h1
-rw-r--r--src/engine/e_map.c5
-rw-r--r--src/game/client/gc_client.cpp181
-rw-r--r--src/game/client/gc_client.h1
-rw-r--r--src/game/client/gc_hooks.cpp11
-rw-r--r--src/game/client/gc_map_image.cpp (renamed from src/game/client/gc_mapres_image.cpp)15
-rw-r--r--src/game/client/gc_map_image.h (renamed from src/game/client/gc_mapres_image.h)9
-rw-r--r--src/game/client/gc_mapres_tilemap.cpp9
-rw-r--r--src/game/client/gc_menu.cpp3
-rw-r--r--src/game/client/gc_render.cpp149
-rw-r--r--src/game/client/gc_render.h4
-rw-r--r--src/game/client/gc_render_map.cpp33
-rw-r--r--src/game/editor/ed_editor.cpp25
-rw-r--r--src/game/editor/ed_layer_tiles.cpp2
-rw-r--r--src/game/g_collision.cpp (renamed from src/game/g_mapres_col.cpp)93
-rw-r--r--src/game/g_collision.h (renamed from src/game/g_mapres_col.h)11
-rw-r--r--src/game/g_game.cpp4
-rw-r--r--src/game/g_game.h4
-rw-r--r--src/game/g_layers.cpp47
-rw-r--r--src/game/g_layers.h11
-rw-r--r--src/game/g_mapitems.h17
-rw-r--r--src/game/g_protocol.h1
-rw-r--r--src/game/server/gs_server.cpp129
32 files changed, 512 insertions, 360 deletions
diff --git a/data/maps/ctf1.map b/data/maps/ctf1_old.map
index c48d84ac..c48d84ac 100644
--- a/data/maps/ctf1.map
+++ b/data/maps/ctf1_old.map
Binary files differdiff --git a/data/maps/ctf2.map b/data/maps/ctf2_old.map
index daaaff15..daaaff15 100644
--- a/data/maps/ctf2.map
+++ b/data/maps/ctf2_old.map
Binary files differdiff --git a/data/maps/dm1.map b/data/maps/dm1_old.map
index b597e95f..b597e95f 100644
--- a/data/maps/dm1.map
+++ b/data/maps/dm1_old.map
Binary files differdiff --git a/data/maps/dm2.map b/data/maps/dm2_old.map
index 65ea2ce9..65ea2ce9 100644
--- a/data/maps/dm2.map
+++ b/data/maps/dm2_old.map
Binary files differdiff --git a/data/maps/dm6.map b/data/maps/dm6_old.map
index b7868279..b7868279 100644
--- a/data/maps/dm6.map
+++ b/data/maps/dm6_old.map
Binary files differdiff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index bae8cb5c..6a3b4220 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -513,13 +513,15 @@ static void client_debug_render()
 	}
 	
 	/* render graphs */
-	gfx_mapscreen(0,0,400.0f,300.0f);
-	graph_render(&predict_graph, 300, 10, 90, 50);
-	graph_render(&predicted_time.graph, 300, 10+50+10, 90, 50);
-	
-	graph_render(&intra_graph, 300, 10+50+10+50+10, 90, 50);
-	graph_render(&input_late_graph, 300, 10+50+10+50+10+50+10, 90, 50);
-	
+	if(config.dbg_graphs)
+	{
+		gfx_mapscreen(0,0,400.0f,300.0f);
+		graph_render(&predict_graph, 300, 10, 90, 50);
+		graph_render(&predicted_time.graph, 300, 10+50+10, 90, 50);
+		
+		graph_render(&intra_graph, 300, 10+50+10+50+10, 90, 50);
+		graph_render(&input_late_graph, 300, 10+50+10+50+10+50+10, 90, 50);
+	}
 }
 
 void client_quit()
@@ -808,7 +810,7 @@ static void client_process_packet(NETPACKET *packet)
 						recived_snapshots++;
 
 						if(current_recv_tick > 0)
-							snaploss += game_tick-current_recv_tick-1;
+							snaploss += game_tick-current_recv_tick-2;
 						current_recv_tick = game_tick;
 						
 						/* we got two snapshots until we see us self as connected */
@@ -978,6 +980,9 @@ static void client_run()
 	int64 reportinterval = time_freq()*1;
 	int editor_active = 0;
 
+	static PERFORMACE_INFO rootscope = {"root", 0};
+	perf_start(&rootscope);
+
 	local_start_time = time_get();
 	snapshot_part = 0;
 	
@@ -1014,14 +1019,27 @@ static void client_run()
 	
 	while (1)
 	{	
+		static PERFORMACE_INFO rootscope = {"root", 0};
 		int64 frame_start_time = time_get();
 		frames++;
 		
+		perf_start(&rootscope);
+		
 		/* update input */
-		inp_update();
+		{
+			static PERFORMACE_INFO scope = {"inp_update", 0};
+			perf_start(&scope);
+			inp_update();
+			perf_end();
+		}
 
 		/* update sound */		
-		snd_update();
+		{
+			static PERFORMACE_INFO scope = {"snd_update", 0};
+			perf_start(&scope);
+			snd_update();
+			perf_end();
+		}
 		
 		/* refocus */
 		if(!gfx_window_active())
@@ -1085,7 +1103,12 @@ static void client_run()
 		}
 		else
 		{
-			client_update();
+			{
+				static PERFORMACE_INFO scope = {"client_update", 0};
+				perf_start(&scope);
+				client_update();
+				perf_end();
+			}
 			
 			if(config.dbg_stress)
 			{
@@ -1097,10 +1120,24 @@ static void client_run()
 			}
 			else
 			{
-				client_render();
-				gfx_swap();
+				{
+					static PERFORMACE_INFO scope = {"client_render", 0};
+					perf_start(&scope);
+					client_render();
+					perf_end();
+				}
+
+				{
+					static PERFORMACE_INFO scope = {"gfx_swap", 0};
+					perf_start(&scope);
+					gfx_swap();
+					perf_end();
+				}
 			}
 		}
+
+		perf_end();
+
 		
 		/* check conditions */
 		if(client_state() == CLIENTSTATE_QUITING)
@@ -1130,6 +1167,10 @@ static void client_run()
 			frametime_high = 0;
 			frames = 0;
 			reporttime += reportinterval;
+			perf_next();
+			
+			if(config.dbg_pref)
+				perf_dump(&rootscope);
 		}
 		
 		/* update frametime */
diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c
index 754d5d63..771c8515 100644
--- a/src/engine/client/ec_gfx.c
+++ b/src/engine/client/ec_gfx.c
@@ -529,6 +529,7 @@ static int record = 0;
 
 void gfx_swap()
 {
+	#if 0
 	if(record)
 	{
 		int w = screen_width;
@@ -597,10 +598,39 @@ void gfx_swap()
 		mem_free(pixel_data);
 		do_screenshot = 0;
 	}
+	#endif
 	
-	glfwSwapBuffers();
-	glFinish();
-	glfwPollEvents();
+	{
+		static PERFORMACE_INFO pscope = {"glfwSwapBuffers", 0};
+		perf_start(&pscope);
+		glFinish();
+		glfwSwapBuffers();
+		perf_end();
+	}
+	
+	if(0)
+	{
+		static PERFORMACE_INFO pscope = {"glFlush", 0};
+		perf_start(&pscope);
+		glFlush();
+		perf_end();
+	}
+
+	if(0)
+	{
+		static PERFORMACE_INFO pscope = {"glFinish", 0};
+		perf_start(&pscope);
+		glFinish();
+		perf_end();
+	}
+
+	if(0)
+	{
+		static PERFORMACE_INFO pscope = {"glfwPollEvents", 0};
+		perf_start(&pscope);
+		glfwPollEvents();
+		perf_end();
+	}
 }
 
 int gfx_screenwidth()
diff --git a/src/engine/e_config_variables.h b/src/engine/e_config_variables.h
index c3bbc524..7271c530 100644
--- a/src/engine/e_config_variables.h
+++ b/src/engine/e_config_variables.h
@@ -62,6 +62,7 @@ MACRO_CONFIG_INT(sv_status, 0, 0, 1)
 MACRO_CONFIG_INT(debug, 0, 0, 1)
 MACRO_CONFIG_INT(dbg_stress, 0, 0, 0)
 MACRO_CONFIG_INT(dbg_pref, 0, 0, 1)
+MACRO_CONFIG_INT(dbg_graphs, 0, 0, 1)
 MACRO_CONFIG_INT(dbg_hitch, 0, 0, 0)
 MACRO_CONFIG_STR(dbg_stress_server, 32, "localhost")
 
diff --git a/src/engine/e_engine.c b/src/engine/e_engine.c
index 3a3f6333..dc6484d6 100644
--- a/src/engine/e_engine.c
+++ b/src/engine/e_engine.c
@@ -118,6 +118,9 @@ void perf_start(PERFORMACE_INFO *info)
 
 void perf_end()
 {
+	if(!current)
+		return;
+		
 	current->last_delta = time_get()-current->start;
 	current->total += current->last_delta;
 	
diff --git a/src/engine/e_interface.h b/src/engine/e_interface.h
index 57b7e9db..701930ee 100644
--- a/src/engine/e_interface.h
+++ b/src/engine/e_interface.h
@@ -519,6 +519,7 @@ void map_get_type(int type, int *start, int *num);
 		A pointer to the raw data, otherwise 0.
 */
 void *map_get_data(int index);
+void *map_get_data_swapped(int index);
 
 /*
 	Group: Network (Server)
diff --git a/src/engine/e_map.c b/src/engine/e_map.c
index 6dfa4aa6..9f7a910e 100644
--- a/src/engine/e_map.c
+++ b/src/engine/e_map.c
@@ -9,6 +9,11 @@ void *map_get_data(int index)
 	return datafile_get_data(map, index);
 }
 
+void *map_get_data_swapped(int index)
+{
+	return datafile_get_data_swapped(map, index);
+}
+
 void map_unload_data(int index)
 {
 	datafile_unload_data(map, index);
diff --git a/src/game/client/gc_client.cpp b/src/game/client/gc_client.cpp
index 556fabee..d3e3009a 100644
--- a/src/game/client/gc_client.cpp
+++ b/src/game/client/gc_client.cpp
@@ -12,7 +12,8 @@ extern "C" {
 #include "../g_game.h"
 #include "../g_version.h"
 #include "../g_mapres.h"
-#include "gc_mapres_image.h"
+#include "../g_layers.h"
+#include "gc_map_image.h"
 #include "gc_mapres_tilemap.h"
 #include "../generated/gc_data.h"
 #include "gc_menu.h"
@@ -166,7 +167,17 @@ public:
 
 };
 
-static damage_indicators damageind;
+static damage_indicators dmgind;
+
+void effect_damage_indicator(vec2 pos, vec2 dir)
+{
+	dmgind.create(pos, dir);
+}
+
+void render_damage_indicators()
+{
+	dmgind.render();
+}
 
 class particle_system
 {
@@ -404,7 +415,7 @@ void process_events(int snaptype)
 		if(item.type == EVENT_DAMAGEINDICATION)
 		{
 			ev_damageind *ev = (ev_damageind *)data;
-			damageind.create(vec2(ev->x, ev->y), get_direction(ev->angle));
+			effect_damage_indicator(vec2(ev->x, ev->y), get_direction(ev->angle));
 		}
 		else if(item.type == EVENT_AIR_JUMP)
 		{
@@ -1106,163 +1117,6 @@ void render_scoreboard(float x, float y, float w, int team, const char *title)
 	}
 }
 
-void mapscreen_to_world(float center_x, float center_y, float zoom)
-{
-	//const float default_zoom = 1.5f;
-	float width = 300*3*zoom*gfx_screenaspect();
-	float height = 300*3*zoom;
-	gfx_mapscreen(center_x-width/2, center_y-height/2, center_x+width/2, center_y+height/2);
-}
-
-// renders the complete game world
-void render_world(float center_x, float center_y, float zoom)
-{
-	mapscreen_to_world(center_x, center_y, zoom);
-	//gfx_mapscreen(center_x-width/2, center_y-height/2, center_x+width/2, center_y+height/2);
-
-	// render background environment
-	int theme_id = 0;
-	mapres_theme *t = (mapres_theme *)map_find_item(MAPRES_TEMP_THEME, 0);
-	if(t)
-		theme_id = t->id;
-	
-	if(config.gfx_high_detail)
-	{
-		if(theme_id == 1)
-		{
-			// Winter night
-			gfx_mapscreen(0,0,1,1);
-			gfx_texture_set(-1);
-			gfx_quads_begin();
-				vec4 top(0x11/(float)0xff, 0x1a/(float)0xff, 0x21/(float)0xff, 1.0f);
-				vec4 bottom(0x2a/(float)0xff, 0x40/(float)0xff, 0x52/(float)0xff, 1.0f);
-				gfx_setcolorvertex(0, top.r, top.g, top.b, top.a);
-				gfx_setcolorvertex(1, top.r, top.g, top.b, top.a);
-				gfx_setcolorvertex(2, bottom.r, bottom.g, bottom.b, bottom.a);
-				gfx_setcolorvertex(3, bottom.r, bottom.g, bottom.b, bottom.a);
-				gfx_quads_drawTL(0, 0, 1, 1);
-			gfx_quads_end();
-
-			mapscreen_to_world(center_x*0.1f, center_y*0.1f, zoom);
-			render_stars();
-			
-			mapscreen_to_world(center_x, center_y, zoom);
-			
-			render_moon(center_x*0.8f, center_y*0.8f);
-			
-			mapscreen_to_world(center_x, center_y, zoom);
-		}
-		else
-		{
-			// Summer day
-			render_sun(20+center_x*0.6f, 20+center_y*0.6f);
-
-			// draw clouds
-			static vec2 cloud_pos[6] = {vec2(-500,0),vec2(-500,200),vec2(-500,400)};
-			static float cloud_speed[6] = {30, 20, 10};
-			static int cloud_sprites[6] = {SPRITE_CLOUD1, SPRITE_CLOUD2, SPRITE_CLOUD3};
-
-			gfx_texture_set(data->images[IMAGE_CLOUDS].id);
-			gfx_quads_begin();
-			for(int i = 0; i < 3; i++)
-			{
-				float parallax_amount = 0.55f;
-				select_sprite(cloud_sprites[i]);
-				draw_sprite((cloud_pos[i].x+fmod(client_localtime()*cloud_speed[i]+i*100.0f, 3000.0f))+center_x*parallax_amount,
-					cloud_pos[i].y+center_y*parallax_amount, 300);
-			}
-			gfx_quads_end();
-
-			// draw backdrop
-			gfx_texture_set(data->images[IMAGE_BACKDROP].id);
-			gfx_quads_begin();
-			float parallax_amount = 0.25f;
-			for(int x = -1; x < 3; x++)
-				gfx_quads_drawTL(1024*x+center_x*parallax_amount, (center_y)*parallax_amount+150+512, 1024, 512);
-			gfx_quads_end();
-		}
-	}
-	
-	// render background tilemaps
-	tilemap_render(32.0f, 0);
-
-	// render items
-	{
-		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_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);
-			}
-		}
-	}
-
-	// render players above all
-	{
-		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)
-			{
-				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 particles
-	temp_system.update(client_frametime());
-	temp_system.render();
-
-	// render foreground tilemaps
-	tilemap_render(32.0f, 1);
-	
-	// render front environment effects
-	if(config.gfx_high_detail)
-	{
-		if(theme_id == 1)
-		{
-			//mapscreen_to_world(center_x, center_y, zoom);
-			render_snow();
-		}
-	}
-
-	// render damage indications
-	damageind.render();
-}
-
 static int do_input(int *v, int key)
 {
 	*v += inp_key_presses(key) + inp_key_releases(key);
@@ -1534,6 +1388,7 @@ void render_game()
 
 	// pseudo format
 	// ZOOM ZOOM
+	/*
 	float zoom = 3.0;
 
 	// DEBUG TESTING
@@ -1625,7 +1480,7 @@ void render_game()
 			p1f.x,p1f.y);
 
 		gfx_quads_end();
-	}
+	}*/
 
 	if(local_character && !spectate && !(gameobj && gameobj->game_over))
 	{
@@ -1993,8 +1848,8 @@ void render_game()
 			vec2(local_character->x, local_character->y));
 		
 		char buf[512];
-		sprintf(buf, "%f", speed);
-		gfx_text(0, 150, 50, 24, buf, -1);
+		sprintf(buf, "%.2f", speed);
+		gfx_text(0, 150, 50, 12, buf, -1);
 	}
 
 	// render score board
diff --git a/src/game/client/gc_client.h b/src/game/client/gc_client.h
index d34ccc78..f1ff02b1 100644
--- a/src/game/client/gc_client.h
+++ b/src/game/client/gc_client.h
@@ -91,3 +91,4 @@ void reset_projectile_particles();
 void send_info(bool start);
 
 void effect_air_jump(vec2 pos);
+void effect_damage_indicator(vec2 pos, vec2 dir);
diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp
index febb6478..d0754c09 100644
--- a/src/game/client/gc_hooks.cpp
+++ b/src/game/client/gc_hooks.cpp
@@ -11,10 +11,12 @@ extern "C" {
 #include <game/g_game.h>
 #include <game/g_version.h>
 
+#include <game/g_layers.h>
+
 #include "gc_client.h"
 #include "gc_skin.h"
 #include "gc_render.h"
-#include "gc_mapres_image.h"
+#include "gc_map_image.h"
 #include "gc_mapres_tilemap.h"
 
 extern unsigned char internal_data[];
@@ -472,10 +474,11 @@ extern "C" void modc_message(int msg)
 extern "C" void modc_connected()
 {
 	// init some stuff
-	col_init(32);
-	
+	layers_init();
+	col_init();
 	img_init();
-	tilemap_init();
+	
+	//tilemap_init();
 	chat_reset();
 
 	reset_projectile_particles();
diff --git a/src/game/client/gc_mapres_image.cpp b/src/game/client/gc_map_image.cpp
index d8de8a1e..ab4d9aa7 100644
--- a/src/game/client/gc_mapres_image.cpp
+++ b/src/game/client/gc_map_image.cpp
@@ -1,8 +1,8 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <engine/e_system.h>
 #include <engine/e_interface.h>
-#include "gc_mapres_image.h"
-#include "../g_mapres.h"
+#include <game/g_mapitems.h>
+#include "gc_map_image.h"
 
 static int map_textures[64] = {0};
 static int count = 0;
@@ -83,14 +83,15 @@ static void calc_mipmaps(void *data_in, unsigned width, unsigned height, void *d
 		mip_h = mip_h>>1;
 	}
 }
-*/
 extern int DEBUGTEST_MAPIMAGE;
+*/
+
 
 int img_init()
 {
 	int start, count;
-	map_get_type(MAPRES_IMAGE, &start, &count);
-	dbg_msg("mapres_image", "start=%d count=%d", start, count);
+	map_get_type(MAPITEMTYPE_IMAGE, &start, &count);
+	dbg_msg("image", "start=%d count=%d", start, count);
 	for(int i = 0; i < 64; i++)
 	{
 		if(map_textures[i])
@@ -103,14 +104,12 @@ int img_init()
 	//void *data_res = (void*)mem_alloc(1024*1024*4*2, 16);
 	for(int i = 0; i < count; i++)
 	{
-		mapres_image *img = (mapres_image *)map_get_item(start+i, 0, 0);
+		MAPITEM_IMAGE *img = (MAPITEM_IMAGE *)map_get_item(start+i, 0, 0);
 		void *data = map_get_data(img->image_data);
-		//calc_mipmaps(data, img->width, img->height, data_res);
 		map_textures[i] = gfx_load_texture_raw(img->width, img->height, IMG_RGBA, data, IMG_RGBA);
 		map_unload_data(img->image_data);
 	}
 
-	//mem_free(data_res);
 	return count;
 }
 
diff --git a/src/game/client/gc_mapres_image.h b/src/game/client/gc_map_image.h
index f841ca53..d73f43d3 100644
--- a/src/game/client/gc_mapres_image.h
+++ b/src/game/client/gc_map_image.h
@@ -8,12 +8,3 @@ int img_num();
 
 // fetches the texture id for the image
 int img_get(int index);
-
-
-class mapres_image
-{
-public:
-	int width;
-	int height;
-	int image_data;
-};
diff --git a/src/game/client/gc_mapres_tilemap.cpp b/src/game/client/gc_mapres_tilemap.cpp
index 99976b64..239d2d92 100644
--- a/src/game/client/gc_mapres_tilemap.cpp
+++ b/src/game/client/gc_mapres_tilemap.cpp
@@ -1,4 +1,5 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+/*
 #include <engine/e_interface.h>
 #include <engine/e_config.h>
 #include "gc_mapres_tilemap.h"
@@ -15,13 +16,6 @@ int tilemap_init()
 {
 	return 0;
 }
-/*
-struct render_info
-{
-	unsigned char *data;
-};
-
-void tilemap_render_one()*/
 
 void tilemap_render(float scale, int fg)
 {
@@ -113,3 +107,4 @@ void tilemap_render(float scale, int fg)
 		}
 	}
 }
+*/
diff --git a/src/game/client/gc_menu.cpp b/src/game/client/gc_menu.cpp
index e0c2a19f..cc9eaaea 100644
--- a/src/game/client/gc_menu.cpp
+++ b/src/game/client/gc_menu.cpp
@@ -18,9 +18,6 @@ extern "C" {
 #include "../g_version.h"
 #include "../g_protocol.h"
 
-#include "gc_mapres_image.h"
-#include "gc_mapres_tilemap.h"
-
 #include "../generated/gc_data.h"
 #include "gc_render.h"
 #include "gc_anim.h"
diff --git a/src/game/client/gc_render.cpp b/src/game/client/gc_render.cpp
index 9a4c35d5..9f55ec5f 100644
--- a/src/game/client/gc_render.cpp
+++ b/src/game/client/gc_render.cpp
@@ -2,12 +2,14 @@
 #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 <game/generated/gc_data.h>
+#include <game/g_protocol.h>
+#include <game/g_math.h>
+#include <game/g_layers.h>
 #include "gc_render.h"
 #include "gc_anim.h"
 #include "gc_client.h"
+#include "gc_map_image.h"
 
 static float sprite_w_scale;
 static float sprite_h_scale;
@@ -235,3 +237,144 @@ void mapscreen_to_world(float center_x, float center_y, float parallax_x, float
 	points[2] = offset_x+center_x+width/2;
 	points[3] = offset_y+center_y+height/2;
 }
+
+static void mapscreen_to_group(float center_x, float center_y, MAPITEM_GROUP *group)
+{
+	float points[4];
+	mapscreen_to_world(center_x, center_y, group->parallax_x/100.0f, group->parallax_y/100.0f,
+		group->offset_x, group->offset_y, gfx_screenaspect(), 1.0f, points);
+	gfx_mapscreen(points[0], points[1], points[2], points[3]);
+}
+
+void render_layers(float center_x, float center_y, int pass)
+{
+	bool passed_gamelayer = false;
+	for(int g = 0; g < layers_num_groups(); g++)
+	{
+		MAPITEM_GROUP *group = layers_get_group(g);
+		
+		mapscreen_to_group(center_x, center_y, group);
+		
+		for(int l = 0; l < group->num_layers; l++)
+		{
+			MAPITEM_LAYER *layer = layers_get_layer(group->start_layer+l);
+			bool render = false;
+			bool is_game_layer = false;
+			
+			if(layer == (MAPITEM_LAYER*)layers_game())
+			{
+				is_game_layer = true;
+				passed_gamelayer = 1;
+			}
+				
+			if(pass == 0)
+			{
+				if(passed_gamelayer)
+					return;
+				render = true;
+			}
+			else
+			{
+				if(passed_gamelayer && !is_game_layer)
+					render = true;
+			}
+			
+			if(render)
+			{
+				if(layer->type == LAYERTYPE_TILES)
+				{
+					MAPITEM_LAYER_TILEMAP *tmap = (MAPITEM_LAYER_TILEMAP *)layer;
+					if(tmap->image == -1)
+						gfx_texture_set(-1);
+					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);
+				}
+				else if(layer->type == LAYERTYPE_QUADS)
+				{
+					MAPITEM_LAYER_QUADS *qlayer = (MAPITEM_LAYER_QUADS *)layer;
+					if(qlayer->image == -1)
+						gfx_texture_set(-1);
+					else
+						gfx_texture_set(img_get(qlayer->image));
+					QUAD *quads = (QUAD *)map_get_data_swapped(qlayer->data);
+					render_quads(quads, qlayer->num_quads);
+				}
+			}
+		}
+	}
+}
+
+// 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 items
+	{
+		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_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);
+			}
+		}
+	}
+
+	// render players above all
+	{
+		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)
+			{
+				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 particles
+	//temp_system.update(client_frametime());
+	//temp_system.render();
+
+	// render foreground layers
+	render_layers(center_x, center_y, 1);
+
+	// render damage indications
+	render_damage_indicators();
+}
diff --git a/src/game/client/gc_render.h b/src/game/client/gc_render.h
index 2f17f6b5..feb04641 100644
--- a/src/game/client/gc_render.h
+++ b/src/game/client/gc_render.h
@@ -37,6 +37,8 @@ void render_game();
 void render_world(float center_x, float center_y, float zoom);
 void render_loading(float percent);
 
+void render_damage_indicators();
+
 // 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);
@@ -48,7 +50,7 @@ void render_player(
 	
 // 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);
+void render_tilemap(TILE *tiles, int w, int h, float scale, 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 fcb8c272..4345aa03 100644
--- a/src/game/client/gc_render_map.cpp
+++ b/src/game/client/gc_render_map.cpp
@@ -88,7 +88,7 @@ void render_quads(QUAD *quads, int num_quads)
 }
 
 
-void render_tilemap(TILE *tiles, int w, int h, float scale)
+void render_tilemap(TILE *tiles, int w, int h, float scale, int flags)
 {
 			//gfx_texture_set(img_get(tmap->image));
 	float screen_x0, screen_y0, screen_x1, screen_y1;
@@ -116,14 +116,29 @@ void render_tilemap(TILE *tiles, int w, int h, float scale)
 		{
 			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;
+			
+			if(flags)
+			{
+				if(mx<0)
+					mx = 0;
+				if(mx>=w)
+					mx = w-1;
+				if(my<0)
+					my = 0;
+				if(my>=h)
+					my = h-1;
+			}
+			else
+			{
+				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;
 				
diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 8c6c0c73..69bf7554 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -11,7 +11,7 @@ extern "C" {
 	#include <engine/e_config.h>
 }
 
-#include <game/client/gc_mapres_image.h>
+#include <game/client/gc_map_image.h>
 #include <game/client/gc_mapres_tilemap.h>
 #include <game/client/gc_ui.h>
 //#include "game/mapres_col.h"
@@ -27,6 +27,16 @@ static int cursor_texture = 0;
 static int entities_texture = 0;
 
 
+class mapres_image
+{
+public:
+	int width;
+	int height;
+	int image_data;
+};
+
+
+
 EDITOR editor;
 
 LAYERGROUP::LAYERGROUP()
@@ -1965,17 +1975,6 @@ template<typename T>
 static int make_version(int i, const T &v)
 { return (i<<16)+sizeof(T); }
 
-enum
-{
-	MAPITEMTYPE_VERSION=0,
-	MAPITEMTYPE_INFO,
-	MAPITEMTYPE_IMAGE,
-	MAPITEMTYPE_ENVELOPE,
-	MAPITEMTYPE_GROUP,
-	MAPITEMTYPE_LAYER,
-};
-
-
 void editor_load_old(DATAFILE *df)
 {
 	// load tilemaps
@@ -2075,7 +2074,7 @@ void editor_load_old(DATAFILE *df)
 					else if(e->data[0] == ITEM_WEAPON_ROCKET) id = ENTITY_WEAPON_ROCKET;
 					else if(e->data[0] == ITEM_NINJA) id = ENTITY_POWERUP_NINJA;
 					else if(e->data[0] == ITEM_ARMOR) id = ENTITY_ARMOR_1;
-					else if(e->data[0] == ITEM_HEALTH) id = ENTITY_HEATH_1;
+					else if(e->data[0] == ITEM_HEALTH) id = ENTITY_HEALTH_1;
 				}
 						
 				if(id > 0 && x >= 0 && x < g->width && y >= 0 && y < g->height)
diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp
index 583426e3..224343e1 100644
--- a/src/game/editor/ed_layer_tiles.cpp
+++ b/src/game/editor/ed_layer_tiles.cpp
@@ -35,7 +35,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);
+	render_tilemap(tiles, width, height, 32.0f, 0);
 }
 
 int LAYER_TILES::convert_x(float x) const { return (int)(x/32.0f); }
diff --git a/src/game/g_mapres_col.cpp b/src/game/g_collision.cpp
index 64a240bf..ffccab05 100644
--- a/src/game/g_mapres_col.cpp
+++ b/src/game/g_collision.cpp
@@ -1,15 +1,66 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <engine/e_system.h>
 #include <game/g_vmath.h>
-#include <game/g_math.h>
 #include <math.h>
-#include "../engine/e_interface.h"
-#include "g_mapres_col.h"
-#include "g_mapres.h"
+#include <engine/e_interface.h>
+#include <game/g_math.h>
+#include <game/g_mapitems.h>
+#include <game/g_layers.h>
+
+static TILE *tiles;
+static int width = 0;
+static int height = 0;
+
+int col_width() { return width; }
+int col_height() { return height; }
+
+int col_init()
+{
+	width = layers_game()->width;
+	height = layers_game()->height;
+	tiles = (TILE *)map_get_data(layers_game()->data);
+	return 1;
+}
+
+
+int col_is_solid(int x, int y)
+{
+	int nx = x/32;
+	int ny = y/32;
+	if(nx < 0 || nx >= width || ny >= height)
+		return 1;
+	
+	if(y < 0)
+		return 0; // up == sky == free
+	
+	return tiles[ny*width+nx].index == TILE_SOLID;
+}
+
+// TODO: rewrite this smarter!
+bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out)
+{
+	float d = distance(pos0, pos1);
+	
+	for(float f = 0; f < d; f++)
+	{
+		float a = f/d;
+		vec2 pos = mix(pos0, pos1, a);
+		if(col_is_solid((int)pos.x, (int)pos.y))
+		{
+			if(out)
+				*out = pos;
+			return true;
+		}
+	}
+	if(out)
+		*out = pos1;
+	return false;
+}
 
 /*
 	Simple collision rutines!
 */
+/*
 struct collision
 {
 	int w, h;
@@ -44,36 +95,4 @@ int col_init(int dividor)
 	return col.data ? 1 : 0;
 }
 
-int col_check_point(int x, int y)
-{
-	int nx = x/global_dividor;
-	int ny = y/global_dividor;
-	if(nx < 0 || nx >= col.w || ny >= col.h)
-		return 1;
-	
-	if(y < 0)
-		return 0; // up == sky == free
-	
-	return col.data[ny*col.w+nx];
-}
-
-// TODO: rewrite this smarter!
-bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out)
-{
-	float d = distance(pos0, pos1);
-	
-	for(float f = 0; f < d; f++)
-	{
-		float a = f/d;
-		vec2 pos = mix(pos0, pos1, a);
-		if(col_check_point((int)pos.x, (int)pos.y))
-		{
-			if(out)
-				*out = pos;
-			return true;
-		}
-	}
-	if(out)
-		*out = pos1;
-	return false;
-}
+*/
diff --git a/src/game/g_mapres_col.h b/src/game/g_collision.h
index 3312ef8e..e738bc64 100644
--- a/src/game/g_mapres_col.h
+++ b/src/game/g_collision.h
@@ -5,15 +5,8 @@
 
 #include <game/g_vmath.h>
 
-struct mapres_collision
-{
-	int width;
-	int height;
-	int data_index;
-};
-
-int col_init(int dividor);
-int col_check_point(int x, int y);
+int col_init();
+int col_is_solid(int x, int y);
 int col_width();
 int col_height();
 bool col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out);
diff --git a/src/game/g_game.cpp b/src/game/g_game.cpp
index 4befc33e..ba70c31c 100644
--- a/src/game/g_game.cpp
+++ b/src/game/g_game.cpp
@@ -118,9 +118,9 @@ void player_core::tick()
 	triggered_events = 0;
 	
 	bool grounded = false;
-	if(col_check_point((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5)))
+	if(col_is_solid((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2+5)))
 		grounded = true;
-	if(col_check_point((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5)))
+	if(col_is_solid((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2+5)))
 		grounded = true;
 	
 	vec2 direction = normalize(vec2(input.target_x, input.target_y));
diff --git a/src/game/g_game.h b/src/game/g_game.h
index 0e405260..395362a9 100644
--- a/src/game/g_game.h
+++ b/src/game/g_game.h
@@ -6,7 +6,7 @@
 #include <game/g_math.h>
 #include <math.h>
 #include "../engine/e_interface.h"
-#include "g_mapres_col.h"
+#include "g_collision.h"
 
 #include "g_protocol.h"
 
@@ -126,7 +126,7 @@ public:
 #define min(a, b) ( a > b ? b : a)
 #define max(a, b) ( a > b ? a : b)
 
-inline bool col_check_point(float x, float y) { return col_check_point((int)x, (int)y) != 0; }
+inline bool col_check_point(float x, float y) { return col_is_solid((int)x, (int)y) != 0; }
 inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); }
 
 struct mapres_entity
diff --git a/src/game/g_layers.cpp b/src/game/g_layers.cpp
new file mode 100644
index 00000000..f60f13d7
--- /dev/null
+++ b/src/game/g_layers.cpp
@@ -0,0 +1,47 @@
+#include <engine/e_interface.h>
+#include "g_layers.h"
+
+static MAPITEM_LAYER_TILEMAP *game_layer;
+
+static int groups_start = 0;
+static int groups_num = 0;
+static int layers_start = 0;
+static int layers_num = 0;
+
+void layers_init()
+{
+	map_get_type(MAPITEMTYPE_GROUP, &groups_start, &groups_num);
+	
+	{
+		map_get_type(MAPITEMTYPE_LAYER, &layers_start, &layers_num);
+			
+		for(int i = 0; i < layers_num; i++)
+		{
+			MAPITEM_LAYER *layer = (MAPITEM_LAYER *)map_get_item(layers_start+i, 0, 0);
+			if(layer->type == LAYERTYPE_TILES)
+			{
+				MAPITEM_LAYER_TILEMAP *tilemap = (MAPITEM_LAYER_TILEMAP *)layer;
+				if(tilemap->flags&1)
+					game_layer = tilemap;
+			}
+		}
+		
+	}
+}
+
+int layers_num_groups() { return groups_num; }
+MAPITEM_GROUP *layers_get_group(int index)
+{
+	return (MAPITEM_GROUP *)map_get_item(groups_start+index, 0, 0);
+}
+
+MAPITEM_LAYER *layers_get_layer(int index)
+{
+	return (MAPITEM_LAYER *)map_get_item(layers_start+index, 0, 0);
+}
+
+MAPITEM_LAYER_TILEMAP *layers_game()
+{
+	return game_layer;
+}
+
diff --git a/src/game/g_layers.h b/src/game/g_layers.h
new file mode 100644
index 00000000..455b74a8
--- /dev/null
+++ b/src/game/g_layers.h
@@ -0,0 +1,11 @@
+#include "g_mapitems.h"
+
+void layers_init();
+
+MAPITEM_LAYER_TILEMAP *layers_game();
+
+int layers_num_groups();
+MAPITEM_GROUP *layers_get_group(int index);
+MAPITEM_LAYER *layers_get_layer(int index);
+
+
diff --git a/src/game/g_mapitems.h b/src/game/g_mapitems.h
index f6375d02..d7d8fa77 100644
--- a/src/game/g_mapitems.h
+++ b/src/game/g_mapitems.h
@@ -9,12 +9,15 @@ enum
 	LAYERTYPE_GAME, // not used
 	LAYERTYPE_TILES,
 	LAYERTYPE_QUADS,
-};
-
-
-// game layer tiles
-enum
-{
+	
+	MAPITEMTYPE_VERSION=0,
+	MAPITEMTYPE_INFO,
+	MAPITEMTYPE_IMAGE,
+	MAPITEMTYPE_ENVELOPE,
+	MAPITEMTYPE_GROUP,
+	MAPITEMTYPE_LAYER,
+	
+	// game layer tiles
 	ENTITY_NULL=0,
 	ENTITY_SPAWN,
 	ENTITY_SPAWN_RED,
@@ -22,7 +25,7 @@ enum
 	ENTITY_FLAGSTAND_RED,
 	ENTITY_FLAGSTAND_BLUE,
 	ENTITY_ARMOR_1,
-	ENTITY_HEATH_1,
+	ENTITY_HEALTH_1,
 	ENTITY_WEAPON_SHOTGUN,
 	ENTITY_WEAPON_ROCKET,
 	ENTITY_POWERUP_NINJA,
diff --git a/src/game/g_protocol.h b/src/game/g_protocol.h
index 93073154..9ae7b170 100644
--- a/src/game/g_protocol.h
+++ b/src/game/g_protocol.h
@@ -153,7 +153,6 @@ struct obj_game
 struct obj_projectile
 {
 	int type;
-	int tick;
 	int x, y;
 	int vx, vy; // should be an angle instead
 	int start_tick;
diff --git a/src/game/server/gs_server.cpp b/src/game/server/gs_server.cpp
index 565e699a..98a99804 100644
--- a/src/game/server/gs_server.cpp
+++ b/src/game/server/gs_server.cpp
@@ -3,7 +3,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <engine/e_config.h>
-#include "../g_version.h"
+#include <game/g_version.h>
+#include <game/g_collision.h>
+#include <game/g_layers.h>
 #include "gs_common.h"
 #include "gs_game_ctf.h"
 #include "gs_game_tdm.h"
@@ -559,6 +561,9 @@ void player::set_team(int new_team)
 	dbg_msg("game", "cid=%d team=%d", client_id, team);
 }
 
+vec2 spawn_points[3][64];
+int num_spawn_points[3] = {0};
+
 struct spawneval
 {
 	spawneval()
@@ -614,15 +619,17 @@ static float evaluate_spawn(spawneval *eval, vec2 pos)
 static void evaluate_spawn_type(spawneval *eval, int t)
 {
 	// get spawn point
+	/*
 	int start, num;
 	map_get_type(t, &start, &num);
 	if(!num)
 		return;
-
-	for(int i  = 0; i < num; i++)
+	*/
+	for(int i  = 0; i < num_spawn_points[t]; i++)
 	{
-		mapres_spawnpoint *sp = (mapres_spawnpoint*)map_get_item(start + i, NULL, NULL);
-		vec2 p = vec2((float)sp->x, (float)sp->y);
+		//num_spawn_points[t]
+		//mapres_spawnpoint *sp = (mapres_spawnpoint*)map_get_item(start + i, NULL, NULL);
+		vec2 p = spawn_points[t][i];// vec2((float)sp->x, (float)sp->y);
 		float s = evaluate_spawn(eval, p);
 		if(!eval->got || eval->score > s)
 		{
@@ -641,17 +648,19 @@ void player::try_respawn()
 	spawneval eval;
 	eval.die_pos = die_pos;
 	
+	eval.pos = vec2(100, 100);
+	
 	if(gameobj->gametype == GAMETYPE_CTF)
 	{
 		eval.friendly_team = team;
 		
 		// try first try own team spawn, then normal spawn and then enemy
-		evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT_RED+(team&1));
+		evaluate_spawn_type(&eval, 1+(team&1));
 		if(!eval.got)
 		{
-			evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT);
+			evaluate_spawn_type(&eval, 0);
 			if(!eval.got)
-				evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT_RED+((team+1)&1));
+				evaluate_spawn_type(&eval, 1+((team+1)&1));
 		}
 	}
 	else
@@ -659,9 +668,9 @@ void player::try_respawn()
 		if(gameobj->gametype == GAMETYPE_TDM)
 			eval.friendly_team = team;
 			
-		evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT);
-		evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT_RED);
-		evaluate_spawn_type(&eval, MAPRES_SPAWNPOINT_BLUE);
+		evaluate_spawn_type(&eval, 0);
+		evaluate_spawn_type(&eval, 1);
+		evaluate_spawn_type(&eval, 2);
 	}
 	
 	spawnpos = eval.pos;
@@ -2041,7 +2050,8 @@ void mods_init()
 	if(!data) /* only load once */
 		data = load_data_from_memory(internal_data);
 
-	col_init(32);
+	layers_init();
+	col_init();
 
 	world = new game_world;
 	players = new player[MAX_CLIENTS];
@@ -2058,70 +2068,59 @@ void mods_init()
 	for(int i = 0; i < MAX_CLIENTS; i++)
 		players[i].core.world = &world->core;
 
-	//
-	int start, num;
-	map_get_type(MAPRES_ITEM, &start, &num);
-
-	// TODO: this is way more complicated then it should be
-	for(int i = 0; i < num; i++)
+	// create all entities from the game layer
+	MAPITEM_LAYER_TILEMAP *tmap = layers_game();
+	TILE *tiles = (TILE *)map_get_data(tmap->data);
+	
+	num_spawn_points[0] = 0;
+	num_spawn_points[1] = 0;
+	num_spawn_points[2] = 0;
+	
+	for(int y = 0; y < tmap->height; y++)
 	{
-		mapres_item *it = (mapres_item *)map_get_item(start+i, 0, 0);
-
-		int type = -1;
-		int subtype = 0;
-
-		switch(it->type)
+		for(int x = 0; x < tmap->width; x++)
 		{
-		case ITEM_WEAPON_GUN:
-			type = POWERUP_WEAPON;
-			subtype = WEAPON_GUN;
-			break;
-		case ITEM_WEAPON_SHOTGUN:
-			type = POWERUP_WEAPON;
-			subtype = WEAPON_SHOTGUN;
-			break;
-		case ITEM_WEAPON_ROCKET:
-			type = POWERUP_WEAPON;
-			subtype = WEAPON_ROCKET;
-			break;
-		case ITEM_WEAPON_HAMMER:
-			type = POWERUP_WEAPON;
-			subtype = WEAPON_HAMMER;
-			break;
-
-		case ITEM_HEALTH:
-			type = POWERUP_HEALTH;
-			break;
-
-		case ITEM_ARMOR:
-			type = POWERUP_ARMOR;
-			break;
-
-		case ITEM_NINJA:
-			if(config.sv_powerups)
+			int index = tiles[y*tmap->width+x].index - ENTITY_OFFSET;
+			int type = -1;
+			int subtype = 0;
+			vec2 pos(x*32.0f+16.0f, y*32.0f+16.0f);
+		
+			if(index == ENTITY_SPAWN)
+				spawn_points[0][num_spawn_points[0]++] = pos;
+			else if(index == ENTITY_SPAWN_RED)
+				spawn_points[1][num_spawn_points[1]++] = pos;
+			else if(index == ENTITY_SPAWN_BLUE)
+				spawn_points[2][num_spawn_points[2]++] = pos;
+			else if(index == ENTITY_ARMOR_1)
+				type = POWERUP_ARMOR;
+			else if(index == ENTITY_HEALTH_1)
+				type = POWERUP_HEALTH;
+			else if(index == ENTITY_WEAPON_SHOTGUN)
+			{
+				type = POWERUP_WEAPON;
+				subtype = WEAPON_SHOTGUN;
+			}
+			else if(index == ENTITY_WEAPON_ROCKET)
+			{
+				type = POWERUP_WEAPON;
+				subtype = WEAPON_ROCKET;
+			}
+			else if(index == ENTITY_POWERUP_NINJA)
 			{
 				type = POWERUP_NINJA;
 				subtype = WEAPON_NINJA;
 			}
-			break;
-		};
-
-		if(type != -1)
-		{
-			 // LOL, the only new in the entire game code
-			 // perhaps we can get rid of it. seems like a stupid thing to have
-			powerup *ppower = new powerup(type, subtype);
-			ppower->pos = vec2(it->x, it->y);
+			
+			if(type != -1)
+			{
+				powerup *ppower = new powerup(type, subtype);
+				ppower->pos = pos;
+			}
 		}
 	}
 
-	if(gameobj->gametype == GAMETYPE_CTF)
-	{
-	}
-
 	world->insert_entity(gameobj);
 
-
 	if(config.dbg_bots)
 	{
 		for(int i = 0; i < config.dbg_bots ; i++)