Dans la partie précédente de cette série, nous avions le vaisseau du joueur en mouvement, les envahisseurs en mouvement et la détection du moment où une balle du joueur avait touché un envahisseur. Dans cette dernière partie de la série, les envahisseurs attaqueront le joueur, géreront les niveaux et ajouteront la possibilité pour le joueur de mourir..
De temps en temps, l'un des envahisseurs tire une balle. Nous allons utiliser une minuterie pour accomplir cela. Ajoutez le code suivant à gamelevel.lua.
function fireInvaderBullet () if (#invadersWhoCanFire> 0) alors local randomIndex = math.random (#invadersWhoCanFire) local randomInvader = invadersWhoCanFire [randomIndex] local tempInvaderBullet = display.newImage ("laser.png", emplacement). invaderSize / 2) tempInvaderBullet.name = "invaderBullet" scene.view: insert (tempInvaderBullet) physics.addBody (tempInvaderBullet, "dynamique") tempInvaderBullet.gravityScale = 0 tempInvaderBullet.isBullet = true tempInvaderBullet.isSenseur table.insert (invaderBullets, tempInvaderBullet) else levelComplete () end end
Dans cette fonction, nous vérifions d’abord si le envahisseursWhoCanFire
La table contient au moins un élément. Si c'est le cas, nous exécutons le code dans l'instruction if. Sinon, cela signifie que le niveau est terminé et nous invoquons le niveau complet
une fonction.
Il y aura toujours au moins un envahisseur qui peut tirer une balle jusqu'à ce que vous tuiez le dernier envahisseur, à quel point le envahisseursWhoCanFire
la table sera vide.
À l'intérieur de l'instruction if, nous générons un nombre aléatoire randomIndex
en fonction du nombre d'articles dans le envahisseursWhoCanFire
table. Nous choisissons ensuite cet article, randomInvader
, du envahisseursWhoCanFire
table.
Nous créons une image de balle, lui donnons une prénom
propriété afin que nous puissions l'identifier ultérieurement, l'insérer dans la scène et définir les mêmes propriétés que nous avons définies pour la balle du lecteur. Enfin, nous insérons la balle dans le invaderBullets
table afin que nous puissions le référencer plus tard.
Nous devons maintenant configurer la minuterie. Ajouter ce qui suit au scène: spectacle
méthode.
scène de la fonction: show (événement) if (phase == "fait") puis --SNIP-- Durée: addEventListener ("collision", onCollision) invaderFireTimer = timer.performWithDelay (1500, fireInvaderBullet, -1) end end
Toutes les 1500 millisecondes fireInvaderBullet
est invoqué. Notez que le dernier paramètre que nous passons est -1
, ce qui signifie que la minuterie se répète pour toujours. Chaque fois que vous créez une minuterie qui se répète éternellement, vous devriez éventuellement l'annuler. Nous faisons cela dans lescène: cacher
fonctionne comme indiqué ci-dessous.
scène de fonction: masquer (événement) si (phase == "sera") puis --SNIP-- Durée: removeEventListener ("collision", onCollision) timer.cancel (invaderFireTimer) end end
Comme les balles du joueur, les balles des envahisseurs sortiront de l'écran et continueront à bouger, occupant une mémoire précieuse. Pour remédier à cela, nous les supprimons comme nous l'avons fait avec les balles du joueur..
function checkInvaderBulletsOutOfBounds () if (#invaderBullets> 0), puis pour i = # invaderBullets, 1, -1 do if (invaderBullets [i] .y> display.contentHeight), puis pour invaderBullets [i]: removeSelf () invaderBullets [i] = nil table.remove (invaderBullets, i) fin fin fin fin
Ce code est très similaire à vérifier si les puces du joueur sont hors limites, je ne discuterai donc pas de son implémentation en détail.
L'étape suivante consiste à détecter si la balle d'un envahisseur a atteint le joueur. Ajoutez le code suivant au onCollision
une fonction.
function onCollision (event) if (event.phase == "commencé") puis --SNIP-- if (event.object1.name == "player" et event.object2.name == "invaderBullet"), puis table.remove (invaderBullets, table.indexOf (invaderBullets, event.object2)) event.object2: removeSelf () event.object2 = nil si (playerIsInvincible == false) puis killPlayer () end retour end end if (event.object1.name == " invaderBullet "et event.object2.name ==" player ") puis table.remove (invaderBullets, table.indexOf (invaderBullets, event.object1)) event.object1: removeSelf () event.object1 = nil si (playerIsInvincible == false ) puis killPlayer () end retour end end end end
Comme avant, on ne sait pas quel objet event.object1
et event.object2
sera donc nous utilisons deux déclarations if pour vérifier les deux situations. Nous retirons la balle de l'envahisseur du invaderBullets
tableau, retirez-le de l'écran et réglez-le sur néant
. Si le joueur n'est pas invincible, on le tue.
Lorsque nous tuons le joueur, nous lui donnons un court temps d'invincibilité. Cela donne à l'utilisateur le temps de se concentrer à nouveau sur le jeu. Si la nombre de vies
variable est égale à 0
, nous savons que le jeu est terminé et la transition à la début scène où l'utilisateur peut commencer un nouveau jeu.
fonction killPlayer () numberOfLives = numberOfLives- 1; if (numberOfLives <= 0) then gameData.invaderNum = 1 composer.gotoScene("start") else playerIsInvincible = true spawnNewPlayer() end end
le spawnNewPlayer
Cette fonction permet au lecteur d’entrer et de disparaître en fondu pendant quelques secondes. C'est un bel effet de faire savoir à l'utilisateur que le vaisseau est temporairement invincible..
function spawnNewPlayer () local numberOfTimesToFadePlayer = 5 local numberOfTimesPlayerHasFaded = 0 fonction locale fadePlayer () player.alpha = 0; transition.to (player, time = 400, alpha = 1,)
Nous utilisons une fonction locale, fadePlayer
, qui utilise la bibliothèque de transition pour modifier le alpha
valeur de la joueur
. Nous gardons une trace de combien de fois le joueur
s'est évanouie et a mis l'invincibilité du joueur à faux
une fois que nous atteignons le numberOfTimesToFadePlayer
. Nous utilisons une minuterie pour appeler le fadePlayer
fonctionner pour cependant plusieurs fois numberOfTimesToFadePlayer
est égal à.
Exécutez le jeu pour tester cela. le joueur
devrait mourir quand la balle d'un envahisseur frappe le navire. Si trois balles touchent le navire, vous devriez être conduit au début scène où vous pouvez commencer un nouveau jeu.
Pour que cela soit plus facile à tester, commentez l'appel à moveInvaders
dans le gameLoop
fonctionne comme indiqué ci-dessous.
fonction gameLoop () checkPlayerBulletsOutOfBounds () --moveInvaders () checkInvaderBulletsOutOfBounds () end
Si vous avez réussi à tuer chaque envahisseur, le jeu aurait appelé le niveau complet
fonction, qui n'existe pas encore. Laisse réparer ça. Ajouter le bloc de code suivant.
fonction levelComplete () gameData.invaderNum = gameData.invaderNum + 1 if (gameData.invaderNum <= gameData.maxLevels) then composer.gotoScene("gameover") else gameData.invaderNum = 1 composer.gotoScene("start") end end
Nous incrémentons gameData.invaderNum
et, s'il est inférieur à gameData.maxLevels
, nous passons au jeu terminé scène. Sinon, le joueur a terminé tous les niveaux et nous réinitialisons gameData.invaderNum
à 1. Nous passons au début scène où le joueur peut commencer un nouveau jeu.
Un moyen simple de tester cela consiste à commenter l'appel à moveInvaders
dans le gameLoop
fonction et utilisez les boutons pour déplacer le navire. Si cela reste trop difficile, vous pouvez également commenter les deux appels à killPlayer
dans le onCollision
méthode.
Ajoutez le code suivant à gameover.lua mettre en œuvre la scène game over.
compositeur local = require ("composer") scène locale = composer.newScene () starFieldGenerator local = require ("starfieldgenerator") local pulsatingText = require ("pulsatingtext") local nextLevelButton local fonction starGenerator: create (événement) groupe local = auto .view starGenerator = starFieldGenerator.new (200, groupe, 5) envahisseurs locauxText = pulsatingText.new ("LEVEL COMPLETE", display.contentCenterX, display.contentCenterY-200, "Conquête", 20, groupe) invadersText: setColor (1, 1, 1) invadersText: pulsate () nextLevelButton = display.newImage ("next_level_btn.png", display.contentCenterX, display.contentCenterY) groupe: insert (nextLevelButton) fonction de fin scène: show (événement) phase locale = événement.pha compositeur .removeScene ("gamelevel") if (phase == "did"), puis nextLevelButton: addEventListener ("tap", startNewGame) Runtime: addEventListener ("enterFrame", starGenerator) end end scène de fonction: masquer (événement) phase locale = événement .phase if (phase == "will") puis Runtime: removeEventListener ("enterF rame ", starGenerator) nextLevelButton: removeEventListener (" tap ", startNewGame) end end fonction startNewGame () composer.gotoScene (" gamelevel ") scène finale: addEventListener (" créer ", scène) scène: addEventListener (" show ", scène) scene: addEventListener ("hide", scene) retourne la scène
Ce code est très similaire à la début scène de sorte que vous devriez être au courant maintenant.
La dernière vérification de collision que nous devons effectuer est une collision entre le joueur et l'un des envahisseurs. Ajoutez le bloc de code suivant au onCollision
méthode que nous avons vue plus tôt.
function onCollision (event) --SNIP-- if (event.phase == "commencé") puis --SNIP-- if (event.object1.name == "player" et event.object2.name == "invader" ) then numberOfLives = 0 killPlayer () end if ((event.object1.name == "invader" et event.object2.name == "player"), alors numberOfLives = 0 killPlayer () end end
Comme d'habitude, nous devons vérifier les deux situations de collision. Nous avons mis le nombre de vies
à 0 et appeler killPlayer
. En mettant nombre de vies
à 0 et invoquer killPlayer
, le jeu est terminé et le jeu passe à la début scène.
Ceci termine notre jeu, mais je vous suggère d’essayer de développer le jeu avec quelques fonctionnalités supplémentaires. Par exemple, vous pouvez afficher la vie du joueur dans un HUD..
J'ai également inclus un graphique UFO dans les fichiers source. Vous pouvez essayer de faire apparaître un OVNI au hasard et si le joueur le frappe avec une balle, donnez-lui une vie supplémentaire.
Si vous avez besoin d'aide avec ces concepts, consultez ma série de jeux de combat d'avion sur Tuts+.
Si vous avez suivi cette série, vous devriez maintenant avoir un jeu entièrement fonctionnel similaire aux Space Invaders d’origine. Développez-le et faites-le vôtre. J'espère que vous avez trouvé ce tutoriel utile et que vous avez appris de nouvelles techniques. Merci d'avoir lu.