1. Erstelle
eine neue Szene "Console" in deinem Projekt mit einem CanvasLayer namens Console als Root Node. Stelle im Inspektor bei Node die Pause-Mode auf "process". Hänge daran ein "Panel"
Das Panel sollte auf der Position 0,0 sein und ein bisschen vergrössert werden für die Übersicht.
2.
Erstelle unter dem Panel folgende Dinge - du musst sie NICHT anordnen, da wir
das im Code machen:
2.1. Ein Label "LabelConsole" mit dem Text "Console" Dieses ist der Titel des Fensters. Bitte ordne dieses Label in der linken oberen Ecke des Panels an. Nur dieses Label muss angeordnet werden.
2.1. Ein Label "LabelConsole" mit dem Text "Console" Dieses ist der Titel des Fensters. Bitte ordne dieses Label in der linken oberen Ecke des Panels an. Nur dieses Label muss angeordnet werden.
2.2 Einen Button "BtnExit" mit einem "X" als Text.
2.3 Einen
Button "BtnClear" mit "Clr" als Text.
2.4 Ein TextEdit-Node namens "ConsoleText":
Hier kommt der Text von der Konsole rein.
2.5 Ein LineEdit-Node namens
"EditText": Hier schreibt der User seinen Text rein.
3. Hänge an das Root-Node
("Console"-Panel) ein Skript namens "Console.gd" an.
Hier ist der Script Code:
Erstmal ein paar Variablen und überall genutzte Komponenten:
Mit den Variablen kann man im Editor einstellen, wie gross das Fenster relativ zur Applikationsgrösse ist und ob es zentriert werden soll. Die Signale sind dazu da, um einige Sachen vom Game einzustellen, wenn die Konsole hervorgeholt oder versteckt wird, wie zum Beispiel den GameState auf Pause zu setzen.
# multipliers for the size.
# its x times screensize so the multipliers should
# be between 0.0 and 1.0
export var hSize_Multiplier: float = 1.0
export var vSize_Multiplier: float = 0.75
export var centerHorizontally: bool = false
export var centerVertically: bool = false
# components
onready var TxtEdit = get_node("EditText")
onready var ConsoleTxt = get_node("ConsoleText")
onready var BtnExit = get_node("BtnExit")
onready var BtnClear = get_node("BtnClear")
# signals
signal console_shown
signal console_hidden
signal console_command_given
Die Signale kann man nun im Editor mit dem Code verknüpfen. Das muss man ausserhalb der Konsolen-Szene machen, sonst ändert man nur den Code von der Konsole...# its x times screensize so the multipliers should
# be between 0.0 and 1.0
export var hSize_Multiplier: float = 1.0
export var vSize_Multiplier: float = 0.75
export var centerHorizontally: bool = false
export var centerVertically: bool = false
# components
onready var TxtEdit = get_node("EditText")
onready var ConsoleTxt = get_node("ConsoleText")
onready var BtnExit = get_node("BtnExit")
onready var BtnClear = get_node("BtnClear")
# signals
signal console_shown
signal console_hidden
signal console_command_given
In der ready-Funktion wird die Konsole erstmal angeordnet durch die resize-Funktion:
func _ready():
resize()
# set size of the console, align all UI elements
# and maybe center it.
func resize()->void:
# clamp the multiplier
if vSize_Multiplier<0: vsize_multiplier="0<br"> if vSize_Multiplier>1.0: vSize_Multiplier = 1.0
if hSize_Multiplier<0: hsize_multiplier="0<br"> if hSize_Multiplier>1.0: hSize_Multiplier = 1.0
# set resolutions
# first get the window resolution and multiply it
var screenRes := Vector2(ProjectSettings.get_setting("display/window/size/width"), ProjectSettings.get_setting("display/window/size/height"))
var consoleRes := Vector2(screenRes.x * hSize_Multiplier, screenRes.y*vSize_Multiplier)
print("Console Resolution: ",str(consoleRes.x),"/",str(consoleRes.y))
# set resolution to the panel
self.rect_size = Vector2(consoleRes.x, consoleRes.y)
# set position of the panel
if screenRes.x != consoleRes.x and centerHorizontally == true:
var halfx=consoleRes.x*0.5
self.rect_position.x = screenRes.x*0.5-halfx
if screenRes.y != consoleRes.y and centerVertically == true:
var halfy = consoleRes.y*0.5
self.rect_position.y = screenRes.y*0.5-halfy
# set resolution to the edit textbox
TxtEdit.rect_size.x = consoleRes.x
TxtEdit.rect_position.y = consoleRes.y- TxtEdit.rect_size.y
# set position of the buttons.
BtnExit.rect_size=Vector2(20.0,20.0) # there was an error aligning this, it growed
BtnExit.rect_position = Vector2(consoleRes
.x-BtnExit.rect_size.x,0)
BtnClear.rect_size.y = BtnExit.rect_size.y
BtnClear.rect_position = Vector2(consoleRes.x-BtnExit.rect_size.x-BtnClear.rect_size.x,0)
# set resolution of the console text box
ConsoleTxt.rect_position = Vector2(0, BtnExit.rect_size.y)
ConsoleTxt.rect_size = Vector2(consoleRes.x, consoleRes.y-BtnExit.rect_size.y-TxtEdit.rect_size.y)
0:>0:>
Nun noch einige Funktionen für die Bedienung der Konsole:
resize()
# set size of the console, align all UI elements
# and maybe center it.
func resize()->void:
# clamp the multiplier
if vSize_Multiplier<0: vsize_multiplier="0<br"> if vSize_Multiplier>1.0: vSize_Multiplier = 1.0
if hSize_Multiplier<0: hsize_multiplier="0<br"> if hSize_Multiplier>1.0: hSize_Multiplier = 1.0
# set resolutions
# first get the window resolution and multiply it
var screenRes := Vector2(ProjectSettings.get_setting("display/window/size/width"), ProjectSettings.get_setting("display/window/size/height"))
var consoleRes := Vector2(screenRes.x * hSize_Multiplier, screenRes.y*vSize_Multiplier)
print("Console Resolution: ",str(consoleRes.x),"/",str(consoleRes.y))
# set resolution to the panel
self.rect_size = Vector2(consoleRes.x, consoleRes.y)
# set position of the panel
if screenRes.x != consoleRes.x and centerHorizontally == true:
var halfx=consoleRes.x*0.5
self.rect_position.x = screenRes.x*0.5-halfx
if screenRes.y != consoleRes.y and centerVertically == true:
var halfy = consoleRes.y*0.5
self.rect_position.y = screenRes.y*0.5-halfy
# set resolution to the edit textbox
TxtEdit.rect_size.x = consoleRes.x
TxtEdit.rect_position.y = consoleRes.y- TxtEdit.rect_size.y
# set position of the buttons.
BtnExit.rect_size=Vector2(20.0,20.0) # there was an error aligning this, it growed
BtnExit.rect_position = Vector2(consoleRes
.x-BtnExit.rect_size.x,0)
BtnClear.rect_size.y = BtnExit.rect_size.y
BtnClear.rect_position = Vector2(consoleRes.x-BtnExit.rect_size.x-BtnClear.rect_size.x,0)
# set resolution of the console text box
ConsoleTxt.rect_position = Vector2(0, BtnExit.rect_size.y)
ConsoleTxt.rect_size = Vector2(consoleRes.x, consoleRes.y-BtnExit.rect_size.y-TxtEdit.rect_size.y)
0:>0:>
# show the console and set the focus on the text edit.
func show()->void:
self.visible = true
TxtEdit.grab_focus()
emit_signal("console_shown")
get_tree().paused = true
# hide the console
func hide()->void:
get_tree().paused=false()
self.visible=false
emit_signal("console_hidden")
4. Nun werden die Signale verknüpft. Doppelklicke rechts im Inspektor auf das signal "pressed" vom Button "BtnExit" und wähle das Panel "Console" mit dem Script als Ziel. Dort erscheint nun eine Funktion, in welche du einfach nur hide() reinschreibst:
func show()->void:
self.visible = true
TxtEdit.grab_focus()
emit_signal("console_shown")
get_tree().paused = true
# hide the console
func hide()->void:
get_tree().paused=false()
self.visible=false
emit_signal("console_hidden")
# event when the exit button was pressed
func _on_BtnExit_pressed():
hide()
Dasselbe machen wir mit dem Clear-Button:
func _on_BtnExit_pressed():
hide()
# event when the clear button was pressed
func _on_BtnClear_pressed():
ConsoleTxt.text=""
TxtEdit.grab_focus() # get the focus back to the lineedit.
Für den Konsole-Text brauchen wir eine Funktion, die den Fokus immer wieder auf das LineEdit "EditText" lenkt. Ansonsten könnte man in den Text reinschreiben und das wollen wir nicht. Mit dem Readonly-Flag wird der Text grau und das wollen wir auch nicht. Doppelklicke also auf das "focus_entered()"-Signal des ConsoleText-Nodes (TextEdit) und verknüpfe es wie oben beschrieben. Hier muss man nur TxtEdit.grab_focus() reinschreiben:
func _on_BtnClear_pressed():
ConsoleTxt.text=""
TxtEdit.grab_focus() # get the focus back to the lineedit.
# grab the focus on the line edit
# when someone clicks on the console text.
func _on_ConsoleText_focus_entered():
TxtEdit.grab_focus()
Und schliesslich brauchen wir noch die Funktion, wenn der Benutzer im LineEdit die Enter-Taste drückt. Das Signal heisst "text_entered" im LineEdit-Node.
# when someone clicks on the console text.
func _on_ConsoleText_focus_entered():
TxtEdit.grab_focus()
# enter was pressed on the line edit.
func _on_EditText_text_entered(new_text):
var txt = TxtEdit.text
add_line("> "+txt)
parse(txt)
TxtEdit.clear()
Mit add_line wird der Text an den Konsolentext angehängt und mit einem \n beendet. Jede Zeile muss also ein \n am Ende haben, sonst funktioniert das Ganze nicht richtig.
func _on_EditText_text_entered(new_text):
var txt = TxtEdit.text
add_line("> "+txt)
parse(txt)
TxtEdit.clear()
func add_line(txt:String)->void:
print(txt) # gib den text im debugger aus.
ConsoleTxt.text += txt
ConsoleTxt.text += "\n"
# scroll vertical to infinity = to end of text
ConsoleTxt.scroll_vertical = INF
Um den Text mit dem Programm zu verknüpfen haben wir die parse-Funktion. Hier werden ein paar interne Kommandos ausgewertet und dann das Signal "console_command_given" emittiert. Dieses Signal kann abgefangen und der Text ausgewertet werden. Als Beispielfunktion gibt es hier einfach "exit" um die Konsole zu beenden.
print(txt) # gib den text im debugger aus.
ConsoleTxt.text += txt
ConsoleTxt.text += "\n"
# scroll vertical to infinity = to end of text
ConsoleTxt.scroll_vertical = INF
func parse(Txt:String)->void:
Txt = Txt.to_lower() # text auf lowercase.
if Txt=="":
return # nothing happens if nothing gets in. if Txt=="exit":
hide()
return
# command not recognized (no return before)
emit_signal("console_command_given", Txt, self)
Für komplexere Befehle muss ich noch ein bisschen recherchieren. ;)if Txt=="":
return # nothing happens if nothing gets in. if Txt=="exit":
hide()
return
# command not recognized (no return before)
emit_signal("console_command_given", Txt, self)
Das Signal hat als Parameter den Text und die Konsole selbst. Man kann also einfach eine Funktion in einem anderen Node mit dem Signal verknüpfen und zum Beispiel Cheats einbauen:
# ein cheat für den player
func on_console_command_given(var Txt, var Console)
if Txt="heileheilesegen":
health=max_health
Console.add_line("CHEAT ACTIVATED")
func on_console_command_given(var Txt, var Console)
if Txt="heileheilesegen":
health=max_health
Console.add_line("CHEAT ACTIVATED")
Hiermit hast du eine funktionsfähige Konsole, welche du einfach an deine Mainscene anhängen kannst. Achte darauf, dass sie zu unterst im Nodetree ist, damit sie immer im Vordergrund ist. Setze das visible-flag auf false und erstelle einen Button oder anderen Event mit Console.show() als Funktionscode. Das sollte erstmal reichen. ;)
Keine Kommentare:
Kommentar veröffentlichen