"quit" read as nil field? - lua
I am making a menu file for my game, and it's can't call "quit" as a field. It always returns nil. Can anyone tell me why this is happening? Note, it is declared earlier in the code and the other button function does work. Thanks!
function love.mousepressed( x, y, button )
if button == "l" then
for k, v in pairs(buttons) do
local ins = insideBox( x, y, v.x - (v.w/2), v.y - (v.h/2), v.w, v.h)
if ins then
if v.action == "play" then
loadState("game")
end
end
if ins then
if v.action == "quit" then
love.event.quit()
end
end
end
end
end
Why would you have play and quit bound to the same button? o.O
Also, there's no need to check ins twice. Duplicate code should be a red flag:
if ins then
if v.action == "play" then
loadState("game")
end
end
if ins then
if v.action == "quit" then
love.event.quit()
end
end
That could be:
if ins then
if v.action == "play" then
loadState("game")
elseif v.action == "quit" then
love.event.quit()
end
end
But short of using a debugger, here's how you track down such problems:
1. Create a file called conf.lua in your project folder.
2. Have at least this much inside it, to attach a console to your app:
function love.conf(t)
t.console = true -- Attach a console (Windows only)
end
3. Add debugging output to your mousepressed function so you can see what's going on.
First define this somewhere early in your app execution. Handy printing function:
function printf(...) print(string.format(...)) end
Then add some debugging stuff to your function:
function love.mousepressed(x, y, button)
print('mouse button %d pressed at %d, %d', button, x, y)
if button == "l" then
printf('checking %d buttons', #buttons)
for k, v in pairs(buttons) do
local ins = insideBox( x, y, v.x - (v.w/2), v.y - (v.h/2), v.w, v.h)
printf('%d, %d is%sinside button %s (%d, %d, %d, %d)',
ins and ' ' or ' not ', k, x, y, v.x, v.y, v.w, v.h)
if ins then
print('executing action', v.action)
if v.action == "play" then
loadState("game")
elseif v.action == "quit" then
love.event.quit()
end
end
end
end
end
You should also used meaningful variables names. v can be button. What is k? An index? Then perhaps i or index. Is it a name? Then name. So on and so forth. k tells us nothing.
Related
How do I keep the renderBlocks() function from going into an infinite loop?
-- This is Minecraft, but 2D, and in Lua. -- ************************************** -- ID 0: Air -- ID 1: Stone -- ID 2 Logs -- ID 3: Leaves -- ID 4: Planks -- ID 5: Crafting Table -- ID 6: Furnance -- ID 7: Player position detector block -- ************************************** blockTable = { -- Stores all the blocks {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6} } tableRow = 1 -- Y value for block render pointer tableColumn = 1 -- X value for block render pointer runOnce = true -- Run a loop once tickNum = 0 -- Number of ticks since startup function renderBlock(X, Y, K) -- Render a block if K == 1 then -- if blockID == 1, draw a grey square screen.setColor(100,100,100) print(X, Y) screen.drawRectF(X, Y, 8, 8) end if K == 6 then -- If the blockID == draw a grey square screen.setColor(100,100,100) screen.drawRectF(X, Y, 8, 8) end end function renderBlocks() -- Render all the blocks (Scans though the blockTable in a raster pattern) while runOnce == true -- Run this code once do while #blockTable >= tableRow do while #blockTable[tableRow] >= tableColumn do print("TC " .. tableColumn) tableColumn = tableColumn + 1 blockID = blockTable[tableRow][tableColumn] renderBlock(tableRow, tableColumn, blockID) if tableColumn > #blockTable[tableRow] then tableColumn = 1 end end runOnce = false end print("TR " .. tableRow) tableRow = tableRow + 1 end end function onTick() print("Tick! Tick count: " .. tickNum) -- Print the current tick, as well as say that there has been a tick tickNum = tickNum + 1 end function onDraw() while runOnce == true -- Run this code once do renderBlocks() runOnce = false end end Here's my code in the IDE for the framework: Link I have no clue why this is happening, I'm at a loss here.
When doing loops over tables it is far better to use for loops than while or repeat loops, that are far more difficult to understand and bugfix. Use for index,value in ipairs(yourtable) do if you want to get the indices (number in the table) and the values associated or for key,value in pairs(yourtable) do if you want to get the keys (generally strings that is used as key for a value: yourTable["key"] = 0) and the values associated with it. for row,innerTable in ipairs(blockTable) do for col,value in ipairs(innerTable) do print("TC " .. col) blockID = value renderBlock(row, col, blockID) end end The last should do it inside your renderBlocks function. But that: while runOnce == true do -- Doing something runOnce = false end Is not very nice stuff. If it shall only be called once, do not put it into a loop! Also it would help to have a little better code identation to understand what is happening faster. And add some Space between blocks of code that handle different concerns. Edit: So your function could look like this: function renderBlocks() if runOnce then runOnce = false for row,innerTable in ipairs(blockTable) do for col,value in ipairs(innerTable) do blockID = value renderBlock(row, col, blockID) end end end end
There are a couple issues in your renderBlocks() function function renderBlocks() while runOnce == true do while #blockTable >= tableRow do while #blockTable[tableRow] >= tableColumn do print("TC " .. tableColumn) tableColumn = tableColumn + 1 blockID = blockTable[tableRow][tableColumn] renderBlock(tableRow, tableColumn, blockID) if tableColumn > #blockTable[tableRow] then tableColumn = 1 end end runOnce = false end print("TR " .. tableRow) tableRow = tableRow + 1 end end First we can look at the inner most loop. Here we have a problem with the contrition used to evaluate the loop and how it is incremented. while #blockTable[tableRow] >= tableColumn do print("TC " .. tableColumn) tableColumn = tableColumn + 1 -- incremented here blockID = blockTable[tableRow][tableColumn] renderBlock(tableRow, tableColumn, blockID) if tableColumn > #blockTable[tableRow] then tableColumn = 1 -- reset here end end in the loop body you do tableColumn = tableColumn + 1 and later in the same body you do if tableColumn > #blockTable[tableRow] then tableColumn = 1 end so this is a problem when tableColumn is increased to a value that would end the loop we reset it to 1 preventing the loop from ever ending. Now lets look at the next loop up. Here we never increment tableRow it is incremented just after the end of this loop so it is not possible for the loop to end. while #blockTable >= tableRow do while #blockTable[tableRow] >= tableColumn do ... end runOnce = false end I believe you intended print("TR " .. tableRow) tableRow = tableRow + 1 to occur within this loop not outside of it.
You're missing a few block definitions here. Don't think that's what's sending it into an infinite loop, but you might not see results, otherwise. function renderBlock(X, Y, blockID) -- Render a block if blockID == 0 then -- Air -- screen.setColor(10, 20, 220, 0) -- is there an alpha channel? screen.setColor(10, 20, 220) elseif blockID == 1 then -- Stone screen.setColor(100, 100, 100) elseif blockID == 2 then -- Logs screen.setColor(200, 50, 50) elseif blockID == 3 then -- Leaves screen.setColor(20, 220, 40) elseif blockID == 4 then -- Planks screen.setColor(180, 30, 10) elseif blockID == 5 then -- Craft Table screen.setColor(180, 30, 10) elseif blockID == 6 then -- Furnace screen.setColor(100, 100, 100) elseif blockID == 7 then -- Player detect screen.setColor(220, 30, 30) end print(X, Y) screen.drawRectF(X, Y, 8, 8) end It's easy to use for loops. set initial condition, then the final, completed condition, and let it run the course. function renderBlocks() -- Render all blocks (Scans though blockTable in a raster pattern) for row = 1, #blockTable do for col = 1, #blockTable[row] do print("TC " ..col) local blockID = blockTable[row][col] renderBlock(row, col, blockID) end print("TR " ..row) end end You likely don't need that runOnce. If you find you do for something else, go ahead, but it shouldn't be needed with a nested for loop. function onDraw() renderBlocks() end
Having problems with TIC-80
heyo! i'm trying to do a simple TIC-80 (basically lüa) script, but i'm getting an error. error started appearing after i added the lastfaced() function. honestly idk what i did wrong. here's the code: --width and height vars w=240 h=136 -- Last faced var lf='r' --Player X and Y, W, H, ID vars p = { id=0, x=w/2, y=h/2, w=16, h=16, draw = function() spr(p.id, p.x, p.y, 1, 1) end } --movement function here function lastfaced() if btn(2) then lf='l' elseif btn(3) then lf='r' elseif lf="l" then p.id=4 elseif lf="r" then p.id=0 end end function TIC() cls(12) move() p.draw() lastfaced() end and here's the error: [string "..."]:49: 'then' expected near '=' can anyone help?
Ehm, when you want to compare you must use == for it to work, one = will not work... function lastfaced() if btn(2) then lf='l' elseif btn(3) then lf='r' elseif lf="l" then p.id==4 elseif lf=="r" then p.id=0 end end
How i use the same keypress for 2 variables?(LUA)
EXAMPLE: If i press the M6 button, my cursor go to a X place, if i press the M6 button again he goes to a Y place, how can i does this alternation ? local TOPX, TOPY, MIDX, MIDY TOPX = 59305 -- Top side X TOPY = 54527 -- Top side Y MIDX = 61764 -- Mid lane X MIDY = 58683 -- Mid lane Y function OnEvent(event, arg) for n = 1,2 do if event == "MOUSE_BUTTON_RELEASED" and arg == 6 then MoveMouseTo(MIDX, MIDY); for n = 2,4 do if event == "MOUSE_BUTTON_RELEASED" and arg == 6 then MoveMouseTo(TOPX, TOPY); end end end end end
One way to do it would be having an outter flag boolean variable which would allow you to identify the state of the M6 button strokes. local buttonPressedOnce = true function onEvent(event, arg) -- Check if the button is the one we desire. if (event == "MOUSE_BUTTON_RELEASED" and arg == 6) then if (buttonPressedOnce) then -- execute X update code else -- execute Y update code end buttonPressedOnce = not(buttonPressedOnce) end end Explanation: The first press will always be the X axis update code, so we initialize the flag as true, and with each click call we proceed to update the flag value, making sure each button stroke will switch to the desired state.
How to increment by one when key is pressed?
Using love2d, I can not increment a variable by one when something happens. For example, when the space bar is pressed I would like x to increment by only one, and not change again until the space bar is pressed again. Currently, while the space bar is down it keeps adding one at a very quick speed, and continues until I release the space bar. Here is an example of the code as it is now. function love.load() x = 0 end function love.update(dt) if love.keyboard.isDown(" ") then x = x +1 end end function love.draw() love.graphics.print("space pressed for "..x.." times.",100,100) end
You can achieve better results using the love.keypressed event handler. function love.load () x = 0 end function love.keypressed (key) if key == ' ' then x = x + 1 end end function love.draw () love.graphics.print ("space pressed for "..x.." times.", 100, 100) end If you have repeated keys on, via love.keyboard.setKeyRepeat: love.keyboard.setKeyRepeat (true) function love.load () x = 0 end function love.keypressed (key, rep) if key == ' ' and not rep then x = x + 1 end end function love.draw () love.graphics.print ("space pressed for "..x.." times.", 100, 100) end
(Lua) Condition statements not behaving as expected
My math teacher has an extra credit halloween problem that goes like this: each letter represents a digit 2-9, and you need the following problem to work: trick + or = treat I decided I want to find ALL possible solutions to the problem (To impress him) so I decide to write a computer program that would tell me the all the answers. Here is my following code: local function checkAdd() local trick =k+(10*c)+(100*i)+(1000*r)+(10000*t) local _or =r+(10*o) local treat = t+(10*a)+(100*e)+(1000*r)+(10000*t) if trick + _or == treat then print(trick) print(" ".._or) print(treat) print(t) print(r) print(i) print(c) print(k) print(o) print(e) print(a) end --print("end") timer.performWithDelay(1,newNumbers) end local function checkNumbers8() if t or r or i or c or k or o or e or a == "9" then checkAdd() else newNumbers() end end local function checkNumbers7() if t or r or i or c or k or o or e or a == "8" then checkNumbers8() else newNumbers() end end local function checkNumbers6() if t or r or i or c or k or o or e or a == "7" then checkNumbers7() else newNumbers() end end local function checkNumbers5() if t or r or i or c or k or o or e or a == "6" then checkNumbers6() else newNumbers() end end local function checkNumbers4() if t or r or i or c or k or o or e or a == "5" then checkNumbers5() else newNumbers() end end local function checkNumbers3() if t or r or i or c or k or o or e or a == "4" then checkNumbers4() else newNumbers() end end local function checkNumbers2() if t or r or i or c or k or o or e or a == "3" then checkNumbers3() else newNumbers() end end local function checkNumbers() if t or r or i or c or k or o or e or a == "2" then checkNumbers2() else newNumbers() end end function newNumbers() t = mRandom(2,9) r = mRandom(2,9) i = mRandom(2,9) c = mRandom(2,9) k = mRandom(2,9) o = mRandom(2,9) e = mRandom(2,9) a = mRandom(2,9) checkNumbers() end newNumbers() *Please note that on in the function checkAdd I call the function timer.performwithdelay ( waits 1 milisecond before calling the function). This is because if I run this code just regularly without the function call, I get a stack overflow error. So i put my code into a framework I use for app developement that had the timer.performwithdelay call, and I implemented that into my code so the computer won't be so overwhelmed and cause an overflow error. I get the following print statements: 97552 27 97579 9 7 5 5 2 2 5 7 and: 49325 59 49384 4 9 3 2 5 5 3 8 I am getting some letters equaling the same as other letters! and not all numbers 2-9 are used! What is wrong with my code? I test to see if every number 2-9 is used
I think there are two main issues. I don't see the function mRandom, but I assume it returns a number and you are comparing it with a string. Number 2 is not the same as string '2', so 2 == '2' returns false. The second issue is that (it seems) you are trying to compare if either of variables has a specific value, but you can't do if a or b == 2 then meaning: execute if either a or b equals 2. For that you need to write if a == 2 or b == 2. What you have is evaluated as: if a is evaluated as true (which is when it's not nil or false) or b equals 2.