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 tas 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 montre 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 l’aurons, il se déplacera un peu plus vite jusqu’à ce que vous le manquiez. Le jeu sera fini et vous redémarrerez une autre partie.
Nous allons utiliser des images. Vous êtes libre d’utiliser les votre :
Ces images sont faites 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 rappels et chargeons la lib 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 too 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 notre largeur quand nous vérifions si nous heurtons 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 too 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 sur de ne pas vouloir faire une superclasse ? »
Ok, laissez moi vous expliquer ça très rapidement. Nous rendons ce jeu « rapide et sale ». 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 tuto soient aussi courts et compacts que possible. En vous faisant faire une superclasse nous allons rendre ce chapitre encore plus long. Tout cela a été 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 qu’elle sera la valeur de la vitesse ?
Elle ne devrait plus être 100 mais -100.
Donc devrions nous mettre self.speed = -100 ?
Bien sur 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 donc elle deviendra -speed.
Et si elle heurte le mur gauche ?
À ce point, la vitesse est un nombre négatif et et nous devons la transformer en un nombre positif. Comment pouvons-nous faire ça ?
Hé bien multiplier 2 nombres négatifs entre eux donne un nombre positif donc si nous disons que la vitesse, laquelle est négatif actuellement, 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 chargons 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 ont besoin d’être vrai pour s’assurer qu’une collision a eu lieu ?
À la place 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 bullets 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 frapper l’ennemi alors qu’il se déplace sur la gauche, le jeu ralenti. C’est parce que la vitesse de l’ennemi est à ce moment un chiffre négatif donc en incémentant le nombre, l’ennemi ira moins vite.
Pour fixer ça, nous avons besoin de savoir si la vitesse de l’ennemi est négative ou non :