Map Editor/Tile Based Games

Blitz3D Forums/Blitz3D Beginners Area/Map Editor/Tile Based Games

I have created my own map editor for my 2d game but the collision in it is very buggy. Can any of you pros. recommend a good article with methods of creating a tile based game? Thanks.

Are you asking specifically about character-to-tile collisions and collision response?

Yes. Character-to-tile collisions. Doesn't this collision work the same as any other?:|

Why would all collisions systems work the same way?

For example, here's my tile collision system for my 2d platformer. It's very simplistic, handling only solid and empty tiles, and behaving badly if velocity > tile_dimensions.

function physics_move_actor(a.actor)
; moves an actor according to vx and vy, does tile collisions

	; abbreviation
	pmg.map_grid = world\map\physical_map_grid

	; reset physics feedback
	a\bump_left   = false
	a\bump_right  = false
	a\bump_top    = false
	a\bump_bottom = false

	;; STAGE 1: prevent actors from leaving the physical map
	max_x2 = pmg\width  * pmg\tile_width  - 1
	max_y2 = pmg\height * pmg\tile_height - 1
	if a\pos\x1+a\vx < 0      then rect_moveX1(a\pos, 0)      : a\vx = 0 : a\bump_left   = true
	if a\pos\y1+a\vy < 0      then rect_moveY1(a\pos, 0)      : a\vy = 0 : a\bump_top    = true
	if a\pos\x2+a\vx > max_x2 then rect_moveX2(a\pos, max_x2) : a\vx = 0 : a\bump_right  = true
	if a\pos\y2+a\vy > max_y2 then rect_moveY2(a\pos, max_y2) : a\vy = 0 : a\bump_bottom = true
 
	;; STAGE 2: prevent movement into physical_map tiles which act as walls
	; figure out what tiles our current position overlaps, and what tiles our position would overlap after a full move
	tile_x1_cur  = floor( (a\pos\x1) / pmg\tile_width)
	tile_x2_cur  =  ceil( (a\pos\x2) / pmg\tile_width) - 1
	tile_y1_cur  = floor( (a\pos\y1) / pmg\tile_height)
	tile_y2_cur  =  ceil( (a\pos\y2) / pmg\tile_height) - 1
	tile_x1_dest = floor( (a\pos\x1+a\vx) / pmg\tile_width)
	tile_x2_dest =  ceil( (a\pos\x2+a\vx) / pmg\tile_width) - 1
	tile_y1_dest = floor( (a\pos\y1+a\vy) / pmg\tile_height)
	tile_y2_dest =  ceil( (a\pos\y2+a\vy) / pmg\tile_height) - 1

	; try to move up (if we can't, move next to the wall and reset velocity on this axis to 0)
	if tile_y1_dest < tile_y1_cur then
		blocked = false
		for tile_x = tile_x1_cur to tile_x2_cur
			if vector_get(pmg\tile_data, (tile_x) + pmg\width * (tile_y1_dest)) = MAP_LOGIC_SOLID then blocked = true : exit
		next
		if blocked then
			rect_moveY1(a\pos, (tile_y1_cur) * pmg\tile_height)             ; move actor to border
			a\vy = 0                                                        ; lose velocity
			a\bump_top = true
		else
			tile_y1_cur = tile_y1_dest : tile_y2_cur = tile_y2_dest         ; pretend we just moved in this direction
		endif
	endif

	; try to move down (if we can't, move next to the wall and reset velocity on this axis to 0)
	if tile_y2_dest > tile_y2_cur then
		blocked = false
		for tile_x = tile_x1_cur to tile_x2_cur
			if vector_get(pmg\tile_data, (tile_x) + pmg\width * (tile_y2_dest)) = MAP_LOGIC_SOLID then blocked = true : exit
		next
		if blocked then
			rect_moveY2(a\pos, (tile_y2_cur+1) * pmg\tile_height)           ; move actor to border
			a\vy = 0                                                        ; lose velocity
			a\bump_bottom = true
		else
			tile_y1_cur = tile_y1_dest : tile_y2_cur = tile_y2_dest         ; pretend we just moved in this direction
		endif
	endif

	; try to move left (if we can't, move next to the wall and reset velocity on this axis to 0)
	if tile_x1_dest < tile_x1_cur then
		blocked = false
		for tile_y = tile_y1_cur to tile_y2_cur
			if vector_get(pmg\tile_data, (tile_x1_dest) + pmg\width * (tile_y)) = MAP_LOGIC_SOLID then blocked = true : exit
		next
		if blocked then
			rect_moveX1(a\pos, (tile_x1_cur) * pmg\tile_width)              ; move actor to border
			a\vx = 0                                                        ; lose velocity
			a\bump_left = true
		else
			tile_x1_cur = tile_x1_dest : tile_x2_cur = tile_x2_dest         ; pretend we just moved in this direction
		endif
	endif

	; try to move right (if we can't, move next to the wall and reset velocity on this axis to 0)
	if tile_x2_dest > tile_x2_cur then
		blocked = false
		for tile_y = tile_y1_cur to tile_y2_cur
			if vector_get(pmg\tile_data, (tile_x2_dest) + pmg\width * (tile_y)) = MAP_LOGIC_SOLID then blocked = true : exit
		next
		if blocked then
			rect_moveX2(a\pos, (tile_x2_cur+1) * pmg\tile_width)            ; move actor to border
			a\vx = 0                                                        ; lose velocity
			a\bump_right = true
		else
			tile_x1_cur = tile_x1_dest : tile_x2_cur = tile_x2_dest         ; pretend we just moved in this direction
		endif
	endif

	;; STAGE 3: move the actor 
	rect_moveBy(a\pos, a\vx, a\vy)

end function


I'll check out that code you posted later, looks easy to understand :o)