Construire un jeu de coureur sans fin à partir de zéro Batailles de boss

Nous avons déjà parcouru un long chemin dans la construction de notre jeu de coureur sans fin. À ce stade de la série, vous devriez déjà avoir une expérience jouable et agréable, mais ce tutoriel vous apprendra comment ajouter une touche supplémentaire: les batailles de boss!

Notre jeu commence maintenant à ressembler à un vrai jeu! Nous avons un personnage contrôlable avec différents types d'obstacles générés de manière aléatoire, nous avons un défilement parrallax implémenté en trois couches différentes, et nous avons un système de score de base qui donne à nos joueurs un sentiment d'accomplissement. Jusqu'ici tout va bien. Maintenant, c’est peut-être suffisant pour le genre de jeu que vous concevez et c’est tout ce dont vous avez besoin. Cependant, supposons que vous vouliez donner du piment à votre jeu avec quelque chose de nouveau. Quelque chose comme… une bataille de boss !!! Bien que la plupart des jeux sans fin de parchemin n'aient pas de combat de boss, ce sera une bonne pratique de voir comment nous pourrions concevoir ce genre d'événement. Alors, commençons!

Vous remarquerez que nous suivons à nouveau le même format avec un ancien dossier dans le téléchargement joint contenant le projet entier que nous avons créé jusqu'à présent et un nouveau dossier contenant le projet après avoir terminé ce didacticiel. La première chose à faire est d’être sûr que les images se trouvent dans le bon dossier. Vous pouvez récupérer boss.png et bossSpit.png dans le nouveau dossier du fichier de téléchargement joint. Remarquez que le patron n'est pas animé et consiste en une seule image. Si vous voulez un boss animé et que vous avez oublié comment animer une image-objet dans Corona, reportez-vous au didacticiel relatif à l'animation d'une image-objet publié précédemment dans cette série..

Maintenant que nous les avons dans le même dossier que notre fichier main.lua, ouvrez main.lua dans votre éditeur de texte préféré. Je ne vais pas expliquer beaucoup de ce qui se passe ici (assurez-vous de lire les commentaires pour obtenir des astuces et de petites explications!), Car nous avons, à ce stade, déjà parlé de tout à plusieurs reprises et je suis sûr que vous ne le feriez pas. sautez dessus quand même. Cela nous aidera également à parcourir le didacticiel rapidement, comme tout ce que nous avons déjà fait ici, ce qui signifie que de nombreux changements sont nécessaires. Alors, commençons.

La première chose à faire est de charger nos images dans le jeu. Encore une fois, tout cela devrait sembler familier. Ajoutez ce code en haut où nous chargeons toutes les autres images. Assurez-vous simplement que bossSpits est déclaré avant d'essayer de mettre quelque chose dedans!

 boss local = display.newImage ("boss.png", 150, 150) boss.x = 300 boss.y = 550 boss.isAlive = false boss.health = 10 boss.goingDown = true boss.canShoot = false --spitCycle C’est la seule chose qui n’est pas auto-explantoire - chaque fois que nous déplaçons une pièce de base vers la droite de l'écran - nous mettons à jour le score par un. Maintenant, nous mettons également à jour le cycle --spite. Chaque fois que spitCycle est un multiple de trois, le chef tire sur son projectile. Cela ne fait que garder une trace - de cela pour nous! boss.spitCycle = 0 pour a = 1, 3, 1 bossSpit = display.newImage ("bossSpit.png") bossSpit.x = 400 bossSpit.y = 550 bossSpit.isAlive = faux bossSpit.speed = 3 bossSpits: insert ( bossSpit) fin

Ensuite, assurez-vous de les ajouter dans l'écran à côté des autres ajouts, un bon endroit pour les mettre serait juste avant d'insérer le collisionRect.

 screen: insert (boss) screen: insert (bossSpits)

Enregistrez-le et lancez-le. Allez-y et vérifiez-le dans la version iPhone 4 et vous devriez voir quelque chose comme ça:

Maintenant, leur faisons faire quelque chose. La façon dont nous allons gérer le patron est d’arriver au hasard dans le jeu, comme pour les autres événements que nous souhaitons que cela se produise à un moment donné. Pour cet exemple, nous allons définir un nombre faible afin que l'événement se rende rapidement à l'événement, mais vous voudrez probablement en faire un temps plus raisonnable dans votre jeu. Donc, ce qui va arriver, c’est chaque fois que votre monstre doit parcourir une distance égale à un multiple de 10. Le patron apparaîtra. En faisant apparaître le boss, nous faisons en sorte que le sol devienne un terrain plat. Nous empêchons également les fantômes et les murs de pointes de se reproduire de cette façon, il n’ya pas de distractions liées au combat! Quand il apparaîtra, il entrera dans la scène du haut et commencera à bouger en crachant de la chaleur en cherchant des boules jaunes… de la mort.!

Ainsi, lorsque le boss tire sur le joueur, celui-ci doit le tuer en lui tirant dessus dix fois. Le joueur peut également se défendre de la broche en tirant dessus. Donc, la stratégie de base pour gagner va sauter et spammer ses compétences de tir! Quelques autres choses à noter est que dans ce jeu, j'ai décidé de ne pas mettre à jour le score tant que le boss est en vie, de cette façon, le joueur est obligé de vaincre le boss pour continuer à obtenir des scores plus élevés. La dernière chose à faire avant que nous passions à autre chose, c’est que le patron soit prêt à tirer tous les trois jours. Cela a encore l'avantage que la difficulté s'adapte automatiquement à la partie. Il fournit également un moyen facile d'obtenir des photos cohérentes. Rien de trop fou, mais globalement, cela ajoute une belle tournure au jeu..

Afin de laisser plus de place au patron sur l'écran, j'ai déplacé le joueur un peu plus loin à l'écran. Je commence maintenant le héros comme suit:

 monstre.x = 60

Cela ouvrira un peu le niveau. La prochaine chose que nous devrions faire est d’aller de l’avant et de mettre nos fonctions à jour afin de mettre à jour le patron et sa réponse:

 function updateBoss () --check pour s'assurer que le boss n'a pas été tué si (boss.health> 0) puis --check pour voir si le patron doit changer de direction si (boss.y> 210), puis boss. goingDown = fausse fin si (boss.y < 100) then boss.goingDown = true end if(boss.goingDown) then boss.y = boss.y + 2 else boss.y = boss.y - 2 end else --if the boss has been killed make him slowly disappear boss.alpha = boss.alpha - .01 end --once the monster has been killed and disappear officially --kill him off and reset him back to where he was if(boss.alpha <= 0) then boss.isAlive = false boss.x = 300 boss.y = 550 boss.alpha = 1 boss.health = 10 inEvent = 0 boss.spitCycle = 0 end end function updateBossSpit() for a = 1, bossSpits.numChildren, 1 do if(bossSpits[a].isAlive) then (bossSpits[a]):translate(speed * -1, 0) if(bossSpits[a].y > monster.y) puis bossSpits [a] .y = bossSpits [a] .y - 1 extrémité si (bossSpits [a] .y < monster.y) then bossSpits[a].y = bossSpits[a].y + 1 end if(bossSpits[a].x < -80) then bossSpits[a].x = 400 bossSpits[a].y = 550 bossSpits[a].speed = 0 bossSpits[a].isAlive = false; end end end end

Avec ceux-ci, nous avons juste besoin de faire quelques ajustements à certaines de nos autres fonctions et de les ajouter à notre fonction update ():

 updateBossSpit () if (boss.isAlive == true), puis updateBoss () se termine

Ajoutez ceux-ci dans la fonction de mise à jour, puis allez à la fonction checkEvent () et voyez le code qui ressemble à ceci:

 if (inEvent> 0 et eventRun> 0) alors --ne rien faire d'autre

Juste en dessous de cette autre déclaration, videz tout ce qui était dedans et changez-le en ceci:

 --C'est ici que nous générons le patron tous les 10 blocs. Nous contrôlons également la santé du patron à partir d'ici si (boss.isAlive == false et que nous obtenons% 10 == 0), puis boss.isAlive = true boss.x = 400 boss.y. = -200 boss.health = 10 end --si le boss est en vie, laissez l'événement à 15 - cela empêchera les autres événements d'apparaître si (boss.isAlive == true) alors inEvent = 15 sinon --everything bas devrait être le même qu’il était avant check = math.random (100) if (check> 80 et check < 99) then inEvent = math.random(10) eventRun = 1 end if(check > 98) then inEvent = 11 eventRun = 2 end si (contrôle> 72 et contrôle < 81) then inEvent = 12 eventRun = 1 end if(check > 60 et vérifier < 73) then inEvent = 13 eventRun = 1 end end

Il ne devrait y avoir rien de trop fou là dedans. Si vous débutez en programmation, vous ne connaissez peut-être pas le symbole de module:%. Cela permet de prendre les chiffres que vous avez et de diviser le premier nombre par le second et de restituer le reste. Ainsi, si le score est 15, le score% 10 renverra 5, ce qui n’est pas 0, donc cela ne déclenchera pas l’événement du boss. Il en va de même pour tout nombre non multiple de 10. C'est ainsi que nous pouvons facilement contrôler le taux de fréquence d'apparition de quelque chose. La prochaine étape sera de retour dans updateBlocks (). Juste en dessous de la déclaration if qui dit:

 si ((blocs [a]). x < -40) then

Vous allez prendre la section scoreText et la placer à l'intérieur d'une déclaration if qui vérifie si le patron est en vie ou non (nous n'allons pas mettre à jour le score tant qu'il est en vie! Dans le cadre de la déclaration if, vous êtes va ajouter un autre qui donne au patron une partie de son comportement). Faites en sorte que cette section ressemble à ceci:

 --met à jour le score uniquement si le boss n'est pas en vie si (boss.isAlive == false), puis score = score + 1 scoreText.text = "score:"… score scoreText: setReferencePoint (display.CenterLeftReferencePoint) scoreText.x = 0 scoreText. y = 30 sinon - le patron crache tous les trois blocs. boss.spitCycle = boss.spitCycle + 1 if (boss.y> 100 et boss.y < 300 and boss.spitCycle%3 == 0) then for a=1, bossSpits.numChildren, 1 do if(bossSpits[a].isAlive == false) then bossSpits[a].isAlive = true bossSpits[a].x = boss.x - 35 bossSpits[a].y = boss.y + 55 bossSpits[a].speed = math.random(5,10) break end end end end if(inEvent == 15) then groundLevel = groundMin end

Toujours rien de terriblement difficile, comme je l’ai dit, il ne devrait pas y avoir beaucoup de nouveau matériel ici. La partie suivante est un peu la même chose et ensuite nous avons terminé. La prochaine chose que nous allons ajouter est la vérification de la détection des collisions pour détecter les destructions. Commençons par l'explosion du monstre, nous devons vérifier à la fois le crachat du boss et le monstre lui-même..

Ajoutez ces lignes à la fonction updateBlasts ():

 --vérifier les collisions avec le patron si (boss.isAlive == true) puis si (souffle [a] .y - 25> boss.y - 120 et souffle [a]. 25 +25 < boss.y + 120 and boss.x - 40 < blasts[a].x + 25 and boss.x + 40 > Explosions [a] .x - 25) puis Explosions [a] .x = 800 Explosions [a] .y = 500 Explosions [a] .isAlive = False - Tout est identique, 1 seul impact ne tue pas le chef, donc enlever un peu de santé boss.health = boss.health - 1 end end - vérifier les collisions entre les explosions et le bossSpit pour b = 1, bossSpits.numChildren, 1 do if (bossSpits [b] .isAlive == true) puis si (explosions [a] .y - 20> bossSpits [b] .y - 120 et explosions [a] .y + 20 < bossSpits[b].y + 120 and bossSpits[b].x - 25 < blasts[a].x + 20 and bossSpits[b].x + 25 > explosions [a] .x - 20) puis exécute des explosions [a] .x = 800 explosions [a] .y = 500 explosions [a] .isAlive = faux bossSpits [b] .x = 400 bossSpits [b] .y = 550 bossSpits [b] .isAlive = faux bossSpits [b] .speed = 0 fin fin fin

Une autre détection de collision est nécessaire et consiste à vérifier le comportement du boss contre notre joueur. Ajoutez ceci à la fonction checkCollisions ():

 --assurez-vous que le joueur n'a pas été touché par la broche du patron! pour a = 1, bossSpits.numChildren, 1 do if (bossSpits [a] .isAlive == true) alors if ((((monster.y-bossSpits [a] .y)))<45)) and ((  ((monster.y-bossSpits[a].y))>-45)) et (((((monster.x-bossSpits [a]. X))> - 45))) puis --arrêtez le monstre speed = 0 monster.isAlive = false - cela met simplement en pause le monstre d'animation actuel: pause () gameOver.x = display.contentWidth * .65 gameOver.y = display.contentHeight / 2 end end end

Encore une fois, cela devrait sembler assez familier. La dernière chose que nous devons faire est d'aller dans notre fonction restartGame () et de la mettre à jour avec les informations du patron avec sa salive..

Notez également que, comme nous avons modifié la position de monster.x dans ce didacticiel, il est important qu'au lieu de réinitialiser le monstre.x à 110, nous devrions maintenant mettre à jour le monster.x pour refléter sa nouvelle position, à savoir 60.

 --réinitialiser le boss boss.isAlive = false boss.x = 300 boss.y = 550 - résout le crachat du boss pour a = 1, bossSpits.numChildren, 1 faire bossSpits [a] .x = 400 bossSpits [a] .y = 550 bossSpits [a] .isAlive = false end

Enregistrez-le, lancez-le et profitez de la nouvelle addition au jeu! Vous devriez être en train de faire bouger quelque chose comme ça maintenant:

et

Comme je l'ai dit à plusieurs reprises, il n'y avait pas vraiment beaucoup de contenu fou, mais je pensais que ce serait un bon exercice pour vous montrer à quel point il est facile de mettre à jour votre jeu avec du nouveau contenu. En outre, il montre de nouvelles approches pour ajouter des événements afin qu'ils soient plus sollicités que aléatoires. La plupart de ces types de jeux implémenteront probablement un mélange des deux. Un bon exemple de jeu qui réussit bien est bit.trip runner. Vérifiez-le pour avoir une bonne idée de ce qui peut être fait avec ce style de jeu. Si nous revoyons quelque chose de trop vite et que vous avez des questions, dites-le-moi, sinon préparez-vous à rendre notre jeu un peu mieux organisé la prochaine fois avec un nouveau système de menus qui rendra le jeu complet. Merci de suivre et à la prochaine fois!