Корона LUA и ООП Дизайн - PullRequest
7 голосов
/ 14 июня 2011

Итак, я пришел из традиционной разработки игр, которая использует принципы ООП, и из того, что я видел, вы можете имитировать это, используя LUA, как только узнаете, что делаете.В некоторых публикациях кода я узнал, как вы можете использовать класс Director и создавать файлы с функцией new () и т. Д.

Я ищу способ управления своим оружием.У меня есть игрок и противник, и я бы предпочел иметь один класс оружия, скажем WeaponCanon.То, что я сделал, это:

-- 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 ]

7 голосов
/ 15 июня 2011

Если позже вам понадобится наследование (т. Е. LaserCannon - это подкласс оружия), вам, вероятно, потребуется более подробно использовать метатаблицы.

Существует множество библиотек, которые позволят вам выполнить "сверху"Луа ".Вы можете видеть очень хороший список здесь:

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

Я автор middleclass .С моей библиотекой вам нужно будет сделать что-то вроде этого:

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 будет легко реализовать - вы просто передадите в класс второй параметр:

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

Это со средним классом, который я предпочитаю, так как я сделал это.Другие библиотеки на странице, о которой я упоминал ранее, предлагают аналогичные функции.

5 голосов
/ 14 июня 2011

Полагаю, вы пытаетесь смоделировать класс с вашим исходным файлом. Это означает, что у вас также должна быть функция для создания нового экземпляра этого класса, если вы не хотите, чтобы они разделяли все свои состояния.

Что-то вроде (не проверено):

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()
1 голос
/ 15 июня 2011

Хотя вы создаете новую таблицу для объекта оружия, вы не создаете новые переменные. Любые переменные, объявленные в верхней части вашего модуля, такие как статические переменные (т. Е. Переменные, общие для всех экземпляров класса). Чтобы создать переменные, уникальные для этого объекта, вам нужно создать их в таблице, например:

weaponCannon = {}
weaponCannon.power = 10

И в любом случае вы создаете объект только один раз, вам нужна функция конструктора, которая создает таблицы:

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


Кстати, две другие вещи, которые не имеют прямого отношения к вашему ответу, но могут быть очень полезными изменениями в вашем коде. Во-первых, использование двоеточия вместо точки для вызова функций в методе позволит вам использовать ключевое слово «self» внутри метода, что-то вроде:

* * 1010

1012 * тогда *

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

Во-вторых, вы можете использовать экранные объекты в качестве таблиц, вместо того, чтобы создавать пустую таблицу и вставлять экранный объект в эту пустую таблицу:

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

Обратите внимание, что вы не можете установить мета-таблицу, если вы сделаете это, однако. Я считаю, что этот подход выглядит более логичным и предпочитаю не использовать мета-таблицы самостоятельно, но это ваш вызов.

0 голосов
/ 17 мая 2013

Мне нравится ответ Понзао.Однако изменил бы его на:

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()

Что я изменил:

  • Создал локальную переменную экземплярачтобы разрешить настройку перед ее возвратом
  • Более компактный способ установки метатаблицы
  • Использование переменной для класса при вызове кода
0 голосов
/ 14 июня 2011

Здесь нет объектов - у вас просто есть куча глобальных данных. Вам действительно нужно создавать экземпляры.

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)
...