Corona LUA和OOP设计

时间:2011-06-14 14:44:01

标签: iphone sdk lua corona

所以我来自传统的游戏开发,它使用OOP原则,而且从我看到过,一旦你知道你在做什么就可以使用LUA来模仿这个。在一些代码发布中,我发现了如何使用director类并创建具有new()函数等的文件。

我正在寻找的是一种管理武器的方法。我有一个球员和一个对手,我宁愿拥有一个武器类,比如武器佳能。我所做的是:

-- private vars here
local power
local canonSprite
local whatever

local someFunction = function()
...
end

-- Private stuff here
local weaponCanon = {}

weaponCanon.fire = function(atX, atY)
...
end

weaponCanon.reset = function()
...
end

return weaponCanon

然后在我的关卡代码中,我只是这样做:

local weaponCanon = require("weaponCanon")
weaponCanon.fire(100, 100)

这很有效,并且允许我在编写武器时使用“私人”和“公共”心态。问题是,如果我希望玩家和对手拥有一个正典:

local playerWeapon = require("weaponCanon")
local opponentWeapon = require("weaponCanon")

这只是将同一个对象而不是新实例返回给该对象。所以我只能在对手武器位置获得一枚武器。这显然是我想要/需要的。

我们的游戏中有很多武器,如果只有一个版本的每个文件都有一个设置告诉我们它是对手武器还是玩家武器会很不错。另一种方法是复制每个文件并创建一个weaponPlayerCanon和一个weaponOpponentCanon,但我想到修改一个文件并且每次都要更改2个以上的文件时会感到畏缩。

如何让它返回一个实例以及LUA文件的结构是什么?

谢谢或任何帮助

-d

5 个答案:

答案 0 :(得分:7)

如果您稍后开始需要继承(即LaserCannon是武器的子类),您可能需要更深入地使用元数据。

有很多库可以让你在Lua之上做“oop”。你可以在这里看到一个非常好的清单:

http://lua-users.org/wiki/ObjectOrientedProgramming

我是middleclass的作者。使用我的lib,你必须做这样的事情:

local Weapon = class('Weapon')

function Weapon:initialize(a,b,c)
  self.x,self.y,self.z = a,b,c
end

function Weapon:fire(x,y)
 ...
end

LaserCannon很容易实现 - 您只需将第二个参数传递给class:

local LaserCannon = class('LaserCannon', Weapon)

function LaserCannon:initialize(a,b,c,d)
  self.w = d
  Weapon.initialize(self, a,b,c) -- superclass' constructor
end

function LaserCannon:foo()
 ...
end

您可以像这样使用它:

require 'middleclass' -- so you can use "class"
LaserCannon = require 'laser_cannon'

local playerWeapon = LaserCannon:new() -- a laser
local opponentWeapon = Weapon:new() -- a regular generic weapon

opponentWeapon:fire(100,200) -- typical use
playerWeapon:fire(100, 200) -- LaserCannon inherits fire from Weapon
playerWeapon:foo() -- LaserCannon-exclusive

这是middleclass,这是我喜欢的,因为我做到了。我之前提到的页面上的其他库提供了类似的功能。

答案 1 :(得分:5)

我猜你是想用你的源文件建模一个类。这意味着您还应该有一个函数来创建该类的新实例,除非您希望它们共享所有状态。

(未经测试)的某些内容:

local WeaponCannon = {}
WeaponCannon.__index = WeaponCannon
function WeaponCannon:new()
  return setmetatable({}, self)
end

function WeaponCannon:fire(x, y)
  -- Do something via the self reference and arguments (x, y)
end

return WeaponCannon

在您的通话代码中(也未经测试):

require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()

答案 2 :(得分:1)

虽然您为武器对象创建了一个新表,但您不会创建新变量。在模块顶部声明的任何变量都是静态变量(即由类的所有实例共享的变量。)要创建该对象唯一的变量,您需要在表中创建它们,如:< / p>

weaponCannon = {}
weaponCannon.power = 10

无论如何你只创建一个对象,你需要一个创建表的“构造函数”函数:

function new()
  local weaponCannon = {}
  weaponCannon.power = 10
end


顺便提一下,另外两个与您的答案没有直接关系但可以对您的代码进行非常有用的修改。首先,使用冒号而不是句点来调用方法中的函数将允许您在方法中使用“self”关键字,如:

function weaponCannon:fire()
  --this is only a test
  print(self.power)
end

然后

local playerWeapon = require("weaponCanon")
playerWeapon:fire()

其次,您实际上可以将显示对象用作表,而不必创建一个空表,然后将显示对象粘贴到该空表中:

weaponCannon = display.newImage("cannon.png")
weaponCannon.power = 10

请注意,如果您这样做,则无法设置元表。我发现这种方法看起来更符合逻辑,并且不想自己使用元表,但这是你的呼唤。

答案 3 :(得分:0)

这里没有任何对象 - 你只有一堆全局数据。你真的需要做实例。

function NewWeapon(arg)
    return {
        fire = function(self, atX, atY) 
            print(self.var)
        end,
        var = arg,
    }
end

NewWeapon(3):fire(1, 2)
NewWeapon(7):fire(3, 5)

答案 4 :(得分:0)

我喜欢ponzao的回答。然而,它会改为:

local WeaponCannon = {}

function WeaponCannon:new()
  local instance = {}
  setmetatable(instance, {__index = WeaponCannon})
  -- setup your new instance here
  return instance
end

function WeaponCannon:fire(x, y)
  -- Do something via the self reference and arguments (x, y)
end

return WeaponCannon

在你的主叫代码中:

local WeaponCanon = require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()

我改变了什么:

  • 创建一个本地实例变量,以便在返回之前进行设置
  • 设置metatable的更紧凑方式
  • 调用代码时为类使用变量