Reading and parsing files with LUA - lua

I am trying to get it to read from a file x y z coordinates into a 3d array. But it does not seem to be working.
file is located in same folder as the .lua script
-9649.481 666.4141 117.3444
-9475.624 563.4871 116.0533
-9338.459 432.295 137.4043
function lines_from(file)
if not file_exists(file) then return {} end
for line in io.lines(file) do
tokens = {};
itr = 1;
for token in string.gmatch(line, "[^%s]+") do
tokens[ itr ] = token;
itr = itr + 1;
end
x = tokens[1];
y = tokens[2];
z = tokens[3];
g_lines_from[g_lines_fromCount] = { x, y, z };
g_lines_fromCount = g_lines_fromCount + 1;
end
end
function AddAll()
for i = 1, g_lines_from, 1 do
x, y, z = g_lines_from[i];
ListBoxEntry.Create( g_lbWaypoints, "X: " .. math.floor( x ) .. ", Y: " .. math.floor( y ) .. ", Z: " .. math.floor( z ) );
end
end
function OnAddWaypointClicked( eventID, button )
local file = "mine1-75.txt";
lines_from(file);
AddAll();
end;

Try the following function:
function readwaypoints(filename, numberofwaypoints)
local file = io.open(filename)
local waypoints = {}
for n = 1, numberofwaypoints do
local x, y, z
x = file:read('*n')
y = file:read('*n')
z = file:read('*n')
waypoints[#waypoints+1] = {['x'] = x, ['y'] = y, ['z'] = z}
end
file:close()
return waypoints
end
It takes a file name and the number of lines in the file. For your example file, it should return a table like this:
{[1] = {x = -9649.481, y = 666.4141, z = 117.3444},
[2] = {x = -9475.624, y = 563.4871, z = 116.0533},
[3] = {x = -9338.459, y = 432.295, z = 137.4043}}

Related

Love2D trying to generate a chunk that has blocks inside it, but after moving a few chunks away it renders more chunks then intended

I have created a basic chunk generator, a chunk is area filled with squares, when the player moves a few blocks away from 0,0 it works correctly but after moving 4 chunks away it renders more then one chunk instead of one, I am not sure what I am doing wrong, I have given it a go changing some values, but I am left head scratching.
here is the full code, you can copy and paste into VSCODE with love2D to see what happens.
I think the main issue is somewhere around check_boarders function since that is what checks if the player is inside a chunk.
function Key_input(key)
if love.keyboard.isDown(key) then
return 1
else
return 0
end
end
function love.load()
Camera = require "camera"
Cam = Camera()
Basic_Player = {}
Basic_Player.X = 100
Basic_Player.Y = 100
Basic_Player.Speed = 15
Movement = {}
end
function love.update(dt)
Movement.X = Key_input("d") - Key_input("a")
Movement.Y = Key_input("s") - Key_input("w")
Basic_Player.X = Basic_Player.X + Movement.X * Basic_Player.Speed
Basic_Player.Y = Basic_Player.Y + Movement.Y * Basic_Player.Speed
Cam:lookAt(Basic_Player.X,Basic_Player.Y)
X, Y = Cam:position() -- Set cam position to global values
end
function love.draw()
love.graphics.setBackgroundColor(0.5,0.5,0.9)
Cam:attach() -- Renders the player and world inside its own scene
generate_world(10,0)
love.graphics.setColor( 0,0,1, 1 )
love.graphics.rectangle("fill",Basic_Player.X,Basic_Player.Y,30,30)
love.graphics.setColor( 1,1,1, 1 )
Cam:detach()
love.graphics.setColor( 1,0,0, 1 ) --Stays on the screen
love.graphics.print(X .. " / " .. Y ,300,400)
love.graphics.print(love.timer.getFPS( ) ,300,450)
love.graphics.setColor( 1,1,1, 1 )
end
function old_generate_world(_world_size, _seed) -- Before optimization
local _chunk_size = 30
local _block_size = 30
for i = 0, _world_size - 1 do
for f = 0, _world_size - 1 do
local x_val = (_chunk_size * _block_size) * i -- Position value for actually building the chunks
local y_val = (_chunk_size * _block_size) * f
gen_chunk(_chunk_size,_block_size,_seed,{X = x_val ,Y = y_val })
end
end
end
function generate_world(_world_size, _seed)
local _chunk_size = 10 -- Chunk size width and height
local _block_size = 30 -- block size inside the chunk
for i = 0, _world_size - 1 do -- loop through world size
for f = 0, _world_size - 1 do
local x_val = (_chunk_size * _block_size) * i -- Position value for actually building the chunks
local y_val = (_chunk_size * _block_size) * f
local chunk_x_local_size = 0 -- To make sure we get a length for when i and f = 0
local chunk_y_local_size = 0
if i == 0 then -- To make sure the size of the chunk isnt zero
chunk_x_local_size = _chunk_size * _block_size -- Get length of chunk when i = 0
else
chunk_x_local_size = x_val
end
if f == 0 then -- ditto
chunk_y_local_size = _chunk_size * _block_size
else
chunk_y_local_size = y_val
end
-- Checks if the player is inside a chunk if true draw it.
if Check_boarders({X = X,Y = Y},{X = x_val,Y = y_val}, {X = chunk_x_local_size, Y = chunk_y_local_size}) then
gen_chunk(_chunk_size,_block_size,_seed,{X = x_val ,Y = y_val }) -- Actually generate the chunk
end
love.graphics.setColor( 0,1,0, 1 )
love.graphics.rectangle("fill",x_val,y_val,15,15)
love.graphics.setColor( 1,1,1, 1 )
end
end
end
function Check_boarders(player_pos, boarder_pos, chunk_length) -- Checks player position is inside the boarder of the currently generated chunk
if player_pos.X > boarder_pos.X and player_pos.X < boarder_pos.X + chunk_length.X then -- Check if the player is greater then top left and less then top right
if player_pos.Y > boarder_pos.Y and player_pos.Y < boarder_pos.Y + chunk_length.Y then -- check if player is greater then top and less then bottom left
return true
end
end
return false
end
function gen_chunk(chunk_size,block_size,seed,position) -- chunk size is how many blocks inside the chunk, block size is self explain, seed n/a, pos starting chunk position
for i = 0, chunk_size - 1 do
for e = 0, chunk_size - 1 do -- loop until chunk size is met this is the amount of blocks being created
love.graphics.rectangle("fill",position.X + i * block_size,position.Y + e * block_size,block_size - 1,block_size - 1)
end
end
love.graphics.setColor( 1,0,0, 1 )
love.graphics.rectangle("fill",position.X ,position.Y,6,6)
love.graphics.setColor( 1,1,1, 1 )
end
You will need this camera.lua script just create it and paste this into it:
local _PATH = (...):match('^(.*[%./])[^%.%/]+$') or ''
local cos, sin = math.cos, math.sin
local camera = {}
camera.__index = camera
-- Movement interpolators (for camera locking/windowing)
camera.smooth = {}
function camera.smooth.none()
return function(dx,dy) return dx,dy end
end
function camera.smooth.linear(speed)
assert(type(speed) == "number", "Invalid parameter: speed = "..tostring(speed))
return function(dx,dy, s)
-- normalize direction
local d = math.sqrt(dx*dx+dy*dy)
local dts = math.min((s or speed) * love.timer.getDelta(), d) -- prevent overshooting the goal
if d > 0 then
dx,dy = dx/d, dy/d
end
return dx*dts, dy*dts
end
end
function camera.smooth.damped(stiffness)
assert(type(stiffness) == "number", "Invalid parameter: stiffness = "..tostring(stiffness))
return function(dx,dy, s)
local dts = love.timer.getDelta() * (s or stiffness)
return dx*dts, dy*dts
end
end
local function new(x,y, zoom, rot, smoother)
x,y = x or love.graphics.getWidth()/2, y or love.graphics.getHeight()/2
zoom = zoom or 1
rot = rot or 0
smoother = smoother or camera.smooth.none() -- for locking, see below
return setmetatable({x = x, y = y, scale = zoom, rot = rot, smoother = smoother}, camera)
end
function camera:lookAt(x,y)
self.x, self.y = x, y
return self
end
function camera:move(dx,dy)
self.x, self.y = self.x + dx, self.y + dy
return self
end
function camera:position()
return self.x, self.y
end
function camera:rotate(phi)
self.rot = self.rot + phi
return self
end
function camera:rotateTo(phi)
self.rot = phi
return self
end
function camera:zoom(mul)
self.scale = self.scale * mul
return self
end
function camera:zoomTo(zoom)
self.scale = zoom
return self
end
function camera:attach(x,y,w,h, noclip)
x,y = x or 0, y or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
self._sx,self._sy,self._sw,self._sh = love.graphics.getScissor()
if not noclip then
love.graphics.setScissor(x,y,w,h)
end
local cx,cy = x+w/2, y+h/2
love.graphics.push()
love.graphics.translate(cx, cy)
love.graphics.scale(self.scale)
love.graphics.rotate(self.rot)
love.graphics.translate(-self.x, -self.y)
end
function camera:detach()
love.graphics.pop()
love.graphics.setScissor(self._sx,self._sy,self._sw,self._sh)
end
function camera:draw(...)
local x,y,w,h,noclip,func
local nargs = select("#", ...)
if nargs == 1 then
func = ...
elseif nargs == 5 then
x,y,w,h,func = ...
elseif nargs == 6 then
x,y,w,h,noclip,func = ...
else
error("Invalid arguments to camera:draw()")
end
self:attach(x,y,w,h,noclip)
func()
self:detach()
end
-- world coordinates to camera coordinates
function camera:cameraCoords(x,y, ox,oy,w,h)
ox, oy = ox or 0, oy or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
-- x,y = ((x,y) - (self.x, self.y)):rotated(self.rot) * self.scale + center
local c,s = cos(self.rot), sin(self.rot)
x,y = x - self.x, y - self.y
x,y = c*x - s*y, s*x + c*y
return x*self.scale + w/2 + ox, y*self.scale + h/2 + oy
end
-- camera coordinates to world coordinates
function camera:worldCoords(x,y, ox,oy,w,h)
ox, oy = ox or 0, oy or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
-- x,y = (((x,y) - center) / self.scale):rotated(-self.rot) + (self.x,self.y)
local c,s = cos(-self.rot), sin(-self.rot)
x,y = (x - w/2 - ox) / self.scale, (y - h/2 - oy) / self.scale
x,y = c*x - s*y, s*x + c*y
return x+self.x, y+self.y
end
function camera:mousePosition(ox,oy,w,h)
local mx,my = love.mouse.getPosition()
return self:worldCoords(mx,my, ox,oy,w,h)
end
-- camera scrolling utilities
function camera:lockX(x, smoother, ...)
local dx, dy = (smoother or self.smoother)(x - self.x, self.y, ...)
self.x = self.x + dx
return self
end
function camera:lockY(y, smoother, ...)
local dx, dy = (smoother or self.smoother)(self.x, y - self.y, ...)
self.y = self.y + dy
return self
end
function camera:lockPosition(x,y, smoother, ...)
return self:move((smoother or self.smoother)(x - self.x, y - self.y, ...))
end
function camera:lockWindow(x, y, x_min, x_max, y_min, y_max, smoother, ...)
-- figure out displacement in camera coordinates
x,y = self:cameraCoords(x,y)
local dx, dy = 0,0
if x < x_min then
dx = x - x_min
elseif x > x_max then
dx = x - x_max
end
if y < y_min then
dy = y - y_min
elseif y > y_max then
dy = y - y_max
end
-- transform displacement to movement in world coordinates
local c,s = cos(-self.rot), sin(-self.rot)
dx,dy = (c*dx - s*dy) / self.scale, (s*dx + c*dy) / self.scale
-- move
self:move((smoother or self.smoother)(dx,dy,...))
end
-- the module
return setmetatable({new = new, smooth = camera.smooth},
{__call = function(_, ...) return new(...) end})

math library is missing in the latest update of Logitech G-Hub

local delay = math.random(25, 50)
[string "LuaVM"]:5: attempt to index a nil value (global 'math')
I can't use math.random anymore is there any way to fix this ?
If math library is missed you can insert the following code block at the beginning of your script.
It will not fix the whole math library, but only some of the most frequently used functions (including math.random).
It will also fix the following errors:
bad argument #1 to 'Sleep' (number has no integer representation)
attempt to call a nil value (field 'getn')
do
local state_8, state_45, cached_bits, cached_bits_qty = 2, 0, 0, 0
local prev_width, prev_bits_in_factor, prev_k = 0
for c in GetDate():gmatch"." do
state_45 = state_45 % 65537 * 23456 + c:byte()
end
local function get_53_random_bits()
local value53 = 0
for shift = 26, 27 do
local p = 2^shift
state_45 = (state_45 * 233 + 7161722017421) % 35184372088832
repeat state_8 = state_8 * 76 % 257 until state_8 ~= 1
local r = state_8 % 32
local n = state_45 / 2^(13 - (state_8 - r) / 32)
n = (n - n%1) % 2^32 / 2^r
value53 = value53 * p + ((n%1 * 2^32) + (n - n%1)) % p
end
return value53
end
for j = 1, 10 do get_53_random_bits() end
local function get_random_bits(number_of_bits)
local pwr_number_of_bits = 2^number_of_bits
local result
if number_of_bits <= cached_bits_qty then
result = cached_bits % pwr_number_of_bits
cached_bits = (cached_bits - result) / pwr_number_of_bits
else
local new_bits = get_53_random_bits()
result = new_bits % pwr_number_of_bits
cached_bits = (new_bits - result) / pwr_number_of_bits * 2^cached_bits_qty + cached_bits
cached_bits_qty = 53 + cached_bits_qty
end
cached_bits_qty = cached_bits_qty - number_of_bits
return result
end
table = table or {}
table.getn = table.getn or function(x) return #x end
math = math or {}
math.huge = math.huge or 1/0
math.abs = math.abs or function(x) return x < 0 and -x or x end
math.floor = math.floor or function(x) return x - x%1 end
math.ceil = math.ceil or function(x) return x + (-x)%1 end
math.min = math.min or function(x, y) return x < y and x or y end
math.max = math.max or function(x, y) return x > y and x or y end
math.sqrt = math.sqrt or function(x) return x^0.5 end
math.pow = math.pow or function(x, y) return x^y end
math.frexp = math.frexp or
function(x)
local e = 0
if x == 0 then
return x, e
end
local sign = x < 0 and -1 or 1
x = x * sign
while x >= 1 do
x = x / 2
e = e + 1
end
while x < 0.5 do
x = x * 2
e = e - 1
end
return x * sign, e
end
math.exp = math.exp or
function(x)
local e, t, k, p = 0, 1, 1
repeat e, t, k, p = e + t, t * x / k, k + 1, e
until e == p
return e
end
math.log = math.log or
function(x)
assert(x > 0)
local a, b, c, d, e, f = x < 1 and x or 1/x, 0, 0, 1, 1
repeat
repeat
c, d, e, f = c + d, b * d / e, e + 1, c
until c == f
b, c, d, e, f = b + 1 - a * c, 0, 1, 1, b
until b <= f
return a == x and -f or f
end
math.log10 = math.log10 or
function(x)
return math.log(x) / 2.3025850929940459
end
math.random = math.random or
function(m, n)
if m then
if not n then
m, n = 1, m
end
local k = n - m + 1
if k < 1 or k > 2^53 then
error("Invalid arguments for function 'random()'", 2)
end
local width, bits_in_factor, modk
if k == prev_k then
width, bits_in_factor = prev_width, prev_bits_in_factor
else
local pwr_prev_width = 2^prev_width
if k > pwr_prev_width / 2 and k <= pwr_prev_width then
width = prev_width
else
width = 53
local width_low = -1
repeat
local w = (width_low + width) / 2
w = w - w%1
if k <= 2^w then
width = w
else
width_low = w
end
until width - width_low == 1
prev_width = width
end
bits_in_factor = 0
local bits_in_factor_high = width + 1
while bits_in_factor_high - bits_in_factor > 1 do
local bits_in_new_factor = (bits_in_factor + bits_in_factor_high) / 2
bits_in_new_factor = bits_in_new_factor - bits_in_new_factor%1
if k % 2^bits_in_new_factor == 0 then
bits_in_factor = bits_in_new_factor
else
bits_in_factor_high = bits_in_new_factor
end
end
prev_k, prev_bits_in_factor = k, bits_in_factor
end
local factor, saved_bits, saved_bits_qty, pwr_saved_bits_qty = 2^bits_in_factor, 0, 0, 2^0
k = k / factor
width = width - bits_in_factor
local pwr_width = 2^width
local gap = pwr_width - k
repeat
modk = get_random_bits(width - saved_bits_qty) * pwr_saved_bits_qty + saved_bits
local modk_in_range = modk < k
if not modk_in_range then
local interval = gap
saved_bits = modk - k
saved_bits_qty = width - 1
pwr_saved_bits_qty = pwr_width / 2
repeat
saved_bits_qty = saved_bits_qty - 1
pwr_saved_bits_qty = pwr_saved_bits_qty / 2
if pwr_saved_bits_qty <= interval then
if saved_bits < pwr_saved_bits_qty then
interval = nil
else
interval = interval - pwr_saved_bits_qty
saved_bits = saved_bits - pwr_saved_bits_qty
end
end
until not interval
end
until modk_in_range
return m + modk * factor + get_random_bits(bits_in_factor)
else
return get_53_random_bits() / 2^53
end
end
local orig_Sleep = Sleep
function Sleep(x)
return orig_Sleep(x - x%1)
end
end

Can this lua code be written better?

Can the following code be refactored to be more concise or more clear? I have also attached a picture below to help illustrate what I have in mind.
local playerAreaPos = {
{x = playerPos.x, y = playerPos.y - 1, z = playerPos.z}, -- NORTH
{x = playerPos.x, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH
{x = playerPos.x + 1, y = playerPos.y, z = playerPos.z}, -- EAST
{x = playerPos.x - 1, y = playerPos.y, z = playerPos.z}, -- WEST
{x = playerPos.x - 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-WEST
{x = playerPos.x + 1, y = playerPos.y + 1, z = playerPos.z}, -- SOUTH-EAST
{x = playerPos.x - 1, y = playerPos.y - 1, z = playerPos.z}, -- NORTH-WEST
{x = playerPos.x + 1, y = playerPos.y - 1, z = playerPos.z} -- NORTH-EAST
}
local posTable = {
{x = playerPos.x, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH"},
{x = playerPos.x, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH"},
{x = playerPos.x + 2, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x + 3, y = playerPos.y, z = playerPos.z, dir = "EAST"},
{x = playerPos.x - 2, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 3, y = playerPos.y, z = playerPos.z, dir = "WEST"},
{x = playerPos.x - 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y - 2, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y - 3, z = playerPos.z, dir = "NORTH_EAST"},
{x = playerPos.x - 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x - 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_WEST"},
{x = playerPos.x + 2, y = playerPos.y + 2, z = playerPos.z, dir = "SOUTH_EAST"},
{x = playerPos.x + 3, y = playerPos.y + 3, z = playerPos.z, dir = "SOUTH_EAST"}
}
for i = 1, #posTable do
if targetPos == Position(posTable[i]) then
if posTable[i].dir == "NORTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[8].x, playerAreaPos[8].y)
elseif posTable[i].dir == "NORTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[7].x, playerAreaPos[7].y)
elseif posTable[i].dir == "NORTH" then
print("TELEPORT TO: ", playerAreaPos[1].x, playerAreaPos[1].y)
elseif posTable[i].dir == "SOUTH_WEST" then
print("TELEPORT TO: ", playerAreaPos[5].x, playerAreaPos[5].y)
elseif posTable[i].dir == "SOUTH_EAST" then
print("TELEPORT TO: ", playerAreaPos[6].x, playerAreaPos[6].y)
elseif posTable[i].dir == "SOUTH" then
print("TELEPORT TO: ", playerAreaPos[2].x, playerAreaPos[2].y)
elseif posTable[i].dir == "EAST" then
print("TELEPORT TO: ", playerAreaPos[3].x, playerAreaPos[3].y)
elseif posTable[i].dir == "WEST" then
print("TELEPORT TO: ", playerAreaPos[4].x, playerAreaPos[4].y)
end
end
end
The aim of this function is to teleport enemies from posTable to playerAreaPos while ensuring they teleport within the corresponding line, which means if they are 3 squares north from main character they will be teleported to 1 square north of main character
local enemyPos = {x = 11, y = 22, z = 33}
local playerPos = {x = 10, y = 20, z = 30}
local beam_length = 3
if enemyPos.z == playerPos.z then
local dx = enemyPos.x - playerPos.x
local dy = enemyPos.y - playerPos.y
local ax, ay = math.abs(dx), math.abs(dy)
local len_max, len_min = math.max(ax, ay), math.min(ax, ay)
if len_max >= 2 and len_max <= beam_length and len_min % len_max == 0 then
print("TELEPORT TO: ", playerPos.x + dx / len_max, playerPos.y + dy / len_max)
end
end
There's a many way to implementation your question but I'm going try to use some math and after I'm going do some considerations about them.
Look at the next diagram there's a minimum distance between our hero and enemy when enemy fall into range it'll be teleport to hero's radius and after, foe can not teleport unless our hero throw it far its radius.
When these consideration, I made this implementation
-- returns math functions as local functions
local deg = math.deg
local sin = math.sin
local cos = math.cos
local atan2 = math.atan2
-- returns the distance between two points
local lengthOf = function ( dots )
local dx, dy = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
return (dx*dx + dy*dy)^.5
end
-- returns the degrees between two points
-- note: 0 degrees is 'east'
local angleBetweenPoints = function ( dots )
local x, y = dots.x[2]-dots.x[1], dots.y[2]-dots.y[1]
local radian = atan2(x, y)
local angle = deg(radian)
angle = angle < 0 and (360 + angle) or angle
return angle
end
--config your hero
local hero = {}
hero.posX, hero.posY = 0, 0
hero.radius = 10
-- config enemy
local foe = {}
foe.posX, foe.posY = 0, 18
foe.radius = 8
foe.theta = 0
foe.teleported = false
foe.distToHero = 18
foe.points = {}
foe.curDist = 0
-- this part will be a sort like frame
foe.points = {x={hero.posX,foe.posX}, y={hero.posY,foe.posY}}
foe.curDist = lengthOf( foe.points )
if foe.distToHero<=foe.curDist and not foe.teleported then
foe.theta = angleBetweenPoints ( foe.points )
foe.posX = hero.radius*sin( foe.theta ) -- yes it's reverse
foe.posY = hero.radius*cos( foe.theta ) -- yes it's reverse
foe.teleported = true
else
foe.teleported = false -- if enemy is hit far of the hero
end
print(foe.posX,foe.posY)
-- printed output: 0, 10
The previous implementation, require a lot calculation if you put a lot foes on the landscape my suggestion is use C API or Box2D this last use a sensor fixture when a collision occur and is very useful for this sort situations. Currently there's many Lua SDK with these features so you can kickstart.

Bug in calling self function?

I wrote this code:
Editor = {
x = 10,
y = 10,
interpreter = nil,
cursor = nil
}
-- Some code here
function Editor:drawValues(w, h)
for x = 0, w - 1 do
for y = 0, h - 1 do
local _x = self.x + x * CELL_SIZE
local _y = self.y + y * CELL_SIZE
love.graphics.print(self.interpreter.grid.cell[x][y], _x, _y) -- ERROR THIS!
end
end
end
function Editor:draw()
local w = self.interpreter.grid.width
local h = self.interpreter.grid.height
Editor:drawGrid(w, h)
Editor:drawValues(w, h)
-- Its Works VVVVVVV
-- for x = 0, w - 1 do
-- for y = 0, h - 1 do
-- local _x = self.x + x * CELL_SIZE
-- local _y = self.y + y * CELL_SIZE
-- local value = self.interpreter.grid.cell[x][y]
-- love.graphics.print(value, _x, _y) -- self.interpreter.grid.cell[x][y]
-- end
-- end
end
return Editor
Function Editor:draw calls Editor:drawGrid and it works, but calling Editor:drawValues(w, h) throws an error:
attempt to index field 'interpreter' (a nil value)
But! If I comment Editor:drawValues(w, h) and uncomment the code below, it works. Why?
Apologies for my English.

Lua - Error Attempt to perform arithmetic on field '?' -- This occurs at the end of the for loop

I'm developing a program for the Ti-nspire CX CAS calculator and at the time of execution it indicates an error on line 52, this is presented at the end of the for loop in the "area" function.
Sorry for my English.
local coX = {0,2,2,0}
local coY = {0,0,2,0}
local xmax = 2
local ymax = 2
-- Matriz de coordenadas para función "on.paint(gc)"
function conCoor(x,y)
local nx = x
for i=1, #x do
table.insert(nx,i*2,y[i])
end
return nx
end
-- Valor absoluto
function math.abs(valor)
if valor < 0 then
valor = valor*(-1)
end
return valor
end
-- Inercia del polígono respecto el eje X
function inerciex(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (x[i+1]-x[i])*(y[i+1]+y[i])*((y[i+1])^2+(y[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Inercia del polígono respecto el eje Y
function inerciey(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (y[i+1]-y[i])*(x[i+1]+x[i])*((x[i+1])^2+(x[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Área del poligono
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
-- Centro de masa del polígono (eje x)
function centroix(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (x[i]+x[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Centro de masa del polígono (eje y)
function centroiy(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (y[i]+y[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Escala de figura
function escala(xmax,ymax)
local sc = 0
if xmax > ymax then
sc = 81/xmax
else
sc = 81/ymax
end
return math.floor(sc)
end
-- Coordenadas del origen en pantalla
function oriDispX(x,y,xmax,ymax)
return math.floor(212 + (-1)*centroix(x,y)*escala(xmax,ymax))
end
function oriDispY(x,y,xmax,ymax)
return math.floor(105 + (-1)*centroiy(x,y)*escala(xmax,ymax))
end
-- Cambio de coordenadas real
function coorCamb(x,y,xmax,ymax)
-- Escalado de coordenadas
local escx = x
local escy = y
local orix = oriDispX(escx,escy,xmax,ymax)
local oriy = oriDispY(escx,escy,xmax,ymax)
for i = 1, #escx do
escx[i] = math.floor(escx[i]*escala(xmax,ymax))
escy[i] = math.floor(escy[i]*escala(xmax,ymax))
end
-- Cambio de coordenadas
for i = 1, #escx do
escx[i] = escx[i] + orix
escy[i] = escy[i] + oriy
end
return conCoor(escx,escy)
end
function on.paint(gc)
local ox = oriDispX(coX,coY,xmax,ymax)
local oy = oriDispY(coX,coY,xmax,ymax)
local c = coorCamb(coX,coY,xmax,ymax)
gc:drawPolyLine(c)
gc:drawLine(ox-3,oy,ox+3,oy)
gc:drawLine(ox,oy-3,ox,oy+3)
gc:fillArc(ox-1,oy-1,2,2,0,360)
gc:fillArc(212-1,105-1,2,2,0,360)
gc:drawString(tostring(area(coX,coY)),10,10)
platform.window:invalidate()
end
More specifically, the error occurs here:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
Your code assumes both X and Y arrays are of equal size (because you use i index for both X and Y array), or at least Y never smaller than X. i index, however, runs from 1 to the size of X array which will be invalid for Y array of smaller size.
So, if the Y array is smaller than the X array, you get that error. And, here's the proof:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end
return math.abs(z/2)
end
print(area({1,2,3},{4,5,6})) -- OK
print(area({1,2,3},{4,5})) -- ERROR
The solution was to initialize the variables and tables at the beginning of the whole script and then call the new values ​​using "var.recall" inside the on.paint function.

Resources