TIC-80中尝试索引nil值错误排查求助
问题排查:TIC-80碰撞检测触发nil值错误
错误信息
[string "function _init()..."]:178: attempt to index a nil value (local 'sprite1')
相关碰撞检测代码
for I=1,#enemy_weak do if collision(enemy_weak[I],player)==true then playerattack(I) end end
完整代码
function _init() --essential_variables mp=5 ap=3 turn=1 kills=0 dir=nil --nonessential_variables end_turn_text=false mspr=272 --tables player={ x=120, y=48, hp=3, sprite=256, } enemy_weak={ x=-5, y=-5, hp=1, sprite=288, } end --initialize game _init() function TIC() --update --turn_control if mp==0 then end_turn_text=true end if btnp(4) then end_turn_text=false turn=turn+1 mp=3 end --misc mx,my,md=mouse() if md==true then mspr=273 else mspr=272 end player_mouse={ x=mx-7, y=my-4, down=md, sprite=mspr } if btnp(2) then dir="left" end if btnp(3) then dir="right" end if btnp(0) then dir="up" end if btnp(1) then dir="down" end --draw/print cls(0) poke(0x3FFB,1) --map map(0,0,30,17,0,0,0) --enemy spawnenemy(120,80) --player playermove() spr(player.sprite,player.x,player.y,0) playerloop() --mouse spr(mspr,grid(mx-2),grid(my-2),0) for I=1,#enemy_weak do if collision(enemy_weak[I],player_mouse)==true then mspr=274 else mspr=272 end end --player_attack for I=1,#enemy_weak do if collision(enemy_weak[I],player)==true then --playerattack(I) end end --text print("KILLS: "..kills,10,20,12) print("TURN: "..turn,100,10,12) print("MP: "..mp,10,30,12) print("AP: "..ap,10,40,12) print(detect_wall_collision(),5,5) print(dir,50,10) print(player.x,150,10) print(player.y,150,20) if end_turn_text==true then print("Press z to end turn",63,120,12) end end --player functions function playermove() if mp>0 then if btnp(2)and not detect_wall_collision() then player.x=player.x-8 mp=mp-1 end if btnp(3)and detect_wall_collision()==false then player.x=player.x+8 mp=mp-1 end if btnp(0)and detect_wall_collision()==false then player.y=player.y-8 mp=mp-1 end if btnp(1)and detect_wall_collision()==false then player.y=player.y+8 mp=mp-1 end end end function playerloop() if player.y>144 then player.y=-8 elseif player.y<-8 then player.y=144 elseif player.x>248 then player.x=-8 elseif player.x<-8 then player.x=248 end end function playerattack(enemyid) kills=kills+1 table.remove(enemy_weak,enemyid) end function inventory() end function detect_wall_collision() if dir=="left" then if mget(player.x-7,player.y)==112 then return true else return false end end if dir=="right" then if mget(player.x+9,player.y)==112 then return true else return false end end if dir=="up" then if mget(player.x,player.y-9)==112 then return true else return false end end if dir=="down" then if mget(player.x,player.y+9)==112 then return true else return false end end end --enemy function spawnenemy(x,y) local enemy={} enemy.hp=1 enemy.sprite=288 enemy.x=grid(x) enemy.y=grid(y) spr(enemy.sprite,enemy.x,enemy.y,0) table.insert(enemy_weak,enemy) end --other function grid(x) return math.floor((x)/8)*8 end function collision(sprite1, sprite2) -- Calculate the bounding boxes for each sprite local sprite1Left = sprite1.x local sprite1Right = sprite1.x+4 local sprite1Top = sprite1.y local sprite1Bottom = sprite1.y+4 local sprite2Left = sprite2.x local sprite2Right = sprite2.x+5 local sprite2Top = sprite2.y local sprite2Bottom = sprite2.y+4 -- Check for overlap if sprite1Right >= sprite2Left and sprite1Left <= sprite2Right and sprite1Bottom >= sprite2Top and sprite1Top <= sprite2Bottom then return true else return false end end
问题原因与修复方案
1. 核心问题:enemy_weak初始化错误
在_init()中,你将enemy_weak定义为一个单个敌人对象(包含x、y等键值对),但后续又用table.insert()往里面添加数组元素,导致表结构混乱:既有非数组的键值对,又有数组索引。当用#enemy_weak获取数组长度时,会得到错误的数值,遍历到无效索引时,enemy_weak[I]会返回nil,传给collision函数后就触发了"index a nil value"错误。
修复:
将_init()中的enemy_weak改为空数组:
enemy_weak={} -- 空数组,专门用于存放敌人对象
2. 次要问题:敌人无限生成
在TIC()函数的每帧循环里都调用spawnenemy(120,80),会不断往enemy_weak中添加敌人,不仅占用性能,还会加剧表结构的混乱。
修复:
调整敌人生成时机,比如只在回合结束时生成:
if btnp(4) then end_turn_text=false turn=turn+1 mp=3 spawnenemy(120,80) -- 移到此处,每次结束回合生成一个敌人 end
3. 可选优化:碰撞检测循环(针对后续恢复删除逻辑)
如果后续恢复playerattack(I)的调用,建议倒序遍历敌人数组,避免删除元素后索引错乱导致漏检:
for I=#enemy_weak,1,-1 do if collision(enemy_weak[I],player)==true then playerattack(I) end end
内容的提问来源于stack exchange,提问作者Sam Cao
相关产品推荐
相关产品推荐

