Prozedur in Variable speichern

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Prozedur in Variable speichern

Beitrag von 4Planes »

Hallo!
Ich programmiere in ein kleines 2D-Spiel. Obwohl das Menü recht übersichtlich ist (Hauptmenü, Spieleinstellungen, Tastenbelegung) kommen da sehr schnell sehr viele If-Befehle bzw. Select-Case-Befehle zusammen. Was das Ganze so aufbläht, ist, dass jeder Menü-Punkt, wenn er vom Spieler ausgewählt wird, eine andere Prozedur aufruft: Der Menüpunkt »New Game« startet ein neues Spiel, »Quit« beendet es usw.

Also frage ich mich, wie ich das vereinfachen und übersichtlicher gestalten kann. Die einfachste Lösung wäre, wenn man die Prozedur, die aufgerufen werden soll, wenn der Spieler einen Menüpunkt auswählt, in eine Variable speichern könnte. Ich habe mit Pointern herumexperimentiert, bin aber zu nichts gekommen.

Hier ein Beispiel, was ich mir vorstelle:

Code: Alles auswählen

AddElement(MainMenu\MenuItems())
MainMenu\MenuItems()\Text = "New Game"
MainMenu\MenuItems()\Procedure = @LoadLevel()
AddElement(MainMenu\MenuItems())
MainMenu\MenuItems()\Text = "Settings"
MainMenu\MenuItems()\Procedure = @SettingsMenu()
AddElement(MainMenu\MenuItems())
MainMenu\MenuItems()\Text = "Quit"
MainMenu\MenuItems()\Procedure = @DoYouReallyWantToQuit()

...

SelectElement(MainMenu\MenuItems(), varInt_SelectedItem)

*Führe aus* MainMenu\MenuItems()\Procedure 
Ich hoffe, es ist verständlich, was ich meine. Die Prozeduren sollen nicht ausgeführt werden, wenn die Listenelemente angelegt werden, sondern erst ganz am Schluss.

Tut mir leid, wenn das eine total doofe Frage ist. Trotzdem schon mal vielen Dank; das Forum war bisher sehr hilfreich!
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prozedur in Variable speichern

Beitrag von STARGÅTE »

Das geht mit Prototype, welche du als Struktur an dein \Procedure hängst:

Code: Alles auswählen

Prototype.i MyProcedure(Param.i)

Procedure Version1(Param.i)
	Debug "Version 1: "+Param
EndProcedure

Procedure Version2(Param.i)
	Debug "Version 2: "+Param
EndProcedure

Structure Item
	Proc.MyProcedure
EndStructure

Define NewList Item.Item()

AddElement(Item())
Item()\Proc = @Version1()

AddElement(Item())
Item()\Proc = @Version2()

ForEach Item()
	Item()\Proc(ListIndex(Item()))
Next
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

Das ist ja genial! Es ist viel übersichtlicher und ich spare mir Codedoubletten.
Vielen, vielen Dank!
:bounce:
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

Klappt das auch mit Variablen?

Zu diesem Code sagt der Compiler nur »Syntaxfehler«:

Code: Alles auswählen

Procedure Menu( varProc_Menu.MyProcedure )
  ...
  varProc_Menu
  ...
EndProcedure

Procedure DebugMenu()
  Protected varProc_Menu.MyProcedure = @MainMenu()
  ...
  Menu(varProc_Menu)
  ...
EndProcedure

DebugMenu()
Ich vermute, die Variable darf nicht so einam rumstehen. Ich hatte allerdings gehofft, dass varProc_Menu ausgeführt wird, also die Prozedur MainMenu(), die ich der Variable zugewiesen habe.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prozedur in Variable speichern

Beitrag von STARGÅTE »

Ja geht auch mit Variablen, aber denke daran, der Name hat keine () erst beim Auffruf kommt die () drum.

Code: Alles auswählen

Prototype.i MyProcedure(Param.i)

Procedure Version1(Param.i)
   Debug "Version 1: "+Param
EndProcedure

Procedure Version2(Param.i)
   Debug "Version 2: "+Param
EndProcedure

; Entweder so:

Define DoIt.MyProcedure

DoIt = @Version1()
DoIt(12345)

; oder so geht es auch:

Procedure Caller(DoIt.MyProcedure, Param.i)
	DoIt(Param)
EndProcedure

Caller(@Version2(), 67890)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

Ahhhh! Nochmals vielen Dank! Vor allem für die beiden Codebeispiele.
In meinem Code fehlten, wie du richtig gesagt hast, die Klammern hinter varProc_Menu in der Prozedur Menu(varProc_Menu.MyProcedure). Jetzt klappt es wunderbar.
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

Noch ein Frage zum Thema.

Gibt es die Möglichkeit, den Parameter schon anzugeben, wenn man das Listenelement erstellt?

So stelle ich mir das vor, aber das fführt wieder nur zu einem Syntaxfehler in der Zeile »Item()\Proc = @Version1(varZahl)«

Code: Alles auswählen

Prototype.i MyProcedure(Param.i)

Procedure Version1(Param.i)
   Debug "Version 1: "+Param
EndProcedure

Structure Item
   Proc.MyProcedure
EndStructure

Define NewList Item.Item()
Define varZahl.i = 123

AddElement(Item())
Item()\Proc = @Version1(varZahl)

ForEach Item()
   Item()\Proc()
Next
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prozedur in Variable speichern

Beitrag von STARGÅTE »

Nein diese Möglichkeit gibt es nicht.
Alle möglichen Parameter müssen neben der Prozedur-Adresse (dieses @BlaKecks()) auch als Strukturfeld innerhalb deines Elements gespeichert werden.
Hier kannst du es dir leicht machen und gleich die ganze Struktur an die Prozedur übergeben, z.B. so:

Code: Alles auswählen

Prototype.i MyProcedure(*Item)

Structure Item
   Proc.MyProcedure
   varZahl.i
   varString.s
EndStructure


Procedure Version1(*Item.Item)
   Debug "Version 1: "+*Item\varZahl
   Debug "           "+*Item\varString
EndProcedure

Define NewList Item.Item()

AddElement(Item())
Item()\Proc      = @Version1()
Item()\varZahl   = 123
Item()\varString = "Blub"

ForEach Item()
   Item()\Proc(Item())
Next
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

STARGÅTE, vielen Dank für deine geduldigen Erklärungen. Das war alles sehr hilfreich!
Ich habe dank deiner Hilfe ein, wie ich finde, sehr elegantes Grundgerüst für ein Menü programmiert.

Eine Frage habe ich noch. Mir ist aufgefallen, dass ich es mit den Parametern nicht so genau nehmen muss. Würde ich Version2() so aufrufen »Version2 (12345)«, bekäme ich eine Fehlermeldung, dass die Zahl der Parameter falsch ist. Rufe ich Version2() aber auf wie im Beispiel unten, wo die Prozedur ja auch den Parameter 12345 bekommt, gibt es keinen Fehler.

Code: Alles auswählen

Prototype.i MyProcedure(Param.i)

Procedure Version1(Param.i)
  Debug "Version 1: "+Param
EndProcedure

Procedure Version2()
  Debug "Version 2: Kein Parameter"
EndProcedure

Structure Item
  Proc.MyProcedure
EndStructure

Define NewList Item.Item()

AddElement(Item())
Item()\Proc = @Version1()

AddElement(Item())
Item()\Proc = @Version2()

ForEach Item()
   Item()\Proc(12345)
Next
Ich finde das sehr praktisch! Allerdings frage ich mich, ob ich darauf vertrauen kann, dass das immer funktioniert, oder es nur Zufall oder ein Fehler ist.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prozedur in Variable speichern

Beitrag von STARGÅTE »

Das dein Beispiel funktioniert heißt leider nicht, dass es richtig ist.

Wenn du Proc als MyProcedure Prototyp definierst, dann sollten alle Funktionen die du übergibst auch exakt diese Definition haben (nicht andere, nicht mehr und auch nicht weniger Parameter).
Ein kurzes Statement gab es von mir selber mal hier: Prototype vs. Procedure – unterschiedl. Parameterdefinition

Was machen kannst ist einfach ein Default-Wert definieren:

Code: Alles auswählen

Procedure Version2(Param.i=0)
  Debug "Version 2: Kein Parameter"
EndProcedure
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten