Reputation: 1
Error: Attempt to index global 'W' (a nil value)
Hello! I am having trouble getting collision working with a different system that spawns sprites in from the map screen.
This is the collision tutorial I used: https://youtu.be/Recf5_RJbZI?si=Df6FbJ2FYfCN39Qx This is the sprite spawning tutorial I used: https://youtu.be/8jb8SHNS66c?si=233nn8z_S1R4R64n
I have watched TONS of tutorials on this and still can't wrap my head around it. A lot of tutorials create very basic collision that has issues, like only being able to work with certain speed values (1,2,4,8,16,etc.) or that don't let your character slide alongside a wall when holding a diagonal.
Can anyone help? I definitely want to use this spawning system in the future to spawn in different types of walls and enemies. I have a feeling that I am misunderstanding how to use the table variables properly, so any explanation would be appreciated!
-- game loop --
function _init()
cls()
walls={}
make_player()
make_walls()
-- top-left and lower-right
-- bounds of player area
a1,b1=8,8
a2,b2=112,112
end
function _update60()
-- keep inside the play area
move_player()
p.x=mid(a1,p.x,a2)
p.y=mid(b1,p.y,b2)
end
function _draw()
cls()
draw_map()
draw_player()
for w in all(walls) do
spr(w.wsp,w.wx,w.wy)
end
end
-- map --
function draw_map()
map(0,0,0,0,16,16)
end
-- player --
function make_player()
p={
x=40,
y=40,
w=8,
h=8,
speed=2,
sprite=1,
}
end
function move_player()
--move player with buttons
--interacts with wall collision
if (btn(⬅️)) then
for newx=p.x,p.x-p.speed,-1
do
if not box_hit(newx,p.y,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
then
p.x=newx
end
end
end
if (btn(➡️)) then
for newx=p.x,p.x+p.speed
do
if not box_hit(newx,p.y,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
then
p.x=newx
end
end
end
if (btn(⬆️)) then
for newy=p.y,p.y-p.speed,-1
do
if not box_hit(p.x,newy,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
then
p.y=newy
end
end
end
if (btn(⬇️)) then
for newy=p.y,p.y+p.speed
do
if not box_hit(p.x,newy,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
then
p.y=newy
end
end
end
end
--draw player
function draw_player()
spr(p.sprite,p.x,p.y)
end
-- walls --
function make_walls()
for x=0,15 do
for y=0,15 do
if mget(x,y)==65 then
add(walls,{
wx=x*8,
wy=y*8,
ww=8,
wh=8,
wsp=66
})
mset(x,y,64)
end
end
end
end
--wall collision calculations
function box_hit(x1,y1,
w1,h1,
x2,y2,
w2,h2)
local hit=false
local xd=abs((x1+(w1/2))-(x2+w2/2))
local xs=w1/2+w2/2
local yd=abs((y1+(h1/2))-(y2+h2/2))
local ys=h1/2+h2/2
if xd < xs and yd < ys then
hit=true
end
return hit
end
Upvotes: 0
Views: 349
Reputation: 51
In case you have not yet found a solution, it appears there is an error in your move_player() function.
box_hit(p.x,newy,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
You use the variable w, which I assume refers to a wall, but you never loop through the table of all the walls to assign the value to w. I think you are missing a for loop, like so:
for w in all(walls) do
box_hit(p.x,newy,
p.w,p.h,
w.wx,w.wy,
w.ww,w.wh)
end
Upvotes: 0
Reputation: 23
in many older games, a system called subpixels was used. theyd calculate collision on a scale smaller than the actual pixels (for example to 0.1 pixels instead of 1 pixel) and when drawing theyd simply use the floor of the x and y values. this allows way more precision and smoothness. this tutorial series has alot of great advice, though its for another platform i still go back to it for help: https://www.youtube.com/playlist?list=PLy4zsTUHwGJIc90UaTKd-wpIH12FCSoLh this article also seems very useful, though i havent read through it all: http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/
Upvotes: 1