Page 1 of 1

[SOLVED] ipairs list only functioning on last item Why?

Posted: Wed Sep 14, 2022 7:38 pm
by 4KbShort
Hey everyone,

I have a list/table of doors that is being iterated through with ipairs. When I tell the game to draw something for all k,v etc it does so. When I tell it to allow me to open the doors/change their status, it does because the animation updates.
However, what it doesn't do is check collision for every door. It will only check and return collision for the last door on the list and all others are ignored and I've no idea why this is happening.

I would provide the .love file as requested, but the door table is built in one file (all the doors are the same except for their x/y positions) and the iteration is done as part of the player collision check so here's a code snippet to show the code that's failing me:

Code: Select all

	--! CHECK DOORS !--
	for k,v in ipairs(doorLayout) do
		if checkCollision(pPosX,pPosY,playerWidth,playerHeight,v.posX+gridSize,v.posY,doorLayout.doorWidth,doorLayout.doorHeight) and v.status == "closed" then
				canPick = false
				if playerUp then
					la.play(sounds.openDoor,"stream",false,"sound")
					v.status = "open"
				end
			else
				canPick = true
			end
		end
	end
The collision function is your standard box collider and DOES WORK, but only on the last item in the table.

I have rewritten this multiple ways, simplified it, used debugging techniques to figure out the length of the table, whether all items in the list are being iterated, everything. The ONLY thing I can think of that's causing this issue is that the for loop is calling a function and isn't doing so until it reaches the end of the table, but I don't know WHY it would be doing that.

Any help would be greatly appreciated.

Re: ipairs list only functioning on last item Why?

Posted: Wed Sep 14, 2022 7:52 pm
by pgimeno
I don't think there's enough context as for allowing us to provide any meaningful help here. Furthermore, the indentation is wrong, misguiding readers to thinking that the 'for' loop does not finish at the end of the snippet.

There's a possibility that the problem is elsewhere, so could you please paste a snippet that allows readers to fully reproduce and debug your issue? You can try to isolate the problem into a short program that still reproduces it, there's no need for providing any assets or anything as long as the program works; circles or rectangles are just fine as placeholders for other graphics.

Re: ipairs list only functioning on last item Why?

Posted: Wed Sep 14, 2022 8:55 pm
by ReFreezed
Could the problem have anything to do with the canPick variable, as it's updated for every item in the loop and always holds the result of the last iterated item after the loop?

Re: ipairs list only functioning on last item Why?

Posted: Wed Sep 14, 2022 10:42 pm
by yal2du
maybe wrap your problem area and turn it into a function. and then don't call it. write a new one, starting with outer loop and prove that it iterates over everything in doorLayout.

just guesses

1) ipairs vs pairs; is doorLayout strictly an array with numerical keys, beginning at 1 and with no gaps in the indices?

2) the form of the if clause, maybe something clearer and less dependent upon operator precedence, like

Code: Select all

 if (afunction() == true) and (v.status == 'closed') then 
because 'and' is lower precedence than '== ' but the operators are for the most part left-associative with weird short circuit evaluation

https://www.lua.org/manual/5.1/manual.html#2.5.6
https://www.lua.org/pil/3.3.html

Re: ipairs list only functioning on last item Why?

Posted: Thu Sep 15, 2022 12:44 am
by 4KbShort
Thank you everyone for your feedback. I don't know how I fixed it as all I did was take a working backup and copy/paste the code from one to the other. Nothing in the code seems to have changed except now all the doors are iterating as they were intended.

Code: Select all

for k,v in ipairs(doorLayout) do
	if checkCollision(pPosX,pPosY,playerWidth,playerHeight, v.posX+gridSize,v.posY,doorLayout.doorWidth,doorLayout.doorHeight) then
		if v.status == "closed" then
			canPick = false
			if playerUp then
				canPick = true
				la.play(sounds.openDoor,"stream",false,"sound")
				v.status = "open"
			end
		end
	end
end
Nothing else was changed and to my eyes, at least, both code snipets are exactly the same. If anyone comes across this and can see a difference in the two code snipets (apart from my bad paste job) then please let us know what could have corrected it.
Hate to be the "I fixed it" without a reason guy, but this one kind of requires it.

Re: ipairs list only functioning on last item Why?

Posted: Thu Sep 15, 2022 1:35 am
by yal2du
glad you got it working. the if clause looks very different.
4KbShort wrote: Thu Sep 15, 2022 12:44 am Nothing in the code seems to have changed except now all the doors are iterating as they were intended.

Code: Select all

if checkCollision(pPosX,pPosY,playerWidth,playerHeight, v.posX+gridSize,v.posY,doorLayout.doorWidth,doorLayout.doorHeight) then
vs

Code: Select all

if checkCollision(pPosX,pPosY,playerWidth,playerHeight,v.posX+gridSize,v.posY,doorLayout.doorWidth,doorLayout.doorHeight) and v.status == "closed" then
that was posted initially.