bad argument #1 to 'pairs' (table expected, got nil)

So I'm trying to program a space invaders like game in lua using löve2d, the first wave of enemies runs smoothly but once i try adding another wave to the levelctrl table i get this error: bad argument #1 to 'pairs' (table expected, got nil) on line 235 (even when i populate a second table)

function love.load()
hero = {}
hero.x = 400 - 16
hero.y = 450
hero.speedx = 300
hero.speedy = 50
hero.shots = {}
bgx = 0 
bgs = .25
fleet1 = {}
f1x = 0
f1f = 0
lost = 0
score = 0
game = 0 
menu = 1
startup = 1
--Images
bg = love.graphics.newImage("img/space.png")
bullet = love.graphics.newImage("img/shot.png")
player = love.graphics.newImage("img/player.png")
trail = love.graphics.newImage("img/trail.png")
ship1 = love.graphics.newImage("img/enemy1.png")
looser = love.graphics.newImage("img/looser.png")
boomp1 = love.graphics.newImage("img/boomp1.png")
boomp2 = love.graphics.newImage("img/boomp2.png")
boomp3 = love.graphics.newImage("img/boomp3.png")
boomp4 = love.graphics.newImage("img/boomp4.png")
boom1 = love.graphics.newImage("img/boom1.png")
boom2 = love.graphics.newImage("img/boom2.png")
boom3 = love.graphics.newImage("img/boom3.png")
boom4 = love.graphics.newImage("img/boom4.png")
winner = love.graphics.newImage("img/winner.png")
title = love.graphics.newImage("img/title.png")
message = love.graphics.newImage("img/message.png")
restart = love.graphics.newImage("img/restart.png")
icon = love.graphics.newImage("img/icon.gif")
boomtimer=0
isdead=0
boom={}
bgs = .25
bgx = 0
menublink = 0
menuf = 0
end

function love.update(dt)
    if bgx < 600 then
        bgx = bgx + bgs
    else 
        bgx = -599
    end
    if bgs > .30 then
        bgs = bgs - 2*dt
    end
    if menublink < 48 and menuf==0 then
        menublink = menublink + 1
    else
        menuf=1
        menublink = menublink -1
        if menublink == 0 then
            menuf=0
        end
    end
    if menu == 1 then
        hero = {}
        hero.x = 400 - 16
        hero.y = 450
        hero.speedx = 300
        hero.speedy = 50
        hero.shots = {}
        f1x = 0
        f1f = 0
        lost = 0
        score = 0
        boomtimer=0
        isdead=0
        won=0
        boom={}
        fleet1 = {}
        for i=0,7 do
            enemy = {}
            enemy.width = 32
            enemy.height = 16
            enemy.img = ship1
            enemy.x = i * (enemy.width + 64) + 48
            if i<4 then
                if i % 2 == 0 then
                    enemy.y = 0 - enemy.height
                else
                    enemy.y = -16 - enemy.height
                end
            else
                if i % 2 == 0 then
                    enemy.y = -16 - enemy.height
                else
                    enemy.y = 0 - enemy.height
                end
            end
            table.insert(fleet1, enemy)
        end
        boss = {}
        level = 1
        levelctrl = {}
        table.insert(levelctrl, fleet1)
        if love.keyboard.isDown(" ") then
            menu = 0
            game = 1
        end
    elseif game == 1 then
        if isdead==0 then
            if love.keyboard.isDown("left") then
                if hero.x > 0 then
                    hero.x = hero.x - hero.speedx*dt
                end
            elseif love.keyboard.isDown("right") then
                if hero.x < 800-32 then
                    hero.x = hero.x + hero.speedx*dt
                end
            end
            if love.keyboard.isDown("up") then
                if hero.y > 300 then
                    hero.y = hero.y - hero.speedy*dt
                    up=1
                else
                    up=0
                end
                if bgs < 4 then
                    bgs = bgs + 5*dt
                end
            elseif love.keyboard.isDown("down") then
                if hero.y < 600-64 then
                    hero.y = hero.y + hero.speedy*2*dt
                end
            else
                    up=0
            end
        end
        for i,v in ipairs(hero.shots) do
                v.y = v.y - dt * 300
        end
        if won == 0 then
            local remShot = {}
            local remEnemy = {}
            for i,v in ipairs(hero.shots) do
                if v.y < 0 then
                    table.insert(remShot, i)
                end
                for ii,vv in ipairs(levelctrl[1]) do
                    if CheckCollision(v.x,v.y,32,32,vv.x,vv.y,vv.width,vv.height) then
                        x = {}
                        x.x = vv.x
                        x.y = vv.y
                        x.t = 0
                        table.insert(boom, x)
                        table.insert(remEnemy, ii)
                        table.insert(remShot, i)
                    end
                end
            end
            for i,v in ipairs(levelctrl[1]) do
                if CheckCollision(hero.x,hero.y,32,64,v.x,v.y,v.width,v.height) then
                    lost = 1
                end
            end
            for i,v in ipairs(remShot) do
                table.remove(hero.shots, v)
            end
            for i,v in ipairs(remEnemy) do
                table.remove(levelctrl[1], v)
                score = score + 1
            end
            if level == 1 then
                for i,v in ipairs(levelctrl[1]) do
                    v.y = v.y + dt * 12
                    if v.y > 512 then
                        lost = 1
                    end
                    if v.x>0 and v.x < 768 then
                        if f1f == 0 then
                            if f1x<3 then
                                f1x = f1x + 1 * dt
                                v.x = v.x + 1
                            else
                                f1f = 1
                            end
                        else
                            if f1x>-3 then
                                f1x = f1x - 1 * dt
                                v.x = v.x - 1
                            else
                                f1f = 0
                            end
                        end
                    end
                end 
            end
        end
        if empty(levelctrl[1]) == true and won == 0 then
            level = level + 1
            table.remove(levelctrl, 1)
            if remEnemy ~= nil then
                for k in pairs (remEnemy) do
                    remEnemy[k] = nil
                end
            end
        end
        if won == 1 and love.keyboard.isDown("return") then
            menu = 1 
            game = 0
        elseif lost == 1 and love.keyboard.isDown("return") then
            menu = 1 
            game = 0
        end
    end
end

function love.draw()
    love.graphics.setIcon(icon)
    love.graphics.setColor(255,255,255,255)
    love.graphics.draw(bg, 0, bgx)
    love.graphics.draw(bg, 0, bgx-1199)
    if menu == 1 then
        love.graphics.draw(title)
        if menuf == 1 then
            love.graphics.draw(message)
        end
    elseif game == 1 then
        for i,v in ipairs(hero.shots) do
            love.graphics.draw(bullet, v.x, v.y)
        end
        if up==1 then
            love.graphics.draw(trail, hero.x, hero.y)
        end
        for i,v in ipairs(levelctrl[1]) do
            love.graphics.draw(v.img, v.x, v.y)
        end
        if lost == 0 then
            love.graphics.draw(player, hero.x, hero.y)
        else
            isdead=1
            if boomtimer<8 then
                love.graphics.draw(boomp1, hero.x-16, hero.y)
                boomtimer = boomtimer + 1
            elseif boomtimer<16 then
                love.graphics.draw(boomp2, hero.x-16, hero.y)
                boomtimer = boomtimer + 1
            elseif boomtimer<24 then
                love.graphics.draw(boomp3, hero.x-16, hero.y)
                boomtimer = boomtimer + 1
            elseif boomtimer<32 then
                love.graphics.draw(boomp4, hero.x-16, hero.y)
                boomtimer = boomtimer + 1
            else
                love.graphics.draw(looser)
                if menuf == 1 then
                    love.graphics.draw(restart, 0, 20)
                end
            end
        end
        for i,v in ipairs(boom) do
            if v.t<8 then
                love.graphics.draw(boom1, v.x, v.y-8)
                v.t = v.t + 1
            elseif v.t<16 then
                love.graphics.draw(boom2, v.x, v.y-8)
                v.t = v.t + 1
            elseif v.t<24 then
                love.graphics.draw(boom3, v.x, v.y-8)
                v.t = v.t + 1
            elseif v.t<32 then
                love.graphics.draw(boom4, v.x, v.y-8)
                v.t = v.t + 1
            else
                table.remove(boom, i)
            end
        end
        if won == 0 then
            if empty(levelctrl) then
                won = 1
            end
        end
        if won == 1 then
            love.graphics.draw(winner)
            if menuf == 1 then
                love.graphics.draw(restart, 0, 20)
            end
        end
    end
end

function shoot()
    local shot = {}
    shot.x = hero.x
    shot.y = hero.y - 4
    table.insert(hero.shots, shot)
end

function CheckCollision(ax1,ay1,aw,ah, bx1,by1,bw,bh)
  local ax2 = ax1 + aw
  local ay2 = ay1 + ah
  local bx2 = bx1 + bw
  local by2 = by1 + bh
  return ax1 <  bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1
end

function love.keyreleased(key)
    if isdead==0 then
        if (key == " ") then
            shoot()
        end
    end
end

function empty(self)
    for _, _ in pairs(self) do
        return false
    end
    return true
end

that's all the code and more specifically i get a problem with this:

for i,v in ipairs(levelctrl[1]) do
     love.graphics.draw(v.img, v.x, v.y)
end

levelctrl initially has 2 tables inside so after i remove the first one to bump the second one down, I recieve the bad argument error


The problem seems to be around line 200:

    if empty(levelctrl[1]) == true and won == 0 then
        level = level + 1
        table.remove(levelctrl, 1)

Here you remove the table from levelctrl when it's empty and increase the level. Since the table is empty already, can't you just re-use it instead of removing it (causing crashes on next rendering)? Removing the table.remove call should help.


I see

    levelctrl = {}
    table.insert(levelctrl, fleet1)

So levelctrl = {fleet1}

and some time later when you win,

    if empty(levelctrl[1]) == true and won == 0 then
        level = level + 1
        table.remove(levelctrl, 1)

So levelctrl = {}

won is still 0, and game is still 1.

Then in your draw function

    for i,v in ipairs(levelctrl[1]) do
        love.graphics.draw(v.img, v.x, v.y)
    end

At this point levelctrl = {} and levelctrl[1] = nil.

One solution would be to surround that bit of your draw function with

if not empty(levelctrl)

Also if you were trying to add fleet1 to levelctrl multiple times,

    levelctrl = {}
    table.insert(levelctrl, fleet1)
    table.insert(levelctrl, fleet1)
    table.insert(levelctrl, fleet1)

Then levelctrl would have three instances of the same table, and removing something from levelctrl[1] would remove it from fleet1 => all of the levels become empty at the same time.

链接地址: http://www.djcxy.com/p/92442.html

上一篇: 调用返回表的lua函数

下一篇: 不好的论点#1到'双'(表预期,无零)