I don't know what I'm doing wrong... Im getting the error in the player.draw() function. the bad argument that its talking about is in the love.graphics.rectangle() method. It's saying that v.x is a bad argument. But it should be working. both v.x and v.y should be working. Because its accessing fields of elements within the table or array right? Can someone tell me what I'm doing wrong and how to fix this? much appreciation! Here is my code:
require "scripts.player"
width = love.graphics.getWidth()
block = {}
block.width = 60
block.height = 10
block.speed = 150
block.timer = 0
block.timerLim = math.random(1,2)
block.spawnX = math.random(0, width - player.width)
function block.spawn(x,y)
table.insert(block, {x = x, y = y})
end
function block.move(dt)
for i,v in ipairs(block) do
v.y = v.y + block.speed * dt
end
end
function block.draw()
for i,v in ipairs(block) do
love.graphics.setColor(255,0,255)
love.graphics.rectangle("fill", v.x, v.y, block.width block.height)
end
end
function block.spawnHandler(dt)
block.timer = block.timer + dt
if block.timer > block.timerLim then
block.spawn(spawnX, -10)
block.timer = 0
block.timerLim = math.random(1,2)
block.spawnX = math.random(0, width - block.width)
end
end
-- Parent Functions --
function DRAW_BLOCK()
block.draw()
end
function UPDATE_BLOCK(dt)
block.move(dt)
block.spawnHandler(dt)
end
in function block.spawnHandler you meant block.spawnX instead of spawnX.
Since spawnX does not exist, its value is nil, which goes into the spawn function and gets set as the x value of the coordinate which then makes its way into rectangle and is the bad argument.
You can read more about that and how to prevent it from biting you again here: https://www.lua.org/pil/13.4.1.html
In short, lua is really weird, until you 'fix' it by making accesses to nonexistent variables throw errors instead of return nil, and about 800 other things like that. Once you 'fix' all those things, you have something which is merely weird and is not quite lua anymore.
Related
I had made a very minimal ray tracer in Julia, and was in the process of implementing a faster version that uses CUDA. The full code is too extensive to share, but here is the part that I think is most relevant to the question:
world = World(RGB(1, 1, 1), 5e-6, shapes, lights, 0.2, 4)
camera = Camera((0, -5000, -5000), 1000, (0, 0, 0), 1920, 1080)
canvas = CUDA.fill(world.background, camera.height, camera.width)
function fillpixel!(arr::CuArray)
height = size(arr)[1]
for j in 1:length(arr)
ind = (j % height, ceil(j / height))
ray = [([ind[2], ind[1]] - [camera.width / 2, camera.height / 2])..., camera.depth]
(ray[2], ray[3]) = (cos(camera.rotation[1] + atan(ray[3], ray[2])), sin(camera.rotation[1] + atan(ray[3], ray[2]))) .* sqrt(ray[2]^2 + ray[3]^2)
(ray[1], ray[3]) = (cos(camera.rotation[2] + atan(ray[3], ray[1])), sin(camera.rotation[2] + atan(ray[3], ray[1]))) .* sqrt(ray[1]^2 + ray[3]^2)
(ray[1], ray[2]) = (cos(camera.rotation[3] + atan(ray[2], ray[1])), sin(camera.rotation[3] + atan(ray[2], ray[1]))) .* sqrt(ray[2]^2 + ray[1]^2)
v = (Inf, nothing, nothing)
for object in world.objects
t = traceray(ray, camera.position, object, mindistance=camera.depth)
t !== nothing && t[1] < v[1] && (v = (t[1], t[2], object))
end
v[1] != Inf && (arr[j] = computecolor(v[3].material, ray, v[1], v[2], world, camera.position .+ v[1] * ray, v[3]))
return nothing
end
end
#cuda fillpixel!(canvas)
but when I run the program, it gives me the following error:
CUDA.jl: ERROR: LoadError: MethodError: no method matching typeof(fillpixel!)(::CuDeviceMatrix{RGB{Float32}, 1})
and I am unable to find out what causes this error and what exactly I'm doing wrong.
Thanks.
Two comments: fillpixel!(arr::CuArray) limits your function to only the type CuArray. CUDA.jl translates the host side representation CuArray to the device side representation `CuDeviceArray. So if you loosen your type restrictions you won't run into this issue.
Secondly you don't want to iterate over the array inside the kernel you launched. You either want to use a function like map or map! to implement the data-parallelism or use the CUDA index primitives.
I'm getting a very irritating error whenever I do anything like this with arrays. I have code that sets up the array in the love.load() function:
function iceToolsInit()
objectArray = {} --for object handling
objectArrayLocation = 0
end
and then code that allows for the creation of an object. It basically grabs all of the info about said object and plugs it into an array.
function createObject(x, y, renderimage) --used in the load function
--objectArray is set up in the init function
objectArrayLocation = objectArrayLocation + 1
objectArray[objectArrayLocation] = {}
objectArray[objectArrayLocation]["X"] = x
objectArray[objectArrayLocation]["Y"] = y
objectArray[objectArrayLocation]["renderimage"] =
love.graphics.newImage(renderimage)
end
After this, an update function reads through the objectArray and renders the images accordingly:
function refreshObjects() --made for the update function
arrayLength = #objectArray
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
renderX = objectArray[arraySearch]["X"]
renderY = objectArray[arraySearch]["Y"]
renderimage = objectArray[arraySearch]["renderimage"]
if movingLeft == true then --rotation for rightfacing images
renderRotation = 120
else
renderRotation = 0
end
love.graphics.draw(renderimage, renderX, renderY, renderRotation)
end
end
I of course clipped some unneeded code (just extra parameters in the array such as width and height) but you get the gist. When I set up this code to make one object and render it, I get this error:
attempt to index '?' (a nil value)
the line it points to is this line:
renderX = objectArray[arraySearch]["X"]
Does anyone know what's wrong here, and how I could prevent it in the future? I really need help with this.
It's off-by-one error:
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
You run through the loop arrayLength+1 number of times, going through indexes 1..arrayLength+1. You want to go through the loop only arrayLength number of times with indexes 1..arrayLength. The solution is to change the condition to arraySearch < arrayLength.
Another (more Lua-ly way) is to write this as:
for arraySearch = 1, #objectArray do
Even more Lua-ly way is to use ipairs and table.field reference instead of (table["field"]):
function refreshObjects()
for _, el in ipairs(objectArray) do
love.graphics.draw(el.renderimage, el.X, el.Y, movingLeft and 120 or 0)
end
end
objectArray and movingLeft should probably be passed as parameters...
I want to insert an array using a graphical interface, but I don't understand why I get these errors:
Error using waitfor
Undefined function or variable 'A'.
Error using waitfor
Error while evaluating uicontrol Callback
THE CODE:
function read()
clear all
clc
n=2;
b=50;
a=300;
B = nan(n);
S.fh = figure('units','pixels',...
'position',[500 500 500 500],...
'menubar','none',...
'numbertitle','off',...
'name','Matrix',...
'resize','off');
for i=1:n
for j=1:n
A(i,j) = uicontrol('style','edit','units','pixels',...
'position',[b a 50 50],'fontsize',20,'string','',...
'Callback', 'B(A == gco) = str2double(get(gco, ''string''));');
b = b+60;
end
b = 50;
a = a-60;
end
S.bb = uicontrol('style','push',...
'units','pixels',...
'position',[300 10 75 50],...
'fontsize',14,...
'string','Done',...
'callback','close');
waitfor(S.fh)
B
Instead of using callbacks for all the edit boxes separately, I recommend a single callback that reads all the values on the button. For instance:
function read()
clear all
clc
n=2;
b=50;
a=300;
% A = zeros(n);
S.fh = figure('units','pixels',...
'position',[500 500 500 500],...
'menubar','none',...
'numbertitle','off',...
'name','Matrix',...
'resize','off');
for i=1:n
for j=1:n
A(i,j) = uicontrol('style','edit','units','pixels',...
'position',[b a 50 50],'fontsize',20,'string','');
% no callback for the edit boxes
b = b+60;
end
b = 50;
a = a-60;
end
S.bb = uicontrol('style','push',...
'units','pixels',...
'position',[300 10 75 50],...
'fontsize',14,...
'string','Done',...
'callback',#(~,~)(readvalues(A,n)));
% callback that reads all the values in one run
% (and closes the figure as you wanted)
waitfor(S.fh)
function readvalues(A,n)
B = zeros(n);
for i=1:n
for j=1:n
B(i,j) = str2double(get(A(i,j), 'String'));
end
end
disp(B)
close
I will try to as concise as possible with my issue.
Firstly, files are:
block.lua
base.lua
main.lua
In block.lua I create a block, add collision detection and a cleanup code.
In base.lua I create a base made up of 4 columns and 10 rows. 40 blocks in total.
In main.lua I create 4 bases made from the base.class.
All is working fine once the game begins.
I remove the bases and call them again on level 2.
They create themselves ok BUT
when the enemy is destroyed once again, and the bases are to be rebuilt, I get an:
array index 1 is beyond array bounds:1..1
-- all the way up to--
array index 800 is beyond array bounds:1..159
it will then create the bases and continue until the enemys are destroyed and do the same again starting at :
array index 800 is beyond array bounds:1..159
-- all the way up to--
array index 4000 is beyond array bounds:1..159
The terminal points me at block.lua line 23
blockGroup:insert(blockNum,self.block)
Now I cant see anything wrong in the class, I have looked and googled for hours but all to no avail.
I would really appreciate a helping hand to guide me here please.
I have tried rewriting the "cleanup" etc but no joy.
I left a few commented out bits in there and removed some of the irrelevant stuff.
I post below the relevant code:
--MAIN.LUA--
function gameOver()
Runtime:removeEventListener("enterFrame", onEnterFrame)
Runtime:removeEventListener("enterFrame", movePlayer)
layers:removeSelf()
layers = nil
enemyCount = 0
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
allEnemys=nil
cleanupBlocks()
end
----------------------------------------------------------------------
-- LEVEL UP --
----------------------------------------------------------------------
function levelUp(level)
enemyCount = 0
local enemys = require("modules.enemy")
if allEnemys ~= nil then
for i = 1,#allEnemys do
timer.cancel(allEnemys[i].clock)
Runtime:removeEventListener( "enterFrame", allEnemys[i] )
display.remove(allEnemys[i].image)
allEnemys[i].image=nil
end
end
allEnemys=nil
cleanupBlocks()
levels()
end
----------------------------------------------------------------------
-- LEVELS --
----------------------------------------------------------------------
function levels(level)
function createInvader(x, y, row)
for j = 1, 2 do
for i = 1, 2 do
if allEnemys == nil then
allEnemys = {}
else
enemysCount=#allEnemys
end
allEnemys[#allEnemys + 1] = enemys:new()
allEnemys[#allEnemys ]:init(i * 60, j * 70 + 70,j)
allEnemys[#allEnemys ]:start()
end
end
end
createInvader()
--[[function createBases1()
local base = require("modules.base")
for i = 1, 4 do
base:new()
base:init(i * 180 - 130, 850)
end
end ]]--
createBases()
end
--BLOCK.LUA--
local block = {}
local block_mt = { __index = block}
local scene = scene
local blockGroup = display.newGroup()
local blockNum = 0
function block:new() -- constructor
local group = {}
return setmetatable( group, block_mt )
end
function block:init(xloc,yloc) --initializer
-- Create attributes
self.block = display.newRect( xloc,yloc,10,10)
self.block:setFillColor ( 2, 255, 14 )
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
local blockCollisionFilter = { categoryBits = 128, maskBits = 387}
physics.addBody( self.block, "static", {filter = blockCollisionFilter})
self.count = 1
end
function cleanupBlocks()
--[[ print(blockNum, blockGroup.numChildren)
for i=1,blockGroup.numChildren do
blockGroup[1]:removeSelf()
blockGroup[1] = nil
end ]]--
print(blockNum, blockGroup.numChildren)
while blockGroup.numChildren>0 do
display.remove(blockGroup[1])
blockGroup[1]=nil
end
end
function block:start()
--- Create Listeneres
self.block:addEventListener( "collision", self )
scene:addEventListener('base_block_event', self)
end
return block
--BASE.LUA--
local base = {}
local base_mt = { __index = base}
local scene = scene
local block = require("modules.block")
function base:new() -- constructor
local group = {}
return setmetatable( group, base_mt )
end
function base:init(xloc, yloc) --initializer
-- Create attributes
local base
for j = 1, 4 do
for i = 1, 10 do
base = block:new()
base:init(xloc+i * 10,yloc+j * 10)
base:start()
end
end
end
return base
I see you use
blockNum = blockNum + 1
blockGroup:insert(blockNum,self.block)
Try to use
blockGroup:insert(self.block)
just to see if you still get that error.
This is a strange question but it baffles me. I want to be able to store x and y co-ords on an id based system such as: id.1.x = 10, id.1.y = 15: id.2.x = 50, id.2.y = 42 and I am trying to make a function to do it for me, I am having issues. here's my code
a = { p = {x,y}}
function box(xpos,ypos,id)
a[id].x = xpos
a[id].y = ypos
end
box(25,30,1)
box(45,10,2)
print(a[1].x.." "..a[1].y)
print(a[2].x.." "..a[2].y)
which I wanted to print:
25 30
45 10
but instead I get the error:
attempt to index global '?' (a nil value)
I am really exhausted and would like to put this to rest so if somebody could help it would be greatly appreciated.
function box(xpos,ypos,id)
a[id] = {x = xpos, y = ypos}
end