Problem with generating shadows

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.
Post Reply
yathern
Prole
Posts: 1
Joined: Mon Feb 13, 2012 7:16 pm

Problem with generating shadows

Post by yathern »

I'm messing around making a prototype for a game, and I have come across a problem that is aggravating me. So far, I have a bit of code which can place a block with left-click, and a light source with right-click. The program doesn't generate lights, just shadows, lights will come later.

My problem is, I only am generating one shadow for each box, I can't have two or more (one for each light source). I'm pretty new to using tables in lua, so I'm guessing my problem is in the implementation of tables, but I've been struggling with this for a little while now to no avail.

Here is my code:

Code: Select all

function love.load()
	boxes = {}
	shadows = {}
	lightImage = love.graphics.newImage("light.png")
	lights = {}
	light = {}
	length = 0
end

function createBox(x,y)
	box = {}
	box.size = math.random(20,65)
	box.xVelocity = math.random(-5,5)
	box.yVelocity = math.random(-5,5)
	box.color = {math.random(40,255),math.random(40,255),math.random(40,255)}
	box.x = x
	box.y = y
	box.shadow = {}

	box.vertices = {box.x, box.y, box.x +box.size, box.y, box.x + box.size, box.y + box.size, box.x, box.y + box.size}
	box.walls = {}
	box.walls = {}
	box.walls[2] = {box.vertices[1],box.vertices[2],box.vertices[3],box.vertices[4]}
	box.walls[3] = {box.vertices[3],box.vertices[4],box.vertices[5],box.vertices[6]}
	box.walls[4] = {box.vertices[5],box.vertices[6],box.vertices[7],box.vertices[8]}
	box.walls[1] = {box.vertices[7],box.vertices[8],box.vertices[1],box.vertices[2]}
	table.insert(boxes, box)
end

function createLight(x,y)
	light = {}
	light.size = math.random(20,65)
	light.color = {math.random(40,255),math.random(40,255),math.random(40,255)}
	light.x = x
	light.y = y
	light.shadows = {}
	table.insert(lights, light)
	light = {}
end
		
function love.update(dt)

	if #lights > 0 then
		for i, v in ipairs (boxes) do	
			v.shadow = {}
			shadow = {}
			for i=1, 4 do
				for k, j in ipairs(lights) do
					number = i+((k-1)*4)
					v.shadow[number] = (getShadow(v.walls[i], j.x, j.y))
					
				end
				
			end
			
			
		end
	end

	
end

function love.mousepressed(x, y, button)
   if button == 'l' then
		createBox(x, y) 
   else
		createLight(x,y)
	end

end

function getShadow(vertices, lightX, lightY)
	x1 = vertices[1]
	y1 = vertices[2]
	
	ydist = y1-lightY
	xdist =  x1-lightX
	
	x2 = vertices[3]
	y2 = vertices[4]
	
	ydist2 =  y2-lightY
	xdist2 =  x2-lightX

	vertices[7] = x1+xdist*200
	vertices[8] = y1+ydist*200
	
	vertices[5] = x2+xdist2*200
	vertices[6] = y2+ydist2*200

	return(vertices)
end



function love.draw()
	love.graphics.setBackgroundColor(30,30,30)
	--for i, v in ipairs (lights) do
		--love.graphics.setColor(255,255,255,100)
		--love.graphics.draw(lightImage, v.x-300, v.y-300)
	--end
	
		
	for i, v in ipairs (boxes) do
		for i=1, #v.shadow do 
			love.graphics.setColor(10,10,10,20)
			love.graphics.polygon('fill', v.shadow[i])
				
		end
		love.graphics.setColor(250,10,100)
		love.graphics.print(#v.shadow, 400,400)
	end
	
	for i, v in ipairs(lights) do
		love.graphics.circle('fill', v.x, v.y, 10)
	end
	
	love.graphics.setColor(200,50,50)

	for i, v in ipairs (boxes) do
		love.graphics.setColor(v.color)
		love.graphics.rectangle('fill', v.x, v.y, v.size, v.size)
	end

end
The main parts that are preventing it from working are all of love.update() and the:

Code: Select all

for i, v in ipairs (boxes) do
		for i=1, #v.shadow do 
			love.graphics.setColor(10,10,10,20)
			love.graphics.polygon('fill', v.shadow[i])
				
		end
		love.graphics.setColor(250,10,100)
		love.graphics.print(#v.shadow, 400,400)
	end
part of love.draw().

What I have managed to figure out is that it is overlaying all of the shadows over itself. If that doesn't make sense- just run it. Look how the shadows get darker the more you right click. It is keeping one shape for all of them, for reasons I don't know.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Problem with generating shadows

Post by kikito »

I haven't run your code (It would help if you included a .love file instead of copy-pasting the code in the forum; that way we can test more quickly) but I would bet that the problem is on this code:

Code: Select all

for i, v in ipairs (boxes) do   
  v.shadow = {}
  shadow = {}
  for i=1, 4 do
    for k, j in ipairs(lights) do
      number = i+((k-1)*4)
      v.shadow[number] = (getShadow(v.walls[i], j.x, j.y))
    end            
  end
These are the possible errors:
  • The variable named "shadow" is initialized to {}, but never used (I think) did you intent to put "shadows" there?
  • On the for i=1, 4, 4 is hardcoded; what is it supposed to represent?
  • How is "number" calculated? Why is it global? Is that "4" the same "4" as in the beginning of the loop, or does it represent a different thing?
Those are all potential problems that could be making your program fail. There is also a problem of style; you are using i as a numeric index, and j as a box. I suggest giving them proper names (whateverindex and box instead of i,j)
When I write def I mean function.
utunnels
Citizen
Posts: 75
Joined: Fri Jan 06, 2012 5:20 pm

Re: Problem with generating shadows

Post by utunnels »

Yes, I think you have some problem understanding tables.
You are returning the same table in getShadow, that is why you have only 1 shadow.
To return a copy or a table, you need to create a new one.

Code: Select all

function getShadow(vertices, lightX, lightY)
   x1 = vertices[1]
   y1 = vertices[2]
   
   ydist = y1-lightY
   xdist =  x1-lightX
   
   x2 = vertices[3]
   y2 = vertices[4]
   
   ydist2 =  y2-lightY
   xdist2 =  x2-lightX

   vertices[7] = x1+xdist*200
   vertices[8] = y1+ydist*200
   
   vertices[5] = x2+xdist2*200
   vertices[6] = y2+ydist2*200

   local v = {}

   for i=1,8 do
      v[i] = vertices[i]
   end

   return(v)
end
This should work, though I didn't not do any optimization to your code, just a quick logic fix.
Post Reply

Who is online

Users browsing this forum: Google [Bot], Semrush [Bot] and 43 guests