1h pour tester Löve2D
Cette semaine, j’ai eu l’occasion d’accomplir un défi qui consistait à développer un jeu de notre choix dans une techno de notre choix en 1h seulement. Un petit gamejam quoi. J’ai choisi de partir sur un shooter top-view comme jeu, et sur Löve2D en techno, le framework de dev de jeu en Lua le plus mignon de tous les temps. Vous pouvez voir le résultat sur la vidéo au dessus, c’est pas fantastique, mais bon on fait pas des miracles.
Mais techniquement, comment est-ce que ça se passe? Il faut savoir que votre hôte est un noob complet en Lua, à savoir qu’il a tout apprit en 10 minutes sur internet pour les besoins du défi. Ce qui donne du code sans doute pas très propre. La structure du projet est par exemple plate, aucun dossier, tout à la racine. Même la seule et unique ressource externe que j’utilise est dans la racine, pour dire. Dans le fonctionnement, Löve2D appelle le fichier conf.lua tout d’abord pour setter les propriétés de la fenêtre, puis lance main.lua dans lequel on aura pris soin de surcharger les fonctions de base de Löve2D.
- function love.load()
- – load code
- end
- function love.update(dt)
- – update code
- end
- function love.draw()
- – draw code
- end
Le fonctionnement est simplissime : on charge nos ressources (love.load) puis la boucle de jeu se lance en exécutant d’abord la logique (love.update) puis le dessin (love.draw). Reste que je viens d’un background C/C++, donc beaucoup de choses m’ont perturbé dans cette syntaxe dont je ne me sers pas tous les jours. Tout d’abord, le fait qu’on ne soit pas obligé de mettre des points virgule en fin de ligne de code, mais qu’on puisse cependant faire des sauts de ligne pour avoir un affichage plus net de son code. Ceci est valide par exemple, et j’ai eu du mal à m’y faire :
- love.graphics.line(self.position.x, self.position.y,
- self.position.x + self.direction.x*4, self.position.y + self.direction.y*4)
De la même manière, lua est codé en C et donc ne contient pas spécialement de logique orientée objet, donc pas de classe à proprement parlée. Il faut donc appréhender le mindfuck que représentent les métatables et tout ce que ça implique par derrière pour créer des « usines » d’objets pour les tirs et les ennemies. Un petit exemple pour vous montrer comment ça fonctionne :
- Player = {}
- Player.__index = Player
- function Player.create(x, y)
- local player = {}
- setmetatable(player,Player)
- — attributs du player
- return player
- end
- function Player:DoSomething(withArgs)
- — votre code
- end
- plyr = Player.create(10,20)
- plyr:DoSomething(42)
Ligne par ligne maintenant.
On créé un table Player vide.
On indique que l’index de cette table est elle même. C’est la partie la plus importante dans la création de métatables. En effet, les métatables fournissent des pseudo fonctions qui permettent de « rediriger » vers une action particulière à leur appel. __index permet quant à lui de dire que pour tout appel d’élément du tableau de type Player non reconnu, merci de se référer à la métatable Player. On verra son application plus bas.
On déclare la fonction « constructeur » qui va nous permettre de créer nos objets de type Player. On y déclare un tableau local vide, et on lui assigne la métatable Player. C’est là que se créé l’objet en question, le lien qui permettra donc d’avoir un « type » générique. Si l’objet doit posséder des attributs, comme sa position, sa vie, etc… c’est aussi à cet endroit qu’on le fait, par principe de lisibilité. N’oubliez pas que par défaut en Lua, toute variable est globale, si vous avez l’intention de restreindre les portées, il faudra le préciser explicitement.
- function Player.create(x, y)
- local player = {}
- setmetatable(player,Player)
- — attributs du player
- return player
- end
On déclare une fonction de test DoSomething, et on teste la « classe ». On créé donc un objet lié à la métatable Player, et on teste la fonction DoSomething sur l’objet plyr.
- function Player:DoSomething(withArgs)
- — votre code
- end
- plyr = Player.create(10,20)
- plyr:DoSomething(42)
Les plus pointilleux d’entre vous auront sans doute remarqué que DoSomething est déclarée en utilisant les deux points plutôt qu’une point. La différence est simple, les deux points créent implicitement une variable self pour accéder facilement à ses attributs et autres fonctions. Le point va nécessiter d’expliciter cette variable self, ce qui est un peu plus contraignant. On considère donc que les « méthodes » de classe sont avec des points, et les « méthodes » d’instance sont avec les deux points.
Voilà donc les petits détails qui font de lua une technologie fort surprenante. Concernant Löve2D, c’est pas bien compliqué, et je vous laisse le soin de regarder la documentation sur leur wiki. Si jamais ça vous intéresse, Love & Guns, le petit jeu que j’ai codé est disponible sur mon Github pour expérimentations, apprentissages ou autres trucs dégueulasses que vous pouvez faire avec du code.
Sur ce, bisous bisous et joyeux noël.
Ah merde, c’est pas ça.
Tuxic

