Page 1 of 1

Nil value problem

Posted: Tue Feb 17, 2015 2:26 am
by Sosolol261
This is a code. And it gives me an error. This is the code:

Code: Select all

--main.lua
require("src/player")

function love.load()

end

function love.update(dt)

	-- main
	mousePosX = love.mouse.getX()
	mousePosY = love.mouse.getY()

end

function love.draw()

	player_draw()

end

--player.lua
local player = {
	posX = mousePosX - 25,
	posY = mousePosY - 30
}

function player_draw()
	love.graphics.setColor(255, 255, 255)
	love.graphics.rectangle('fill', player.posX, player.posY, 50, 60)
end
Is says that mousePosX and Y are nil values, which they aren't.

Thank you for your help :D

Re: Nil value problem

Posted: Tue Feb 17, 2015 2:53 am
by bdjnk
They are rightfully nil at the outset, when you attempt to use them. They're defined in your update function, which hasn't run yet.

An associated problem. Currently player.posX and player.posY will never be updated. You must set those values from within the update function. Updating mousePosX and mousePosY is not sufficient.

Re: Nil value problem

Posted: Tue Feb 17, 2015 11:08 am
by Muris
Basically the problem is, how values are passed and how they react after being passed. For example

Code: Select all

local a = 3
local b = a + 1
a = 5
print(b) -- prints 4
So when you set the players position to mousePos, the mousePos is nil at that moment, because when you require lua-file it does everything that is on the file-scope of stuff, meaning the update hasn't been called even once, and when you try to add value to nil, it doesn't work. Also like bdjnk pointed out, the players position will not be updated automatically, because the value is copied from mousePosX and mousePosY when you use the =.

It is good to know that values aren't like mathematical equal, meaning that when a = b, then a will always be the same value as b (there is something called pass-by-reference in other languages like c++/c# for this kind of thing, but lua doesn't have references up to my knowledge). For example when you assign string to local a, then you assign local b to what local a is assigned to, changing a will not change b. On the otherhand if you assign local a to be a table, and then assign local b to value of a, changing stuff inside table will be seen in both a and b. If you think tables are more like pointers from c/c++ it is a lot easier to understand why this is happening, although lua might not be exactly like this. I think this is one of those reasons why every programmer should know a bit of C/C++ or Assembly to at least have understanding how integers/strings etc. use memory, what are underflow/overflow and why would these happen. Why using <, <=, >=, > is prefered when dealing with floating points, instead of using exact values (such as while a ~= 0.1 vs while a < 0.1).

Re: Nil value problem

Posted: Wed Feb 18, 2015 2:18 am
by Sosolol261
Muris wrote: So when you set the players position to mousePos, the mousePos is nil at that moment, because when you require lua-file it does everything that is on the file-scope of stuff, meaning the update hasn't been called even once, and when you try to add value to nil, it doesn't work. Also like bdjnk pointed out, the players position will not be updated automatically, because the value is copied from mousePosX and mousePosY when you use the =.
So should I put the player table into love.update() ?

Re: Nil value problem

Posted: Wed Feb 18, 2015 10:20 am
by Muris
Sosolol261 wrote: So should I put the player table into love.update() ?
Nope, but you need to update player.posX and player.posY inside update method. Also you should take out the mousePosX and mousePosY out from the table definition, because they will just crash the program.

Like this, I didn't try running the code tho, so hopefully I didn't make a typo:

Code: Select all

--main.lua
local player = require("src/player")

function love.load()

end

function love.update(dt)

   -- main
   mousePosX = love.mouse.getX()
   mousePosY = love.mouse.getY()
   player.xPos = mousePosX - 25
   player.yPos = mousePosY - 30

end

function love.draw()

   player.draw()

end

--player.lua
local player = {
   posX = 0,
   posY = 0
}

function player.draw() -- making draw function part of player-object
   love.graphics.setColor(255, 255, 255)
   love.graphics.rectangle('fill', player.posX, player.posY, 50, 60)
end

return player

On the above code I also changed the players draw function to be part of the player-object, instead of making more global functions. And the code is now returning the player-object in the end of lua file, then assigning the object into local player in the main.lua.

Somehting to note tho, if you require player.lua multiple times, you always get the same instance, so to get multiple instances, you need to use something that creates new object every time when that function is being called.