Page 1 of 3

3 doesn't equal 3?

Posted: Thu Aug 01, 2019 2:42 pm
by MrGreen
Hello, I am new to LÖVE and I want to start with a very basic snake game. But as soon as I started, I got a problem.

What I am trying to do with this is, that when I am going in one direction, I cannot be able to move in the opposite direction. So I created an equation for it: (4/3)*(x^3) - 10*(x^2)+ (65/3)*x - 10

Code: Select all

control = {"up", 1, "right", 2, "down", 3, "left", 4}
x =(4/3)*((control[1 + 1])^3)-10*((control[1 + 1])^2)+(65/3)*(control[1 + 1])-10
print(x) <---- 3 gets printed
if x == 3 then
	print("dumm") <---- "dumm" is not printed, WHY????
end
Although the equation returns 3, "dumm" is not printed.

What am I doing wrong?


This is my actual code, but the code above shows my problem more clearly, I think.

Code: Select all

if love.keyboard.isDown(control[1]) and direction ~= x and direction ~= control[1 + 1] then
--	if grid[frontX][frontY] + 1 ~= grid[frontX][frontY - 1] and verti ~= -1 then
		direction = control[1 + 1]

--	end
end

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 6:00 pm
by raidho36
Floating point numbers don't store values exactly, only approximately. Lua uses 64 bit floats so you get approximation with precision to about 15 digits. There could be about 300 zeroes on either side but only 15 decimal places to hold the actual number.

Double precision floats have a special property: they can store integers exactly. So you get 53 bits of integer storage to play around, but the numbers must be exact integers - every operation is limited by the precision and this tiny error accumulates and amplifies, so arriving back at an "integer" through some math won't work, because it won't be an exact integer.

If your number is only slightly off, you can use rounding at the end of your operation. Alternatively, you can check if the final number is within certain range, rather than exactly equal to a specific number.

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 6:39 pm
by MrGreen
Okay thank you for your answer. I will try to round it then.

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 6:42 pm
by pgimeno
MrGreen wrote: Thu Aug 01, 2019 2:42 pm

Code: Select all

print(x) <---- 3 gets printed
if x == 3 then
	print("dumm") <---- "dumm" is not printed, WHY????
end
What raidho said. Lua by default does not print numbers with enough decimal digits as to distinguish them. Try this instead:

Code: Select all

print(string.format("%.17g", x))
An improvement on your formula would be to defer the division to the very end:

Code: Select all

x =(4*control[1 + 1]^3-30*control[1 + 1]^2+65*control[1 + 1]-30) / 3
Note I've multiplied by 3 all terms.

If the numerator in parentheses is a multiple of 3, the division will be exact. Your intermediate results like 4/3 and 65/3 are not exact and may introduce rounding errors.

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 7:05 pm
by MrGreen
pgimeno wrote: Thu Aug 01, 2019 6:42 pm

Code: Select all

x =(4*control[1 + 1]^3-30*control[1 + 1]^2+65*control[1 + 1]-30) / 3
Oh, that is even better.

Rounding worked, too:

Code: Select all

math.floor(4/3*(control[1 + 1])^3-10*(control[1 + 1])^2+65/3*(control[1 + 1])-10)
But I like your idea better. Thank you.

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 10:07 pm
by pgimeno
Good to know you have it working. Just a note in case you find yourself in similar situations in the future and decide to go the rounding way:
MrGreen wrote: Thu Aug 01, 2019 7:05 pm Rounding worked, too:

Code: Select all

math.floor(4/3*(control[1 + 1])^3-10*(control[1 + 1])^2+65/3*(control[1 + 1])-10)
That's rounding towards negative infinity, i.e. floor. That only works if your numbers are consistently equal or higher than the target number, but depending on how the intermediate operations are rounded, it may be the opposite case, i.e. instead of 3.000000x you could have gotten 2.999999x, and the floor of that is 2.0 instead of 3.0.

To solve that, you can use "Round to nearest" which can be implemented by adding 0.5:

Code: Select all

local function round(x)
  return math.floor(x + 0.5)
end
With this rounding method, ties are always rounded towards positive infinity, e.g. round(2.5) is 3 and round(-2.5) is -2.

Re: 3 doesn't equal 3?

Posted: Thu Aug 01, 2019 11:23 pm
by MrGreen
Okay, I think this will be very helpful in the future. Thank you for your help and tips.

Re: 3 doesn't equal 3?

Posted: Fri Aug 02, 2019 8:55 am
by YoungNeer
MrGreen wrote: Thu Aug 01, 2019 2:42 pm What I am trying to do with this is, that when I am going in one direction, I cannot be able to move in the opposite direction. So I created an equation for it: (4/3)*(x^3) - 10*(x^2)+ (65/3)*x - 10
Honestly saying you don't even need that equation on first place! Creating is snake game is much more simpler than that. i don't know why are you making it any more complicated than it already is - but here is an *awesome* snake game that you can refer to. You shouldn't find anything more complicated than the aabb collision :rofl:

Regards

Re: 3 doesn't equal 3?

Posted: Fri Aug 02, 2019 9:32 am
by zorg
True, you could just do something like the following:

Code: Select all

-- assuming you store the movement direction as dx,dy in a table, like direction = {0,0} initially
love.keypressed = function(k,s)
  if s == 'up' then
    direction[1] = love.keyboard.isScancodeDown('down') and direction[1] or 1.0
    direction[2] = 0.0 -- orthogonal movement
  elseif s == 'down' then
    direction[1] = love.keyboard.isScancodeDown('up') and direction[1] or -1.0
    direction[2] = 0.0 -- orthogonal movement
  elseif s == 'left' then
    direction[1] = 0.0 -- orthogonal movement
    direction[2] = love.keyboard.isScancodeDown('right') and direction[2] or -1.0
  elseif s == 'right' then
    direction[1] = 0.0 -- orthogonal movement
    direction[2] = love.keyboard.isScancodeDown('left') and direction[2] or 1.0
  end
end
This code should guarantee that the opposite directions on both axes will not turn the snake around, without having bias for any of the keys, and it's easier to do the movement based on normalized vectors like the direction variable (and it forces movement only vertically and horizontally, not diagonally)
Usually the keyreleased callback would also be used, but for snake, it's not necessary, since the snake will still continue moving even if you release the last key input.
Also, i used scancodes instead of keyconstants, because it's better if you want to consider people who don't use qwerty keyboards. (not really relevant this time though, with just the cursor keys)

Re: 3 doesn't equal 3?

Posted: Fri Aug 02, 2019 10:13 am
by MrGreen
YoungNeer wrote: Fri Aug 02, 2019 8:55 am Honestly saying you don't even need that equation on first place! Creating is snake game is much more simpler than that. i don't know why are you making it any more complicated than it already is - but here is an *awesome* snake game that you can refer to. You shouldn't find anything more complicated than the aabb collision :rofl:
To be honset I was not able to get this going. I saw some issues which I wanted to try out, but I think the version is too old. I do not have a good knowledge in programming and that is why I make it so complicated.
zorg wrote: Fri Aug 02, 2019 9:32 am True, you could just do something like the following:

Code: Select all

-- assuming you store the movement direction as dx,dy in a table, like direction = {0,0} initially
love.keypressed = function(k,s)
  if s == 'up' then
    direction[1] = love.keyboard.isScancodeDown('down') and direction[1] or 1.0
    direction[2] = 0.0 -- orthogonal movement
  elseif s == 'down' then
    direction[1] = love.keyboard.isScancodeDown('up') and direction[1] or -1.0
    direction[2] = 0.0 -- orthogonal movement
  elseif s == 'left' then
    direction[1] = 0.0 -- orthogonal movement
    direction[2] = love.keyboard.isScancodeDown('right') and direction[2] or -1.0
  elseif s == 'right' then
    direction[1] = 0.0 -- orthogonal movement
    direction[2] = love.keyboard.isScancodeDown('left') and direction[2] or 1.0
  end
end
I was not able to understand what it is really doing; If you could explain me that again for an idiot like me, that would be awesome.

Thank you for your replies and for trying to help me. I attached my files, even if they are very chaotic.
main.lua
(8.61 KiB) Downloaded 166 times
Gitter.png
Gitter.png (5.27 KiB) Viewed 6260 times
conf.lua
(52 Bytes) Downloaded 163 times