Mismatch when duplicating lua table - lua

I'm writing a game using Lua and Love2d but I've hit a snag when dealing with nested tables.
I have a function that runs through a table containing numbers corresponding to walls, buttons, etc. and prints colored blocks based on the keys. An example of one of these tables would look like this:
map = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }
{ 1, 0, 0, 0, 0, 0, 0, 0, 1 }
{ 1, 0, 1, 1, 2, 0, 0, 0, 1 }
{ 1, 0, 0, 0, 0, 0, 0, 0, 1 }
{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }
}
This works fine when rendered. However when I attempt to create this same table using a function that reads this data from a text file looking like this:
111111111
100000001
101120001
100000001
111111111
It creates a table that seems identical but it simply doesn't work when I try to render it.
So I tried debugging using a bit of code that prints out table contents and though the contents are the same, the bit of hex describing the nested tables are different. Example:
Reading the first nested table of the map file:
1 table: 0x106c5a720
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
Reading the first nested table of the manually created table:
1 table: 0x106c64120
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
What's going on here? The values are all identical but something strange is happening.
edit: Here's the bit of code that renders the map for reference:
for y=1, #map do
for x=1, #map[y] do
if map[y][x] == 1 then
print("found a wall")
love.graphics.rectangle("fill", x * 30, y * 30, 30, 30)
elseif map[y][x] == 2 then
print("found a button")
love.graphics.setColor(255, 0, 0)
love.graphics.rectangle("fill", x * 30, y * 30, 30, 30)
love.graphics.setColor(0, 0, 255)
end
end
end

When reading data from a text file, you are getting strings.
In your original map table you have numbers.
Numbers are not equal to strings.
assert(1 ~= '1')

Related

how to parse strings from a file?

I have a text file.
each block parameter is separated by a colon
WoodBlock : 0.886275, 0.607843, 0.25098 : 2, 2, 2 : true : -75.5656891, -11.899992, -416.506866, 1, 0, 0, 0, 1, 0, 0, 0, 1 : 0, 0, 0 : 0, 0, 0
RustedBlock : 0.639216, 0.635294, 0.647059 : 2, 2, 2 : true : -35.5656891, -11.899992, -424.506866, 1, 0, 0, 0, 1, 0, 0, 0, 1 : 0, 0, 0 : 0, 0, 0
StoneBlock : 0.639216, 0.635294, 0.647059 : 2, 2, 2 : true : -50.5656891, -11.899992, -425.506866, 1, 0, 0, 0, 1, 0, 0, 0, 1 : 0, 0, 0 : 0, 0, 0
MetalRod : 0.388235, 0.372549, 0.384314 : 1, 3, 1 : true : -51.5656891, -11.399992, -412.506866, 1, 0, 0, 0, 1, 0, 0, 0, 1 : 0, 0, 0 : 0, 0, 0
Each line contains information about a block. I want to make an algorithm that will work like this:
the first line is selected
the second parameter of the line is selected - the script does something with this parameter
the third parameter of the line is selected - the script does something with this parameter
the fourth parameter of the line is selected - the script does something with this parameter
select the fifth parameter of the line - the script does something with this parameter
etc.
I tried using gsub but I don't know how I can select a certain line or parameter in it
You can use string.gmatch to match all parameters in the colon-delimited string. The pattern used to indicate the separator is [^:]+, which translates to "match everything but : (a colon)".
Here's an example script that loops over each line, then prints each parameter.
for line in io.lines("blocks.txt") do
for param in string.gmatch(line, "[^:]+") do
print(param)
end
end

Love2d / LUA grid locked movement NO DIAGONAL

I thought this would be a common problem but after days of research I can't find a solution. Very new to programming in general and LUA specifically. I'm building a SUPAPLEX clone as a CS50 personal project: the character moves along the grid based map and there's a code that everyone seems to suggest (attached). On release of arrow buttons the movement is continued until the end of a tile, smoothly. But if 2 movement buttons are pushed, it causes brief diagonal movement and that's the problem I'm unsuccessfully trying to solve.
Basically I'm trying to either ignore any input until the movement of the sprite is finished at the end of the grid tile or prevent updating until movement in one direction is complete. Seems like a simple thing but I'm about to give up this whole thing. Frustrating. Any input is hiiiighly appreciated and I'm sure this would be a lot of help for very many people...
function love.load()
love.keyboard.setKeyRepeat(true)
player = {
grid_x = 256,
grid_y = 256,
act_x = 256,
act_y = 256,
speed = 5,
}
map = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
{ 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
}
function testMap(x, y)
if map[(player.grid_y / 32) + y][(player.grid_x / 32) + x] == 1 then
return false
end
return true
end
function love.keypressed(key)
if key == "up" then
player.grid_y = player.grid_y - 32
elseif key == "down" then
player.grid_y = player.grid_y + 32
elseif key == "left" then
player.grid_x = player.grid_x - 32
elseif key == "right" then
player.grid_x = player.grid_x + 32
end
end
end
function love.update(dt)
player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
end
function love.draw()
love.graphics.rectangle("fill", player.act_x, player.act_y, 32, 32)
for y=1, #map do
for x=1, #map[y] do
if map[y][x] == 1 then
love.graphics.rectangle("line", x * 32, y * 32, 32, 32)
end
end
end
end
you're trying to get it to only walk along grid-lines?
take out love.keyboard.setKeyRepeat(true)
and don't use love.keypressed(key)
that's for one-at-a-time keypresses, and it would be hard to use that
with love.keyreleased() to see if all the other keys are released.
use isDown instead, and if one of them isDown, then none of the other dir keys allow input. (along with the couple player.act lines you already have in your update)
player = {
grid_x = 256,
grid_y = 256,
act_x = 256,
act_y = 256,
speed = 5,
dir = ''
}
function love.update(dt)
if love.keyboard.isDown("up", "down", "left", "right") then
if love.keyboard.isDown("up") and ( player.dir == 'up' or player.dir == '' ) then
player.dir = 'up' -- only go up if currently held, or no other dir key being pressed
player.grid_y = player.grid_y - 32
elseif love.keyboard.isDown("down") and ( player.dir == 'down' or player.dir == '' ) then
player.dir = 'down' -- only go down if currently held...
player.grid_y = player.grid_y + 32
elseif key == "left" and ( player.dir == 'left' or player.dir == '' ) then
player.dir = 'left'
player.grid_x = player.grid_x - 32
elseif key == "right" and ( player.dir == 'right' or player.dir == '' ) then
player.dir = 'right'
player.grid_x = player.grid_x + 32
end
else -- none of those keys are being pressed, so player is idle
player.dir = ''
end -- isDown()
player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
end -- update()

How to parse animations.samplers.input from gltf

The spec explains the animations.samplers.input property as:
The index of an accessor containing keyframe input values, e.g., time. That accessor must have componentType FLOAT. The values represent time in seconds with time[0] >= 0.0, and strictly increasing values, i.e., time[n + 1] > time[n].
However, I'm having a bit of trouble understanding this from the first basic example on the demo repo, Animated Triangle
Specifically, if we bring the relevant binary data for the animation from animation.bin and decode it into a Float32Array, we get the following list of values:
[0, 0.25, 0.5, 0.75, 1, 0, 0, 0, 1, 0, 0, 0.7070000171661377, 0.7070000171661377, 0, 0, 1, 0, 0, 0, 0.7070000171661377, -0.7070000171661377, 0, 0, 0, 1]
This of course does not make sense in light of "strictly increasing values".
What am I misunderstanding here? How are these values meant to be used (in combination with output) in order to update the rotation over time?
Note that animation.bin is the view referenced from the input sampler. In other words, from the gltf
input == accessor 2
accessor 2 == bufferView 2
bufferView 2 == bytes(0-100) from buffer 1
buffer 1 == animation.bin
You've decoded too far. Although bufferView 2 is bytes 0 to 100, accessor 2 does not call for all those bytes. Here's accessor 2:
{
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 5,
"type" : "SCALAR",
"max" : [ 1.0 ],
"min" : [ 0.0 ]
},
Note the count: 5 in there. Count is defined as:
The number of attributes referenced by this accessor, not to be confused with the number of bytes or number of components.
So, accesessor 2 is the first five SCALAR values from offset 0 in bufferView 2, namely the first five numbers from your decoded output above:
[0, 0.25, 0.5, 0.75, 1]
FWIW, there are tools to help investigate glTF binary files. Here's the "Peek Definition" function from VSCode's glTF extension:
(Disclaimer, I'm one of the authors of this extension, although I did not write this decode feature myself).

Mapping the index of values in an array that match a specific value?

Disclaimer, I'm a beginner.
I have an array that is 16 digits, limited to 0's and 1's. I'm trying to create a new array that contains only the index values for the 1's in the original array.
I currently have:
one_pos = []
image_flat.each do |x|
if x == 1
p = image_flat.index(x)
one_pos << p
image_flat.at(p).replace(0)
end
end
The image_flat array is [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
With the code above, one_pos returns [3, 3] rather than the [3, 5] that I'd expect.
Where am I going wrong?
Where am I going wrong?
When you call
image_flat.index(x)
It only returns first entry of x in image_flat array.
I guess there are some better solutions like this one:
image_flat.each_with_index do |v, i|
one_pos << i if v == 1
end
Try using each_with_index (http://apidock.com/ruby/Enumerable/each_with_index) on your array.
image_flat = [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
one_pos = []
image_flat.each_with_index do |value, index|
if value == 1
one_pos << index
end
end
I think this is the most elegant solution here:
image_flat.each_index.select{|i| image_flat[i] == 1}
Here is a solution if you are looking for a solution that doesn't reach out of the enumerable block although it does require a chained solution.
image_flat.each_with_index.select { |im,i| im==1 }.map { |arr| arr[1] }
Its chained and will require an additional lookup so Gena Shumilkin's answer will probably be more optimal for larger arrays.
This was what I originally thought Gena Shumilkin was trying to reach until I realized that solution used each_index instead of each_with_index.

Lua: index expected, got nil

Well, I'm very new to lua, LITERALLY today began to study this. So this is my code:
local l = {1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}
local n = table.getn(l)
local path = {{l[1], 1}}
local index = 1
for i=2,n do
if l[i] ~= l[i-1] then
index = index + 1
path[index][1] = l[i]
path[index][2] = 0
end
path[index][2] = path[index][2] + 1
end
What I want to do is to get path array (table) where zeros and ones should be grouped with their consequent amount. The output should be:
{{1, 1}, {0, 3}, {1, 3}, {0, 8}, {1, 1}}
But the problem is I get index expected, got nil error in line: path[index][1] = l[i] What is wrong with this code? index should be incremented and new item in path array should be created... But it isn't...
Index is set to to and you are attempting to index into path at position 2, which returns nil. Then you are attempting to set index 1 on nil. You need to create a table at index 2 of path. Try doing this
path[index] = {l[i], 0}

Resources