Nous avons donc ajouté et organisé toutes les ressources que nous voulions utiliser dans l’éditeur. Mais comment faire en sorte que des choses se produises ? Comme le joueur va il interagir avec le monde ? Comment allons-nous calculer le score ? Les scripts vont nous permettre tout cela.
Pour le code, Godot utilise son propre langage : le GDScript, qui emprunte beaucoup à Python. Il est fait pour être simple à apprendre, lisible et offre de nombreuses classes prédéfinies qui accélère le temps de développement. Il n’a pas besoin d’être compilé, mais bien sûr, cela n’accélère pas le rendu mais son apprentissage. La principale optimisation est opérée au niveau du moteur et le GDScript améliore considérablement les performances par rapport à Python dans le contexte du jeu.
Pour lire ce chapitre, il est préférable d’avoir quelques bases du concept de programmation. Vous pouvez trouver quelques informations sur Python dans notre manuel.
La partie principale de la structure du code est donnée par Godot, directement. Les scriptes sont attachés aux Nodes et étendent les classes sur lesquelles ces Nodes sont basés. Nous avons simplement besoin de définir ce qui est spécifique au jeu comme les variables et les fonctions.
Variables
Il existe deux types de valeurs dans GDSript :
Les constantes : Une fois définis, elle n’est plus modifiable.
Les variables : Même une fois définis, sa valeur et son type sont modifiable à tout moment.
Les variables sont explicitement déclarées :
En haut du fichier d’un script si elles ont besoin d’être partagées dans les fonctions,
Dans les fonctions elles même.
Qu’importe le type de la valeur, sa portée est une donnée importante. Si elle est définie dans une fonction, elle ne pourra pas atteindre une autre fonction et s’y cantonnera. A la fin de la lecture de la fonction, la valeur n’existe donc plus. Pour la rendre atteignable n’importe quand par n’importe quelle fonction, il suffit de la définir en dehors de celles-ci. Une variable définis qui n’est pas utilisée est indiquée dans l’output d’erreur pour vous inciter à la supprimer.
Utilisez le mot clef var pour déclarer la variable. Puisque GDScript est un langage dynamique, il n’y a pas besoin de définir la nature d’une variable. Cette information sera définie lorsqu’une valeur lui sera attribuée, sinon, elle est nulle (ce qui reste un format de variable).
Var speed
Il est évidement possible de leur attribuer des valeurs dès le début :
Var speed = 100
Ou bien à n’importe quel moment dans n’importe quelle fonction :
Speed = 100
Il est également possible de la contraindre à un type de variable grâce au typage de la 3.1 :
var speed : int = 1
Cela contiendra la variable au type de variable Integer.
GDScript intègre des types de variables standards (comme les int, float, string, bool, null, array, dict…) mais également quelques types spécifiques à celui-ci pour certains calcules mathématique (comme les Rect2, Vector2, Vector3…) et quelques types relatifs au moteur de jeu (Color, Image, Object, InputEvent…). L’objectif de ce livre n’est pas de vous les décrire, vous allez pouvoir en apprendre plus sur l’aide intégrée à l’éditeur
Notez qu’il est aussi possible de définir des constantes avec le mot clef const.
Nous allons parfois avoir besoin « d’exporter » la variable d’un script. Une fois fait, la variable est visible et modifiable dans l’inspecteur. C’est une option importante que certains codeurs feraient mieux d’utiliser pour leurs variables importantes. Cette option aide les Game designer à tester certaines valeurs pour améliorer le jeu sans casser tout le code.
Export var speed = 100
Fonctions
Pour déclarer une fonction il suffi d’utiliser le mot clef func ainsi :
Func function_name() :
# le contenue viens ici
Si vous jetez un coup d’œil à Python, vous aurez remarqué qu’il n’y à pas de def ni de self qui est considéré comme implicite. Sinon, les fonctions while et for sont identiques.
Les fonctions prédéfinis de Godot commencent avec un Under score « _ ». Par exemple _ready(), qui se joue à l’entré du script dans l’arborescence.
Func _ready() :
Evidemment, à mesure de l’étendue du script, chaque fonction est une méthode d’une classe et peut être appelée en tant que membre.
Onerady Var player = get_node(«player »)
Player.do_this()
Assez parlé, voyons comment utiliser un script.
func score() :
print(« lecture de la fonction score»)
func _ready()
print(« test »)score()
If (get_node(« label »))
Print(« Label found »)
Else :
Print(« No label node »)
if (get_node("Label")):
get_node("Label").set_text("0")
else:
print("No label node")
Notez qu’il est également possible de modifier toutes les variables associées à un Node (mêmes celles définis depuis un script !). Par exemple, on peut voir dans l’inspecteur que le Node Label à une variable nommée text et qu’on y définis son contenue, on peut alors modifier cette variable pour changer le texte ainsi :
if (get_node("Label")):
get_node("Label").text = « mon texte »
La prochaine étape va être de remplacer le texte par un integer (type de variable nombre entier) qui sera modifiée chaque seconde. Pour cela, il nous faut d’abord attribuer la variable score au Node racine du niveau afin de la redistribuer plus facilement à tous les autres Nodes de la scène, notamment à notre interface. Pour cela, on créer un script sur le Node2D du niveau et on définis :
var score = 0
Ensuite, on créer un chronomètre qui appel une fonction chaque seconde. Pour cela, on créer un Node Timer dans notre arborescence qu’on peut nommer score_timer. On modifie la propriété Wait Time à 1 et on coche Autostart. Dans l’onglet Noeud > Signaux, on retrouve des fonctions qui sont appelées selon diverses conditions. La première d’entre elles se nomme timeout et est appelée dès que le temps du Timer arrive à 0. En cliquant dessus, on à la possibilité de connecter ce signal à un script en sélectionnant un Node qui y est rattaché, il nous suiffe alors de sélectionner le Node racine de notre scène pour intégrer au script une fonction qui est lancée dès que le chronomètre est terminé !
Ensuite, dans la fonction on_score_timer_timout() qui s’est intégrée au script, on peut incrémenter de 1 la variable score et relancer le timer en appelant la méthode start() présenta dans la documentation :
score += 1
s_timer.start()
Maintenant, nous allons devoir récupérer cette variale depuis le Node de l’interface. Pour cela, on commence par récupérer le Node racine du niveau dans une variable :
onready var niveau = get_node("../")
le chemin ../ permet de revenir au Node précédent, ici en occurrence le Node précédent est le Node racine du niveau puisqu’il y est directement instancié. Ensuite, il nous suffi de mettre à jour chaque frame la variable score et de modifier le texte du Label (on pourrait à la place créer un signal personnaliser, mais la démarche est plus compliquée).
func _process(delta):
get_node("points").text = str(niveau.score)
Dans notre interface, on va également créer un Node Label qui va s’afficher à la mort du personnage pour l’inviter à cliquer sur « r » pour relancer le jeu. Pour cela on créer une variable game_runing dans le Node racine du niveau. Cette variable va permettre de savoir si le joueur est mort ou non. À la mort du personnage, Le Node de la chauve-souris modifie la variable sur le Node racine du niveau et s’auto-détruit.
func bat_die():
get_node("../").game_runing = false
self.queue_free()
L’interface vérifie ensuite s’il doit afficher ou non le message.
if niveau.game_runing == false :
get_node("reload_txt").show()
passons plus rapidement sur le code pour faire apparaître les obstacles :
func _on_cloud_timer_timeout():
if game_runing == true :
var obs = load("res://Scene/obstacle_haut.scn").instance()
obs.set_position(Vector2(bat.position.x + 1000,rand_range(-200, 400)))
add_child(obs)
print("Obstacle spawned at ", obs.get_position())
c_timer.wait_time = rand_range(1, 5)
c_timer.start()
On commence donc, comme pour le score, par créer un Node Timer et on connecte son signal timeout() au script du niveau. On vérifie ensuite si le joueur n’est pas mort et on créer une variable qui vas contenir une instance du nuage. On définis ensuite la position de l’instance : en abscisse on récupère la position x du joueur et on y ajoute une distance dépassant la vision de la caméra, en ordonné on génère un nombre aléatoire entre -200 et 400 (correspondant aux valeurs des extrémités hautes et bases de la caméra dans notre scène). Puis on intègre l’instance à l’arborescence du jeu pour l’intégrer au niveau.
Pour finir, on génère à nouveau un nombre aléatoire pour déterminer le Wait Time du Timer et on le relance. Pour résumer, la fonction permet de générer des obstacles à une hauteur aléatoire à un intervalle de temps également aléatoire.
Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.
Vous devriez rafraîchir la page.