[GELÖST] Hilfe Prozedural > OOP

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

plan_b

Betreff: [GELÖST] Hilfe Prozedural > OOP

BeitragDi, Nov 05, 2013 16:46
Antworten mit Zitat
Benutzer-Profile anzeigen
*Edit:* Sorry dies sollte ins Blitzmax Forum nicht Blitzbasic.

Hallo zusammen,

Ich habe erst kürzlich angefangen mit Blitzmax und minib3d und habe eine frage wie ich am besten meine bisheriges Prozedurales vorgehen besser als OOP Code umsetzen kann. Ich vermute das ich einen Denkfehler mache. Mein Code braucht nur das native minib3d und keine externen medien:

BlitzMax: [AUSKLAPPEN]

SuperStrict

Import sidesign.minib3d

Global width:Int = 800, height:Int = 600
Graphics3D width,height,32,2,85

' player
Local player:TPivot = CreatePivot()
Local camera:TCamera = CreateCamera(player)
PositionEntity(player, 0, 1, 0)

' scene
VariousOtherThings(30)
Local light:TLight = CreateLight(2)

' main
While Not KeyHit(KEY_ESCAPE)

' player movement
If KeyDown(KEY_W) Then MoveEntity(player,0,0,0.1*2)
If KeyDown(KEY_S) Then MoveEntity(player,0,0,-0.1*2)
If KeyDown(KEY_A) Then MoveEntity(player,-0.1 *2,0,0)
If KeyDown(KEY_D) Then MoveEntity(player,0.1 *2,0,0)

UpdateWorld
RenderWorld

Flip(-1)

Wend

' function create scene (author: Flyod)
Function VariousOtherThings(quantity:Int)
Local n:Int, temp:TMesh, angle:Float, dist:Float
For n = 1 To quantity
Select Rand(1, 4 )
Case 1 temp = CreateSphere()
Case 2 temp = CreateCone()
Case 3 temp = CreateCylinder()
Case 4 temp = CreateCube()
End Select
ScaleEntity temp, Rnd( 0.6, 1.5 ), Rnd( 0.6, 1.5 ), Rnd( 0.6, 1.5 )
EntityColor temp, Rand( 100, 255 ), Rand( 100, 255 ), Rand( 100, 255 )
RotateEntity temp, Rnd( -20, 20 ), Rnd( -50, 50 ), Rnd( -20, 20 )
angle# = Rnd( -45, 225)
dist# = Rnd( 2.5, 6 )
PositionEntity temp, dist * Cos( angle ), Rnd( - 3, 3 ), dist * Sin( angle )
Next
End Function


Das klappt ja wunderbar. Nachdem ich die beigelieferten examples von Blitzmax gesehen hab dachte ich mir das ich jetzt das gleiche nochmal versuche aber in einer OOP-Struktur. Das habe ich wie folgt umgesetzt:

BlitzMax: [AUSKLAPPEN]

SuperStrict

Import sidesign.minib3d

Global width:Int = 1280, height:Int = 720
Graphics3D width,height,32,2,85

' player
Global test:TPlayer = New TPlayer
test.Init(0,1,0)

' scene
VariousOtherThings(30)
Local light:TLight = CreateLight(2)

' main
While Not KeyHit(KEY_ESCAPE)

test.Update() ' update player

UpdateWorld
RenderWorld

Flip(-1)

Wend

' function create scene (author: Flyod)
Function VariousOtherThings(quantity:Int)
Local n:Int, temp:TMesh, angle:Float, dist:Float
For n = 1 To quantity
Select Rand(1, 4 )
Case 1 temp = CreateSphere()
Case 2 temp = CreateCone()
Case 3 temp = CreateCylinder()
Case 4 temp = CreateCube()
End Select
ScaleEntity temp, Rnd( 0.6, 1.5 ), Rnd( 0.6, 1.5 ), Rnd( 0.6, 1.5 )
EntityColor temp, Rand( 100, 255 ), Rand( 100, 255 ), Rand( 100, 255 )
RotateEntity temp, Rnd( -20, 20 ), Rnd( -50, 50 ), Rnd( -20, 20 )
angle# = Rnd( -45, 225)
dist# = Rnd( 2.5, 6 )
PositionEntity temp, dist * Cos( angle ), Rnd( - 3, 3 ), dist * Sin( angle )
Next
End Function

' type
Type TPlayer
Field player:TPivot
Field camera:TCamera
Field x:Float, y:Float, z:Float

' create player
Method Init(x:Float, y:Float, z:Float)
Global player:TPivot = TPivot.CreatePivot() ' create pivot
Global camera:TCamera = TCamera.CreateCamera(player) 'create camera (parent: player)
End Method

' update player
Method Update()
If KeyDown(KEY_W) Then z=z +0.1 * 2
If KeyDown(KEY_S) Then z=z -0.1 * 2
If KeyDown(KEY_A) Then x=x -0.1 * 2
If KeyDown(KEY_D) Then x=x +0.1 * 2

'player.MoveEntity(x,y,z)
Player.PositionEntity(x,y,z)

End Method

End Type


Wenn ich jetzt bei der Methode Update() das player.MoveEntity(x,y,z) auskommentiere startet das Programm (mein Spieler bewegt sich nicht aber die Szene wird gerendert) lass ich es aber so sein wie jetzt kommt er mit einer Exception und crasht.

Kann mir jemand sagen was ich hier falsch mache ?

Danke für's lesen
- plan_b
  • Zuletzt bearbeitet von plan_b am Di, Nov 05, 2013 20:57, insgesamt einmal bearbeitet
 

CO2

ehemals "SirMO"

BeitragDi, Nov 05, 2013 18:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Weil du in deiner Methode Init nicht die Variablen des Objektes setzt, sondern neue anlegst, die allerdings nichts mit der Instanz der Klasse zu tun haben und in der Methode Update nicht mehr benutzt werden können (vor allem die Klassen-Variable Player betrifft dies).
Mein Vorschlag: benutz statt einer Init-Methode einen Konstruktor:

BlitzMax: [AUSKLAPPEN]
Type TPlayer
' Variablen

Function Create:TPlayer(x:Float, y:Float, z:Float)
Local ReturnMe:TPlayer = New TPlayer ' Neue Instanz von der Klasse erzeugen
ReturnMe.x = x
ReturnMe.y = y
ReturnMe.z = z

ReturnMe.player = TPivot.Create()
ReturnMe.camera = TCamera.CreateCamera(ReturnMe.player)

Return ReturnMe ' Das erstellte Objekt zurückgeben
End Function


Nun erstellst du außerhalb der Klasse ein neues Objekt, indem du folgendes schreibst BlitzMax: [AUSKLAPPEN]
Global Player:TPlayer = TPlayer.Create(100, 100, 100) ' Beispielwerte


Danach kannst du über die Variable Player auf dessen Methode Update ohne Fehler zugreifen.

Falls du keinen Konstruktor verwenden, sondern es weiterhin über eine extra Methode machen willst, kannst du auch den obigen Code entsprechend anpassen (Function Create:TPlayer() wird zu Method Init(), In der Methode musst du dann noch die Zeile "Local ReturnMe:TPlayer = New TPlayer" löschen, alle Vorkommnisse von ReturnMe durch Self ersetzen und die Return-Zeile muss ebenfalls gelöscht werden).
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

Holzchopf

Meisterpacker

BeitragDi, Nov 05, 2013 19:11
Antworten mit Zitat
Benutzer-Profile anzeigen
~VERSCHOBEN~

Aus offensichtlichen Gründen Razz
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Midimaster

BeitragDi, Nov 05, 2013 19:30
Antworten mit Zitat
Benutzer-Profile anzeigen
meiner Meinung nach würde auch schon reichen, einfach die beiden GLOBAL aus der Init() zu entfernen:

BlitzMax: [AUSKLAPPEN]
' player
Global test:TPlayer = New TPlayer
test.Init(0,1,0)

' scene
Global camera:TCamera
....
Type TPlayer
Field player:TPivot
Field x:Float, y:Float, z:Float

Method Init(x:Float, y:Float, z:Float)
player:TPivot = TPivot.CreatePivot() ' create pivot
camera = TCamera.CreateCamera(player) 'create camera (parent: player)
End Method
....


GLOBAL Variablen werden in BMax außerhalb der Methoden/Funktionen deklariert. GLOBAL ganz außen schafft eine GLOBALE, die überall zur Verfügung steht. GLOBAL statt FIELD innerhalb eines Types erreicht, dass diese Variable dann innerhalb des TYPE in Funktionen und Methoden allen Objekten von diesem Typ zur Verfügung steht.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

DAK

BeitragDi, Nov 05, 2013 20:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Eine globale Variable in einem Type kann auch von außerhalb angesprochen werden:

BlitzMax: [AUSKLAPPEN]
Type TTest
Global a:Int
End Type
TTest.a = 5
Gewinner der 6. und der 68. BlitzCodeCompo

ZEVS

BeitragDi, Nov 05, 2013 20:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Eine "globale" Variable in einer Funktion aber nicht.
BlitzMax: [AUSKLAPPEN]
	Method Init(x:Float, y:Float, z:Float)
Global player:TPivot = TPivot.CreatePivot() ' create pivot
Global camera:TCamera = TCamera.CreateCamera(player) 'create camera (parent: player)
End Method


ZEVS
 

plan_b

BeitragDi, Nov 05, 2013 20:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für das rasche feedback, das ging schnell!

Ich habe es jetzt realisiert wie CO2 - danke dir das klappt wunderbar! Gibt es nennenswerte Gründe das auch mit einer Methode zu machen ? Oder soll man generell zum erstellen einer Instanz eine Funktion verwenden ?

Interessant das Globale Variabeln nicht "überall" angesprochen werden kann je nach dem wo man sie erstellt.

Nochmals Danke für's Feedback!

- plan_b
 

CO2

ehemals "SirMO"

BeitragDi, Nov 05, 2013 23:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Gibt es nennenswerte Gründe das auch mit einer Methode zu machen

Eigentlich nicht. Wink

Zitat:
Oder soll man generell zum erstellen einer Instanz eine Funktion verwenden
Ein "Konstruktor" ist die beste Variante ein Objekt von einer Klasse zu erstellen, da ich im Code nur 1 Zeile (Global NeuesObjekt:MeineKlasse = MeineKlasse.Create()) schreiben muss und nicht zwei (BlitzMax: [AUSKLAPPEN]
Global NeuesObjekt:MeineKlasse = New MeineKlasse
NeuesObjekt.Init()
), was natürlich Fehler durch "menschliches Versagen" (bspw. Vergessen der "New"-Zeile) stark minimiert.

Es wäre außerdem sinnvoll, nach der Initialisierung der Instanz das Objekt auf "= Null" zu prüfen, in etwa so (um mein obiges Beispiel fortzusetzen) BlitzMax: [AUSKLAPPEN]
Global NeuesObjekt:MeineKlasse = MeineKlasse.Create()
If(NeuesObjekt = Null) Then 'Fehlerbehebung durch "sauberes Abschalten" des Prozesses oder Ähnlichem
um einen Null-Exception-Fehler zu "verhindern".

Wenn du es ganz "einfach" haben willst, schreibst du zudem außerhalb der Klasse nochmals eine Funktion, die erst ein Objekt initialisiert und dieses dann zurückgibt. Dann entfällt auch das "MeineKlasse.Create()" und du brauchst nur die geschriebene Funktion aufzurufen. Beispiel BlitzMax: [AUSKLAPPEN]
Type MeineKlasse
' Variablen, Funktionen, Methoden, etc.
End Type

Function CreateMeineKlasse:MeineKlasse()
Return MeineKlasse.Create()
End Function

' Nun brauchst du zum erzeugen einer Instanz nur noch Folgendes zu schreiben:
Global NeuesObjekt:MeineKlasse = CreateMeineKlasse()

Xeres

Moderator

BeitragDi, Nov 05, 2013 23:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Eine Methode kann man nur auf eine bereits existierende Instanz anwenden - man könnte zwar (new TType).Init() schreiben, aber das sieht eher unschön aus... Üblicherweise definiert man eine Create-Funktion, da man bei BMax den Konstruktor nicht mit Parametern überladen kann - aber ausführen kann man etwas.
Beispiel:

BlitzMax: [AUSKLAPPEN]

Type TTest
Field val:Int
Global count:Int

Method New()
'* Nachdem die Instanz erzeugt wurde, zähle Sie
count:+1
EndMethod

Method Delete()
'* delete wird automatisch vom Garbage Collector aufgerufen
'* Rufe diese Methode _nicht_ selbst auf - Objekte ohne Referenz werden automatisch
'* entfernt
count:-1
EndMethod

Function Create:TTest(_val:Int)
Local o:TTest = New TTest
o.val = _val
Return o
EndFunction

EndType

Local t:TTest
t = TTest.Create(1)
t = TTest.Create(2)
t = TTest.Create(3)
Print(TTest.count)
GCCollect() '* Erzwinge Speicherfreigabe (nur zu Demonstrationszwecken)
Print(TTest.count)



Edit:
CO2 hat Folgendes geschrieben:
Wenn du es ganz "einfach" haben willst, schreibst du zudem außerhalb der Klasse nochmals eine Funktion, die erst ein Objekt initialisiert und dieses dann zurückgibt.
Bitte macht das auf gar keinen Fall. BlitzMax macht das, damit man ohne OOP Arbeiten kann - was Niemand will, wenn er tatsächlich OOP nutzt. Das verschmutzt höchstens den Globalen Namensraum mit Ellenlangen Funktionsnamen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group