2017-08-21 3 views
1

Ich versuche, meine Füße mit LUA und Love2D nass zu machen, und ich habe ein Problem mit Objekt Instanziierung/Zugang in Lua.Liebe 2D (Lua) unerwartete Null im Objekt

Quelle mit dem Bug ist hier zu finden: https://bitbucket.org/dannsee/love_scrollingshooter In meinem Haupt, ich ein Objekt, Feinde

enemies = Enemies:new() 

und innerhalb der Feinde widersprechen,

Ich bin erstellen erstelle ich ein Objekt zu halten Peristante Werte, die ich Timers nenne.

timers = Timers:new() 

So die feindlichen Konstruktor "Methode aussieht (im Grunde) wie dieses

Enemies = {} -- so that Enemies will not be nil when new() is called 
timers = {} -- so that timers will be accessible in the class scope 

function Enemies:new(enemies) 
    enemies = enemies or {} 
    timers = Timers:new() 
    setmetatable(enemies, self) 
    self.__index = self 
    return enemies 
end 

während die Timer suchen als solche

Timers = {} -- so that Timers will not be nil when new() is called 

function Timers:new(timers) 
    timers = timers or { 
     miniBombTimerMax = 0.2, 
     miniBombTimer = minibombTimerMax 
    } 
    setmetatable(timers, self) 
    self.__index = self 
    return timers 
end 

erstellt werden, aber wenn ich versuche, ein bis refrence von den Timern (aus dem Objekt des Feindes) erhalte ich eine Ausnahme von null Wert.

timers.miniBombTimer -- Produces nil exception 

Es scheint mir, dass dies sowohl 1. in Umfang, da es sich um ein Objekt in dieser Klasse erstellt wird, und wird lokal als Timer = {} instanziiert, bevor er ein Wert zugewiesen wird, und 2. nicht, weil es im Konstruktor einen Wert erhält. Aber hier scheint mehr los zu sein, als dass ich es nicht verstehe.

Ich bin neu bei Lua, was an dieser Stelle offensichtlich sein kann, aber aus dem, was ich über den Variablenbereich gelesen habe, scheint es, dass dies gültig sein sollte. Ich verstehe nicht, warum die Timer nicht mit Werten erstellt werden.

+0

Lesen durch http://lua-users.org/wiki/ObjectOrientationTutorial? Sie haben den Teil des Codes nicht mit dem Problem gezeigt, aber vermutlich verwenden Sie nicht "selbst"? – smarx

+0

Ihre Konstruktoren verwenden auch nicht "self". Ich gehe davon aus, dass Sie möchten, dass "Timer" ein Mitglied der "Enemies" -Klasse sind, aber vielleicht nicht? Vielleicht können Sie ein minimales Beispiel dafür geben, wie Sie diese Klasse verwenden möchten. – smarx

Antwort

0

Vorsicht mit Ihren Globalen! In Lua ist es sehr einfach, versehentlich eine globale Variable zu setzen, wenn Sie es nicht wollen, und es sieht so aus, als würde genau das passieren.

function Enemies:new(enemies) 
    enemies = enemies or {} 
    timers = Timers:new() 
    setmetatable(enemies, self) 
    self.__index = self 
    return enemies 
end 

In der dritten Zeile hier, da timers nicht als lokaler Variable existiert hier, dieser Wert landet in ein timers statt genannten globalen Variable gesetzt zu werden. Wenn Sie eine Eigenschaft von enemies festlegen möchten, müssen Sie enemies ausdrücklich erwähnen:

function Enemies:new(enemies) 
    enemies = enemies or {} 
    enemies.timers = Timers:new() 
    setmetatable(enemies, self) 
    self.__index = self 
    return enemies 
end 

Nun schreiben Sie:

Aber wenn ich versuche, eine der Timer refrence (aus innerhalb des Objekts des Feindes), bekomme ich eine Nullwert-Ausnahme.

Lua hat eigentlich kein Konzept, "innerhalb eines Objekts" oder "innerhalb einer Klasse" zu sein. In einigen Sprachen, wenn Sie Code innerhalb einer Klasse schreiben, sind alle Mitglieder der Klasse im Geltungsbereich und Sie können auf sie "bare" verweisen. Lua ist keine dieser Sprachen; Wenn Sie in Lua auf ein "Klassenmitglied" verweisen möchten, müssen Sie die Punktnotation verwenden und explizit angeben, auf welches Objekt Sie zugreifen. (Oder Sie können die "erweiterte Methode", mit _ENV.)

Übrigens ...

timers = {} -- so that timers will be accessible in the class scope 

Von was ich in der Frage sehe, macht diese Linie nicht viel; es erstellt nur eine globale Variable, die nie verwendet wird.

Auch diese Linie in Enemies:new:

self.__index = self 

Das gerade setzt Enemies.__index jedes Mal Enemies:new genannt wird. Dies ist feine, aber Sie können auch sie nur einmal eingestellt:

function Enemies:new(enemies) 
    enemies = enemies or {} 
    enemies.timers = Timers:new() 
    setmetatable(enemies, self) 
    return enemies 
end 

Enemies.__index = Enemies