Tile based scrolling

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Ryne
Party member
Posts: 444
Joined: Fri Jan 29, 2010 11:10 am

Tile based scrolling

Post by Ryne » Wed Dec 15, 2010 4:53 am

I'm back with more issues unfortunately. Iv'e set my game up with basic tile based scrolling (just shamelessly ripped from the tutorial on the wiki) though adding enemies has become a bit of a bother. Since the player controls change the map_x and map_y variables enemies sort of get messed up since they are being drawn at specific screen coordinates. After lurking the forum for a bit It seems I need to convert grid coordinates into screen coordinates but I'm not sure exactly how to do that, and even then how it would affect my enemy code. I'm really aiming for setting up collision with certain tiles. Alas, I will post what I have.

love.load

Code: Select all

	-- map code
    tile = {}
    for i=0,4 do -- change 3 to the number of tile images minus 1.
		tile[i] = love.graphics.newImage( "img/tiles/tile"..i..".png" )
    end
	
	map = map1
	
	map_w = #map[1] -- Obtains the width of the first row of the map
    map_h = #map -- Obtains the height of the map
    map_x = 16
    map_y = 2
    map_display_buffer = 2 -- We have to buffer one tile before and behind our viewpoint.
    map_display_w = 15
    map_display_h = 7
    tile_w = 32
    tile_h = 32
The Map (just held in a separate file)

Code: Select all

map1 = {
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
    }
Map Draw Function

Code: Select all

function draw_map()
    offset_x = map_x % tile_w
    offset_y = map_y % tile_h
    firstTile_x = math.floor(map_x / tile_w)
    firstTile_y = math.floor(map_y / tile_h)
    
    for y=1, (map_display_h + map_display_buffer) do
        for x=1, (map_display_w + map_display_buffer) do
            -- Note that this condition block allows us to go beyond the edge of the map.
            if y+firstTile_y >= 1 and y+firstTile_y <= map_h
                and x+firstTile_x >= 1 and x+firstTile_x <= map_w
            then
                love.graphics.draw(
                    tile[map[y+firstTile_y][x+firstTile_x]], 
                    (x*tile_w) - offset_x - tile_w/2, 
                    (y*tile_h) - offset_y - tile_h/2)
            end
        end
    end
end
Any help would be appreciated, right now I'm just (very noobishly) forcing the enemies closer to the player if the left or right key is down (player movement). This is obviously pretty ugly, and I'm still screwed for collision.
@rynesaur

User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Tile based scrolling

Post by tentus » Wed Dec 15, 2010 5:05 am

Ehhh giant matrixes. I find that per-entity map creation ends up being a lot less effort for the artists in the long run, you may want to consider a different approach (not to toot my own horn, but Kurosuke's code is open for all, I could make you a stripped-down version if you want).
Kurosuke needs beta testers

User avatar
Ryne
Party member
Posts: 444
Joined: Fri Jan 29, 2010 11:10 am

Re: Tile based scrolling

Post by Ryne » Wed Dec 15, 2010 5:07 am

tentus wrote:Ehhh giant matrixes. I find that per-entity map creation ends up being a lot less effort for the artists in the long run, you may want to consider a different approach (not to toot my own horn, but Kurosuke's code is open for all, I could make you a stripped-down version if you want).
I would appreciate it if you wouldn't mind. It may need some explanation though (I'm a downie) so if you're not up to it It's cool.
@rynesaur

User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Tile based scrolling

Post by Robin » Wed Dec 15, 2010 5:19 am

Why would it work differently for enemies? The player position is offset by map_x and map_y when drawn, right? Can't you do the same with enemy objects?
Help us help you: attach a .love.

User avatar
Ryne
Party member
Posts: 444
Joined: Fri Jan 29, 2010 11:10 am

Re: Tile based scrolling

Post by Ryne » Wed Dec 15, 2010 5:26 am

Robin wrote:Why would it work differently for enemies? The player position is offset by map_x and map_y when drawn, right? Can't you do the same with enemy objects?
Well, this is how I have it programmed. The player controls, left and right, both manipulate map_x (so the player technically just run's in place). If enemies are being drawn at say x - 300, y - 100 then they just stay still while the map is moving. The only way I was able to fix that was like this:

Code: Select all

	if love.keyboard.isDown('right') then
		curranim = anim.runright
		player.dir = "right"
		map_x = map_x + 100 * dt
		for i=1, #enemies do
			enemies[i].x = enemies[i].x - 100 * dt -- notice this code
		end
	elseif love.keyboard.isDown('left') then
		curranim = anim.runleft
		player.dir = "left"
		map_x = map_x - 100 * dt
		for i=1, #enemies do
			enemies[i].x = enemies[i].x + 100 * dt -- notice this code
		end
	end
@rynesaur

User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Tile based scrolling

Post by Robin » Wed Dec 15, 2010 5:58 am

Noooo! :P

What is your drawing code for the enemies?

Then, instead of:

Code: Select all

love.graphics.draw(something, enemies[i].x, enemies[i].y)
you could do:

Code: Select all

love.graphics.draw(something, enemies[i].x - map_x, enemies[i].y - map_y)
(you may need to replace - with +, btw, but I think not.)

Then your moving code could be O(1) instead of O(n).
Help us help you: attach a .love.

User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Tile based scrolling

Post by kikito » Wed Dec 15, 2010 8:18 am

The tile scrolling tutorial isn't really good. It isn't easy enough to be a good tutorial and it isn't flexible enough to be a good building base.

I must create a better one. Soon.
When I write def I mean function.

User avatar
Ryne
Party member
Posts: 444
Joined: Fri Jan 29, 2010 11:10 am

Re: Tile based scrolling

Post by Ryne » Wed Dec 15, 2010 4:22 pm

Robin wrote:Noooo! :P

What is your drawing code for the enemies?

Then, instead of:

Code: Select all

love.graphics.draw(something, enemies[i].x, enemies[i].y)
you could do:

Code: Select all

love.graphics.draw(something, enemies[i].x - map_x, enemies[i].y - map_y)
(you may need to replace - with +, btw, but I think not.)

Then your moving code could be O(1) instead of O(n).
That seems to work great, though I think It messes up my "follow the player" code. Since now neither the player.x nor the enemy x changes.

Code: Select all

	for i=1, #enemies do
		if not CheckCollision(player, enemies[i]) and Distance(player, enemies[i]) then
			-- the vector from enemy to the player
			local vx = player.x - enemies[i].x
			local vy = player.y - enemies[i].y

			-- normalize it, i.e. divide it by it's length
			local length = math.sqrt(vx * vx + vy * vy)
			vx = vx / length
			vy = vy / length

			-- move the zombie towards the player
			enemies[i].x = enemies[i].x + vx * enemies[i].speed * dt
			-- enemies[i].y = enemies[i].y + vy * enemies[i].speed * dt
		end
		
		if CheckCollision(player, enemies[i]) and enemies[i].dir == "left" then
		enemies[i].anim = eanim.idleleft
		
		elseif CheckCollision(player, enemies[i]) and enemies[i].dir == "right" then
		enemies[i].anim = eanim.idleright
		end
	end	
As well as that distance function

Code: Select all

function Distance(obj1, obj2)

	dx = obj1.x - obj2.x
	dy = obj1.y - obj2.y
	
	dist = math.sqrt(dx * dx + dy * dy)
	
	if dist <= 100 then
	return true
	else
	return false
	end

end
@rynesaur

User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Tile based scrolling

Post by Robin » Wed Dec 15, 2010 6:19 pm

Ryne wrote:That seems to work great, though I think It messes up my "follow the player" code. Since now neither the player.x nor the enemy x changes.
Then why don't you change the player position? That is much less work for the computer than updating every enemy, just when the player moves.
Ryne wrote:As well as that distance function
Doesn't that make more sense as:

Code: Select all

function Distance(obj1, obj2)
	local dx = obj1.x - obj2.x -- very important to make these local
	local dy = obj1.y - obj2.y

	return math.sqrt(dx * dx + dy * dy)
end

-- use like this:
if Distance(a, b) < 100 then ... end
Help us help you: attach a .love.

User avatar
Ryne
Party member
Posts: 444
Joined: Fri Jan 29, 2010 11:10 am

Re: Tile based scrolling

Post by Ryne » Wed Dec 15, 2010 9:28 pm

Robin wrote: Then why don't you change the player position? That is much less work for the computer than updating every enemy, just when the player moves.
Yea that distance code makes more sense now, Though I still don't understand what you mean about changing the player position. If I change the player position (meaning affect his x/y) then wouldn't that mess with the scrolling then?
@rynesaur

Post Reply

Who is online

Users browsing this forum: No registered users and 36 guests