变量是 nii 吗?

最近我在使用 LOVE2D 和 Lua 制作游戏。我在更新 Breakout 时,Paddle.lua 中出现了一个错误。

代码:

Paddle = Class{}

--[[
    我们的 Paddle 会在每次初始化时在水平方向上位于世界中间,靠近屏幕底部。
]]

size = math.random(4)

function Paddle:init(skin, size)
    -- x 位于中心
    self.x = VIRTUAL_WIDTH / 2 - 32

    -- y 在屏幕底部的上方一点
    self.y = VIRTUAL_HEIGHT - 32

    -- 让我们没有速度启动
    self.dx = 0

    self.size = size

    self.height = 16
    if self.size == 1 then
        self.width = 32
    elseif self.size == 3 then
        self.width = 96
    elseif self.size == 4 then
        self.width = 128
    else
        self.width = 64
    end

    -- 皮肤只有改变颜色的效果,稍后我们用它来抵消
    -- 在 gPaddleSkins 表中
    self.skin = skin
end

function Paddle:update(dt)
    -- 键盘输入
    if love.keyboard.isDown('left') then
        self.dx = -PADDLE_SPEED
    elseif love.keyboard.isDown('right') then
        self.dx = PADDLE_SPEED
    else
        self.dx = 0
    end

    -- math.max 确保我们将 0 或玩家的当前计算 Y 位置作为较大值,以便我们不会
    -- 进入负数;移动计算仅是我们
    -- 先前定义,在 dt 的缩放下的挡板速度
    if self.dx < 0 then
        self.x = math.max(0, self.x + self.dx * dt)
    -- 类似于之前,这次我们使用 math.min 确保我们不会
    -- 走得比屏幕底部减去球拍高度更远(否则它将部分下降,因为位置
    -- 是基于其左上角)
    else
        self.x = math.min(VIRTUAL_WIDTH - self.width, self.x + self.dx * dt)
    end
end

--[[
    通过绘制主纹理,传入相应的皮肤和大小所对应的 quad
    渲染挡板。
]]
function Paddle:render()
    love.graphics.draw(gTextures['main'], gFrames['paddles'][self.size + 4 * (self.skin - 1)],
        self.x, self.y)
end

错误信息:

错误

src/Paddle.lua:83: attempt to perform arithmetic on field 'size' (a nil value)

Traceback

src/Paddle.lua:83: in function 'render'
src/states/ServeState.lua:68: in function 'render'
src/StateMachine.lua:26: in function 'render'
main.lua:210: in function 'draw'
[C]: in function 'xpcall'

它说值是 nii,即使我已经赋值给它。我要如何解决?

点赞
用户2858170
用户2858170

函数参数是局部变量。因此,在 Paddle.Init 中,size 是一个局部变量,会遮蔽全局变量 size

当你调用 Paddle.Init 时没有提供 size 参数,函数内部的 size 就是 nil,导致错误的发生。

详见 Wikipedia: Variable Shadowing

许多人使用前缀来表示全局变量。例如, g_size。这样你就可以做如下的事情:

g_size = 4

function Paddle:Init(skin, size)
  self.size = size or g_size
end

如果没有提供 size 参数,self.size 就会默认为 g_size

另一种选择是将球拍构造器调用时的全局尺寸作为输入。

2020-07-10 04:19:53