基本对象生成

在游戏设计中,一个常见的元素是对象生成,无论是生成数量可变的敌人并将它们随机放置在屏幕上,还是在计时器增量上重复生成物品。在本教程中,我们将逐步介绍一个基本的生成模块,其中包含以下功能:

初始设置

让我们从几个初始命令开始……

local spawnTimer
local spawnedObjects = {}

-- Seed the random number generator
math.randomseed( os.time() )

第一个变量 spawnTimer 只是对我们将用于控制生成过程的计时器对象的 Lua 前向引用。第二个变量 spawnedObjects 是一个基本表,我们将在其中插入生成的项目,为我们提供跟踪它们、计数它们、循环它们等的基本方法。

第三个命令设置伪随机数生成器的“种子”。在某些操作系统上,此生成器以相同的初始值开始,这会导致随机数以可预测的模式重复。添加到我们的代码中可以确保生成器始终以不同的种子开始。

生成参数

现在,让我们设置一个基本生成参数表,我们可以使用它来调整/控制生成

local spawnParams = {
    xMin = 20,
    xMax = 300,
    yMin = 20,
    yMax = 460,
    spawnTime = 200,
    spawnOnTimer = 12,
    spawnInitial = 4
}

所有这些参数都是可选的,并且将默认为各种值(稍后详细介绍),但通常应将它们设置为适合您游戏的值。本质上,前四个参数定义了屏幕上将生成项目的矩形区域,由 x y 的最小值和最大值定义。下一个参数 (spawnTime) 定义了生成新项目的时间增量(以毫秒为单位),假设项目数量由 spawnOnTimer 参数定义。最后,如果游戏设计需要,spawnInitial 参数可用于立即生成一定数量的项目。

基本生成函数

接下来,我们需要一个创建对象的基本生成函数

-- Spawn an item
local function spawnItem( bounds )

    -- Create an item
    local item = display.newCircle( 0, 0, 20 )

    -- Position item randomly within set bounds
    item.x = math.random( bounds.xMin, bounds.xMax )
    item.y = math.random( bounds.yMin, bounds.yMax )

    -- Add item to "spawnedObjects" table for tracking purposes
    spawnedObjects[#spawnedObjects+1] = item
end

前几行创建了一个示例项目——在本例中是一个基本的白色矢量圆圈。显然,这些项目可以是图像、动画精灵、您随后启用物理使用的对象等。

接下来的几行将项目随机放置在声明的边界内。回想一下,我们将这些声明为 spawnParams 表中的前四个参数。

最后一行只是将新项目添加到 spawnedObjects 表中,提供了一种跟踪和管理生成对象的简单方法。

生成控制器

下一步是创建一个简单但功能强大的“控制器”函数,它允许我们启动、停止、暂停和恢复生成过程。此函数将接受两个参数:表示要执行的操作的 action 参数和 params 参数(这表示我们上面声明的 spawnParams 表)。

local function spawnController( action, params )

    -- Cancel timer on "start" or "stop", if it exists
    if ( spawnTimer and ( action == "start" or action == "stop" ) ) then
        timer.cancel( spawnTimer )
    end

    -- Start spawning
    if ( action == "start" ) then

        -- Gather/set spawning bounds
        local spawnBounds = {}
        spawnBounds.xMin = params.xMin or 0
        spawnBounds.xMax = params.xMax or display.contentWidth
        spawnBounds.yMin = params.yMin or 0
        spawnBounds.yMax = params.yMax or display.contentHeight

        -- Gather/set other spawning params
        local spawnTime = params.spawnTime or 1000
        local spawnOnTimer = params.spawnOnTimer or 50
        local spawnInitial = params.spawnInitial or 0

        -- If "spawnInitial" is greater than 0, spawn that many item(s) instantly
        if ( spawnInitial > 0 ) then
            for n = 1,spawnInitial do
                spawnItem( spawnBounds )
            end
        end

        -- Start repeating timer to spawn items
        if ( spawnOnTimer > 0 ) then
            spawnTimer = timer.performWithDelay( spawnTime,
                function() spawnItem( spawnBounds ); end,
            spawnOnTimer )
        end

    -- Pause spawning
    elseif ( action == "pause" ) then
        timer.pause( spawnTimer )

    -- Resume spawning
    elseif ( action == "resume" ) then
        timer.resume( spawnTimer )
    end
end

让我们检查一下这个函数一步一步:

-- Cancel timer on "start" or "stop", if it exists
if ( spawnTimer and ( action == "start" or action == "stop" ) ) then
    timer.cancel( spawnTimer )
end

我们为什么要在停止操作上取消计时器,这很明显,但为什么我们也要在启动操作上取消它呢?基本上,这只是一个故障安全机制,因此如果使用启动操作多次调用该函数,则会取消之前的计时器对象,并且它可以以干净的状态开始。

在此条件块的初始行中,我们根据先前声明的 spawnParams 表中定义的参数收集/设置各种参数。如前所述,所有这些参数都是可选的,因此如果未定义任何参数,我们将在其位置设置一些基本默认值。

-- Start spawning
if ( action == "start" ) then

    -- Gather/set spawning bounds
    local spawnBounds = {}
    spawnBounds.xMin = params.xMin or 0
    spawnBounds.xMax = params.xMax or display.contentWidth
    spawnBounds.yMin = params.yMin or 0
    spawnBounds.yMax = params.yMax or display.contentHeight

    -- Gather/set other spawning params
    local spawnTime = params.spawnTime or 1000
    local spawnOnTimer = params.spawnOnTimer or 50
    local spawnInitial = params.spawnInitial or 0

接下来,我们检查 spawnInitial 参数是否大于 0,如果是,我们立即生成该数量的项目。请注意,我们将 spawnBounds 表传递给 spawnItem() 函数,以便它识别生成项目的限制。

-- Start spawning
if ( action == "start" ) then

    -- Gather/set spawning bounds
    local spawnBounds = {}
    spawnBounds.xMin = params.xMin or 0
    spawnBounds.xMax = params.xMax or display.contentWidth
    spawnBounds.yMin = params.yMin or 0
    spawnBounds.yMax = params.yMax or display.contentHeight

    -- Gather/set other spawning params
    local spawnTime = params.spawnTime or 1000
    local spawnOnTimer = params.spawnOnTimer or 50
    local spawnInitial = params.spawnInitial or 0

    -- If "spawnInitial" is greater than 0, spawn that many item(s) instantly
    if ( spawnInitial > 0 ) then
        for n = 1,spawnInitial do
            spawnItem( spawnBounds )
        end
    end

之后,我们检查 spawnOnTimer 参数是否大于 0,如果是,我们启动一个计时器,该计时器在设置的 spawnTime 增量上生成该数量的项目。请注意,我们将此计时器对象设置为 spawnTimer 引用,以便我们可以根据需要暂停、恢复或停止它。如上所述,我们将 spawnBounds 表传递给匿名函数,以便所有项目都在所需的边界内生成。

-- Start spawning
if ( action == "start" ) then

    -- Gather/set spawning bounds
    local spawnBounds = {}
    spawnBounds.xMin = params.xMin or 0
    spawnBounds.xMax = params.xMax or display.contentWidth
    spawnBounds.yMin = params.yMin or 0
    spawnBounds.yMax = params.yMax or display.contentHeight

    -- Gather/set other spawning params
    local spawnTime = params.spawnTime or 1000
    local spawnOnTimer = params.spawnOnTimer or 50
    local spawnInitial = params.spawnInitial or 0

    -- If "spawnInitial" is greater than 0, spawn that many item(s) instantly
    if ( spawnInitial > 0 ) then
        for n = 1,spawnInitial do
            spawnItem( spawnBounds )
        end
    end

    -- Start repeating timer to spawn items
    if ( spawnOnTimer > 0 ) then
        spawnTimer = timer.performWithDelay( spawnTime,
            function() spawnItem( spawnBounds ); end,
        spawnOnTimer )
    end
    -- Pause spawning
    elseif ( action == "pause" ) then
        timer.pause( spawnTimer )

    -- Resume spawning
    elseif ( action == "resume" ) then
        timer.resume( spawnTimer )
    end
end

调用生成控制器

从这一点开始,可以轻松地使用四种可能的动作调用生成控制器。请注意,使用 "start" 作为 action 参数调用 spawnController() 函数是唯一需要 spawnParams 表的用例——其他操作假定生成过程已经在进行中。

spawnController( "start", spawnParams )
spawnController( "pause" )
spawnController( "resume" )
spawnController( "stop" )

总结

希望本教程为您提供一个简单的基础模块,您可以在此基础上构建更全面的生成方法,包括动画精灵、物理对象、可变时间增量等等。