Construire un jeu de coureur sans fin à partir de zéro mouvement de fond

Bienvenue dans le deuxième tutoriel de notre série sur la création d'un jeu de course à partir de zéro avec le SDK Corona. Dans cette section, nous allons voir comment obtenir rapidement un niveau de base de défilement de l’arrière-plan. Ouvrez votre éditeur de texte et commençons!


Conditions préalables

Si vous n'avez pas encore vu le premier tutoriel de cette série, vérifiez-le rapidement avant de passer à celui-ci. Si vous avez un peu d’expérience en codage, vous pourrez parcourir rapidement le premier tut, mais si vous ne l’avez pas encore fait, vous devriez perdre du temps pour vous familiariser avec les bases de la programmation avec Lua et le SDK Corona.


Configuration du projet

La première chose à couvrir est donc le fichier build.settings. Ce fichier doit être placé dans le même dossier que le fichier main.lua et nous permet de définir certaines de nos spécifications d’application. Désormais, en fonction de la plate-forme sur laquelle vous travaillez (Android ou iOS), votre fichier build.settings sera utilisé pour définir différentes choses. Par exemple, les développeurs Android doivent gérer le fichier manifeste de leurs applications et leurs autorisations, tandis que les développeurs iOS doivent se soucier de leur fichier * .plist. Le fichier build.settings est l'emplacement où un grand nombre de ces paramètres de niveau d'application seront gérés. L’un des avantages du kit de développement Corona SDK est que nous pouvons combiner nos informations de build.settings pour Android et iOS dans le même fichier build.settings. Ainsi, si vous travaillez sur les deux types de périphériques, vous n'avez pas à gérer plusieurs fichiers build.settings. Pour les besoins actuels, nous n'utiliserons le fichier build.settings que pour définir l'orientation de notre périphérique. Donc, créez un nouveau fichier appelé build.settings dans le même dossier que celui où vous allez avoir votre fichier main.lua et mettez-y ce code:

 --Notez que vous pouvez également utiliser les commentaires dans cette section settings = orientation = default = "landscapeRight", supporté = "landscapeRight", "landscapeLeft",,

Cela nous donne un appareil orienté paysage sur les appareils iOS et Android. Le code est assez simple et nous allons passer en revue plus de paramètres que vous voudrez utiliser dans les prochains tutoriels, mais pour le moment, cela devrait être tout ce dont nous avons besoin pour avancer. Si vous voulez aller plus loin, vous pouvez trouver toutes les options de build.settings ici. Pour vous assurer que le fichier fonctionne, faisons un test rapide dans le simulateur. Ouvrez votre fichier main.lua et mettez ce code là:

 --Cette ligne supprimera la barre d'état en haut de l'écran. Certaines applications peuvent être conservées, mais pas pour les jeux! display.setStatusBar (display.HiddenStatusBar) testRect local = display.newRect (0,0,50,50) testRect: setFillColor (150,0,0);

Donc, après avoir mis tout cela ensemble, si votre build.settings est au bon endroit, vous devriez avoir quelque chose qui ressemble à ceci:

Si l'appareil est vertical (mode portrait) et ne repose pas sur le côté comme ci-dessus (mode paysage), il se produit alors un problème. Cependant, espérons que ce n'est pas le cas car le code ci-dessus est tout ce qu'il y a à faire. Donc, maintenant que cela n’est plus possible, nous pouvons commencer à faire fonctionner notre jeu. L'objectif de chacun des tutoriels est de créer une nouvelle section de travail. Chacun s'appuiera sur le dernier, mais après chaque itération, vous aurez quelque chose qui devrait être jouable..


Ajout d'un fond

La première chose que nous allons vouloir faire est de faire bouger notre niveau. Nous allons avoir plusieurs couches dans notre jeu qui vont défiler à différents niveaux de vitesse. Cela va nous donner l’illusion de ce que nous appelons le défilement de parallaxe. Lorsque vous exécutez le programme dans le simulateur, continuez et sélectionnez iPhone pour l'instant (si ce n'est déjà fait). Changer cela en allant à Fenêtre> Afficher en tant que> iPhone dans le simulateur. Les actifs ont été conçus pour un périphérique fonctionnant à une résolution de 480x320px. Il existe bien sûr des moyens de s’assurer que cela fonctionne pour toutes les résolutions, mais pour les besoins de nos tests, il ne reste plus qu’à utiliser le simulateur iPhone. Allez-y et mettez ce code dans votre programme:

 --supprime la barre d’affichage en haut de l’écran display.setStatusBar (display.HiddenStatusBar) - ajoute une image à notre jeu centrée sur les coordonnées x et y local backbackground = display.newImage ("images / background.png") backbackground. x = 240 backbackground.y = 160 backgroundfar local = display.newImage ("images / bgfar1.png") backgroundfar.x = 480 backgroundfar.y = 160

Pour que cela fonctionne, utilisez les images que j'ai fournies. Pour que le code fonctionne «tel quel», vous devez placer les images dans un dossier appelé images. Le dossier images doit se trouver dans le même dossier que vos fichiers main.lua et build.settings. Une fois que vous faites cela, vous devriez obtenir un écran qui ressemble à ceci:

Remarquez comment l'image d'arrière-plan est devant l'arrière-plan? Imaginez que vous empilez plusieurs assiettes les unes sur les autres. Plus vous empilez, plus vous couvrez cette première assiette, vous commencez par tout empiler. Ceci est également vrai pour les images et le texte que vous avez insérés dans votre code. Chaque fois que vous souhaitez ajouter quelque chose à l'écran, sauf indication contraire, cet élément ajouté couvrira tout ce que vous avez déjà empilé. Continuons et empilons encore quelques choses sur notre écran. Ajoutez ceci à votre code sous les autres lignes:

 backgroundnear1 local = display.newImage ("images / bgnear2.png") backgroundnear1.x = 240 backgroundnear1.y = 160 backgroundnear2 = display.newImage ("images / bgnear2.png") backgroundnear2.x = 760 backgroundnear2.y = 160

Maintenant, nous devrions avoir une autre couche superposée comme ceci:

Maintenant, quand vous regardez ceci, vous remarquerez que même si nous avons ajouté 2 instances de bgnear2.png, une seule d’entre elles apparaît à l’écran. La raison pour laquelle nous faisons les choses deviendra un peu plus évident quand nous commencerons à tout bouger. Pour l'instant, passez de l'iPhone 4 à l'affichage comme vous le faisiez auparavant. Parce que nous avons conçu nos images autour de la résolution d'un iPhone sans rétine (par exemple 480x320px), si nous passons à une résolution supérieure, telle que l'iPhone 4 (par exemple 960x640px), tout se réduit et nous pouvons voir davantage de ce qui se passe. Changez pour la résolution de l'iPhone 4 et vous devriez voir ceci maintenant:

Chaque fois que nous voulons voir ce qui se passe, passer à une vue plus large sera très utile. Notez que le fait de ne pas voir quelque chose ne signifie pas que rien ne se passe. Maintenant que nous avons ces images d’arrière-plan, faisons-les bouger. En parcourant les didacticiels, je vais essayer de documenter tout ce qui se passe à l'intérieur du code lui-même. Par conséquent, si vous n'êtes pas sûr de ce qu'il se passe, assurez-vous de lire les commentaires dans le code! Maintenant, sous le code ajouté précédemment, ajoutez ceci:

 --la fonction de mise à jour contrôlera presque tout ce qui se passe dans notre jeu - elle sera appelée chaque image (30 images par seconde dans notre cas, valeur par défaut du SDK Corona) mise à jour de la fonction locale (événement) --updateBackgrounds appellera une fonction faite spécifiquement pour gérer le mouvement de fond updateBackgrounds () end function updateBackgrounds () --far mouvement de fond backgroundfar.x = backgroundfar.x - (.25) --near mouvement de fond backgroundnear1.x = backgroundnear1.x - (3) --if l'image-objet s'est éloignée de l'écran, déplacez-la de l'autre côté afin qu'elle se déplace si (backgroundnear1.x < -239) then backgroundnear1.x = 760 end backgroundnear2.x = backgroundnear2.x - (3) if(backgroundnear2.x < -239) then backgroundnear2.x = 760 end end --this is how we call the update function, make sure that this line comes after the --actual function or it will not be able to find it --timer.performWithDelay(how often it will run in milliseconds, function to call, --how many times to call(-1 means forever)) timer.performWithDelay(1, update, -1)

Lorsque vous l'exécutez, lancez-le d'abord alors que vous êtes toujours dans la vue iPhone 4. Cela vous permettra de voir ce qui se passe réellement avec tous les différents sprites que nous déplaçons. Une fois que vous avez examiné la vue dans cette vue, passez à l’affichage normal de l’iPhone afin de voir à quoi il ressemble vraiment. Avec tout cela, vous devriez maintenant avoir tout en mouvement! Maintenant, voici quelques points à examiner avant de poursuivre. Notez qu'il n'y a qu'une seule instance de backgroundfar, mais qu'il existe deux instances de backgroundnear? Ceci est quelque chose qui est complètement à vous. La raison pour laquelle il y en a deux, c'est parce que pour le fond plus proche (par exemple, les arbres qui passent), nous voulons que cela se répète encore et encore. Pour le fond, je voulais que ce soit quelque chose qui passe très lentement et ne se répète pas (par exemple, vous ne le ferez que pour des fonds très lointains, cela donne aux niveaux une sensation unique). C’est quelque chose que vous feriez quand votre niveau de défilement va s’arrêter. Si vous vouliez vraiment un scroller sans fin, vous voudriez adopter la même approche que celle que vous aviez utilisée pour le fond proche et mettre deux côte à côte. En plaçant deux côte à côte, ou trois, ou autant que vous le souhaitez, vous créez un monde apparemment grand avec des actifs très minimes. La seule chose à faire est de déplacer le sprite de l'autre côté de l'écran..

La prochaine chose que nous allons faire est d’ajouter du terrain. Cela va faire quelques pas de plus, mais nous allons ralentir et nous assurer que tout est mis au bon endroit. Si vous n'avez pas fait le premier tutoriel et que vous ne comprenez pas comment utiliser les groupes ou ce qu'ils sont, ce serait le bon moment pour le vérifier. Voici le code à insérer (placez-le juste en dessous du code où nous avons configuré backgroundnear2, avant la fonction de mise à jour):

 --créer un nouveau groupe pour contenir tous nos blocs locaux blocks = display.newGroup () --setup quelques variables que nous utiliserons pour positionner le sol local groundMin = 420 local groundMax = 340 local groundLevel = groundMin - cette boucle sera générée toutes vos pièces au sol, nous allons - faire 8 en tout. pour a = 1, 8, 1 do isDone = false - récupère un nombre aléatoire compris entre 1 et 2, c’est ce que nous allons utiliser pour décider quelle - texture utiliser pour nos sprites au sol. Cela nous donnera des pièces au sol aléatoires, de sorte qu'il semble que le sol continue éternellement. Vous pouvez avoir autant de textures différentes que vous le souhaitez. Plus vous en avez, plus il sera aléatoire, rappelez-vous simplement de - augmenter le nombre dans math.random (x) en fonction du nombre de textures que vous avez. numGen = math.random (2) newBlock local print (numGen) if (numGen == 1 et isDone == false), puis newBlock = display.newImage ("images / ground1.png") isDone = true end si (numGen == 2 et isDone == false) alors newBlock = display.newImage ("images / ground2.png") isDone = true end - maintenant que nous avons la bonne image pour le bloc que nous allons utiliser --pour lui attribuer des variables membres qui nous aidera à garder une trace de chaque bloc et à les placer où nous le voulons. newBlock.name = ("block" ... a) newBlock.id = a - car a est une variable en cours de modification à chaque exécution, nous pouvons affecter --values ​​au bloc en fonction de a. Dans ce cas, nous voulons que la position x soit - positionnée à la largeur d’un bloc. newBlock.x = (a * 79) - 79 newBlock.y = groundLevel blocs: insérer (newBlock) fin

Les commentaires dans le code devraient vous aider à comprendre ce que tout fait jusqu'à présent. Espérons que ce que vous regardez maintenant ressemble à ceci:

Maintenant, la dernière chose à faire est de commencer à faire bouger les blocs. Continuons et ajoutons le code pour cela. Mettez ce code après la fin de la fonction de mise à jour:

 function updateBlocks () pour a = 1, blocks.numChildren, 1 do if (a> 1), puis newX = (blocs [a - 1]). x + 79 sinon newX = (blocs [8]). x + 79 end si ((blocs [a]). x < -40) then (blocks[a]).x, (blocks[a]).y = newX, groundLevel else (blocks[a]):translate(-5, 0) end end end

Avant que quoi que ce soit ne bouge réellement, nous devons nous assurer que nous appelons réellement la fonction à partir de la fonction de mise à jour. Ainsi, dans la fonction de mise à jour située sous la ligne updateBackgrounds (), appelez la fonction updateBlocks (). Avec cela, nous devrions avoir tout en mouvement maintenant. Notez qu'au lieu de déplacer manuellement les blocs, nous avons utilisé la fonction de traduction. Cette fonction est disponible pour tout objet créé via l'appel newImage. Quelle que soit la méthode utilisée, utilisez l’une ou l’autre ou utilisez un mélange. Une autre chose que vous devriez remarquer est qu’il existe un écart entre certains blocs. Cela se produit car nous définissons l'emplacement des nouveaux blocs juste à côté de l'ancien emplacement du dernier bloc. Le problème est que lorsque nous procédons de cette façon, nous essayons de le placer à côté d'un objet en mouvement, de sorte que nous ne pouvons pas toujours frapper juste à côté. Ce problème deviendra encore plus grave une fois que nous essaierons d’augmenter la vitesse de déplacement des blocs. Plus ils se déplaceront rapidement, plus l’écart deviendra grand. Ce problème peut être résolu en ajoutant simplement une variable de vitesse et en effectuant nos calculs en fonction de cette vitesse. Remonter aux lignes de code où nous avons initialisé les variables GroundMin et GroundMax, et ajoutez ceci:

 vitesse locale = 5;

Ensuite, remplacez les fonctions updateBlocks () et updateBackgrounds () par celles-ci:

 function updateBlocks () pour a = 1, blocks.numChildren, 1 do if (a> 1), puis newX = (blocks [a - 1]). x + 79 sinon newX = (blocks [8]). x + 79 - fin de vitesse if ((blocs [a]). x < -40) then (blocks[a]).x, (blocks[a]).y = newX, (blocks[a]).y else (blocks[a]):translate(speed * -1, 0) end end end function updateBackgrounds() --far background movement backgroundfar.x = backgroundfar.x - (speed/55) --near background movement backgroundnear1.x = backgroundnear1.x - (speed/5) if(backgroundnear1.x < -239) then backgroundnear1.x = 760 end backgroundnear2.x = backgroundnear2.x - (speed/5) if(backgroundnear2.x < -239) then backgroundnear2.x = 760 end end

Avec ces fonctions mises à jour, vos blocs devraient bien bouger sans laisser de trous.!

Une dernière chose à faire pour que cela ressemble plus à un jeu. Retournez dans la fonction de mise à jour et mettez cette ligne de code après les fonctions de mise à jour:

 vitesse = vitesse + .05

Une fois que c'est là-bas, vous pourrez voir le niveau s'accélérer sous vos yeux! Bien sûr, la valeur exacte n’est qu’un exemple: la vitesse de mise à jour du jeu dépendra de votre jeu et de votre public. Il ne reste plus qu’à jeter un héros et quelques obstacles et nous avons nous-mêmes un match. Cela viendra plus tard, car cela clôt le projet pour le moment. Faire fonctionner tout cela n'était pas si mal, et nous allons continuer à ajouter beaucoup de fonctionnalités à chaque itération. Assurez-vous de revenir pour le prochain tutoriel, et si vous avez des questions ou des remarques faites le moi savoir dans les commentaires ci-dessous!