Utilisons tout ce que nous avons appris jusqu’ici pour créer un jeu simple. Vous pouvez lire tout ce que vous voulez sur la programmation, mais pour l’apprendre réellement, vous devez pratiquer.
Un jeu est essentiellement un ensemble de problèmes que vous devez résoudre. Lorsque vous demandez à un programmeur expérimenté de faire un PONG, il ne cherchera pas comment le faire. Il sait déjà comment le diviser en plusieurs problèmes séparés et comment les résoudre.
Ce chapitre est là pour vous montrer comment diviser un jeu en plusieurs tâches.
Le jeu que nous allons faire est simple :
un ennemi rebondit contre les murs et nous devons l’abattre. Chaque fois que nous le toucherons, il se déplacera un peu plus vite jusqu’à ce que vous le manquiez. Le jeu sera alors fini et vous redémarrerez une autre partie.
Le jeu que l’on va coder
Nous allons utiliser des images. Vous êtes libre d’utiliser les vôtres :
Ces images sont créées par Kenney, qui crée beaucoup d’éléments « gratuits » que tout le monde peut utiliser pour ses jeux.
Commençons avec les 3 fonctions de rappel et chargeons la bibliothèque classic, celle simulant les classes.
--! file: player.luafunctionPlayer:update(dt)iflove.keyboard.isDown("left")thenself.x=self.x-self.speed*dtelseiflove.keyboard.isDown("right")thenself.x=self.x+self.speed*dtend--Get the width of the windowlocalwindow_width=love.graphics.getWidth()--If the x is too far to the left then..ifself.x<0then--Set x to 0self.x=0--Else, if the x is too far to the right then..elseifself.x>window_widththen--Set the x to the window's width.self.x=window_widthendend
Oups, notre joueur peut encore sortir sur la droite. Nous avons besoin d’inclure sa largeur quand nous vérifions s’il heurte le mur de droite :
functionPlayer:new()self.image=love.graphics.newImage("panda.png")self.x=300self.y=20self.speed=500self.width=self.image:getWidth()endfunctionPlayer:update(dt)iflove.keyboard.isDown("left")thenself.x=self.x-self.speed*dtelseiflove.keyboard.isDown("right")thenself.x=self.x+self.speed*dtend--Get the width of the windowlocalwindow_width=love.graphics.getWidth()--If the left side is too far to the left then..ifself.x<0then--Set x to 0self.x=0--Else, if the right side is too far to the right then..elseifself.x+self.width>window_widththen--Set the right side to the window's width.self.x=window_width-self.widthendend
Maintenant que le problème est résolu, notre joueur ne peut plus sortir de la fenêtre.
Tâche: Créer un ennemi mobile
Créons la classe Enemy en créant un nouveau fichier appelé enemy.lua et entrez le code suivant :
« Cela devient très similaire à notre classe joueur. Êtes-vous sûr de ne pas vouloir faire une superclasse ? »
Ok, laissez-moi vous expliquer ça très rapidement. Nous créons ce jeu de façon « rapide et simple ». Ce chapitre porte sur un jeu fonctionnel, pas sur l’efficacité du code. Ça sera pour un autre chapitre.
Oui, avoir un code propre est important, mais ce n’est pas aussi important que de savoir comment faire un jeu. Je souhaite que ces tutoriels soient aussi courts et compacts que possible. En vous faisant créer une superclasse, nous allons rendre ce chapitre encore plus long. Cela dit, je vous encourage à améliorer le code à la fin de ce chapitre.
Revenons maintenant à notre code. Notre ennemi s’arrête contre le mur, mais nous voulons qu’il rebondisse. Comment allons-nous faire cela ?
Il heurte le mur de droite et ensuite ?
Il devrait se déplacer dans une autre direction. Comment faisons-nous pour qu’il aille dans une autre direction ?
En changeant la valeur de la vitesse. Et quelle sera la valeur de la vitesse ?
Elle ne devrait plus être 100 mais -100.
Donc devrions-nous mettre self.speed = -100 ?
Bien sûr que non, parce que comme je l’ai dit auparavant, nous rendrons l’ennemi de plus en plus rapide quand nous le toucherons. À la place, nous devrions inverser la valeur de la vitesse pour qu’elle devienne -speed.
Et s’il heurte le mur gauche ?
À ce point, la vitesse est un nombre négatif et nous devons la transformer en un nombre positif. Comment pouvons-nous faire ça ?
Eh bien, multiplier 2 nombres négatifs entre eux donne un nombre positif. Donc si nous disons que la vitesse, laquelle est actuellement négative, devient -speed, elle deviendra un nombre positif :
La balle devrait se déplacer verticalement au lieu d’horizontalement :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--We pass the x and y of the player.functionBullet:new(x,y)self.image=love.graphics.newImage("bullet.png")self.x=xself.y=yself.speed=700--We'll need these for collision checkingself.width=self.image:getWidth()self.height=self.image:getHeight()endfunctionBullet:update(dt)self.y=self.y+self.speed*dtendfunctionBullet:draw()love.graphics.draw(self.image,self.x,self.y)end
Maintenant, nous avons besoin de tirer des balles. Dans le main.lua, chargeons le fichier et créons une table :
Nous donnons au joueur une fonction qui crée des balles quand la barre d’espace est enfoncée :
1
2
3
4
5
6
7
8
--! file: player.luafunctionPlayer:keyPressed(key)--If the spacebar is pressedifkey=="space"then--Put a new instance of Bullet inside listOfBullets.table.insert(listOfBullets,Bullet(self.x,self.y))endend
Et nous avons besoin d’appeler cette fonction dans la fonction de rappel love.keypressed :
Vous souvenez-vous toujours comment faire ?
Vous souvenez-vous des 4 conditions qui doivent être vraies pour s’assurer qu’une collision a eu lieu ?
Au lieu de retourner vrai ou faux, nous incrémentons la vitesse de l’ennemi. Nous ajoutons la propriété dead à la balle que nous utiliserons pour la supprimer de la liste :
Maintenant, nous avons besoin d’appeler checkCollision dans main.lua :
1
2
3
4
5
6
7
8
9
10
11
functionlove.update(dt)player:update(dt)enemy:update(dt)fori,vinipairs(listOfBullets)dov:update(dt)--Each bullet checks if there is collision with the enemyv:checkCollision(enemy)endend
Maintenant, nous avons besoin de détruire les balles qui sont mortes :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
functionlove.update(dt)player:update(dt)enemy:update(dt)fori,vinipairs(listOfBullets)dov:update(dt)v:checkCollision(enemy)--If the bullet has the property dead and it's true then..ifv.deadthen--Remove it from the listtable.remove(listOfBullets,i)endendend
La dernière chose à faire est de redémarrer le jeu quand nous manquons l’ennemi. Nous avons besoin de savoir si la balle est en dehors de l’écran :
1
2
3
4
5
6
7
8
9
10
--! file: bullet.luafunctionBullet:update(dt)self.y=self.y+self.speed*dt--If the bullet is out of the screenifself.y>love.graphics.getHeight()then--Restart the gamelove.load()endend
Testons tout ça.
Vous remarquerez peut-être que lorsque vous frappez l’ennemi alors qu’il se déplace vers la gauche, le jeu ralentit. C’est parce que la vitesse de l’ennemi est à ce moment un chiffre négatif, donc en incrémentant le nombre, l’ennemi ira moins vite.
Pour corriger ça, nous avons besoin de savoir si la vitesse de l’ennemi est négative ou non :