[LUA] Keine Rückgabe von veränderten Objektvariablen?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

Firstdeathmaker

Betreff: [LUA] Keine Rückgabe von veränderten Objektvariablen?

BeitragMo, Okt 05, 2009 17:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

I versuche gerade lua in BMax für meine Zwecke zu entdecken, aber jetzt bin ich auf eine Frage gestoßen:

Ich würde gerne für meine KI Lua-Scripte für die Steuerung benutzen. Also habe ich eine Klasse (TEnemy) welche jeden Schleifendurchlauf ein kleines Lua-Script aufruft. In Lua selbst wird das objekt erkannt und die Variablen auch richtig verändert, nur scheint das keine Auswirkungen auf das Objekt in BMax zu haben; dort bleiben die variablen x und y auf 0.

BMax Code
Code: [AUSKLAPPEN]

superstrict

'
Type TEnemy
   Field name:String = "Angry Enemy"
   Field luaclass:TLuaClass
   Field luaobject:TLuaObject
   Field x:float
   Field y:float
   
   Method setScript(scriptpath:String)
      Local f:TStream = ReadFile(scriptpath)
      Local source:String = f.ReadString(f.size() )
      CloseFile f
      Self.luaclass = TLuaClass.Create(source)
      Self.luaobject = TLuaObject.Create(luaclass , Self)
      Assert luaobject,"TEnemy.setScript() luaobject not created"
   End Method
   
   Method process()
      luaobject.Invoke "process_ki" , Null
      render()
   End method
   
   Method render()
      DrawRect Self.x,Self.y,10,10
   End method
End Type


Graphics 400,300
Local e:TEnemy = New TEnemy
e.setScript("script1.lua")

repeat
cls
   e.process()
flip
Until KeyHit(KEY_ESCAPE)
end



LUA script1.lua
Code: [AUSKLAPPEN]

function process_ki()
   self.x = self.x + 1
   self.y = self.y + 1
   print(self.x)
   if ( self.x>=400 ) then self.x = 0 end
   if ( self.y>=300 ) then self.y = 0 end
   print(self.name)
   print("process ki")
end
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Suco-X

Betreff: ....

BeitragMo, Okt 05, 2009 21:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Benutze im Script mal Super statt self.
Mfg Suco
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB

Firstdeathmaker

BeitragDi, Okt 06, 2009 9:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann bekomme ich folgende Fehlermeldung:

Zitat:
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR
[string "function process_ki()..."]:2: attempt to index global 'Super' (a nil value)ERROR


Script sieht jetzt so aus:
Code: [AUSKLAPPEN]
function process_ki()
   Super.x = Super.x + 1
   Super.y = Super.y + 1
   print(Super.x)
   if ( Super.x>=400 ) then Super.x = 0 end
   if ( Super.y>=300 ) then Super.y = 0 end
   print(Super.name)
   print("process ki")
end




Folgendes Funktioniert aber:
Code: [AUSKLAPPEN]
'superstrict

'
Type TEnemy
   Global list:TList = New TList
   
   Method New()
      TEnemy.list.addlast(Self)
   End method
   
   Function Update()
      For Local e:TEnemy = EachIn list
         e.process()
      next
   End function
   
   Field name:String = "Angry Enemy"
   Field luaclass:TLuaClass
   Field luaobject:TLuaObject
   Field x:Float
   Field y:Float
   
   Method setScript(scriptpath:String)
      Local f:TStream = ReadFile(scriptpath)
      Local source:String = f.ReadString(f.size() )
      CloseFile f
      Self.luaclass = TLuaClass.Create(source)
      Self.luaobject = TLuaObject.Create(luaclass , Self)
      Assert luaobject,"TEnemy.setScript() luaobject not created"
   End Method
   
   Method process()
      LuaRegisterObject(Self , "enemy")
      luaobject.Invoke "process_ki" , Null
      render()
   End Method
   
   Method render()
      DrawRect Self.x,Self.y,10,10
   End Method
End Type


Graphics 800 , 600

For Local i:Int = 0 Until 100
Local e:TEnemy = New TEnemy
e.setScript("script1.lua")
e.x = Rand(0 , GraphicsWidth())
e.y = Rand(0,GraphicsHeight())
next


Repeat
Cls
   TEnemy.Update()
Flip
Until KeyHit(KEY_ESCAPE)
End


Code: [AUSKLAPPEN]
function process_ki()
   enemy.x = enemy.x + 1
   enemy.y = enemy.y + 1
   if ( enemy.x>=800 ) then enemy.x = 0 end
   if ( enemy.y>=600 ) then enemy.y = 0 end
end

Suco-X

Betreff: ....

BeitragDi, Okt 06, 2009 14:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe dein Script natürlich vor meiner Antwort getestet und ich denke es liegt daran dass du super groß geschrieben hast(Also den Anfangsbuchstaben). Lua ist Case sensitve.

Aber dein Code war ein guter Anfang rumzutesten, da Mark es scheinbar nicht für nötig hält auch nur kleinste Beispielcodes beizulegen die die Funktion des Moduls verdeutlichen.

Hier mal meine bisherigen Ergebnisse:

Code: [AUSKLAPPEN]

SuperStrict


Type TLuaFunctions
   
   Method Rnd:Double(min_value:Double=1, max_value:Double)
      Return .Rnd(min_value, max_value)
   End Method
   
   Method Rand:Int(min_value:Int, max_value:Int=1)
      Return .Rand(min_value, max_value)
   End Method
   
   Method Sin:Double(x:Double)
      Return .Sin(x)
   End Method
   
   Method Cos:Double(y:Double)
      Return .Cos(y)
   End Method
   
   Method GraphicsWidth:Int()
      Return .GraphicsWidth()
   End Method
   
   Method GraphicsHeight:Int()
      Return .GraphicsHeight()
   End Method
   
   Method Print(str:String)
      .Print(str)
   End Method
End Type



Type TPlayer
   Field x:Float, y:Float
   
   Method draw()
      DrawOval x,y,10,10
   End Method
End Type

Local LuaFunctions:TLuaFunctions = New TLuaFunctions
LuaRegisterObject(LuaFunctions,"bmx")

Local Player:TPlayer = New TPlayer
LuaRegisterObject(Player, "player")

Type TEnemy
   Field luaclass:TLuaClass
   Field luaobject:TLuaObject
   Field x:Double, y:Double
   Field angle:Double, speed:Double
   Field FollowSpeed:Double =1.0
   Field size:Int

   
   Function Create:TEnemy(script:String)
   Local tmp:TEnemy
   tmp = New TEnemy
   tmp.SetScript(script)
   tmp.Init()
   Return tmp
  End Function

  Method SetPosition(x:Double, y:Double)
   Self.x = x
   Self.y = y
  End Method

  Method SetAngle(angle:Double)
   Self.angle = angle
  End Method

  Method SetSpeed(speed:Double, followSpeed:Double)
    Self.speed = speed
   Self.followSpeed = followSpeed
  End Method
 
  Method SetSize(size:Int)
    Self.size = size
  End Method


   Method Init()
      luaobject.Invoke("init_ki", Null)
   End Method

   Method Move()
   x:+Sin(angle)*speed
   y:-Cos(angle)*speed
   End Method

  Method FindAngle:Float(obj:TPlayer)
   Return ATan2(obj.y-y, obj.x-x)+90
  End Method
 
  Method Distance:Float(obj:TPlayer)
   Return Sqr(((obj.x-x)*(obj.x-x))+((obj.y-y)*(obj.y-y)))
  End Method

   Method setScript(script:String)
      Self.luaclass = TLuaClass.Create(script)
      Self.luaobject = TLuaObject.Create(luaclass , Self)

   If Not luaobject Throw "Lua Objekt konnte nicht erstellt werden"
   End Method
   
   Method process()
      luaobject.Invoke("process_ki" , Null)
   End Method

   Method render()
      DrawOval Self.x,Self.y,size, size
   End Method
End Type


Function LoadLuaScript:String(filename:String)
   Local script:String
   
   If FileType(filename)<>FILETYPE_FILE Throw "Datei existiert nicht"
   
   script = LoadString(filename)
   
   Return script
End Function


Graphics 800,600,0
HideMouse
Const count:Int = 100
SeedRnd(MilliSecs())

Local enemys:TEnemy[count]

Local script:String = LoadLuaScript("script.lua")


For Local i:Int = 0 Until count
   enemys[i] = TEnemy.Create(script)
Next

Local tmp:String

Repeat
Cls
   
   Local timer:Int = MilliSecs()

   For Local i:Int = 0 Until count
      enemys[i].process()
   Next
   tmp = "Lua time: "+(MilliSecs()-timer)

   For Local i:Int = 0 Until count
   enemys[i].render()
   Next 

   player.x = MouseX()
   player.y = MouseY()
   player.draw()

  DrawText tmp,10,10
Flip
Until KeyHit(KEY_ESCAPE)
End


Code: [AUSKLAPPEN]

function init_ki()
   super.SetSize(bmx.Rand(3,10))
   super.SetPosition(bmx.Rnd(0.0, bmx.GraphicsWidth()), bmx.Rnd(0.0, bmx.GraphicsHeight()))
   super.SetSpeed(0.0, bmx.Rnd(0.01, 0.003))
end


function process_ki()
   super.Move()
   super.angle = FindAngle(player)+bmx.rnd(-10.0, 10.0)
     super.speed = Distance(player)*super.FollowSpeed
end


Ich denke ich probiere mich mal die Tage an einem Spaceshooter dessen Objekte über LUA gesteuert werden.

Mfg Suco
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB

Firstdeathmaker

BeitragDi, Okt 06, 2009 15:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ah, mit "super" funktionierts!

Das mit dem Spaceshooter und die KI damit machen ist genau das was ich vorhabe. Leider ist die Geschwindigkeit von LUA nicht so hoch, aber ich denke wenn man nicht mehr als 100 Gegner hat geht das noch klar (in meinem Beispiel geht es bei 1000 nicht mehr, aber mit 100 funktioniert es noch super). Das Grundgerüst für meinen Shooter steht schon soweit, dass man die Gegner über ein ausgeklügeltes Weichensystem lustig in Formationen oder Reihen über den Bildschirm flitzen lassen kann. Das funktioniert allerdings über XML und in BMax, wodurch es sehr schnell ist.

Nur wollte ich das individuelle Verhalten (also wann geschossen wird etc. durch LUA festlegen). Ebenso Endgegnerbewegungen. Denke dafür ist LUA genau das richtige.
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group