【问题标题】:Corona / Lua Function scopeCorona / Lua 函数作用域
【发布时间】:2012-02-15 13:44:41
【问题描述】:

我是科罗娜的新手。我不确定如何解决这个问题。

我主要创建 2 个本地对象,玩家和敌人。

播放器有一个名为 takeDamage 的函数。

当我尝试从敌人内部调用 player.takeDamage 时,它​​看不到函数。

我认为这是因为 main 拥有这两个对象并且它们彼此不知道。

我怎样才能让 Enemy 调用该函数以便它可以对 Player 造成伤害?

main.lua 包含:

-- Create player character
local player = require("player");
player = player.new();

-- Create enemy character
local enemy = require("enemy");
enemy = enemy.new();

我认为我可以让玩家全球化,但据我所知,这不是最佳做法。

任何帮助将不胜感激。

【问题讨论】:

  • 不应该是player:takeDamage 吗?分号表示它是一个实例方法。

标签: lua coronasdk


【解决方案1】:

如果可以安全地假设只有一个“玩家”实例,您可以将其设为全局。否则,您将不得不按照以下方式做一些事情:

-- main.lua
local player = require 'player'.new()
local enemy = require 'enemy'.new()
enemy:setPlayer(player)

-- enemy.lua
...
function enemy:setPlayer(player)
  self.player = player
end

然后在敌人代码中使用self.player 来引用玩家。请注意,这会消耗内存,因为玩家引用将被复制到每个敌人实例。

附带说明,我认为将模块和实例称为相同的名称并不好,即player。如果您指的是模块还是实例,稍后将变得不清楚。一种安全的方法是将模块称为PlayerEnemy,代码如下所示:

Player = require 'Player'
local player = Player.new()

【讨论】:

  • 谢谢米哈尔。这场比赛只有一名球员。其他一切要么是可以与之交互的静态对象,要么是敌人。我看到你在这里做什么,给敌人一个玩家的参考。你会说这比让玩家全球化更好吗?感谢您澄清命名约定。我同意为了清楚起见,这些名称至少应该有不同的上限。
  • 我个人会使用全局变量来设计player。一个原因是它无处不在,而且你不必像我写的那样设计复杂的方案。另一个原因是记忆——你只有一个对玩家的引用,而不是 N(敌人的数量)。最后一种方法是拥有一个gameState 全局变量,它将包含玩家和其他必要的游戏状态。
  • 我忘了提到敌人可能还需要相互交互,所以我不确定全局选项是否会很好。我们不希望所有实体都是全球性的,对吗?
  • 当然不是 :) 但是话又说回来,你可以在全局状态下保存所有敌人,例如gameState.enemies = {}。然后你可以用这种方式遍历每个敌人:function Enemy:checkCollision() for _,e in ipairs(gameState.enemies) do if e ~= self then --[[ your processing here ]] end end
【解决方案2】:

理想情况下,您不希望玩家直接引用敌人或敌人引用玩家。相反,您可以在游戏循环中轮询每个参与者并根据结果更新游戏状态。

local player = make_player()
local enemy = make_enemy()

--game loop - in a real game this isn't a busy while
while true do

    local move = player.move()
    local result = validate_move(move)
    if result.is_valid then 
        update_position(player, result) 
    end

    move = enemy.move()
    result = validate_move(move)
    if result.is_valid then 
        update_position(enemy, result) 
    end

    local attack = player.attack()
    local attack_result = validate_attack(attack)
    if attack_result.hit then 
        update_health(enemy, attack_result) 
    end

    -- more game logic here

    render(player)
    render(enemy)
end

在真正的游戏中,状态变化将由events - 触摸事件、drawing events 等驱动。我的繁忙循环 (while true do) 说明了总体思路。

你还必须发挥你的想象力才能错过实现。

有很多方法可以为游戏建模。我并不是说这是最好的。然而,它确实展示了一种解耦交互元素的方式。

【讨论】:

  • 感谢您回复科尔宾。您在此处展示的模型更多地适用于回合制游戏,还是适用于任何游戏?我不确定这是否是我正在寻找的东西,但我会考虑一下,看看我是否能弄清楚它是否适合我正在尝试做的事情。
  • @Kenny - 它适用于回合或实时游戏。将我的 while 循环替换为事件 - UI 动作(转动或实时)或帧事件(仅实时)。关键特征是控制器/代理/管理器,它协调可以交互的元素之间的操作,而不是将这些元素与直接引用联系起来。让他们保持独立可以更容易地推理他们的行为和责任。
猜你喜欢
  • 2012-03-07
  • 2013-06-01
  • 2015-04-03
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
相关资源
最近更新 更多