Lua - 迭代表格的问题

我正在尝试编写一个游戏。

这个游戏有玩家和我将生成朝向玩家行走的僵尸。

这些是我的文件:

main.lua

local Player = require("player")
local Zombie = require("zombie")

love.window.setTitle("Shooter")

function love.load()
    sprites = {}
    sprites.background = love.graphics.newImage('sprites/background.png')

    player1 = Player
    player1.setPos(300, 300)

    zombies = {}
end

function love.update(dt)
    player1.move(dt)
    player1.rotate()

    for i, z in ipairs(zombies) do
        z.rotate(player1)
        z.move(dt)
    end
end

function love.draw()
    love.graphics.draw(sprites.background, 0, 0)
    love.graphics.draw(player1.sprite, player1.position.x, player1.position.y, player1.angle, nil, nil, player1.sprite:getWidth()/2, player1.sprite:getHeight()/2)

    for i,z in ipairs(zombies) do
        love.graphics.draw(z.sprite, z.position.x, z.position.y, z.angle, nil, nil, z.sprite:getWidth()/2, z.sprite:getHeight()/2)
        love.graphics.printf("order" ..i, 0, 50, love.graphics.getWidth(), "center")
    end
end

function distance(player, enemy)
    return math.sqrt((player.position.x - enemy.position.x)^2 + (player.position.y - enemy.position.y)^2)
end

function love.keypressed(key, scancode, isrepeat)
    if key == "u" then
        spawnZombie(zombies)
    end
end

zombie.lua

local Zombie =  {
    position = {},
    speed = 1,
    angle = 0,
    sprite = love.graphics.newImage('sprites/zombie.png')
}

function Zombie.setPos(x, y)
    Zombie.position.x = x
    Zombie.position.y = y
end

function Zombie.move(dt)
    distance = Zombie.speed * dt * 60
    Zombie.position.x = Zombie.position.x + math.cos(Zombie.angle) * distance
    Zombie.position.y = Zombie.position.y + math.sin(Zombie.angle) * distance
end

function Zombie.rotate(player)
    Zombie.angle = math.atan2(player.position.y - Zombie.position.y, player.position.x - Zombie.position.x)
end

function spawnZombie(zombieTable)
    zombie = Zombie
    zombie.setPos(math.random(0, love.graphics.getWidth()), math.random(0, love.graphics.getHeight()))

    table.insert(zombieTable, zombie)
end

return Zombie

最后,用来完成的 player.lua 文件。

spawnZombie() 应该创建一个新的僵尸并将其插入到 zombies 表格中。love.draw() 应该迭代 zombies 表格并将它们全部绘制出来。

我遇到了两个问题,很可能是相关的:

  1. 只有一个僵尸生成。

  2. 每个生成的僵尸都比上一个快。

这可能意味着只有一个僵尸(表格中的第一个)被绘制出来,并且他的速度在 love.update() 函数中得到增加。如果这个假设是正确的,那么问题可能在 spawnZombie() 函数中。

我应该怎么修复我的程序?

点赞
用户2616735
用户2616735

Zombie 是您唯一的僵尸。您创建的“新”僵尸实际上只是它的别名:

zombie = Zombie 不创建副本,而是表示zombie只是同一对象的另一个名称。

您需要为每个新的僵尸创建一个新表格。您可能想要使用 _methods_,以便可以对每个实例使用相同的函数。

方法使用 : 定义,并自动获取一个名为 self 的不可见参数,该参数是调用该方法的对象。方法的调用方式为 :move(0.5) 而不是 .move(0.5)

function Zombie:move(dt)
    local distance = self.speed * dt * 60
    self.position.x = self.position.x + math.cos(self.angle) * distance
    self.position.y = self.position.y + math.sin(self.angle) * distance
end

要创建一个新的僵尸实例,您需要创建一个新的表格,并具有所需的初始属性

local newZombie = {
    position = {},
    speed = 1,
    angle = 0,
}

然后给它所有的Zombie应该有的方法。最简短的方法是使用 _metatables_。__index 元方法告诉 Lua 当请求一个未明确设置的字段/方法时应该执行什么操作。这使我们可以将Zombie“类”复制到新实例上:

setmetatable(newZombie, {__index = Zombie})

这可以包装成Zombie“类”的“构造函数”方法。由于这个构造器不作用于现有的僵尸对象,因此您应该使用“.”来定义和调用它,而不是“:”:

local Zombie = {}

-- 这个属性在所有僵尸之间共享,
-- 改变它将改变所有僵尸的属性
Zombie.sprite = love.graphics.newImage('sprites/zombie.png')

-- 返回一个新创建的Zombie实例
function Zombie:create()
    local newZombie = {
        position = {},
        speed = 1,
        angle = 0,
        sprite = love.graphics.newImage('sprites/zombie.png')
    }
    return setmetatable(newZombie, {__index = Zombie})
end

-- 修改在此调用的僵尸
function Zombie:move(dt)
    local distance = self.speed * dt * 60
    self.position.x = self.position.x + math.cos(self.angle) * distance
    self.position.y = self.position.y + math.sin(self.angle) * distance
end

function Zombie:setPos(x, y)
    self.position.x = x
    self.position.y = y
end

-- 通过将新创建的僵尸添加到其中修改僵尸
function spawnZombie(zombies)
    local newZombie = Zombie:create()
    newZombie:setPos(math.random(0, love.graphics.getWidth()), math.random(0, love.graphics.getHeight()))

    table.insert(zombieTable, newZombie)
end

-- 在update函数中:
for i, z in ipairs(zombies) do
    z:rotate(player1)
    z:move(dt)
end

您应该养成在函数中使用 local 变量的习惯,例如 Zombie:move 中的 distance。全局变量可能会导致错误,并且还会产生(小)性能损失,因为与所有人共享变量需要更多时间(还使JIT优化器的工作更加困难)。

2018-09-22 01:17:42