Page 1 of 1

how to update draw when move without creating new quads?

Posted: Wed Jun 26, 2013 6:24 pm
by batatinha
I need to keep repeating the my background and the ground, and i want it to be infinite, how can i do that?
I thought about 2 ways:

1°: creating new images everytime that the player moves, but this should be terrible to performance.
2°: creating quads instead, but that should be terrible to performance too, as the wiki says...

The other thing i thought is about "go against the border of the screen"(can't say it with another words) with images and loading more when it's necessary, but my doubt is: draws out of screen bounds keep loaded in the memory?
I already readed the tutorial about scroling in the wiki, but i don't have a clue about how to implement it in my code...

I attached a .love archive if you wanna see what's the issue with your own eyes...

Re: how to update draw when move without creating new quads?

Posted: Thu Jun 27, 2013 5:31 am
by micha
What do you mean by infinite? Is it one set of tiles that repeats over and over? Do you mean a large (but finite) map?

In the first case you need 4 copies of the spritebatch and the spritebatch itself does not change, only the drawing position.

In the second case, I suggest putting the whole map into the spritebatch withouth worrying about offscreen-tiles. So the spritebatch does not change at all.

Re: how to update draw when move without creating new quads?

Posted: Thu Jun 27, 2013 7:54 am
by batatinha
micha wrote:What do you mean by infinite? Is it one set of tiles that repeats over and over? Do you mean a large (but finite) map?

In the first case you need 4 copies of the spritebatch and the spritebatch itself does not change, only the drawing position.

In the second case, I suggest putting the whole map into the spritebatch withouth worrying about offscreen-tiles. So the spritebatch does not change at all.
I tried to do your first option(but using images instead of a spritebatch), since it seems to be impossible to detect colision with the second, i failed in 2 points: my colision detector gonna crazy and it's not infinite...
i needed to stop my colision detection to test it...
Can you help me? I can't realise where is the error... Here is the main.lua:

Code: Select all

require('config')

function checkCollision(ax1,ay1,aw,ah, bx1,by1,bw,bh)
  ax2,ay2,bx2,by2 = ax1 + aw, ay1 + ah, bx1 + bw, by1 + bh
  return ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1
end

local pairs = pairs
local table = table
local love = love

local sprites = {}
sprites['bg'] = {}
sprites['walkable'] = {}
sprites['char'] = {} -- [1] = player

local dir = 1
local image_dir = {}

local falling = false
local jumping = false
local jumpframe = 0
local maxjumpframe = 30

local pot = 0
local mx = 0
local my = 0

function table.insert(t, i)
	local a = #t + 1
	t[a] = i
	return a
end

function love.load()
	love.graphics.setMode(800, 600)
	love.graphics.setBackgroundColor(0, 0, 0)
	local img = love.graphics.newImage('graphics/background.jpg')
	img:setWrap('repeat', 'repeat')
	table.insert(sprites['bg'], {src = img, pos ={150, 50}})
	table.insert(sprites['bg'], {src = img, pos ={662, 50}})
	table.insert(sprites['bg'], {src = img, pos ={-362, 50}})
	img = love.graphics.newImage('graphics/ground.jpg')
	img:setWrap('repeat', 'repeat')
	table.insert(sprites['walkable'], {src = img, pos ={150, 500}})
	table.insert(sprites['walkable'], {src = img, pos ={662, 500}})
	table.insert(sprites['walkable'], {src = img, pos ={-362, 500}})
	image_dir[1] = love.graphics.newImage('graphics/owl1.png')
	image_dir[2] = love.graphics.newImage('graphics/owl2.png')
	table.insert(sprites['char'], {src = image_dir[1], pos ={350, 393}})
	love.graphics.setColor(255, 255, 255, 255)
end

function love.update(dt)
	local ppos = sprites['char'][1].pos
	local psrc = sprites['char'][1].src
	if love.keyboard.isDown('right') then
		mx = mx+1
		if dir == 2 then
			sprites['char'][1].src = image_dir[1]
			dir = 1
		end
		if mx > 370 then
			sprites['bg'][2].pos[1] = sprites['bg'][2].pos[1]+mx/370
			sprites['bg'][1].pos[1] = sprites['bg'][1].pos[1]+mx/370
			sprites['bg'][3].pos[1] = sprites['bg'][3].pos[1]+mx/370
		end
	elseif love.keyboard.isDown('left') then
		mx = mx-1
		if dir == 1 then
			sprites['char'][1].src = image_dir[2]
			dir = 2
		end
		if mx < -360 then 
			sprites['bg'][3].pos[1] = sprites['bg'][3].pos[1]+mx/360
			sprites['bg'][1].pos[1] = sprites['bg'][1].pos[1]+mx/360
			sprites['bg'][2].pos[1] = sprites['bg'][2].pos[1]+mx/360
		end
	end
	for _,v in pairs(sprites['walkable']) do
		--fix me, please...
		if checkCollision(ppos[1], ppos[2], psrc:getWidth(), psrc:getHeight(), v.pos[1]+mx , v.pos[2]+20-my, v.src:getWidth(), v.src:getHeight()) then
			falling = false
			jumping = false
			jumpframe = 0
		else
			falling = false -- = true after fixing
		end
	end
	if jumping then
		if jumpframe <= maxjumpframe and jumpframe ~= 0 then
			my = my-5-pot
			jumpframe = jumpframe + 1
			if pot > 0 then
				love.timer.sleep(pot/100)
			else
				love.timer.sleep(0.001)
			end
		else
			jumpframe = 0
		end
	end
	if falling then
		my = my+1
	end
end

function love.keypressed(key, unicode)
	if ((key == 'up') and (jumping == false) and (jumpframe == 0)) then
		my = my-5-pot
		jumpframe = 1
		jumping = true
	end
end

function love.draw()
	for _,v in pairs(sprites['bg']) do
		love.graphics.push()
		love.graphics.translate(-mx, -my)
		love.graphics.draw(v.src, v.pos[1], v.pos[2])
		love.graphics.pop()
	end
	for _,v in pairs(sprites['walkable']) do
		love.graphics.push()
		love.graphics.translate(-mx, -my)
		love.graphics.draw(v.src, v.pos[1], v.pos[2])
		love.graphics.pop()
	end
	for _,v in pairs(sprites['char']) do
		love.graphics.draw(v.src, v.pos[1], v.pos[2])
	end
	love.graphics.print('X: '.. mx ..' Y: '.. my*-1, 10, 10)
end

Re: how to update draw when move without creating new quads?

Posted: Thu Jun 27, 2013 9:10 am
by micha
Could you please create a .love file with the images you use. That would make it easier to see what is going on.

Edit: Just a small sidenote: (image):setWrap only influences, what happens, if you draw the image using a quad. Otherwise it has no effect.

Re: how to update draw when move without creating new quads?

Posted: Thu Jun 27, 2013 12:29 pm
by batatinha
Sure, i didn't uploaded it again because i only changed the main.lua and the others files are in the first post.

Re: how to update draw when move without creating new quads?

Posted: Thu Jun 27, 2013 8:44 pm
by micha
I noticed an error in your code (unrelated to your original question): If you want the config-file to work you need to name it conf.lua. You don't need to require it then.

Also you don't need a copy of the mirrored images. You can flip an image by using -1 as the y-scale:

Code: Select all

love.graphics.draw(image,x,y,0,1,-1)
And instead of

Code: Select all

sprites['bg'][2].pos[1]
you can write

Code: Select all

sprites.bg[2].pos[1]
Now to your question:
If you want the background to repeat over and over again and it has a width of 512 then the y-coordinate of the images would start at 0, 512, 1024, ... (multiples of 512). If the player is not at position mx, you need to find the nearby multiples of 512.
This can be done by this lines:

Code: Select all

sprites.bg[2].pos[1] = math.floor(mx/512)*512
sprites.bg[1].pos[1] = math.floor(mx/512+1)*512
sprites.bg[3].pos[1] = math.floor(mx/512+2)*512
(Divide the position by 512, round towards zero and then multiply by 512 again).
Have a look at the attached .love

For the collision: I give you a hint where to look. In the love.update the player coordinates are not changed at all. All you change, are the camera coordinates mx and my. Then you should not use love.timer.sleep in the loop. To get jumping right, you need to store the velocity in y-direction. Have a look at this tutorial: Platform Game Programming.

Re: how to update draw when move without creating new quads?

Posted: Fri Jun 28, 2013 6:51 am
by batatinha
micha wrote:I noticed an error in your code (unrelated to your original question): If you want the config-file to work you need to name it conf.lua. You don't need to require it then.

Also you don't need a copy of the mirrored images. You can flip an image by using -1 as the y-scale:

Code: Select all

love.graphics.draw(image,x,y,0,1,-1)
And instead of

Code: Select all

sprites['bg'][2].pos[1]
you can write

Code: Select all

sprites.bg[2].pos[1]
Now to your question:
If you want the background to repeat over and over again and it has a width of 512 then the y-coordinate of the images would start at 0, 512, 1024, ... (multiples of 512). If the player is not at position mx, you need to find the nearby multiples of 512.
This can be done by this lines:

Code: Select all

sprites.bg[2].pos[1] = math.floor(mx/512)*512
sprites.bg[1].pos[1] = math.floor(mx/512+1)*512
sprites.bg[3].pos[1] = math.floor(mx/512+2)*512
(Divide the position by 512, round towards zero and then multiply by 512 again).
Have a look at the attached .love

For the collision: I give you a hint where to look. In the love.update the player coordinates are not changed at all. All you change, are the camera coordinates mx and my. Then you should not use love.timer.sleep in the loop. To get jumping right, you need to store the velocity in y-direction. Have a look at this tutorial: Platform Game Programming.
Thank you... Problem solved.