Transcription
1. Introduction: Qu'est-ce qui fait un jeu parfait ? graphismes détaillés et fabriqués à la main, des environnements
fantastiques et une grande variété de personnages
animés ? Ou s'agit-il plutôt de
la mécanique du jeu, la physique des interactions et IA pour que les
créatures se sentent vivantes ? Quel est l'ingrédient spécial la recette de développement de jeux ? Dans ce cours, nous allons
approfondir les secrets du JavaScript,
de l' animation
Web et du développement Web
frontal. Essayons de découvrir ce qui fait un bon jeu et comment
nous pouvons le créer du début à la fin en utilisant uniquement notre propre code
JavaScript,
sans frameworks ni bibliothèques. Ce cours est destiné aux débutants, mais certaines connaissances de base développement Web
frontal sont nécessaires pour en tirer
le meilleur parti. Allons-y.
2. Configuration de base: Je vais offrir une tonne d'illustrations de jeu
gratuites pendant ce
cours, je vais être comme ça. Nous contrôlerons la boule bleue. Son travail consiste à protéger les
œufs à éclore des vagues d'ennemis
affamés. Le joueur peut positionner
tous les objets du jeu en les poussant. Nous pouvons mettre le X et les
nouveau-nés en sécurité, ou nous pouvons repousser les
ennemis pendant la construction de ce projet.
Je vais vous montrer comment utiliser
le HTML, le CSS
et du
JavaScript standard
pour implémenter nombreuses techniques importantes d'animation Web et de développement de jeux Nous appliquerons la physique pour faire interagir les objets d'un jeu les uns
avec les autres. Nous allons apprendre comment redémarrer notre jeu en appuyant sur un bouton, comment contrôler le FBS
de l'ensemble du jeu, comment déclencher des événements périodiques. Nous appliquerons la plupart des contrôles. Apprenez à gérer et animer des
feuilles de calcul directionnelles. Nous déclencherons et
animerons des particules lorsqu'un certain événement
se produit, et bien plus encore. Prolons-y
étape par étape pour nous
assurer de bien
comprendre le code. À la fin de ce cours, vous aurez toutes les
compétences nécessaires pour créer vos propres jeux et projets
d'animation. Je crée un élément IMG
avec un identifiant de superposition. La source sera un point PNG
superposé. Vous pouvez télécharger tous les éléments
du projet dans la section
des ressources ci-dessous Il y a des images et des
sprites individuels tels que je
les utilise dans ce cours, ainsi qu'un dossier bonus contenant fichiers
sources où
chaque objet du jeu Gmb divisé en pièces haute
résolution. Vous pouvez les modifier et les animer. Donc, si vous le souhaitez, vous
pouvez les mélanger, les
combiner avec des
œuvres d'art que je vous ai données pour d'autres cours où nous utilisons ce thème de
la forêt de champignons. Et vous pouvez créer vos propres environnements de jeu
uniques. Toutes les œuvres de ce
cours sont libres de droits d'auteur. N'hésitez pas à
les télécharger, à les modifier et à les réutiliser dans vos propres
projets comme vous le souhaitez. Je
vous donne déjà toutes les œuvres dont vous aurez besoin pour suivre ce cours. Mais pour ceux d'entre vous, je veux aller plus loin. Si vous utilisez un éditeur graphique tel que Photoshop, vous pouvez par exemple modifier les
couleurs des images pour créer encore plus de variété visuelle. Les fichiers sources des personnages peuvent
également être violés et animés dans des outils de sprite 2D tels que des os de
dragon ou une colonne vertébrale Consultez les fichiers sources et
utilisez-les comme bon vous semble. C'est un cadeau que je te fais en guise remerciement pour le temps que tu as passé
avec moi. Nous avons donc une configuration de base dans
index.HTML et un style CSS. Gammas utilise par défaut cette petite
taille de 300, 150 pixels. Si je définissais sa taille avec du CSS, je ne définirais
que la taille de son élément. Et cela
élargirait mes dessins. Le canevas HTML a
en fait deux tailles. Taille de l'élément,
taille de la surface de
dessin qui peut être
définie indépendamment. Je veux que les deux tailles soient identiques pour éviter toute distorsion. Je vais donc dimensionner mon canevas
avec le JavaScript ici. J'intègre tout dans Load Event Listener, car nous utiliserons de nombreuses ressources artistiques. Et je voulais m'assurer que
toutes mes images étaient complètement chargées et disponibles avant l'exécution de
tout code JavaScript. abord, nous devons pointer
JavaScript vers notre élément de canevas en utilisant
get element by ID. Nous enregistrons cette référence dans cette variable personnalisée
que j'appelle par exemple canvas. Ensuite, je prends cette
variable et j' appelle la méthode intégrée GetContext, passant à D en tant qu'argument de type de
contexte. Cela initialisera un objet
intégré qui contient toutes les propriétés
et méthodes de dessin du Canvas. Nous pouvons maintenant les appeler
à partir de cette variable CD x. Comme je l'ai déjà dit, je souhaite définir la taille du canevas, la taille des éléments
et la taille la surface
de
dessin sur la même valeur. On peut le faire comme ça. La largeur des points du canevas est de 1 280 pixels et la
hauteur du canevas est de 720 pixels. Maintenant, l'illustration d'
arrière-plan complète que j'ai préparée pour vous se
révèle parfaite.
3. Programmation orientée objet en JavaScript: Je voulais écrire ce jeu sous forme base de code orientée
objet
pour le rendre plus modulaire Nous aurons une classe
pour le joueur et autre classe pour le jeu pour
gérer toute la logique du jeu. Le cerveau principal de
cette base de code. Nous aurons également besoin d'
une boucle d'animation pour dessiner et mettre à jour notre jeu encore et encore afin de
créer une illusion de mouvement. constructeur de classe de jeu s'
attendra à une référence à
un élément du canevas comme argument comme celui-ci. À l'intérieur, nous la convertissons en propriété de classe et nous aurons
besoin de la propriété de largeur. Et la valeur sera ce
point Canvas à partir de la ligne 15, largeur du
point. Comme ça. Cela nous donnera 1 280 pixels lorsque nous l'avons configuré
en ligne, nous faisons la même chose
pour cette hauteur de point. Nous prenons une référence à élément
Canvas et
nous définissons la largeur
et la hauteur de notre jeu de manière à ce qu'elles soient identiques à la largeur et à la
hauteur de Canvas. Nous terminerons cette
configuration en connectant cet argument de canevas à cette variable de
canevas un
peu plus tard. Lorsque nous
créerons une instance de notre classe de jeu en utilisant le nouveau mot clé, nous y
arriverons plus tôt. Je vais te montrer. Avant cela, j'ai également
besoin que le joueur
ait accès aux propriétés de
largeur et de hauteur de notre jeu, car il doit savoir, par exemple quand il se déplace hors de
la zone de jeu, etc. Je vais lui donner accès à l'ensemble de la classe de jeu toutes ses propriétés
et méthodes en lui
transmettant une référence
à cette classe de jeu sous forme d'argument, nous la convertissons en
propriété de classe. Gardez à l'esprit que je ne
crée pas de copie de
Game Object lorsque je crée des objets de joueur en JavaScript qui sont des types de données de
référence. Donc, ce jeu de points sur la
neuvième ligne ne crée pas de copie. Cela indique simplement un
espace dans la mémoire où notre
objet de jeu principal est stocké. Le code à l'intérieur d'un constructeur de
classe. Il se déclenche lorsque nous créons une instance d'une classe
en utilisant le nouveau mot clé, nous le ferons dans une minute. Je veux que notre base de code crée
automatiquement un joueur lorsque nous créons une instance
de notre objet de jeu principal. Je peux donc le faire dans
le constructeur de classe. Je crée une propriété
appelée ce point Player et je la définis sur New
Player comme ceci. Je peux voir que le constructeur de
classe de joueurs, l'aide
en ligne, attend le
jeu comme argument. Je lui passe donc ce mot clé, puisque nous sommes ici
dans cette classe de jeu. Ce mot clé fait ici référence
à l'ensemble de l'objet du jeu. Ici, à la ligne 18, nous
créons une instance de classe de joueur et
nous l'enregistrons sous ce point.
La propriété Player de la structure des classes du jeu dans forme de
ce point.
La propriété Player de la structure des classes du jeu dans
notre code créera
automatiquement un joueur. Lorsque nous créons un jeu, nous créons une instance d'objet
de jeu comme cette
variable personnalisée que j'appelle par exemple game, et je la définis comme
étant égale à new game. À la ligne 14, je peux voir que le constructeur de la classe de jeu
attend Canvas comme argument. Je passe donc la
variable canvas de la ligne à cette variable
qui sera convertie en propriété de classe et
la largeur et
la hauteur de la zone de jeu en seront
extraites comme prévu. Vérifions si
tout a fonctionné en consolidant cette variable de
jeu. Super, je peux voir les propriétés de
largeur et de hauteur correctes et nous avons également une instance de classe de
joueur dedans. C'est l'une des manières d'
organiser et de connecter vos objets dans une base de code JavaScript
orientée objet. Gardez à l'esprit que l'ordre dans lequel nous définissons les
classes est important. Le fichier Javascript est lu ligne
par ligne de haut en bas. Les classes Javascript sont hissées, mais elles ne sont initialisées que
lorsque cette
ligne particulière est correcte. classe du joueur doit donc être
définie avant d'être utilisée. Une très bonne idée serait de
diviser notre code JavaScript en modules
individuels et d'importer
et d'exporter nos classes entre fichiers selon les besoins. Pour ce projet, j'
écrirai tout le code dans un seul fichier JavaScript afin de le rendre aussi
convivial que possible pour les débutants L'utilisation de
modules JavaScript
nous obligerait à exécuter ce code
via un serveur local. Il n'exécuterait plus le
code en ouvrant simplement un fichier HTML d'index dans
un navigateur Web Si vous êtes plus expérimenté, il vous sera très facile de terminer le projet avec moi. Ensuite, si vous le souhaitez, vous pouvez vous-même
diviser les cours individuels en modules distincts. Ce cours est destiné aux débutants Concentrons-nous
donc sur les principes
orientés objet et les techniques
d'animation.
4. Dessiner le joueur: La fonction qui se trouve sur un
objet s'appelle une méthode. Le joueur devra utiliser la
méthode de dessin pour dessiner et animer. Il s'attendra à ce
que le contexte soit un argument pour spécifier sur quel type d'
entre nous nous appuyons. Nous allons connecter cet argument de
contexte à notre variable CTX à
partir de la troisième ligne Lorsque nous appellerons cette méthode de dessin un peu plus tard,
je vous le montrerai. Au
début, je voulais dessiner un cercle
simple , représentant notre joueur. Pour dessiner un cercle sur Canvas, nous utilisons des contextes et nous appelons begin path pour
indiquer à JavaScript que
nous voulons commencer à
dessiner une nouvelle forme. Nous voulons fermer la forme précédente. S'il y en a, nous
appelons la méthode arc intégrée, qui attend au
moins cinq arguments. Il attend les
coordonnées x et y du
point central du cercle. Son rayon, son angle de départ
en radians, est mesuré à partir de l'axe X positif et un
angle où l'arc se termine, toujours en radians, mesuré
à partir de l'axe X positif. Il existe un sixième
argument facultatif pour le sens antihoraire. Si nous ne le définissons pas,
il sera défini par défaut sur false, ce qui signifie que l'arc
sera dessiné dans le sens des aiguilles d'une montre. Donc, l'angle de départ est de 0 rad et l'angle final est de math.pi fois
deux, c'est un cercle complet. Nous pouvons maintenant choisir d'appeler remplissage, remplir la forme avec de la couleur, de tracer juste pour
définir la forme. Ou on pourrait utiliser les deux. Nous le ferons bientôt. Comment dessiner réellement
le joueur sur Canvas ? Maintenant, dans la classe de jeu, je crée une méthode que j'appelle, par exemple, un
rendu. Cette méthode permettra de dessiner et de
mettre à jour tous les objets de notre jeu. Il attend des contextes
comme argument. À l'intérieur, je prends ce point Player
de la ligne 23 et, grâce à cette référence, nous
accédons à la méthode de tirage sur la classe de joueur que nous venons de
définir à partir de la ligne 11. Cette méthode contient
le code pour dessiner un cercle représentant
le joueur. Je peux voir qu'il attend
des contextes comme argument, donc je le transmets à ce contexte, nous l'avons passé à la méthode de rendu. Je peux maintenant prendre cette variable de
jeu qui contient une instance de
la classe de jeu complète. Et à partir de là, j'appelle render, et je le passe à CTX. À partir de la troisième ligne, ce CTX se verra attribuer un contexte de
nom variable ici, et il sera transmis à méthode de
dessin en fonction de la classe du joueur. Super, nous dessinons un cercle noir représentant
la présence du joueur. Peut-être que tu ne peux pas le voir. Donnons-lui donc des coordonnées x
et y différentes pour le déplacer. Au lieu de coder en dur
toutes ces valeurs, je souhaite que vous créiez
des propriétés dans la classe Player. Alors utilisez-les ici. Nous aurons besoin des coordonnées x et y
pour la position du joueur. Mais parce que dans ce cours, nous
découvrons les cases de
position et de frappe et les images de personnages qui peuvent avoir des
formes et des tailles très différentes. Je devrai
créer une propriété pour les positions
X et Y de la boîte
d'identification du joueur. Et j'aurai besoin d'
une
propriété x et y différente pour l'image de la feuille de
sprite du joueur. Cela aura plus de
sens au fur et à mesure que nous le construirons. Je veux être très explicite avec noms de
mes variables afin de
préciser clairement quelle valeur est la position de la zone de collision et quelle valeur est la
position d'une feuille de calcul. Donc, au lieu de nommer ces
propriétés uniquement x et y, je les nommerai collision
x et collège et position Y, X et Y de
la
zone de collision située au centre
du cercle de collision. Tous les objets de notre
jeu d'aujourd'hui seront dotés de
zones de frappe circulaires, car je
voulais vous montrer comment les
faire pousser et glisser les uns sur
les autres sur la position
de départ du joueur exactement au milieu
de la zone de jeu. Collision X sera donc ce jeu de
points à partir des lignes 9. Et à partir de cette propriété, je vais extraire la
largeur de la ligne 23. Et au milieu, donc multiplié par 0,5, la collision y
sera la même. Ce point joue avec la
hauteur multipliée par 0,5. Maintenant, je peux utiliser ces
valeurs comme arguments x et y pour la méthode Canvas
arc comme celle-ci. Nous pouvons maintenant déplacer le
joueur en modifiant les valeurs de collision
et de collision. Pourquoi des propriétés ? Nous aurons également besoin d'une propriété
appelée rayon de collision, qui définira la taille de cette couche
circulaire. Il avait des livres. Je l'utilise également ici dans
la méthode arc. couleur de remplissage par défaut
est toujours le noir. Je peux remplacer, adhérer
par certains types de propriétés FillStyle
au blanc comme ceci. Au lieu de remplir
la forme de couleur, nous pourrions aussi simplement la caresser. Encore une fois. Par défaut, la largeur de ligne du trait est d'un pixel et
la couleur est noire. J'ai réglé la largeur de ligne à trois pixels et j'ai défini le style de
trait sur blanc. Notez que je définis
ces propriétés Canvas en dehors de toute classe ou méthode. Je le fais exprès
car ce code ne s'exécutera qu'une seule fois lors du chargement
initial de la page. Cela n'est pas toujours possible si vous avez plusieurs objets avec des champs, des
styles et des couleurs de trait
différents . Dans ce cas, vous devrez
définir ces propriétés dans la méthode de dessin et passer de l'une à l'autre
encore et encore. Le problème,
c'est que la méthode de dessin sera appelée 60
fois par seconde. Et un changement dans un
tel état peut coûter cher en termes de
performances. C'est une bonne idée de
structurer le code de manière modifier le
moins possible un état. Et quand je parle d'état du canevas, je veux dire tout, des transformations aux modifications des couleurs du
FillStyle et du style des traits. C'est pourquoi j'ai mis ce code ici au lieu de le placer
directement dans la méthode de dessin pour qu'elle
s'exécute le moins possible tout en appliquant les couleurs et les paramètres dont j'ai besoin. Je peux aussi appeler Fill ici. Nous
remplissons et traçons maintenant
le même chemin défini
par la méthode de l'arc. Je veux que le remplissage soit blanc, mais je voulais qu'il soit
légèrement transparent. Kind of us possède une propriété
alpha globale qui définit opacité des formes
que nous dessinons. Le problème, c'est que lorsque j'ai donné alpha
globale à une valeur
différente, tout ce qui
sera dessiné par la suite sera semi-transparent. Je souhaite que la transparence
ne s'applique qu'à la couleur de fond du cercle de collision des joueurs afin de limiter certains types de paramètres
à des appels de tirage spécifiques. Nous pouvons intégrer ce code de
dessin entre méthodes Canvas
sécurisées et restaurées. Et si je disais que l'alpha
global est égal à 0,5, cela n'affectera que cette action de dessin
spécifique. Dans notre cas, cela n'
affectera que le remplissage de ce cercle. La méthode save crée donc un
instantané de l'état actuel, y compris son FillStyle, son opacité en
largeur de ligne, ainsi que les
transformations et la mise à l'échelle. Si c'est ce que nous faisons, je peux apporter toutes les modifications
nécessaires à l'état que je souhaite. Dans ce cas, je viens de
régler l'opacité à 0,5. Cette couleur de remplissage sera affectée par cette
modification de l'opacité. Ensuite, nous appelons restauration, c'est-à-dire la restauration de toutes sortes de
paramètres tels qu'ils étaient lorsque nous avons appelé pour la première fois la méthode de sauvegarde
associée. Pour cette raison, l'accident vasculaire cérébral
ne sera pas affecté par
une opacité réduite. Les méthodes de sauvegarde et de restauration nous
permettent d'appliquer des paramètres de
dessin spécifiques uniquement pour sélectionner les
formes sans affecter le reste de
nos dessins Canvas.
5. Contrôles de la souris: Je veux déplacer le joueur à l'aide
de la souris. Nous savons déjà que le code contenu dans le
constructeur de classe de jeu sera exécuté au moment
où nous créerons une instance de cette classe à
l'aide du nouveau mot clé. Nous tirons
parti des données en créant
automatiquement une
instance de classe de joueur ici Nous pouvons en fait exécuter n'importe quel code
JavaScript ici. Je peux même placer des
auditeurs d'événements ici pour m'assurer qu'ils sont
automatiquement appliqués. Lorsque je crée une
instance de classe de jeu, je crée un écouteur d'événements
pour les événements liés à la souris enfoncée. Lorsque vous cliquez sur le bouton de la souris, le code contenu dans cette fonction de
rappel s'exécute. J'ai testé en enfonçant
simplement le mot souris sur la console. Si j'enregistre les modifications
parce que je suis déjà train d'instancier cette
classe en ligne pour D6. écouteur D7 est
automatiquement appliqué. Maintenant, lorsque je clique sur Canvas, journal de la
console déclenche belle fonction de rappel
sur EventListener qui
génère automatiquement un
objet d'événement contenant toutes sortes d'informations sur l'événement qui vient de se produire. Pour accéder à cet objet, il suffit de
lui donner un nom de variable. Tu peux le nommer
comme tu veux. Mais la convention
est généralement un événement ou E. Consignez cet événement sur la console. Je clique sur Canvas
et je le vois ici. J'ai inspecté. Vous pouvez
voir qu'il contient de nombreuses informations sur
ce clic de souris, par exemple, nous voyons les coordonnées x et y
de ce clic ici. Il existe de nombreuses autres
propriétés qui nous indiquent quel bouton de
la souris a été pressé
et bien d'autres choses encore. Je veux que vous preniez les
coordonnées du clic et les
enregistrez en tant que propriétés
sur l'objet principal du jeu. Et à partir de là, nous
pourrons également y
accéder depuis notre objet
joueur. Je crée une nouvelle propriété sur la classe de
jeu appelée
cette souris à points. Ce sera un objet
avec la propriété x avec valeur
par défaut de cette largeur de
point multipliée par 0,5. Et y sera cette hauteur de
point multipliée par 0,5. Donc, le milieu de la toile,
horizontalement et verticalement. Nous voudrons également
surveiller
le moment où le bouton de la souris
est enfoncé. Dans un premier temps, il
sera défini sur false. Si je console log e point x et y, vous pouvez voir que nous
obtenons les
coordonnées x et y lorsque nous
cliquons autour de nous. Le problème est que les
coordonnées proviennent
du bord supérieur gauche de
la fenêtre du navigateur. Je voudrais plutôt mesurer
les coordonnées du clip à partir du coin supérieur gauche
de Canvas. Ainsi, lorsque nous cliquons ici dans le
coin supérieur gauche du canevas, nous obtenons x et y zéro. Pour cela, nous pouvons utiliser une propriété
différente sur cet
objet d'événement généré automatiquement appelée offset x, qui nous donnera la coordonnée
horizontale
du clic sur le nœud cible. Dans notre cas, le nœud cible, la cible du clic,
est en quelque sorte un élément. Vous pouvez maintenant voir les
valeurs se rapprocher de zéro lorsque je clique près
du bord de Canvas. Je pourrais également ajouter l'écouteur d'
événements à l'élément de toile lui-même
plutôt qu'à l'ensemble de l'objet de la fenêtre
du navigateur. Si je clique plus près
du coin supérieur gauche, nous obtenons
des valeurs proches de 00. Parfait. Il
serait probablement logique que j' utilise plutôt cette propriété point Canvas
ici à partir de la ligne 31, puisque nous sommes à l'intérieur
d'une classe et que la référence à
Canvas est disponible ici. Nous obtenons maintenant la coordonnée
du clic mesurée en
pixels à partir du coin
supérieur gauche de Canvas. Même lorsque nous redimensionnons la fenêtre du navigateur,
cela fonctionne bien. Je souhaite que vous enregistriez les coordonnées
cycliques dans propriété de la souris de
notre client afin qu'elles soient accessibles à d'autres
objets de notre base de code, tels que le lecteur intégré à l'écouteur d'événements
avec la souris enfoncée. Je prends cette propriété
point x de la souris à partir de la ligne 36, et je la définis comme
étant égale à E point offset x. Ce point y de souris
sera décalé par e point. Pourquoi ? Je crée
un autre journal de console et j'examinerai ces propriétés de souris récemment
mises à jour. Lorsque je clique sur Canvas, une erreur indique qu'il est
impossible de définir des propriétés sur certains
x non définis en ligne pour D3 Cela me dit que je ne peux pas définir propriété
x sur quelque chose
qui n'est pas défini. Pour une raison quelconque,
cette souris à points n'est pas définie lorsqu'on y accède
depuis Event Listener. C'est parce que lorsque
cette fonction de rappel sur l'écouteur d'événements s'exécute, elle a oublié qu'elle avait été
initialement définie dans ce constructeur de
classe de jeu. Il oublie ce que signifie ce
mot clé. Cela devrait permettre à l'écouteur d'événements de se souvenir de l'
endroit où il a été défini pour la première fois, de sa position dans le
champ lexical de notre base de code. Nous pouvons simplement utiliser la
fonction de flèche ES6 ici à la place. L'une des particularités des fonctions de flèche d' ES6 est
qu'elles ont automatiquement hérité de la référence à ce mot clé du
scope parent. Toutes des fonctions. Rappelez-vous où, dans la base de code ils ont été initialement
déclarés lexicalement. Et ils ajustent
leur mot clé
de bureau pour pointer vers le bon objet, vers l'objet parent. Désormais, ce point x de souris et ce point de souris visuel y sont correctement mis
à jour avec les nouvelles valeurs, ce qui rend les
coordonnées actuelles de la souris disponibles dans
toute notre base de code
chaque fois qu'elles sont nécessaires. Plus tard, je supprime
les journaux de la console. Lorsque l'événement « souris enfoncée » se produit. J'ai dit que le prix allait de
la ligne 38 à vrai. J'ai copié cet écouteur d'événements. Celui-ci sera
réservé à l'événement Mouse Up. Lorsque le
bouton de la souris est relâché, tout reste le même ici et la poitrine redevient fausse. Je crée également un écouteur d'événements
pour les événements de déplacement de la souris. Laissons-nous consulter pour vérifier. Oui, ça marche. Faisons bouger le joueur.
6. Faire déplacer le joueur: Créez une
méthode personnalisée que j'appelle mise à jour. À l'intérieur, j'ai dit
collision x de la ligne 14 à la position X actuelle de
la souris. Et la collision y sera la
position Y actuelle de la souris, comme ceci. Pour exécuter ce code, nous
devons en fait appeler la méthode de mise à jour. Je vais l'appeler depuis le rendu
interne ici. Je supprime ce journal de console. Si nous voulions
voir un mouvement, nous devons appeler
Render encore et encore. Mettons-le donc dans
la boucle d'animation ici. J'appelle Request
Animation Frame intégré une méthode qui se trouve sur l'objet de la fenêtre du
navigateur, mais nous pouvons également l'appeler
directement comme ceci. Si nous le voulons. Je le passe, j'anime le nom de sa fonction mère pour créer
une boucle d'animation infinie. Maintenant, je dois appeler animate pour démarrer l'animation. Quand je passe la souris au-dessus de
nous, nous voyons des traces. Je voulais juste voir les images d'animation
actuelles. Donc, entre chaque boucle, j'utilise la méthode
rectangulaire transparente intégrée pour effacer l'ancienne peinture. Je voulais effacer
toute la zone de la toile, de coordonnée zéro à la largeur et à
la hauteur de la toile. Maintenant, le joueur tape
la souris pendant que nous la déplaçons autour
du cannabis, parfait. Je voulais créer une ligne
entre la souris et le joueur pour indiquer clairement la direction dans laquelle le joueur va se déplacer. Dans la méthode de tirage au sort
sur la classe du joueur, nous commençons une nouvelle forme
par Colin Begin Bath. La méthode Move to définira les
coordonnées x et y de départ de la ligne. Dans ce cas, je
voulais que la ligne
commence à partir des coordonnées
de l'objet du joueur. Méthode de la deuxième ligne, nous allons définir la fin en
coordonnées x et y de la ligne. Dans ce cas, il s'agira des coordonnées x et y de la souris. Ensuite, nous appelons trait pour
réellement tracer la ligne. Cela fonctionne, mais
comme le joueur est toujours capable de rattraper le curseur
de la souris si rapidement, nous pouvons à peine voir la ligne. Donnons au joueur vitesse, vitesse X vitesse horizontale. Au départ, je
l'ai réglé à zéro. Pourquoi la vitesse verticale l'
a également initialement mise à zéro. Dans la méthode de mise à jour, nous
allons calculer la vitesse x. Tout d'abord, je l'ai réglée sur un pixel
codé en dur
par image d'animation. Et j'augmente l'
exposition des joueurs en fonction de la vitesse horizontale. Cela a fonctionné. Je le fais aussi
pour la position verticale. Il existe deux manières d'obliger
le joueur à suivre la souris. Une solution serait simplement de
prendre la différence entre
la position actuelle de la souris et la position du joueur sur
l'axe X horizontal. Et définissez cette différence
comme vitesse horizontale. Et nous le faisons également
pour les mouvements verticaux. Maintenant, la position
du joueur corrige
la différence en fonction de la distance
totale. Cela rend le
mouvement instantané. Et si je le faisais bouger d'un vingt-cinquième de
la différence entre
la position du joueur et celle de la souris horizontalement d'un vingt-cinquième de
la différence entre
la position du
joueur et celle de la souris
pour l'image d'animation. Et aussi verticalement. Je crée une classe de
propriétés pour dx, distance entre
la souris et le joueur horizontalement et la distance
verticale. Je remplace ces valeurs ici. C'est plus facile de le lire de cette façon. Je ne veux pas que le joueur
suive tout le
temps lorsque nous déplaçons
la souris sur Canvas. Je ne le veux que lorsque nous
cliquons quelque part ou lorsque nous maintenons le
bouton de la souris enfoncé et que nous nous déplaçons. Dans l'écouteur d'
événements de déplacement de la souris, je dis de ne mettre à jour que la position x et
y de la souris. Si la souris est pressée. Maintenant, je peux cliquer pour déplacer le joueur
vers cet endroit, ou je peux faire glisser ce point tout en maintenant la
souris enfoncée. Parfait. Le problème de cette
technique est que la vitesse n'est pas constante. se déplacent très vite au début, car un 20e
de la distance est d'
abord un gros morceau
lorsqu'ils sont éloignés l'un de l'autre. Mais à mesure qu'ils se rapprochent, un 20e de cette
distance
diminue et le nombre de pixels à parcourir
par image d'animation diminue. Vous souhaiterez peut-être intégrer cette
émotion particulière à votre projet, mais pour le jeu que
nous sommes en train de créer aujourd'hui, je voulais que le joueur
se déplace à une vitesse constante. Nous devrons utiliser la
deuxième technique pour
cette méthode de mise à jour des informations. J'ai calculé la distance. Nous avons déjà dx, la distance entre la souris
et le joueur horizontalement. Nous avons également d, la distance verticale
entre la souris et le
joueur. Nous voulons calculer la distance entre
ces deux points. Nous pouvons le faire en
calculant l'hypoténuse, le côté le plus long de ce triangle droit
imaginaire. Nous pouvons utiliser la formule du
théorème de Pythagore
ou, en JavaScript, nous avons cette méthode d'
hypoténuse par points mathématiques intégrée. Cette méthode calculera la longueur du côté le
plus long pour nous si nous la transmettons aux autres côtés du
triangle comme arguments Gardez à l'esprit qu'elle attend d, dy et dx secondes, ce qui peut être un peu inattendu si vous ne l'avez jamais vu auparavant. vitesse horizontale est
le rapport entre dx, distance
horizontale entre la
souris et le joueur et la distance réelle.
Vitesse du sandwich. Pourquoi ? Il s'agira du rapport
entre la distance sur axe
vertical y et
la distance réelle entre les deux points. titre de sauvegarde, lorsque certaines de
ces valeurs ne sont pas définies au début, nous disons ou
zéro. Ainsi, nous sommes divisés en distance horizontale
et verticale, ces côtés par la distance
réelle représentée par le
côté le plus long d'un triangle droit. Dx et DY sont toujours un nombre
inférieur la distance car la distance correspond à
l' hypoténuse, le côté le plus long. Pour cette raison,
les valeurs que nous obtenons pour vitesse x et la vitesse y
seront comprises entre 0 et 1. Cela nous donnera la
bonne direction de mouvement à une vitesse constante. Il y a encore beaucoup à
dire sur cette technique. Mais pour l'instant, c'est
tout ce que nous avons besoin de savoir. Je vais y revenir. Maintenant. Le joueur se déplace à vitesse constante
vers la souris. Je peux avoir un modificateur de vitesse. Je l'ai réglé sur cinq, par exemple je l'utilise ici et je
multiplie la vitesse x et la vitesse. Pourquoi, avec ce modificateur, après avoir ajouté le modificateur de vitesse, le cercle des joueurs
ne restera plus immobile. Il oscillera d'avant en
arrière, dans ce cas de
50 pixels, car le modificateur de vitesse le pousse
trop loin dans les deux sens. Je peux y remédier en disant ne déplacer le joueur que lorsque
la distance entre souris et le joueur est
supérieure au modificateur de vitesse. Sinon, la vitesse x était à zéro
et la vitesse y à zéro également. Cela fonctionne parfaitement. Nous avons donc abordé une technique simple et une technique plus avancée pour amener le joueur à se déplacer
vers la souris. Il est maintenant temps d'ajouter des obstacles solides, aléatoires et
qui ne se chevauchent pas.
7. Créer des obstacles: Je crée une classe
que j'appelle obstacle. constructeur s'attend à ce que
le jeu soit un argument. Et à l'intérieur, j'ai converti
cette référence propriété de
classe, comme avant. Il pointera vers
l'objet principal du jeu. Et nous en avions besoin,
car grâce à cette référence, nous avons accès
à la largeur et à la hauteur du jeu, la position de la souris et à d'
autres propriétés. Nous serons ajoutés ultérieurement. Nous aurons accès à
toutes ces valeurs depuis classe
d'obstacles via cette référence .name
à partir de la ligne 54. Comme je l'ai déjà expliqué, les objets de notre jeu se
composeront d'une boîte circulaire chauffée en cas de
collision et d'une feuille de calcul
rectangulaire séparée. C'est pourquoi
j'appellerai ces propriétés avec des noms très
descriptifs afin de m'
assurer que
ce qui se passe lorsque
nous déplacerons et animerons
tout sera très clair ultérieurement. Collision x, le
point central du cercle de collision de chaque obstacle,
sera une valeur aléatoire comprise entre zéro et la
largeur du jeu. Cette largeur
provient de la ligne 62 ici. Et nous y accédons via cette référence de jeu de points
que nous avons créée à la ligne 54. Nous aurons également besoin d'une collision. Pourquoi le point central vertical
de la collision est un cercle. Ce sera une valeur aléatoire
comprise entre zéro et la hauteur du jeu. Cette valeur de
rayon de collision sera de 60. Nous devrons également
dessiner une méthode qui attend les contextes comme argument. Je veux que le cercle qui
représente la zone de frappe de chaque obstacle ressemble
au cercle
représentant le joueur. Je prends donc le
code de dessin d'ici, juste pour le cercle. Donc ce bloc de code, je le copie et je le
colle ici. Ce code fonctionnera ici
car, comme pour le joueur à qui nous avons attribué
la propriété d'obstacles, s'
appelle collision x, collision et rayon de collision. Nous aurons également besoin
du même nom toutes ces propriétés entre les
différents types d'objets. Au cas où nous souhaiterions disposer d'une fonction de
détection de collision réutilisable. Je vous montrerai comment
l'utiliser plus tard. C'est simple. Quoi qu'il en soit, nous avons ici un
code pour dessiner un cercle d'un rayon de 60 pixels
avec une opacité de 50 %, un fond blanc et un trait blanc, entièrement visible et
opacité totale. Cette classe d'
obstacles est un plan. Nous l'utiliserons pour créer des objets d'obstacles
individuels. La véritable logique pour
créer et gérer ces objets se trouvera ici dans la classe de jeu principale, qui est le cerveau principal
de notre base de code. Je crée une propriété appelée
ce point obstacles. Ce sera un tableau contenant
tous les objets d'
obstacles actuellement actifs. Au début, il s'agira d'un tableau
vide, le nombre d'obstacles
sera par exemple de cinq. Je crée une méthode personnalisée pour
notre classe de jeu, que j'appelle par exemple dans IT.
Pour l'instant, son travail consistera à créer cinq
objets d'obstacles aléatoires et à
les placer dans le
tableau d'obstacles que nous venons de définir. À l'intérieur, je crée une boucle en forme de « for ». Elle sera exécutée cinq
fois parce que nous avons indiqué le nombre d'obstacles à
cinq sur la ligne 76. Chaque fois qu'il s'exécute, il prend ce tableau d'obstacles à points
de la ligne 77 et, sur celui-ci, il appelle la méthode push intégrée du
tableau à méthode
push sous la forme d'un
ou de plusieurs éléments jusqu'
à la fin d'un tableau, et il renvoie la nouvelle
longueur du tableau. Je vais lui passer un nouvel
obstacle comme celui-ci. Le nouveau mot clé recherchera une classe portant le nom obstacle, et il déclenchera son
constructeur de classe en ligne 53 Je peux voir que le constructeur de
classe d'obstacles attend le jeu comme argument. Ici, la méthode init se trouve
dans cette classe de jeu, donc je lui transmets le mot clé, ce qui représente ici
l'ensemble de l'objet du jeu avec toutes ses propriétés
et les méthodes associées, les
rendant toutes disponibles
depuis la classe d'obstacles. Maintenant, je joue sur
console et je peux voir que le tableau d'obstacles
est complètement vide. Pour le remplir, tout ce que j'ai à
faire est d'appeler la méthode init. Nous venons d'écrire comme ça. Maintenant, je peux voir que le tableau
contient cinq objets obstacles. Je vérifie que
toutes les propriétés ont des valeurs. Si vous voyez undefined
dans l'un d'entre eux, cela signifie qu'il y a un
problème dans votre base de code. Tout va bien ici. Tout comme je suis en train de dessiner
une mise à jour et que
le joueur utilise la méthode de rendu du
jeu, j'aimerais dessiner les cinq
obstacles sur Canvas. Je prends un éventail d'obstacles de -77. Nous savons déjà qu'il contient cinq objets et que chacun de ces objets a été créé à l'aide notre
classe d'obstacles personnalisée de I'm 52. Ils ont tous accès à cette méthode de dessin que nous avons
définie à la ligne 59. Donc, ici, dans le rendu, je prends ce tableau d'obstacles, j'appelle un tableau intégré
pour chaque méthode, la méthode forEach exécute une fonction fournie une fois
pour chaque élément du tableau. abord, nous devons définir un nom de variable qui
sera utilisé dans cette méthode forEach pour faire référence à des objets individuels
dans ce tableau. Je vais appeler chaque
objet obstacle. Donc, pour chaque
objet d'obstacle d'un tableau d'obstacles, j'appelle leur
méthode de dessin associée à partir de 1959 en ligne 59, je peux voir qu'elle attend
une référence au contexte comme argument pour spécifier type d'élément Us sur
lequel
nous voulons dessiner. Je transmets simplement
ce contexte qui a été transmis à la méthode de rendu
parent. Agréable. Nous dessinons
un joueur et 12345 obstacles
positionnés aléatoirement. Je monte ici et j'agrandis un peu les
obstacles. Chaque fois que j'actualise la fenêtre
du navigateur, ils sont positionnés de manière aléatoire quelque part dans la zone du canevas car c'est ainsi que nous définissons leur position sur les lignes 55.56. Et si je voulais m'assurer
que les obstacles ne
se chevauchent jamais comme ça et peut-être
aller encore plus loin, car ce seront des
obstacles solides que le joueur ne
pourra pas franchir et
devra les contourner. J'aimerais également qu'il y
ait un espacement minimum entre eux et également entre
les bords de la zone de jeu. Juste pour s'assurer que toutes
les créatures qui vont bientôt ramper
ici ne restent pas
coincées et puissent éventuellement contourner automatiquement chaque obstacle. Il est en fait plus facile de mettre en œuvre tout
cela, que vous ne le pensez peut-être, mais nous devons
y aller étape par étape et expliquer quelques astuces que
nous pouvons utiliser ici pour y parvenir.
8. obstacles non chevauchants: Dans la méthode init,
nous
ajoutons simplement cinq obstacles
positionnés au hasard. Hein ? Maintenant. Je dois le supprimer. Nous aurons besoin que cette structure soit appelée un peu différemment ici. Je voulais donc d'abord m'assurer que les obstacles ne se touchent pas, qu'ils ne
se chevauchent pas comme ça. Nous pouvons également ajuster
le nombre d' obstacles pour qu'il soit
possible de placer le nombre
maximum de cercles dans une zone donnée sans que
deux d'entre eux ne se chevauchent. ce que nous appelons parfois l'emballage circulaire. Réécrivons donc un cercle
très simple dans l'algorithme ici. Je vais utiliser la
technique de base qui consiste
à essayer plusieurs fois de jouer des cercles à
des positions aléatoires. Et seuls ceux qui
n'entrent pas en collision avec des cercles
déjà existants
seront réellement transformés en
objets d'obstacles et dessinés. C'est ce qu'on appelle également un algorithme de force
brute. Ce n'est pas très intelligent, il essaie encore et
encore de nombreuses fois. Je vais créer une
variable principale appelée tentatives. Ce sera ma mesure de sécurité. Nous compterons le nombre de
fois où nous avons essayé de tracer un cercle et nous abandonnerons après un certain
nombre de tentatives. L'hypothèse étant qu'
il devait
déjà y avoir suffisamment d'opportunités
pour placer les obstacles. Je vais utiliser une boucle pendant un certain temps. Tu dois être prudent
avec celui-ci. Si vous créez une boucle de temps
infinie, vous ralentirez votre navigateur et vous devrez le redémarrer. très vieux ordinateurs peuvent même se bloquer si vous utilisez
While Loop Rome, les
nouveaux navigateurs peuvent
généralement y faire face. Mon objectif ici est de
placer des cercles au hasard encore et encore. Et avant de transformer ce cercle en objet
obstacle, nous vérifions s'il chevauche
des cercles d'existence. Si cela ne se chevauche pas, nous l'avons ajouté au tableau
des obstacles. Je veux que cette boucle continue de fonctionner tant que la
longueur du réseau d'obstacles est inférieure à, nombre d'obstacles,
inférieure à cinq. Nous avons défini ce tableau ici, et le nombre d'obstacles
a été défini ici. En guise de sauvegarde, j'ai également défini
une condition secondaire ne continuer à l'exécuter
que pendant la boucle
tant que le nombre de tentatives
est inférieur à 500. C'est important
car si je disais rayon d'un obstacle est très grand, ou si je fixe un nombre
d'obstacles si grand qu' ils ne peuvent pas rentrer physiquement
dans la zone disponible, nous obtiendrions une boucle
infinie. Mais lorsque la
condition secondaire est JavaScript, nous allons juste essayer 500 fois. Et si, à ce moment-là,
ils n'arrivaient pas à trouver un
emplacement pour surmonter tous les
obstacles, il abandonnerait. Je pense que 500 tentatives
sont plus que suffisantes. Chaque fois que la boucle fonctionne, nous devons augmenter le nombre de
tentatives d'une unité
pour
que notre plan de sécurité fonctionne. Chaque fois que cette boucle s'exécute, nous créons un
objet temporaire que j'appelle, par exemple obstacle de
test. Il sera à
la hauteur du nouvel obstacle et je lui passe un jeu, ce mot clé comme
argument, comme nous le faisions auparavant. Configurons
cet obstacle de test dans la console. Agréable. Nous avons 500
obstacles de test sur console. Vous pouvez maintenant voir
qu'ils ont les propriétés de collision, collision y et de
rayon de collision de
collision y et de
rayon de collision
comme il se doit. Mon objectif est maintenant de prendre cet objet d'essai
temporaire et le
comparer tous les autres obstacles
du tableau d'obstacles. Bien sûr, au début, ce tableau est vide, donc le premier obstacle doit toujours être placé sans problème. Le deuxième obstacle de test se
comparera au premier déjà présent
dans la matrice, et ainsi de suite. Donc, pour chaque obstacle, réseau d'
obstacles, je vais utiliser une formule de
détection des collisions circulaires. La détection des collisions circulaires en
JavaScript est assez simple. Nous devons essentiellement
calculer la distance entre les deux
points centraux de ces deux cercles. Ensuite, nous comparons la
distance entre deux points centraux à
la somme des rayons. Si la distance est
inférieure au rayon 1 plus le rayon du cercle,
ils se chevauchent. Si c'est exactement pareil, les cercles se touchent. La distance est
supérieure à la somme des rayons. n'y a pas de collision. Nous l'avons déjà fait en mesurant la distance
entre le joueur et la souris. Cette fois, les deux points que
nous voulons mesurer
la distance entre eux sont le point central
du premier cercle d'obstacles. Et le point central des
obstacles est également circulaire. Encore une fois, nous créons
ce triangle droit imaginaire où dx est la différence entre deux points horizontalement. D est la différence entre
les deux points verticalement. Et la distance réelle est l'hypoténuse de ce triangle. Nous utilisons donc ici la formule du
théorème de Pythagore ou une méthode mathématique intégrée d'
hypoténuse par points, en lui passant un DY d'abord
et un second. Nous savons maintenant quelle est la distance entre
les deux points centraux. somme au-dessus de l'ADI est le
rayon du cercle 1, dans ce cas, le rayon
de l'obstacle d'essai. Et le second
est le rayon de n'
importe quel objet obstacle
à l'intérieur d' un réseau d'obstacles, sur lequel nous sommes actuellement en train de parcourir un cycle. Comme nous l'avons dit, si la
distance est inférieure à
la somme des rayons, comment dois-je procéder ? En dehors de la méthode pour chaque méthode, je crée une
variable de longueur d'indicateur que j'appelle chevauchement, et je la définis initialement sur false. La distance est
inférieure à la somme des rayons. Nous avons défini le chevauchement comme vrai
car une collision a été détectée en dehors de la
pour chaque méthode. Si le chevauchement est toujours
faux après avoir
créé un obstacle de bureau
et après l'avoir comparé à l'aide de la formule de
détection des collisions avec tous les autres
obstacles existants de la matrice. S'il n'entre en collision
avec aucun d'entre eux. Et la variable de chevauchement
est toujours fausse. Après toutes ces vérifications, nous prenons
un réseau d'obstacles et nous insérerons
cet obstacle de test qui a réussi
nos contrôles dans le tableau. Maintenant, lorsque je rafraîchis le jeu, cinq obstacles seront
positionnés au hasard et ils ne se
chevaucheront pas, car ceux qui se
chevauchent sont supprimés. Et seuls les
cercles qui ne se chevauchent pas sont utilisés. Comme j'ai ma
mesure de sécurité sur la ligne 10008, et que nous arrêtons toujours cela en boucle lorsque
nous atteignons 500 tentatives, je peux monter ici
et régler le nombre d'
obstacles à un nombre élevé qui je le sais, ne correspondra jamais à notre code. Nous allons simplement placer
autant d'obstacles que possible, puis il
cessera d'essayer. Nous savons que cela
fonctionne, car si je continue à actualiser mon
projet encore et encore, nous ne verrons jamais de cercles
qui se chevauchent. Je veux dire, aucun obstacle ne
se chevauche. À ce
stade, le joueur peut se chevaucher avec des obstacles. Ça ne nous intéresse pas
pour le moment. J'ai parlé d'un certain nombre d'
obstacles à dix.
9. Images randomisées à partir d'une feuille de sprite: Permettez-moi maintenant de vous montrer comment
nous allons attacher des images aux cases de
collision circulaire et comment positionner l'image par rapport à la boîte principale de
manière à ce qu'elle ait sens visuel et crée illusion qu'il ne s'
agit pas d'
une toile plate, mais d'un
environnement tridimensionnel dans lequel le joueur peut réellement
contourner ces obstacles. Vous pouvez télécharger
tous les projets forme d'actifs dans la section
des ressources ci-dessous. Dans index.HTML, je crée un autre élément d'
image avec un identifiant d'obstacles et la source
sera obstacles point PNG. Cette image est une feuille de sprites. Nous allons sortir aléatoirement l'un de ces cadres pour chaque objet d'
obstacle. Je ne veux pas vraiment dessiner
l'élément d'image réel, donc je le cache avec du CSS dans le constructeur de classe d'
obstacles, je crée une nouvelle propriété, j'appelle cette image à points. J'ai pointé du doigt cette feuille de calcul d'
obstacles utilisant get element
by ID comme celle-ci. Fixons le nombre d'
obstacles à un pour le moment. Dans la méthode de dessin
sur la classe d'obstacles, j'appelle la méthode intégrée de
dessin d'image sur toile. Cette méthode nécessite au
moins trois arguments, l'image que nous voulons dessiner. Alors, cette image ponctuelle de la ligne 58 et des coordonnées x et y,
où la dessiner ? Je vais le dessiner lors cette collision de points x
et de cette collision de points. Pourquoi ? commencer,
nous allons simplement dessiner la feuille de sprite
complète de l'image. Et le coin supérieur gauche de
cette feuille de calcul partira point central du cercle d'obstacles,
car c'est ainsi que, par défaut, images et les cercles sont
dessinés sur le canevas HTML. Si j'actualise le projet ou un
nouvel obstacle est positionné de
manière aléatoire quelque part sur Canvas, j'ai créé cette
feuille de calcul pour vous. Je sais donc que les
cadres individuels ont une largeur de 250 pixels. J'enregistre cette valeur en tant que sprite avec une hauteur de sprite variable
qui sera également de 250 pixels. Si vous utilisez une
autre feuille de calcul, vous pouvez obtenir la largeur en
divisant la largeur de la feuille de calcul entière par
le nombre de colonnes. Et la hauteur est la hauteur de la feuille de sprite
divisée par le nombre de lignes au cas où nous
voudrions ajouter une échelle. Et plus tard, je créerai également des propriétés
indépendantes de largeur et de
hauteur. Pour l'instant, la largeur et la
hauteur du
sprite seront égales, car j'ai dimensionné
les cadres de sprite exactement à
la même taille que celle que je
souhaite qu' largeur et la
hauteur du
sprite seront égales, car j'ai dimensionné les cadres de sprite exactement à la même taille que celle que je ils soient
dessinés dans le jeu. Draw image peut également accepter les quatrième et
cinquième arguments
facultatifs définis dans la largeur et la hauteur. L'image entière
sera compressée ou étirée jusqu'à la zone que nous avons
définie par ces valeurs. Cela ressemblera à ceci. Ce que je veux vraiment
faire, c'est recadrer l'un de ces 12
obstacles et
ne dessiner que celui-ci à la taille
de 250 fois 250 pixels. Pour cela, je dois utiliser
la version la plus longue de la méthode
draw image qui
attend neuf arguments. Ces neuf arguments
sont l'image
que nous voulions dessiner, la source x, y, source avec la hauteur de la zone que nous voulons
recadrer à partir de l'image source. Et destination x, destination. Pourquoi la destination avec et hauteur
de la
destination pour définir où se trouve la destination sur laquelle je veux placer cette image recadrée. Donc, si je lui passe un zéro comme source x et zéro
comme hauteur de la source. Sprite avec une hauteur de sprite comme
celle-ci comme largeur et hauteur de la source, je dois l'épeler correctement. Nous dessinons maintenant le cadre supérieur gauche
de notre feuille de calcul. Comme je l'ai déjà dit, je vais définir des
positions x et y distinctes pour la feuille de calcul. Il existe
différentes manières de procéder. Je peux simplement positionner l'image directement
au-dessus de la collision x, qui est le point central du cercle
de collision, moins la largeur de
l'image multipliée par 0,5. Cela centrera l'image horizontalement exactement au-dessus
du cercle de collision. Pour réellement appliquer cela, je dois utiliser le sprite X comme propriété x de
destination transmise
à la méthode draw image ici, soyez prudent lorsque vous passez des
arguments à la méthode draw image. L'ordre dans lequel vous transmettez ces arguments est
très important. D'accord, si je rafraîchis la page, je peux voir qu'elle est correctement
centrée horizontalement. Je fais la même chose
pour Sprite y, et je l'utilise comme destination. Pourquoi la propriété a été transmise
à la méthode Draw Image. La feuille de calcul se trouve maintenant directement au-dessus
du cercle de collision. J'ai dit rayon
de collision à une valeur plus petite. Je veux que cette petite
zone de collision soit positionnée à la base de la plante
où se trouve la pierre. Parce que ce sera la zone
solide qui touchera le sol dans laquelle les personnages
du jeu
devront se déplacer. Comme nos sprites ont défini une taille
de 250 fois 250 pixels, je peux en fait utiliser une valeur
codée en dur ici. Plus 40 le déplaceront vers le haut. -40, -50, -60, -70. Oui, cela semble correct. J'ai dit que le nombre
d'obstacles était de dix.
10. Règles de positionnement: Et si je
voulais m'assurer que non seulement les obstacles
ne se chevauchent pas, mais aussi qu'il y ait un espace supplémentaire d'au moins 100
pixels entre les deux. Ils sont donc répartis
de manière
plus uniforme autour de la zone de jeu
disponible, tout
en laissant suffisamment d'espace entre
les obstacles. Les personnages du jeu peuvent
facilement les contourner. Je crée une
variable d'assistance que j'appelle, par exemple ,
distance buffer, et je la règle à 100 pixels comme ceci. Ensuite, j'ai inclus un
tampon de distance ici dans certains rayons pour appliquer ce
tampon entre les obstacles lorsque
nous les plaçons. Agréable. Pour m'assurer que cela fonctionne, j'augmente la distance
tampon de 250 pixels. Cela devrait le rendre
encore plus évident. Oui, c'est ainsi que nous pouvons facilement contrôler l'espacement des obstacles. Je tiens également à m'
assurer que les images de
sprites d'obstacles sont entièrement dessinées dans la zone de jeu et qu'elles ne sont pas partiellement cachées
derrière les bords. J'aurais pu utiliser ce constructeur de classe d'
obstacles Insight lors de la définition initiale de ces
valeurs. Ou je peux aussi le faire ici, étant donné que nous ne dessinons pas autant d'obstacles et
que leurs positions ne sont
calculées qu'
une seule fois lors du chargement de la première
page. De toute façon, je m'assure que le bord gauche de la feuille de calcul des obstacles
est supérieur à zéro, afin qu'elle ne soit pas cachée derrière
le bord gauche de Canvas. En même temps, je m'
assure que le
bord droit n'est pas masqué. sprite X doit donc être
inférieur à la largeur de la zone de jeu moins la
largeur de l'obstacle. Agréable. Lorsque je rafraîchis la page, je peux voir horizontalement, les obstacles sont toujours
parfaitement visibles. Pour la position verticale, je
veux vérifier si l'image, le point central
du cercle de collision situé à plus zéro à la verticale, ne
suffira pas. Je souhaite définir une zone
réservée à cette illustration d'
arrière-plan. Je ne veux pas que des obstacles apparaissent au-dessus de cette zone. Je crée une propriété
appelée marge supérieure. Je suppose que cette zone supérieure mesure
environ 260 pixels de hauteur. Vérifions-le ici. Oui, la version 2.6D semble correcte, parce que je voulais m'
assurer que la base des obstacles ne
chevauche pas cette zone supérieure, mais cela ne me dérange pas que le haut des feuilles de calcul des obstacles se
chevauche de cette manière, car cela donne l'impression que la plante d'obstacles
se trouve devant l'
arrière-plan pour que nous puissions la voir. Donc c'est très bien. Je vais également vérifier si
le point central du cercle de la zone de collusion d'
obstacles est inférieur à la hauteur
de la zone de jeu. Je veux des marges. Je peux par exemple créer une
variable d'assistance égale au rayon de collision de l'obstacle d'
essai multiplié par deux. Je remplace cette valeur
codée en dur par cette
propriété de marge supérieure en pointillés que nous avons définie. De plus, je veux lui
donner une marge supérieure supplémentaire
afin que les personnages, et
en particulier les ennemis, puissent se
faufiler entre les obstacles et franchir des limites. Traverser le terrain de jeu horizontalement de droite à gauche. Je vais également tenir compte
de la marge depuis le bas de la zone de jeu
pour y créer de l'espace. Nous avons écrit un code qui
place automatiquement des obstacles
dans notre monde de jeu. Ces obstacles ne se chevauchent jamais et leurs
zones de corrélation sont placées de manière à laisser suffisamment
d'espace entre eux. Cela facilitera grandement la prochaine
étape car nous avons besoin d'ennemis
et de PNJ amis pour pouvoir
les contourner automatiquement
à l'aide d'une intelligence
artificielle très simple. Nous avons différentes
images pour les obstacles, mais pour le moment, nous
ne dessinons que le premier cadre en haut à gauche
à la coordonnée zéro-zéro. Nous pouvons recadrer
différentes zones à partir de la feuille de calcul des obstacles, de la zone de recadrage
horizontale. Nous allons partir de la
position que nous transmettons comme argument
source x pour
dessiner une image ici, zéro fois le sprite avec
ce cadre. Un. La largeur du sprite sera celle de ce cadre. Deux, c'est 13, c'est celui-ci. Retour à zéro. Pour sélectionner la ligne à partir de
laquelle nous allons recadrer, nous utilisons la source Why argument here ? Encore une fois, nous multiplions
le nombre de
règles par la hauteur réelle des cadres lumineux des
individus, zéro fois la hauteur du sprite est ce terme
hauteur du sprite est celui-ci. Maintenant, nous en déroulons
deux et il
n'y a pas de ligne trois car nous
partons de la ligne zéro. Les images sont dessinées et
recadrées par le haut. Donc, au lieu de coder en dur ces valeurs qui sont
actuellement définies sur 00, transformons-les en
propriétés de classe pour plus de clarté. Et c'est un contrôle. Ce cadre d'affichage x déterminera quelle colonne nous nous trouvons dans
notre feuille de calcul des obstacles. Si je fais un nombre aléatoire de 0 à 4, cela ne fonctionnera pas. n'y a pas de colonne 1.74, par exemple nous avons besoin d'entiers, de nombres
sans décimales. Je l'enveloppe donc dans
Math.floor pour arrondir la valeur
aléatoire générée par Math.random à l'entier inférieur le
plus proche. Ce code me donnera zéro
ou un, ou deux ou trois. Ainsi, l'une de nos colonnes de sprites, lorsque nous multiplions
ces entiers par la largeur d'un
seul cadre de sprite et que nous transmettons cette valeur comme argument source à la méthode de
dessin de l'image,
nous définissons
une coordonnée de
recadrage horizontale. Cela a parfaitement fonctionné. Je ferai de même pour le cadre y, qui déterminera la ligne des sprites. Nous n'avons que trois rôles. Cette ligne de code me
donnera des entiers, soit zéro, soit un ou
deux correspondant
au nombre de lignes disponibles dans notre feuille de calcul des
obstacles. Nous pouvons maintenant remplacer ce zéro
codé en dur par
ce cadre de points y. Donc, l'argument source Pourquoi mais invité à dessiner
une image
sera ce cadre de points y fois
cette hauteur de sprite. Je vais le faire dans une seconde. Les valeurs aléatoires dans l'image x
et l'image pourquoi combinées nous
donneront une image aléatoire parmi ces 12 obstacles
disponibles sera attribuée à
chaque objet d'obstacle image
aléatoire de cette
feuille de calcul lui sera attribuée à
chaque objet d'obstacle. J'en finirai un peu plus tard.
11. Physique: Sur l'objet du faisceau principal, je crée une méthode que j'
appelle vérifier la collision. Je veux que ce soit une méthode utilitaire
réutilisable qui prend l'objet a et l'objet B et qui
les comparera et vérifiera s'ils
entrent en collision ou non. Nous pourrons l'utiliser dans
toute la base de code
chaque fois que la détection de collision entre deux cercles est nécessaire. Dans la façon dont je construis mon jeu, tous les personnages et objets
auront une zone de collision circulaire, qui constituera une base solide
que rien ne pourra
traverser et où tout
réagira et
contournera tout. Grâce à cela, nous pouvons également
faire bouger les choses. Je vais vous montrer comment vérifier la
collision entre deux cercles. Nous avons le cercle a
et le cercle B. Ici. Nous devons d'abord vérifier dx, la distance entre le point
central du cercle a et le point central du cercle B sur l'axe
horizontal des abscisses. Ces méthodes réutilisables ne
fonctionneront que si tous les objets concernés possèdent des propriétés ayant
la même convention de dénomination. Nous allons donc nous assurer d'avoir
nommé les positions
x et y chaque objet comme collision
x et pourquoi ? J'utilise ces noms de propriétés trop
descriptifs pour qu'il soit très
clair quand les
coordonnées x et y sont liées au cercle de la zone de
collision et quand elles se rapportent à la position de la feuille de
sprite de l'image. Il s'agit d'un tutoriel, donc je veux que les choses soient très
claires et faciles à comprendre. Nous aurons également besoin d'un D, pourquoi la différence entre le point
central du cercle a et le centre du cercle B sur l'axe vertical y. Ensuite, nous voulons connaître la distance entre
ces deux points centraux. Donc, l'hypoténuse, le
côté le plus long de ce triangle
droit imaginaire, à angle droit de 90 degrés, est là. Et c'est la
distance b Dagger a une formule
théorique ou bien des mathématiques intégrées
seraient une méthode d'hypoténuse. Et nous lui transmettons le Dui d'abord et le x comme
deuxième argument. Pour déterminer s'il y a eu collision ou
non, nous comparons la distance entre
ces deux points centraux avec le rayon du cercle a
plus le rayon du cercle B Je vais enregistrer cette valeur en
tant que variable personnalisée, j'appelle par exemple certains rayons. Donc, si la distance est
inférieure à la somme des rayons, nous savons que le cirque entre en collision. Si la distance est égale à
la somme sur l'ADI, les cercles se touchent. Si la distance est
supérieure à la somme des rayons, nous savons qu'il n'y a pas de collision. Cette fonction
renvoie simplement la valeur true en cas collision et la valeur false s'
il n'y a pas de collision. Utilisons notre fonction de
vérification personnalisée des collisions. Ici, dans la
méthode de mise à jour de la classe du joueur, nous vérifions s'il y a une collision
entre le joueur et les obstacles. Nous avons un objet pour un joueur et plusieurs objets obstacles. Donc, pour tout comparer, nous allons faire appel à un réseau d'obstacles, qui contient tous les objets d'obstacles actuellement
actifs. J'appellerai chaque objet du tableau avec un nom de variable
auxiliaire, un
obstacle et
la
méthode de collision par obstacle et vérification du journal de la console que nous venons de définir. Nous savons qu'il s'attend à ce que l'
objet circulaire a et
l'objet B soient des
arguments pour comparer la distance leurs points centraux à
la somme des rayons. Je passe donc ceci, ce qui signifie que cet objet joueur, cercle et l'obstacle que
nous sommes en train parcourir à
vélo avec cette méthode
ForEach sous forme de cercle B. Gardez à l'esprit que cette méthode réutilisable de vérification et de
collision ne
peut comparer
que des objets dont la propriété de
collision x, de collision et de
rayon est définie dans leur constructeur de
classe. Je vais donc m'assurer de conserver les mêmes conventions de dénomination pour tous les objets du jeu
que nous construisons aujourd'hui. Au fur et à mesure que le joueur se déplace,
nous devenons faux et vrais sur la console. On dirait que cela fonctionne. En fait, n'
enregistrons le mot collision sur console que lorsqu'une collision entre un joueur
et un obstacle se produit. Maintenant, il est encore plus facile de voir
que notre code fonctionne. Parfait.
12. Méthode de détection de collision: Dans la méthode de rendu, je
vais d'abord dessiner les obstacles, donc derrière et le joueur après, pour qu'ils soient dessinés au-dessus. Et si je voulais également
résoudre nos collisions ? Ce que je veux dire, c'est que s'ils entrent
en collision avec un obstacle, je ne veux pas qu'il puisse le
franchir comme ça. Je veux que le
cercle du joueur soit repoussé un pixel par au cercle d'obstacles dans
la direction qui pointe directement vers le centre
de l'obstacle. C'est simple, nous allons
rendre les obstacles solides. Le joueur va
réellement contourner les obstacles et cela
créera une belle physique. Laisse-moi te montrer. J'ai déjà calculé tout ce
dont j'ai besoin pour obtenir ces informations, notre méthode de vérification par
collision personnalisée, mais cette fonction ne
renvoie actuellement que vrai ou faux. J'ai besoin de cette méthode réutilisable
pour renvoyer plus de valeurs afin que nous puissions les utiliser
dans la classe du joueur pour calculer
la résolution de collision
des fonctions vectorielles . Les méthodes en JavaScript peuvent
renvoyer une valeur comme celle-ci, mais elles peuvent également renvoyer un tableau contenant
plusieurs valeurs. Je souhaite renvoyer l'état de collision vrai ou
faux en tant que premier élément du tableau avec
un indice de zéro. Nous voulons également
renvoyer la distance nous calculons à la ligne 127. Nous aurons également besoin
de certains rayons de la ligne 128. Et nous aurons besoin de DX et
DY à partir des lignes 100.2526. présent, notre méthode de
vérification personnalisée des collisions permet
non seulement de vérifier si une collision
se produit ou non, mais
elle nous donne également
d'autres valeurs à partir de calculs effectués en cours de route. Il est important de mémoriser l'ordre dans lequel ces valeurs nous sont
renvoyées. L'élément dont l'indice est
zéro est-il vrai ou faux ? L'élément dont
l'indice est égal à un est la distance. Certains rayons sont indexés sur. Dx est l'indice trois et d y est indexé pour. Je vais simplement copier ce tableau
qui est renvoyé ici. Et j'ai commenté juste pour que je puisse le voir comme
une référence utile. Maintenant, je veux prendre chacune de ces valeurs et les enregistrer sous forme de variables
distinctes afin que
nous puissions les utiliser pour calculer résolution
des
collisions et pousser deux joueurs dans la
bonne direction,
loin de l' obstacle auquel il se heurte
actuellement et de sa largeur Je vais utiliser ce que l'on appelle une assignation de
restructuration. Écrivons-le et je l'
expliquerai quand nous aurons tout
vu. Je dis que let variable
est ce tableau. Et cela revient à
vérifier la collision entre cet objet du joueur et l'obstacle qui, pour chaque méthode, est
en train de franchir. Je dois remplacer
cette première expression un nom de variable. Je voulais appeler ça, je veux appeler ça une collision. Ce sera cette valeur
vraie ou fausse en fonction de la distance
entre le point central du cercle. Donc, si c'est vrai,
il y a collision. Si c'est faux,
il n'y a pas de collision. Cette structure et cette syntaxe d'
affectation sont une expression JavaScript
qui permet de
décompresser des valeurs provenant de tableaux ou propriétés d'objets
dans des variables distinctes. En gros, ici, créez
cinq variables pour moi. La première variable
appelée collision est le tableau renvoyé lorsque nous appelons la
méthode check collision entre ce joueur et l'indice d'
obstacle zéro. La variable de distance est l'indice 1 du
tableau, et ainsi de suite. Cette structure et
cette
mission le font automatiquement en
arrière-plan. Il crée ces cinq
variables et les associe. Les valeurs situées
à ces index dans le tableau sont renvoyées par la méthode
check collision. Cela peut être un
peu étrange si vous
ne l'avez jamais vu avant JavaScript, cette structuration est une bonne
chose pour vous familiariser. Les frameworks modernes les
utilisent beaucoup et
se contentent de prendre le tableau renvoyé
par la méthode check collision. Et j'attribue chaque valeur à ses noms de variables distincts
afin de pouvoir les utiliser ici. Nous voici donc dans la
méthode de mise à jour de la classe du joueur. Nous parcourons à vélo un ensemble d'
obstacles en comparant le joueur à
chaque objet d'obstacle. S'il y a collision
entre le joueur et l'obstacle, si la variable de collision est vraie, la console enregistre AAA. Cela fonctionne. Je voulais
créer un vecteur, une sorte de petite ligne, à
1 pixel de long. Cette ligne indiquera la
direction dans laquelle le joueur doit être poussé pour
résoudre la collision circulaire, afin
de s'assurer que la collision entre le joueur et obstacle se repoussent, faisant
glisser le joueur le long
du rayon de l'obstacle au lieu de le
traverser directement. vecteur horizontal
sera le rapport entre Dx, distance entre le joueur et le point central de l'
obstacle sur l'axe X horizontal, et la distance réelle
entre ces deux points que nous avons calculée avant d'utiliser la méthode
check collision. Parce que dx
sera toujours inférieur à la distance, parce que la distance est
l'hypoténuse est toujours le côté le plus long du triangle droit
imaginaire. L'unité x
aura toujours une valeur de 0 à 1, car nous divisons une
valeur plus petite par une valeur plus grande. L'unité y sera le
rapport entre Dui, la distance entre les points
centraux sur l'axe vertical et la distance réelle
entre les deux points centraux. Encore une fois, ce sera une
valeur comprise entre 0 et 1. Il peut également s'agir de valeurs
négatives en fonction de la position de
nos objets les uns par rapport aux autres sur les axes horizontal et vertical. Donc, en fait,
les unités x et y auront une valeur comprise entre moins
un et plus un. Si je console les
unités x et unité, pourquoi nous pouvons voir ces valeurs La combinaison de
ces deux valeurs ajoutées à la position
horizontale et verticale du joueur position
horizontale et verticale pour chaque image d'animation la
fera se déplacer dans une
certaine direction et certaine vitesse par rapport
au point central de l'obstacle. Pour ce faire, je prends l'exposition aux
collisions du
joueur, le point central du cercle de collision du joueur, pour la pousser hors du rayon de l'obstacle avec
lequel il entre en collision. Je le déplace horizontalement
jusqu'à la position du point
central du
cercle d'obstacles, plus la somme des rayons du cercle du joueur et
du cercle d'obstacles, plus un pixel supplémentaire
en dehors des termes, ce ratio unitaire x qui lui donne la bonne direction en s'
éloignant du point
central de l'obstacle. Nous faisons la même chose verticalement. point central du
cercle de collision du joueur sera déplacé à la position du
centre de collision du cercle d'obstacles plus la somme des rayons de l'obstacle
et du cercle du joueur plus un pixel (unité Y) pour lui donner la bonne
direction de poussée. J'essaie d'expliquer cela d'une
manière très conviviale pour les débutants, mais ne vous inquiétez pas si ce n'est
toujours pas clair. C'est une technique importante
et chaque fois que vous l'utiliserez, vous vous
familiariserez de plus en plus avec ce manteau. Finalement, il cliquera
pour vous expliquer comment cela fonctionne. Tout ce que vous devez
comprendre ici, c'est que ce code pousse
le joueur d'un pixel en dehors du rayon de collision de l'obstacle dans la direction
opposée au point central. Et c'est ainsi que vous créez une très simple mais très efficace simulation
physique
très simple mais très efficace dans votre jeu. Essayez de déplacer le joueur. Ça fait du
bien, n'est-ce pas ? Soudain, nos cercles d'obstacles se sont transformés en objets solides et
impossibles. Bravo si vous avez
suivi jusqu'au bout, c'est la principale astuce que nous utilisons aujourd'hui pour
notre jeu de physique. J'ajuste le modificateur
de vitesse à une valeur plus petite. Nous avons appris à faire en sorte que
le joueur se déplace vers une souris ou vers un
point précis dans un espace 2D, et comment le faire
contourner automatiquement des obstacles
solides. C'est une
technique puissante et vous pouvez en faire
plus que vous ne pouvez l'imaginer. Nous allons explorer
certaines de ces questions aujourd'hui. J'espère que tu t'amuses bien.
13. animation de sprite directionnelle: J'ai préparé une
feuille de sprite
directionnelle spéciale pour les joueurs pour ce cours. Vous pouvez le télécharger dans la section
des ressources ci-dessous. Je vais inclure quelques couleurs
alternatives. Le mien est probablement
trop bleu pour les champignons
dans mon jeu. Je vais le cacher avec du CSS ici. Constructeur de classe Inside Player. Je crée une référence à cette image en utilisant
get element by ID, et je l'enregistre en tant que propriété d'image à
points. Dans notre méthode de dessin personnalisée, je prends des contextes et
j'appelle
des toiles intégrées la méthode de dessin d'image
que nous utilisions déjà auparavant. Nous avons déjà dit que la méthode draw image nécessite
au moins trois arguments. L'image que nous voulons dessiner
et x et y devaient la dessiner. Cela ne fera que dessiner la feuille de calcul
entière. Nous pouvons lui transmettre la largeur
et la hauteur pour insérer la feuille de calcul entière
dans la zone spécifiée. En fait, nous n'avons pas défini
ces propriétés. sprite ayant la largeur d' une seule image
sera de 255 pixels. La hauteur du sprite est également de 255. Ensuite, nous créons des propriétés de
largeur et de hauteur distinctes pour tenir compte du potentiel si nous voulions l'
introduire ultérieurement. Maintenant, nous insérons l'intégralité de
la feuille de calcul dans la zone d'
un seul cadre de sprite. Vous
savez probablement déjà que nous aurons besoin version
la plus longue de la méthode de
dessin d' image
dans laquelle nous ajouterons la source x, y, la largeur et la hauteur de la source. Ces valeurs vont d'abord
découper une partie de l'image, dans notre cas, une
seule image de sprite. Ensuite, nous dessinons ce cadre, la position définie par
les quatre derniers arguments. Dessiner le cadre supérieur gauche à la coordonnée
zéro-zéro est simple. Nous venons de le faire avec une feuille de calcul des
obstacles, source x, y, z, zéro pour définir le début
du rectangle de recadrage. Et Sprite with et
Sprite height comme arguments de largeur de source et de
hauteur pour définir sa taille. Maintenant, nous ne voyons qu'un seul cadre. Je vais calculer la position de l'image de la
feuille de calcul par rapport
à la collision et aux
coordonnées Y de collision du joueur. Il inscrirait ces deux propriétés
distinctes juste pour plus de clarté. Gardez donc à l'esprit que
ces propriétés définissent le point central du cercle des collisions entre
joueurs. Ces deux propriétés, nous allons
définir le coin supérieur gauche de l'image du cadre de la
feuille de calcul que nous sommes en train de dessiner pour
représenter le joueur. Sur nous. Les coordonnées sphériques
r à partir du point central, rectangle et les coordonnées de l'image proviennent de son coin supérieur gauche. Et l'image et le rectangle
vont vers le bas à droite, en fonction de leur largeur
et de leur hauteur à partir de là. Nous devons en tenir compte lors de l'
écriture du code suivant. Sprite X sera positionné par rapport
à la zone de collision. Ce sera la collision x, le point central du cercle de
collision moins la moitié de la largeur du cadre du
joueur. Comme ça. Je dois utiliser le sprite X dans le dessin comme argument de destination
x ici. Pour que cela fonctionne, nous
devons recalculer cette valeur chaque fois qu'
une collision x est mise à jour. Je dois donc mettre cela dans
la méthode de mise à jour ici. Et je le fais aussi pour Sprite y, qui sera la collision y moins la moitié de la taille du joueur. Je peux le supprimer ici. Et j'utilise Sprite.
Pourquoi cette propriété est ici un argument Y de destination
transmis à la méthode Draw Image. Il est maintenant positionné sur le dessus. En fait, je veux que ce cercle de
collision corresponde
le plus possible à la petite ombre
au sol sous le joueur, car c'est le point de
contact que nous utiliserons lorsque nous interagirons avec
d'autres objets dans notre jeu. Comme le lecteur a une taille de pixel
fixe, je peux la compenser par
une valeur codée en dur. Si nous devions redimensionner nos
personnages dans ce jeu, j'utiliserais une valeur
relative ici. -100 déplace l'image du joueur vers le haut. C'est bon pour le moment.
14. angles d'animation: Comme nous l'avons fait avec la feuille de calcul des
obstacles. Je voulais naviguer dans notre feuille de calcul en
passant d'une image à l'autre. La navigation horizontale est gérée en multipliant sprite par un entier représentant
la colonne du passé de
la feuille de calcul en tant qu'argument source ici. Lorsque nous aurons parcouru cette étape, nous animerons des directions
individuelles, boucles d'animation
individuelles
pour passer d'une direction à l'autre
dans la feuille de calcul De
la même manière que notre
feuille de calcul spécifique est organisée aujourd'hui, nous devons multiplier la hauteur du
sprite par un entier représentant le rôle du
sprite, vous pouvez voir une ligne, zéro étant joueur orienté vers le haut,
loin de nous. Rho One est en haut à droite et
le joueur fait-il face à la droite ? Trois est en bas à droite car il est orienté vers le bas
vers la caméra. cinquième ligne de notre feuille de calcul représente la face du joueur en bas à gauche, sixième est tournée vers la gauche. Je pense que tu as compris l'idée. J'ai mis ces nombres entiers
dans les propriétés de classe. Cadre x pour une
navigation horizontale. Châssis Pourquoi, pour la verticale, je remplace ces
valeurs codées en dur par mes nouvelles variables, et maintenant je peux modifier image
que nous sommes en train de
découper de
la feuille de sprite du joueur en valeurs différentes à l'
image x et à l'image pourquoi ? Je voulais changer de cadre, vient la ligne que nous sommes en train d'animer
à partir de la feuille de sprites, où
vient la ligne que nous sommes
en train d'animer
à partir de la feuille de sprites,
qui déterminera
la position du joueur. Je veux que cela dépende l'angle actuel
entre la souris et le joueur et de la
position où ils se trouvent actuellement l'un
par rapport à l'autre. Pour cela, nous avons une
méthode intégrée appelée Math dot eta. Et pour Martha, atan2 renvoie un angle
en radians entre l'axe X positif et la ligne projetée de zéro à zéro
vers un point spécifique. Nous allons l'utiliser pour calculer l'angle entre le joueur
et le curseur de la souris. Et en fonction de cet angle, nous sélectionnerons la ligne la feuille de calcul que nous
voulons animer afin que le joueur soit toujours face à la direction dans laquelle
il se déplace. Vers le curseur de la souris. Nous aurons besoin de DX et de DY. Je les ai donc déplacés ici. Ces valeurs ont donc calculé
la distance entre le joueur et le curseur de la souris
horizontalement et verticalement. Gardez à l'esprit que cela
fait une différence si vous utilisez d'abord la souris
ou le joueur en premier. Dans ce calcul, j'ai déjà écrit ce
code ici auparavant. Sans réfléchir, nous l'
utiliserions pour cela, se peut
donc que nous devions nous y
adapter un peu. Je vais vous montrer
exactement ce que je veux dire. Les données de Martha s'attendent à ce que
dy, dy et dx soient le
deuxième argument. Je vais consulter l'angle que nous calculons et je peux
voir qu'il change. Et les valeurs vont de -3,14 moins pi à
plus 3,14 plus Pi. Cela est vrai parce que nous savons que le cercle complet est égal à deux pi, soit environ 6,28 rad, ce qui
se convertit en 360 degrés. Je vais répéter cette méthode. Atan2 renvoie un angle
en radians entre l'axe X positif et l'alignement projeté de zéro à zéro
vers un point spécifique. Comme j'utilise la souris d'abord et la position du joueur ensuite, lorsque je calcule DX et DY, j'obtiens des valeurs à partir de données de base. Pour en savoir plus, la position actuelle de la souris
représente 0,00 et position du
joueur est le point vers lequel nous projetons une ligne. Pour des raisons
de qualité visuelle, cela fonctionnerait bien mieux si
Player était composé de zéros statiques, zéros, d'un important, mais
je vais le laisser tel quel. Et à partir des valeurs que j'
obtiens dans la console, je vais créer ce graphique
avec des points d'arrêt en radians. C'était en fait facile
à créer car je
n'avais besoin que d'une seule
valeur comme point d'ancrage. Et je savais que toute la zone se
situait entre -3,14, deux plus 3,14. Et nous avons huit instructions pour les
joueurs. Chaque tranche était donc de 6,20 8/8. Quoi qu'il en soit, vous n'
avez pas nécessairement besoin de comprendre
tout cela, n'est-ce pas ? Maintenant, lorsque nous aurons le code complet, vous pourrez jouer avec les
valeurs qui espérons-le, apporteront plus de clarté. Il m'a fallu un certain temps pour utiliser les mathématiques mais atan2 avant de
bien comprendre. Donc, si c'est la
première fois que vous le voyez, ne vous mettez pas trop de
pression. Si je mets l'écran en pause, c'est le 0,00, c'est la ligne projetée
vers un autre point. Et les données de Martha et deux nous
donnent un angle en radians entre cet
axe X positif et cette droite. Donc, en utilisant ce journal de
console pour obtenir un point d'ancrage afin que je puisse voir quelles valeurs d'angle
nous obtenons. J'ai créé ce visuel
d'assistance, que je vais maintenant utiliser
pour échanger correctement les lignes notre feuille de calcul afin que le joueur soit toujours
face à la souris. Si l'angle est inférieur à -1,17, définissez le cadre y sur zéro. Je vais le copier à quelques reprises. -0,2, 39 est une image y un
plus 0,39 est une image. rayonnement de Y à 1,17 est encadré. Y3, 1.96 est le cadre Y4. Voyons voir. Jusqu'à présent, cela
fonctionne très bien. Je pense que nous l'avons. Je
peux supprimer la console. log 2.74 est la cinquième image. Cette zone est un peu étrange car
le cercle se termine et commence. Je dois dire si l'
angle est inférieur -2,74 ou si l'angle est supérieur à
plus 274. Je souhaite utiliser Frameworks Six. Si l'angle est inférieur à -1,96, le cadre y est égal à sept. Faites attention aux crochets ici, moins n valeurs plus et
moins que les opérateurs. Si vous obtenez un comportement
inattendu, assurez-vous que tout ce
code est le même que le mien. Il est facile de faire
une petite erreur ici et de casser votre
code accidentellement. Pour que cela fonctionne
dans toutes les directions, je dois l'ajuster
un peu. Je peux par exemple prendre ces diapositives et les mettre ici, car avec l'instruction
else-if, il est important de savoir laquelle
est cochée en premier. Parfois, je réduisais le modificateur de vitesse du
joueur à trois pour que nous puissions
clairement voir comment il évolue. Alors que Destin. Nous pouvons maintenant faire pivoter le joueur dans
les huit directions. Parfait. Nous en apprendrons davantage sur l'animation des sprites
plus tard dans le cours. Pour l'instant, j'en suis content.
15. Mode de débogage: Puisqu'il s'agit d'un
jeu de physique où nous
plaçons des zones de collision à
la base de chaque objet. Nous voulons pouvoir passer rapidement
d'une vue où ces zones de collision
sont visibles à une vue invisible. Cela nous aidera à peaufiner la physique et les
éléments de jeu au fur et
à mesure que nous
les développons , tout en nous donnant un moyen facile de vérifier comment les
modifications que nous venons d'apporter seront visibles pour les joueurs qui
ne verront pas ces cases. Je veux créer un mode de débogage en appuyant sur la lettre
D du clavier Nous activerons et désactiverons tous les éléments
de
collision auxiliaires sur la classe
principale du jeu, je crée une propriété
appelée ainsi pour déboguer. Au départ, je l'ai défini comme vrai ici, là où nous avons
placé les auditeurs de nos événements, puis j'en crée un autre. Nous écouterons l'événement
clé. Disons simplement un objet d'événement dans le
journal de la console. Lorsque je sélectionne Canvas en
cliquant dessus, puis que j'appuie sur
n'importe quelle touche du clavier, nous obtenons cet objet d'événement de
clavier généré automatiquement. À l'intérieur, nous avons une
propriété appelée clé. Vous pouvez voir que j'appuie sur
la lettre R, donc la clé dont le prix était fixé se trouve à l'intérieur de la propriété à point E. Je dis que si la touche E est D, définissez la propriété de débogage de la ligne
123 à sa valeur opposée. Donc, si c'est actuellement vrai, définissez-le sur faux. Si c'est faux, définissez-le sur vrai. De cette façon, si vous présentez
la même lettre clé D, vous activerez et désactiverez le
mode de débogage. J'ai testé en testant ou en déboguant la
connexion à la console. J'appuie sur le d encore et encore. Et dans la console, je vois qu'il bascule
entre vrai et faux. Parfait. Je supprime
le journal de la console, apparais dans la
méthode de dessin selon la classe d'obstacles. Je dis que si ce chien est venu vérifier
si c'est vrai dans un restaurant, dessine le cercle de la zone de collision. Maintenant, je peux appuyer sur la lettre D, les afficher et les masquer. Cela fonctionne bien. Je veux faire de
même pour le joueur. Si ce jeu à débugger
est vrai dans un restaurant, tracez le cercle de collision
ainsi que la ligne entre le
joueur et la souris. Dans ce cas, la position et la
taille des boîtiers
principaux ne sont pas encore parfaites, mais nous avons maintenant toute la logique
en place, excellent travail. Je peux réduire le
rayon de collision de chaque obstacle pour qu'il corresponde mieux à la partie où il
touche le sol. Nous avons ici différents types d'
obstacles. Le champignon et cette grosse plante
carnivore devraient probablement avoir des cercles de
collision différents , ce qui peut être facilement fait. Mais pour l'instant, j'en suis
content. Vous pouvez voir que la formule de
collision nous avons écrite auparavant est tout ce
dont nous avons besoin pour donner au joueur une capacité de recherche de chemin très
simple. Il contournera simplement
les obstacles automatiquement. Et comme nous avons placé les obstacles de
manière à ce qu'ils soient
toujours des espaces entre les deux, il est peu probable que le
joueur reste bloqué. Je peux également constater que je n'obtiens que les quatre premières images d'obstacles, ce qui me rappelle
d'aller jusqu'à la ligne 10008 et d'inclure la valeur Y de l'
image aléatoire comme source. Pourquoi argumenter dans la méthode de
dessin d'images par obstacles. Maintenant, je reçois au hasard l'une
des images du 12e obstacle. Vous pouvez jouer avec cela, positionner
et dimensionner. Votre manuel dit
autre chose si vous le souhaitez. Je suis content de ce que
nous avons fait jusqu'à présent.
16. Limites de mouvement du joueur: Je voulais m'assurer que
le joueur ne puisse pas marcher trop haut au point de se trouver au-dessus de cette zone d'illustration d'
arrière-plan. Créons des limites
horizontales. D'abord. Si le point central cercle
de collision du joueur est inférieur à la
coordonnée x zéro plus le rayon de
collision, définissez-le sur zéro plus le rayon de
collision. Ainsi, lorsque le
bord gauche du cercle touche le
bord gauche de la zone de toile, ne le laissez
pas aller plus à gauche. Je veux faire la même
chose pour le bord droit. Bien entendu, nous pouvons supprimer ce
zéro plus ici et ici. Si le point central du
cercle de collision du joueur est supérieur la largeur du jeu moins le rayon du cercle de
collision du joueur. Assurez-vous que ça ne peut
pas aller plus loin, non ? Agréable. Limites verticales. Si la collision y est inférieure coordonnée
verticale
zéro plus la marge supérieure, nous l'avons définie comme étant à 260 pixels du haut plus le rayon de
collision. Assurez-vous que le joueur ne
peut plus monter. Cela fonctionne bien. Oui, c'est ce que je voulais. Encore une fois, nous pouvons supprimer
zéro plus ici et ici. Limite inférieure. C'est simple. Si la collision y est
supérieure à la hauteur du jeu moins le rayon de
collision, assurez-vous qu'elle s'arrête
là comme suit. Cela fonctionne si je réduis le rayon de
collision des joueurs à celui des
obstacles. En raison de la marge que nous avons définie lors du
positionnement des obstacles, un joueur pourra toujours se faufiler
entre les obstacles. Les bords de la zone de jeu. Il n'y en a pas. Donc, ici, j'augmente cette
marge. Ils devraient le faire. Vous pouvez comparer votre code avec le code source
en cours que je
vais inclure et télécharger
dans la section projet ci-dessous à plusieurs reprises au cours de ce
cours au
fur et à mesure que nous progressons dans plusieurs reprises au cours de ce
cours au notre projet.
17. FPS: Je peux voir que le bas
de la feuille de
calcul est coupé sur les rangées inférieures. C'est parce que la hauteur
d'une image est en fait de 256 pixels. Maintenant c'est corrigé. Dans l'éditeur de code Visual Studio, je sélectionne l'option Afficher le
texte pour en faire un saut de
code vers une autre
ligne s'il ne tient pas. Si c'est trop long. Je
voulais configurer FBS pour l'ensemble du jeu, car
dans mes projets précédents, beaucoup d'entre vous ont mentionné
que les jeux tournaient trop vite sur votre jeu. Les écrans à taux de
rafraîchissement élevé demandent une image d'animation ou une
méthode que nous utilisons ici s'
ajustera automatiquement au taux de rafraîchissement de l'écran. Donc, pour les écrans normaux, ce sera environ
60 images par seconde. Mais sur certains des nouveaux
écrans de jeu que les utilisateurs utilisent, cette vitesse serait le double, ou peut-être pas exactement le
double, mais beaucoup plus rapide. Nous allons calculer
le temps delta, le nombre de
millisecondes qui se sont écoulées entre chaque objectif de l'image d'animation de la
demande. Et nous n'autoriserons
le jeu à diffuser l'image d'animation suivante que lorsqu' un certain nombre de
millisecondes se sera écoulé. Nous pouvons calculer
le temps delta
ici dans notre fonction
d'animation personnalisée. Tout d'abord, j'ai défini la dernière fois en dehors de la
fonction comme ceci. Au départ, je l'ai mis à zéro. Cette variable contiendra toujours une référence à l'
horodatage de la
boucle d'animation précédente afin que nous puissions le
comparer à l'horodatage
actuel. Et la différence entre
eux sera le temps delta. Le cadre d'animation de la demande présente deux caractéristiques spéciales. Comme nous l'avons dit, il essaiera
automatiquement de s'
adapter au taux de rafraîchissement de l'
écran, dans la plupart des cas, 60
images par seconde. Il générera également
automatiquement un horodatage
que nous pourrons utiliser. Et il transmettra
cet horodatage comme argument à la
fonction qu'il appelle. Dans notre cas, animez. Imaginez qu'il passe cet
horodatage ici, comme ça. Automatiquement, il est
généré automatiquement. Pour l'
utiliser, il suffit de
lui attribuer un nom de variable ici. Je vais appeler cela un horodatage,
orthographié comme ceci Faites attention aux lettres
minuscules et majuscules lorsque vous définissez les noms de vos variables
en JavaScript, c'est important. Faisons un journal de console cette variable temporaire de
timbres générée automatiquement, que cette
image d'animation de demande nous a donnée juste pour voir de quel format
il s'agit. Vous pouvez voir que cela nous donne des millisecondes
puisque la première animation a été appelée. 1 s, c'est 1
000 millisecondes. Donc, ici, je peux littéralement
voir que le jeu a commencé 9101112, il y a 13 s. Je supprime ce journal de console. Nous savons que nous avons accès à
l'horodatage actuel Utilisons-le
donc pour
calculer le temps delta. Ce sera la différence
entre l'horodatage de cette boucle d'animation et celui de la boucle d'animation
précédente. temps delta est le nombre
de millisecondes nécessaires à notre ordinateur pour afficher l'image d'animation
suivante. Une fois que nous avons utilisé la dernière fois pour
calculer l'heure delta, nous l'attribuons à l'horodatage
actuel. De cette façon, l'
horodatage actuel peut être utilisé dans la prochaine boucle d'animation en
tant qu'ancien horodatage. Pour la toute première boucle
d'animation, dernière fois sera
nulle, mais ensuite, elle contiendra toujours la valeur de l'horodatage de l'image d'animation
précédente afin
que nous puissions la comparer
à la valeur de l'
horodatage de cette image d'animation
en cours d'exécution. Et la différence entre
eux est le temps delta. Nous allons donc enregistrer le
temps delta sur la console pour voir si cela a fonctionné. Mon temps delta est d'environ
16,6 millisecondes. Mille millisecondes
divisées par 60 font 16,6. Donc, ça se vérifie. Je me demande combien
d'entre vous ont obtenu le même temps
Delta et combien d'entre
vous ont obtenu un chiffre différent. Si votre écran de
rafraîchissement est élevé, votre temps de delta sera
beaucoup plus petit. Si vous avez un vieil ordinateur qui
a du mal à
animer notre jeu, votre temps delta sera peut-être beaucoup plus long si vous avez une
seconde ici, temps
delta dans les commentaires. Nous savons donc que si
la plupart des gens obtiennent des valeurs identiques ou très
différentes des
miennes, cela m'aidera à mieux
optimiser mes futurs cours. Si je fais défiler la console vers
le haut jusqu'au tout premier horodatage, vous pouvez voir que les deux
premières valeurs du temps
delta ne sont
pas des nombres. C'est parce que le tout
premier horodatage n'est pas défini car ce n'
est que dans la deuxième boucle cette valeur d'horodatage est
générée automatiquement par le cadre d'animation de la
demande. La première boucle n'est pas déclenchée par le cadre
d'animation de la requête, elle est déclenchée par cette ligne. Donc, au début, lorsque
nous disons que le temps delta est indéfini moins zéro,
nous n'en obtenons aucun, pas un nombre. Il
se corrige automatiquement au fur et à mesure que la boucle s'exécute. Mais ces deux valeurs initiales et
non numériques pourraient casser votre code. Cela dépend du
temps delta, à moins que vous ne le preniez en compte par une sorte
de déclaration orale. Par exemple, le moyen le plus simple de résoudre
ce problème est de passer zéro ici comme horodatage de la
première boucle d'animation. À partir de la deuxième boucle, la valeur deviendra le tampon tau
généré automatiquement. Parce qu'après cela,
animate sera appelé par request
animation frame. Comme vous pouvez le voir,
nous avons des chiffres ici et il n'y a plus de valeurs
non valables. Parfait. Je supprime
ce journal de console. Utilisons le temps delta pour définir
la fréquence d'images de notre jeu. Nous aurons besoin de certaines variables
d'assistance. Fps, les images par
seconde seront par exemple 20. Le chronomètre comptera
encore et encore à partir de zéro. Vers une valeur spécifique. Lorsqu'elle atteint cette valeur, elle déclenche l'image d'animation
suivante et elle revient à zéro. L'intervalle sera la valeur du
point d'arrêt
qui , une fois atteinte,
réinitialisera le chronomètre. Ce sera mille
millisecondes, 1 s divisées par FBS. Cela nous donnera le
nombre de millisecondes nécessaires pour atteindre
ce FBS spécifique. Nous allons gérer cette
logique de gestion des
cadres ici
dans la méthode de rendu. Si le compte à rebours est supérieur à
un intervalle, faites quelque chose. Dans le même temps,
continuez à augmenter le chronomètre de la valeur du
temps delta encore et encore. Lorsque le chronomètre a accumulé
suffisamment de temps delta, suffisamment de millisecondes pour que sa
valeur soit supérieure à un intervalle. Nous allons animer l'image suivante. Nous allons également remettre le chronomètre
à zéro afin qu'
il puisse à nouveau être pris en compte pour
la prochaine mise à jour du cadre. Je vais prendre tout ce
code et le mettre dans l'instruction if. Comme ça. Nous utilisons la
valeur du temps delta à la ligne 173. La valeur du point sera transmise en
tant qu' argument pour la
méthode de rendu ici. Et dans la boucle d'animation, nous calculons le temps delta ici et nous le
transmettrons pour obtenir un rendu comme celui-ci. OK, il se passe donc quelque chose. La raison pour laquelle tout clignote
est que nous supprimons constamment de la
vieille peinture, mais que nous ne redessinons notre jeu lorsque le chronomètre atteint un intervalle. J'ai obtenu ce
rectangle clair à partir d'ici. Maintenant, nous ne sommes plus du tout clairs
avec la vieille peinture. Et tout s'anime
à 20 images par seconde. Et tout
laisse des traces. Et je n'effacerai l'
ancienne peinture que lorsque nous serons prêts à redessiner le cadre A de la prochaine mise à jour
du jeu ici. Donc, contexte, rectangle clair entre les coordonnées zéro et zéro
jusqu'à cette largeur de point, cette hauteur de point pour vider toute
la zone de jeu, une optimisation
serait de dessiner notre jeu sur plusieurs
éléments liés au cannabis et de ne les portions de cannabis
qui le mettent réellement à jour. De cette façon, nous n'aurions pas à tout
redessiner tout le temps. Pour l'instant, cela fonctionnera bien. Vous devriez pouvoir
constater un ralentissement de vitesse d'animation
du jeu,
car nous
avons fixé images par seconde ici à 20. Pour le rendre encore plus évident, je ne veux
peut-être animer que
cinq images par seconde. 30405060. Je suis certain que FBS
passe à
60 images par seconde, mais nous n'
animons pas vraiment notre jeu à mais nous n'
animons pas vraiment notre jeu à
60 images par seconde, car chaque fois que je remets le chronomètre à zéro, il
reste du temps delta dont je ne tiens pas compte. Donc, même si je dis 60, le FPS réel est un peu plus bas. Je peux descendre et je peux expliquer le temps delta
restant. Mais peut-être que je veux garder
ce code léger. Peut-être que je ne veux pas
créer JavaScript pour faire encore et encore plus
de calculs. Donc, tout en gardant cela à l'esprit, je saurai que je
dois régler FBS une valeur légèrement plus élevée ici pour obtenir quelque chose d'
environ 60 images par seconde. Si je mets cette valeur à 70, je pense que nous obtenons des mouvements
suffisamment fluides et que nous n'obligerons pas JavaScript à
calculer le delta tan restant, ce qui
augmenterait légèrement la demande de
performances
dans notre jeu. Je viens d'
y penser maintenant, je ne
sais pas quelle est la meilleure solution. Je vais laisser mon code
comme ça pour le moment, mais je suppose que la bonne solution dépendra des préférences
personnelles de chacun. Donc trois pour en
discuter dans les commentaires. Je tiendrai compte de vos commentaires dans mes futurs projets.
Maintenant que nous savons comment contrôler la vitesse d'animation de
notre jeu en utilisant le temps delta, le jeu fonctionnera à la même
vitesse sur toutes les machines, même pour ceux d'entre nous qui
utilisent des écrans à taux de rafraîchissement élevé.
18. Cours d'œufs: Je voulais ajouter des œufs
qui peuvent être
déplacés pour apporter encore
plus de physique à notre jeu Ces x se transformeront en
créatures au bout d'un certain
temps ou après un certain temps. Et le travail des joueurs sera de protéger les créatures
que Hodge. Le x peut être
bousculé par les ennemis, mais ils ne seront pas détruits. Le défi pour le
joueur est que lorsqu'ils éclosent, les
ennemis mangent les nouveau-nés. Dans notre jeu, le travail des joueurs
sera donc de positionner le x, de le
protéger
ou d'
éloigner les ennemis de la trajectoire des créatures
nouvellement écloses. La larve qui
sort de chaque œuf essaiera toujours de se mettre
en sécurité et de se cacher dans les buissons à l'intérieur de la
forêt de champignons située au sommet. Cela offrira un large choix
aux joueurs et leurs options dans notre jeu ,
tout en utilisant la physique que
nous avons mise en œuvre J'ai eu l'idée de cette mécanique de
jeu en regardant un
documentaire sur la nature dans lequel petites tortues
éclosent sur la plage et essaient de se rendre en mer pour
des raisons de sécurité. Dans notre jeu, nous
contrôlons la balle bleue. Son travail consiste à protéger les
nouveau-nés en repoussant X, laves et les ennemis. Ce jeu est entièrement axé sur
la physique et le positionnement. J'aurai une
classe personnalisée que j'appellerai, par exemple constructeur
s'
attendra à une référence Comme d'habitude, le constructeur
s'
attendra à une référence à l'
objet principal du jeu, afin de s'assurer que la
classe Ec a accès à de nombreuses
propriétés importantes de l'objet de jeu. X fera partie de
la physique du jeu. Je dois donc m'assurer de définir x et y
distinctes coordonnées x et y
distinctes pour le point central du
cercle de collision. Et pour la feuille de sprite. Commençons par la propriété
collision x. Il s'agira d'une
valeur aléatoire comprise entre zéro et la largeur
de la zone de jeu. collision y sera comprise entre
zéro et la hauteur du jeu, comme celui-ci, le
rayon de collision, par exemple 40 pixels. Cette image de chargement sera
le document point à obtenir élément par ID, et l'ID se trouve dans index.HTML. En fait, je dois créer
cet élément d'image. Comme toujours, les images peuvent être téléchargées dans la section
des ressources ci-dessous. Je le cache avec du CSS ici. Je conserve les mêmes conventions de
dénomination tous mes objets. C'est une bonne pratique. La largeur du sprite sera donc 110 pixels et la
hauteur du sprite de 135. La largeur et la hauteur seront
définies sur les mêmes valeurs. Dans notre jeu, chaque objet a une
collision x et une collision. Pourquoi les propriétés qui représentent le point central de la
collision constituent un cercle, même le joueur et les obstacles portent les propriétés ainsi nommées
afin que nous puissions utiliser une méthode de
détection des collisions réutilisable pour appliquer notre
physique à tout. Il en va de même pour Sprite
x et Sprite. Pourquoi des propriétés ? Elles représentent la position du coin
supérieur gauche à partir de laquelle l'
image de l'objet sera dessinée. sprite X de l'image
sera une collision x plus la moitié de la
largeur de l'image. Pour centrer l'image horizontalement au-dessus du cercle de
collision. sprite y sera la collision y
plus la moitié de la hauteur de l'image. Nous devrons peut-être ajuster cela un peu plus tard, car verticalement, nous voulons que la
zone de collision se
situe à la base du cou, et
non au milieu. Nous y reviendrons bientôt. La méthode Draw s'attend à un
contexte comme argument. Comme d'habitude, nous appelons draw image, et cette fois, nous n'avons
besoin que de trois arguments. L'image que nous voulons dessiner et les coordonnées x et y
où la dessiner. Si nous devions effectuer une mise à l'échelle, nous inclurions également des arguments
facultatifs de largeur et de hauteur comme celui-ci. Mais je vous donne toutes les
images de la même taille. Nous les dessinons dans le jeu. Ce n'est donc en fait pas nécessaire. Comme pour tous les objets du jeu, nous ne dessinons pas seulement l'image représentant
l'objet, nous dessinons également cercle de
collision si le mode de
débogage est actif Comme nous conservons les
mêmes conventions de dénomination pour les propriétés
sur l'ensemble de notre base de code, nous nous facilitons la vie. Je peux simplement copier l'intégralité de ce bloc de
code et l'utiliser ici. Nous dessinons donc x MHz
et si le mode de débogage est activé, nous dessinons la zone de collision. Oui, c'est probablement
une bonne idée de
placer ce code dans des méthodes
réutilisables, car nous utilisons
le même code pour
dessiner des cercles de collision
pour tout. Je le ferai peut-être plus tard. Pour l'instant, je voulais
créer une méthode qui
ajouterait périodiquement un nouvel
œuf à notre jeu. Dans la classe de jeu, nous
aurons un tableau contenant tous les
objets contenant des œufs actuellement
actifs. J'aurai également une autre
propriété appelée nombre d'œufs. Ou un x maximum
le décrit encore mieux. Nous n'ajouterons de
nouveaux éléments au jeu que jusqu'à ce que le total soit inférieur ou
égal à la valeur x maximale.
19. Ajouter périodiquement de nouveaux œufs: Dans la méthode
de rendu, nous allons gérer la logique pour ajouter x périodiquement. Nous l'avons déjà fait. Nous avons créé un événement périodique dans cette base de code où
nous utilisons le temps delta et n'avons déclenché une nouvelle trame de jeu que lorsqu'une certaine valeur d'
intervalle était atteinte. Nous allons en fait faire
la même chose ici. Nous aurons besoin de
variables d'assistance pour cela. Le chronomètre à œufs passera de
zéro à la valeur d'intervalle x. Ensuite, il ajoutera un nouvel œuf et il se réinitialisera pour
pouvoir compter. Encore une fois. Nous fonctionnons en temps
delta, donc en millisecondes, je veux ajouter un nouvel œuf, disons toutes les
500 millisecondes. Ici, je vais vérifier si le minuteur à
œufs est
supérieur à l'intervalle x. Nous ajoutons un nouvel œuf en appelant
cette méthode à partir de la ligne 220. À l'intérieur, je
prends simplement la matrice d'œufs, que j'appelle méthode de poussée intégrée
. Je vais y ajouter une nouvelle instance de nos clients,
par exemple class. Comme d'habitude, nous savons que le verre à œufs s'attend à ce que le
jeu soit une dispute. Je lui passe donc ce mot clé parce que nous sommes
à l'intérieur de cet objet de jeu ici. Donc, si le compteur d'œufs est
supérieur à l'intervalle x, nous appelons ajouter un œuf. Nous allons également remettre le
chronomètre à zéro afin qu'il puisse à nouveau compter
pour le prochain œuf. Sinon, nous continuons à augmenter le temps des
œufs en fonction du temps delta, que nous transmettions déjà ici à la
méthode de rendu d'avant. Je consigne ce point x sur la console pour voir si les objets
sont ajoutés. Désolé, cela ne fera que créer
un tableau qui s'agrandira à l'infini. Je dois créer une condition
supplémentaire ici, ajouter un nouveau x
uniquement tant que
la longueur du tableau
x est inférieure à la valeur
maximale de x, c'est mieux. J'inspecte l'un des objets. Je dois m'assurer que
toutes les propriétés ont des valeurs. Si, par exemple, je n'ai pas défini comme coordonnée x de
collision, mon x ne serait pas dessiné
sur Canvas car JavaScript ne saurait pas
où les dessiner. Je vois des valeurs dans tout.
Ça a l'air génial. Dans la méthode de rendu, je voudrais
également dessiner mon x. Je copie simplement cette ligne et j'ai ajusté chaque
élément en rayons X, nous l'appellerons par exemple. Nous appellerons la méthode de
dessin dessus. Parfait. Nous obtenons maintenant des visuels
qui nous permettront de peaufiner les
détails et de les peaufiner encore plus facilement. La première chose que je remarque, c'est que tous les œufs sont ajoutés
presque instantanément, même si j'ai dit que je voulais un œuf toutes les 500 millisecondes. Si j'augmente
l'intervalle x à 1 s ici, je peux voir que quelque chose ne
va pas avec mon code. Je sais que le problème doit être
dans ce bloc de code. Et comme le chronomètre à œufs est bien plus qu'un intervalle et que ce
n'est qu'ensuite qu'il faut ajouter un nouvel œuf, nous devons utiliser cet opérateur de
comparaison ici. Désolée pour cette faute de frappe. Vous l'avez probablement
déjà remarqué. Maintenant, ça marche. Un nouvel œuf est
ajouté toutes les 1 s, tant que nous en avons
moins de dix. Je peux également voir que
les images sont positionnées en dehors des cercles de
collision. Je change ce plus en moins ici et aussi ici.
Maintenant, c'est mieux. Je souhaite ajuster la feuille de calcul en fonction
de son cercle de collision. Plus 35 le déplacera vers le haut de -35, nous le déplacerons vers le bas de -30. Je voulais que le bas de l'image soit le plus
proche possible, mais je ne voulais pas non le cercle de collision
soit trop haut, car je veux que le joueur puisse marcher derrière l'œuf
sans le pousser, pour avoir l'illusion
que notre zone de jeu est en 3D et qu'
elle a une certaine profondeur, même si en réalité
il ne s'agit que d'une surface plane. Nous ferons davantage pour l'
appliquer dans un instant. Maintenant, je veux créer
une marge pour m'assurer que le x apparaît à une certaine
distance minimale
des bords de la zone de jeu, afin
que le joueur puisse placer le joueur entre l'œuf et le bord
pour le pousser où bon lui semble. Je veux que la marge soit, disons que les termes du rayon de collision à la position x initiale du cercle de collision seront une valeur aléatoire en
partant de la gauche. À partir de cette
valeur de marge, nous venons de définir et de jouer avec moins cette marge. Ici, je règle l'intervalle de
200 millisecondes. Je veux 50 x juste pour avoir une meilleure idée de l'endroit où ils peuvent
apparaître dans notre jeu. Nous avons la
marge gauche que je voulais, mais je vois que le x est
trop éloigné du bord droit. Donc, ici, j'augmente cette marge
droite comme ceci. Oui, j'en suis content. Dx sont désormais toujours entièrement
visibles horizontalement, avec un espace supplémentaire à gauche et à droite entre les âges
de la zone de jeu. Verticalement, je vais faire
quelque chose de similaire. La position aléatoire
doit commencer en dessous la zone de marge supérieure
que nous avons définie précédemment. Je ne veux pas de x devant cette illustration
d'arrière-plan. La façon dont Math.random fonctionne, j'ai juste poussé la fourchette
d'ici à ici. Je dois également réduire
la plage en
réduisant la plage de valeurs
aléatoires que nous obtenons. Donc hauteur de jeu moins marge supérieure. Maintenant, x peut apparaître
d'ici à ici. Je vais réduire la
valeur aléatoire par marge pour lui donner un peu d'espace
en bas, comme ceci. Parfait. Si vous êtes débutant, Math.random peut ne pas être intuitif. C'est en fait très simple. Cela peut juste demander un peu de pratique. Donc, ici, je dis «
Définir la collision ». Pourquoi choisir une valeur aléatoire commençant par la marge supérieure ici ? Parce que nous partons
du haut et que la plage de valeurs
aléatoires correspond à la
hauteur du jeu moins cette marge, moins cette autre marge. Donc x peut apparaître n'importe où entre ici et ici. Verticalement. J'ai réglé l'intervalle à 500
millisecondes et le maximum x à
dix, par exemple . Pour l'instant, cela signifie
qu'un œuf apparaîtra toutes les demi-secondes
jusqu'à ce que le nombre total soit de dix. Comme il s'agit d'un jeu de physique, nous voulions que le joueur
soit capable de pousser les œufs pour
les éloigner des ennemis,
ou de les positionner
stratégiquement pour donner à
la larve qui en sortira ou de les positionner stratégiquement pour donner à
la larve qui les meilleures chances
de survie. Dans ce jeu, j'ai choisi que x
soit indestructible. ennemis repousseront simplement le x
s'ils entrent en collision, mais la larve qui éclot
sera mangée si l'ennemi l'attrape. donc très important
de positionner et de déplacer le x. Donnons un peu de physique au x.
20. Physique des œufs: Je donne à chaque œuf et
à chaque méthode de mise à jour à l'intérieur, nous allons créer un tableau d'assistance
temporaire appelé objet de collision. Il contiendra tous les objets de notre jeu avec lesquels x
interagira. Nous vérifierons la
collision entre chaque œuf et ces objets. Nous aurons donc besoin d'un joueur ici, jeu à points, d'
un joueur de points comme celui-ci. Et bien entendu, nous avons besoin de
solides obstacles. Je veux que tous ces éléments soient
au même niveau. Dans un tableau d'objets en collision. Nous avons un objet de joueur ici. Et nous allons répartir le réseau d'
obstacles dans le tableau d' objets de
collision à l'aide d'un opérateur de
propagation. Comme ça. L'opérateur de propagation
nous permet d'étendre rapidement les éléments d'un tableau
à un autre tableau. Je vais en fait appeler cette
collision un objet avec de la glace. Je vais appeler pour chacun de ces objets, pour chacun de ces objets. Donc, dans ce cas, pour le joueur et pour tous les
obstacles individuels que nous avons ici, je souhaite utiliser cette méthode de
vérification des collisions nous avons définie à la ligne 225. Si vous vous en souvenez, il prend l'objet a et l'objet B comme arguments. Et il renvoie un tableau
qui nous donne la valeur vraie ou fausse pour la distance de collision entre points
centraux des cercles de
deux collisions, certains de leurs rayons
et la distance horizontale et verticale entre
les deux points centraux. Je copie ce tableau. Je le colle ici. Encore une fois, nous utiliserons cette
structure pour
définir rapidement ces cinq variables en utilisant une seule ligne de code J'ai besoin d'un nom de variable ici, donc je vais appeler la première
collision vraie ou fausse,
qu'elle entre en collision avec un joueur ou un obstacle quelconque. Nous l'avons déjà fait. Je veux que ce soient
des variables principales et qu'elles soient égales à ce jeu de points. Ne vérifiez pas la collision entre
cet œuf car nous sommes dans la méthode de mise à jour de la classe Ec et de l'un des objets du tableau d'objets des
collisions. Ainsi, lorsque la méthode forEach s'exécute, nous exécutons la méthode de vérification de
collision entre cet œuf et chaque
élément de ce tableau. Et nous obtenons
cinq variables qui nous fournissent plus de détails sur la position et
la collision des deux objets
que nous comparons. Si une collision est détectée, nous utiliserons en fait toutes
ces valeurs pour calculer
jusqu'où et dans quelle direction
nous voulons pousser l'œuf. direction horizontale
de la poussée
sera le rapport entre le x, la distance horizontale
entre les deux points centraux et la distance hypoténuse de ce triangle
droit imaginaire. Comme dx est un site de ce triangle et que la
distance est l'hypoténuse, le côté le plus long,
nous sommes divisés en valeur
plus petite par une valeur plus grande. En raison de cette unité, x sera compris entre
moins un et plus un. D x peut être positif
ou négatif. Unité y. direction de poussée
verticale sera le rapport entre
D et la distance. Maintenant, nous allons l'utiliser
pour déplacer l'œuf. Nous sommes à l'intérieur d'un bloc de code
qui ne s'exécutera que si x entre en collision avec le joueur
ou l'un des obstacles. Ainsi, lorsqu'une collision se produit, nous prenons la collision x de
l'œuf et nous
le poussons d'un pixel en dehors
du rayon de l'objet. C'est la collision et la largeur. Donc, collision x de l'
objet, point central, plus un pixel supplémentaire pour déplacer l'œuf en dehors de la zone de
collision. Voici donc la distance et la direction
horizontale de ce mouvement
qui seront définies en la
multipliant par l'unité x,
qui, comme nous l'avons dit, peut être positive ou négative. Nous devons également déplacer la
collision et l'œuf verticalement. point central de collision y de l'œuf sera la collision
y de l'objet. Il entre en collision avec
plus le rayon de l'œuf plus le rayon de l'objet
plus un pixel supplémentaire. Donc, dans la boucle suivante, la
condition est fausse. Termes direction verticale
définis par l'unité y. Notez qu'ici
nous détectons une collision et que je me déplace collision et collision, pourquoi de l'œuf en fonction de la
position de l'obstacle ? C'est juste mon choix
et cela fera bouger
l'œuf et tous ces éléments seront
solides dans cette interaction. Lorsque l'interaction se produit, nous
déplacerons le joueur et les obstacles
resteront solides. Ils ne seront pas
poussés par l'œuf. Ici, nous appelons
méthode de dessin sur chaque œuf. Nous voulons également appeler cette nouvelle
méthode de mise à jour que nous venons d'écrire. Nous allons tester cela. Nous sommes en train de pousser
le cercle de collision de cet œuf. Je dois m'assurer
que la zone de collision et le Sprite restent solidaires. Le moyen le plus simple
serait de prendre ce code qui positionne le
sprite X et le Sprite. Pourquoi, en ce qui concerne la
collision et la collision y et je l'appellerai méthode de
mise à jour des informations. Je peux supprimer les valeurs ici et maintenant nous pouvons pousser dx en utilisant le joueur, et elles entreront également
en collision et glisseront autour de nos champignons et de nos plantes, autour des obstacles solides. Les Dx n'interagissent pas les uns
avec les autres. C'est juste mon choix. Je veux que les x se chevauchent pour qu'un joueur expérimenté
puisse pousser plusieurs œufs, les blesser ensemble et les
pousser tous en même temps. Ce choix simplifiera également notre code, car
nous apprenons.
21. Dessiner l'ordre: Nous dessinons tout
sur un seul élément de toile. Ainsi, l'ordre de dessin de
nos objets de jeu, la position du drone
derrière et ce qui se
trouve à l'avant dépendra de l'ordre dans lequel nous appelons les méthodes de dessin sur chaque objet à partir de
la méthode de rendu ici. heure actuelle, j'ai dessiné des obstacles, donc des champignons et des plantes. Ensuite, je dessine des x. Donc, les x sont
dessinés au-dessus des obstacles, comme vous pouvez le voir ici. Ensuite, nous dessinons le joueur. Le joueur est dessiné au-dessus
de tout le reste. Si je prends le x et que je le
dessine en premier, il y
aura toujours un dessin derrière les obstacles derrière le joueur. Et ici, nous pouvons voir que cela n'a pas vraiment de
sens visuel. Je voulais créer une
illusion de profondeur, fausse 3D ou peut-être
deux d et demi. objets bas
devraient être placés à l'avant. Au fur et à mesure
que nous montons, les objets dessinés sur cette ligne de base verticale
doivent être dessinés derrière, par exemple cet œuf doit
être dessiné
devant cette plante, et non derrière elle. Nous ne pouvons pas vraiment y parvenir. Si nous dessinons tous les x,
puis tous les obstacles , puis le joueur, nous devons ajuster légèrement notre
code. Je vais devoir mettre tous ces
objets dans un seul tableau, et je vais trier ce tableau en
fonction de coordonnées verticales. Laisse-moi te montrer ce que je veux dire. Je crée une nouvelle propriété
sur la classe de jeu principale. Je vais appeler cela des objets de jeu. Au début, ce
sera un tableau vide. Dans la
méthode aléatoire, je vais prendre un objet de jeu et j'utiliserai opérateur de
propagation pour étendre l'ensemble
du tableau qu'il contient. Je vais également élargir l'ensemble
des obstacles ici. Et je vais ajouter le joueur. Maintenant, nous regroupons tous les objets du jeu
dans un seul tableau. Ce tableau sera
recréé chaque fois méthode de
rendu nécessite
une bonne optimisation.
Un conseil serait de n'
effectuer cette opération qu'
une seule coordonnée verticale
de tout changement d'élément. Ou lorsque nous ajouterons ou retirerons un œuf, je réutiliserai
ce bloc de code. Au lieu d'appeler
chaque méthode sur array, je vais l'appeler sur ce
nouveau tableau d'objets de jeu. Pour chaque élément du tableau, je vais lui attribuer un nom de
variable temporaire, par exemple l'objet de chaque objet
du
tableau d'objets du jeu appelle ses méthodes de
dessin et de mise à jour associées. Pour que cela fonctionne, il est important que
tous les objets que nous ajoutons au
tableau d'objets du jeu à la ligne 217 aient des
méthodes de dessin et de mise à jour définies en
fonction de leurs classes. Sinon, le code se
casserait car JavaScript ne serait pas
en mesure de trouver cette méthode. Nous appelons donc à dessiner et
à mettre à jour tous les objets du jeu , tous les x, tous les obstacles
et le joueur. Cela signifie que je peux maintenant supprimer
ces lignes de code. frappe, j'ai orthographié les objets
du jeu avec un S. Maintenant, nous dessinons le premier obstacle,
puis nous obtenons une erreur. Nous appelons le tirage au sort sur
le premier obstacle. Et lorsque nous avons essayé d'
appeler la mise à jour dessus, nous obtenons une erreur de type indiquant que mise à jour par points de
l'objet n'
est pas une fonction. Je passe à ma classe d'obstacles
et vous pouvez voir, comme je l'ai dit, que nous avons une méthode de dessin ici, mais il n'y a pas de méthode de mise à jour. Nous demandons à JavaScript
d'appeler une méthode qui n'
existe pas sur cet objet, je vais créer une méthode de
mise à jour ici. Dans le cadre de cette méthode, nous pourrions par exemple animer
des feuilles de calcul représentant ces plantes et champignons chaque fois que le joueur en collision avec eux ou quelque chose comme ça Peut-être que j'ajouterai des obstacles
interactifs plus tard. Pour l'instant, nous allons laisser
cette méthode vide. Maintenant, cela fonctionne et nous appelons Draw and
Update sur tous les x, tous les obstacles et sur le joueur. Sinon, j'aurais
également pu résoudre l'absence de méthode de mise à jour sur les obstacles en
utilisant une sorte de
déclaration « sinon » ici, il y a toujours plusieurs
façons de faire quelque chose. N'hésitez pas à discuter de la façon dont vous aborderiez cela différemment. Peut-être trouverons-nous de
meilleures solutions dans les commentaires que je pourrais
utiliser dans les prochains cours. J'apprécie lorsque vous
me faites part de vos commentaires sur mon code et lorsque vous
suggérez des améliorations. Bon, maintenant, nous
appelons tirage et mise à jour lorsque nous parcourons les
objets du jeu, ce qui signifie que x sont dessinés en premier, les obstacles sont au-dessus de x et le
joueur est dessiné
au-dessus de tout. Si je modifie l'ordre
de ces éléments ici, le joueur est
désormais attiré par X et les obstacles sont
au-dessus de tout. Nous pouvons donc maintenant comprendre
comment fonctionne la superposition. Cela dépend de l'ordre dans
lequel nous appelons la méthode de dessin sur chaque objet pour dessiner nos objets de jeu dans l'ordre
qui convient visuellement. Je peux maintenant trier
le tableau des objets du jeu en fonction de la position
verticale de chaque objet. Je prends un tableau d'objets de jeu et j'appelle la méthode de tri intégrée
. Cette méthode trie les
éléments d'un tableau et renvoie le
même tableau maintenant trié. Par défaut, si nous l'appelons
sans passer d'arguments, il convertira simplement les
éléments du tableau en chaînes. Et il les triera en
fonction de leurs valeurs Unicode. n'est pas ce que nous voulons vraiment, alors nous allons en discuter. Cet argument facultatif
que nous pouvons transmettre à la méthode de tri des
tableaux est
une fonction de comparaison, une fonction personnalisée qui
définit une certaine logique. Il définit un ordre de
tri spécifique que nous souhaitons. Cette fonction spéciale
prendra deux arguments, l'élément a et l'élément étant
tous les éléments du tableau. Dans notre cas, dans les objets
du jeu, le tableau sera représenté par a et B utilisés dans la
logique que nous définissons ici Je peux renvoyer comme ceci, et je veux trier les
éléments par
ordre croissant en fonction de la valeur
de chaque collision d'objets. Pourquoi l'immobilier ? Nous
trions donc en fonction du point central vertical de la zone
du cercle de collision. Nous pouvons également trier par le bas
de l'image du sprite, qui serait triée
en fonction de la valeur de Sprite y plus la hauteur du sprite. La méthode de tri peut être compliquée à comprendre si
vous êtes débutant, tout ce que vous devez comprendre
ici, c'est que je place tous mes éléments dans un tableau d'objets de
jeu. Alors je suis la méthode de
tri intégrée de Colin sur ce tableau. Et j'organise
ces éléments en fonction de leur position
verticale. Cela ne fonctionne pas maintenant
parce que je crée un tableau que je dessine
puis que je trie. Je dois trier les éléments
après avoir créé le tableau, mais avant de les dessiner. Donc comme ça. Parfait. Maintenant, il est dessiné
devant la plante, mais si j'utilise le
joueur pour le pousser vers le haut, la
position verticale des œufs devient inférieure à la
position verticale de la plante. Maintenant, l'œuf est dessiné
derrière la plante. Il s'agit d'un moyen simple de dessiner des éléments dans un jeu 2D d'une manière plus
logique sur le plan visuel. Il s'agit d'une technique très puissante à ajouter à votre boîte à outils de codage. Vous avez des questions ?
Laisse un commentaire. Vous n'avez pas à faire la chose
suivante que je vais faire maintenant. J'ai réglé l'intervalle à 20 millisecondes
et le x maximum sera de 150. suffit de tester s'il y a des
problèmes à résoudre. Au fur et à mesure que je les
parcoure, la physique semble très bonne. Tout fonctionne bien. fait d'avoir autant d'œufs à
tester me donne également une assez bonne idée de l'endroit où ils
pourraient potentiellement apparaître. Ils apparaissent dans la
zone que nous avons spécifiée avec une grande marge supérieure et une marge
plus petite à
gauche, en bas et à droite. Nous avons X, de bons codeurs. J'ai dit intervalle de
2000 millisecondes, un œuf par seconde, et le maximum x sera de 20. Comme cette formule de
collision est en place, si elle apparaît au-dessus d'
un obstacle ou du joueur, elle est automatiquement poussée hors de son rayon de collision. Je supprime ce
journal de console à la ligne 237. Nous avons notre monde de jeu. Nous avons réparti aléatoirement des obstacles
solides. Nous avons un personnage de
joueur contrôlé par la souris qui peut se déplacer dans une direction. Et nous avons x qui apparaissent
dans un intervalle spécifique. En plus de cela, tout entre en collision et réagit
à tout. Nous pouvons créer tellement de jeux
différents avec ça, ajoutons des ennemis.
22. Cours ennemi: Je crée une
classe personnalisée que j'appelle, par exemple ennemi. Comme d'habitude, le constructeur
prendra un jeu comme argument et nous
convertirons cette référence
en propriété de classe. Nous faisons cela pour accéder facilement
à toutes les propriétés de la classe de jeu principale depuis
la classe ennemie grâce
à
cette référence en matière de jeux pour chiens. Nous devons conserver les mêmes conventions
de dénomination ici. Ainsi, le rayon de collision de 30 pixels, la
collision x, le point central du cercle de collision seront
le bord droit du Canvas. Ce jeu de points a la largeur des points. Collision y sera une valeur
aléatoire comprise entre zéro et la valeur de hauteur de jeu
provenant d'ici. Vitesse X vitesse horizontale sera une valeur aléatoire
comprise entre 0,5 et 3,5. Vous pouvez télécharger l'image de l'ennemi
dans la description de la vidéo. Dans un premier temps, nous allons commencer par
le cadre unique statique. L'identifiant sera remorqué, source sera indiquée par le point PNG. Je le cache avec du CSS
parce que nous voulons dessiner là où le
JavaScript sur Canvas, cette propriété d'image par points
sera obtenue élément par ID. Et la carte d'identité que nous lui avons donnée a été remorquée. Sprite avec, dans ce cas 140 pixels et la
hauteur du Sprite est de 260. Je vais également créer des propriétés de largeur
et de hauteur. Et nous allons définir les positions du sprite X
et du sprite y de l'image de la feuille de calcul qui
sera positionnée
par rapport aux coordonnées du
cercle de collision. La méthode Draw prendra le contexte comme argument. Méthode de
dessin d'image intégrée. Et parce que le
fichier image que j'utilise a déjà la même
résolution que la taille. Je veux qu'
il l'affiche dans le jeu. Je n'ai qu'à
lui présenter trois arguments. L'image que je voulais dessiner
et x et y devaient la dessiner. Je vais également copier le visuel du
cercle de collision qui n'
apparaîtra que lorsque la
propriété du mode de débogage est définie sur true. Uniquement lorsque le mode de débogage est actif. Je ne fais que le copier et le coller ici. Puisque ce code est le même pour tous nos objets. Méthode de mise à jour. À l'intérieur, je veux que les ennemis se déplacent
vers la gauche dans le sens négatif sur l'axe
horizontal X à la vitesse x, une valeur que nous avons définie sur la ligne 179. Nous déplaçons donc les
ennemis vers la gauche si le bord droit de
la feuille de calcul est caché derrière le
bord gauche du cannabis. Nous pouvons remettre sa
position x sur la largeur du
jeu afin qu'il puisse à nouveau traverser
l'écran à gauche. Nous allons également modifier
sa position verticale en Y de manière à ce que les ennemis
empruntent des voies différentes. J'aurai donc des ennemis
qui marchent de droite à gauche, puis qui se
réinitialisent et marchent à nouveau. Sinon, j'aurais pu
créer de nouveaux
objets animés encore
et encore, les détruire, les jeter lorsqu'
ils sortent de l'écran. Le code serait
simple, mais réutiliser des objets en réinitialisant
leur position
plutôt que d'en créer de nouveaux
et de les supprimer ultérieurement est une bonne technique
d'optimisation. Réutilisons vos objets
et réinitialisons leurs
positions si possible Plutôt que d'en créer de nouveaux, l'utilisation du nouveau mot clé pour
créer un nouvel objet coûte plus cher que la
réinitialisation d'un objet existant. la classe de jeu principale, je crée une méthode personnalisée que j'appelle par exemple at, NME. Ici, nous aurons un
tableau qui contiendra tous les objets
animés actuellement actifs. Chaque fois qu'un ennemi court, nouvel
objet animal
est projeté dans le réseau ennemi. En ligne 174, je peux voir que le constructeur de la classe
ennemie
attend le jeu comme argument. Je lui passe donc ce mot clé, car nous voici
dans cette classe de jeu. faisant cela, je transmets simplement
une référence qui pointe vers un espace de la mémoire où
un objet de jeu est stocké. Je ne suis pas en train de créer une
copie de l'objet du jeu. À chaque fois, je crée un nouvel ennemi. La méthode Init s'exécutera. Je veux juste initialiser notre jeu et
tout configurer à l'intérieur. Nous sommes déjà en
train de créer des obstacles. Nous allons également créer des ennemis
dans cette boucle FOR qui s'exécuteront,
disons, trois fois. Et chaque fois qu'il fonctionne,
il appelle. Et puis, selon la méthode que
nous venons de définir, je peux sélectionner ce point, les ennemis. Et comme prévu, il contient
trois objets animés. J'inspecte l'un d'entre eux juste pour assurer que rien n'est indéfini, ce qui pourrait poser problème. Tout va bien ici. Je peux
supprimer le journal de la console. C'est une bonne idée de toujours vérifier vos objets et vos tableaux à l'
aide des journaux de console lorsque vous créez vos
projets étape par étape afin détecter les bogues
et les fautes de frappe potentiels à temps. Pour dessiner et mettre à jour des ennemis, il
me suffit d'étendre le tableau d'
ennemis à l'objet
du jeu à l'aide
de l'opérateur de propagation. Nous l'avons déjà fait. Je ne vois que des zones de collision, je dois donner quelques
valeurs au sprite X et au Sprite y pour
que le JavaScript sache où dessiner la position des images du
sprite. Nous allons déménager. Lorsque les cercles de collision se déplacent. J'ai donc mis ce code
dans la méthode de mise à jour. Commençons par le centroïde,
puis nous le décalons. Sprite X est une collision
x moins la moitié de Sprite avec un sprite comme celui-ci. Pourquoi la collision est-elle égale
à la mi-hauteur ? Je veux que les cercles de collision correspondent
à l'ombre
au sol. En dessous, les ennemis
flottent le plus
près possible. Nous devons ajuster les
positions de l'image verticalement. -40 -60. Qu'en est-il de la
hauteur négative ? Plus de 40 ans ? Je peux activer et désactiver mode de
débogage pour afficher
et masquer les zones de succès en appuyant sur la lettre d.
Nous avons des ennemis qui viennent de droite à
gauche puis se réinitialisent. Je veux qu'ils se
réinitialisent complètement derrière le bord droit afin que nous ne
les voyions le bord droit afin que nous ne
les voyions pas simplement apparaître. les avons donc réinitialisés à la
largeur des points du jeu plus la largeur de l'ennemi. Et en plus de cela,
un autre jeu avec le terme 0,5 pour donner à chacun un délai aléatoire
différent. Pourquoi est-ce ici ? Je supprime ça. Juste pour les tests. Augmentons la vitesse. réinitialiser de manière aléatoire
derrière le
bord droit fonctionne bien, c'est
peut-être un peu trop rapide. Je dois restreindre leurs positions
verticales. Disons que nous partons de
la marge supérieure. Et à partir de là, une fourchette
aléatoire entre zéro et la hauteur de jeu
moins la marge supérieure. Je copie cette valeur pour
l'utiliser comme position x de collision initiale
dans le constructeur. Et je prends cette nouvelle collision expliquer pourquoi je l'utilise dans le cadre de la méthode d'
enregistrement et de mise à jour du récepteur. Cela ne fonctionnera pas car ici,
à la ligne 176, j'utilise cette largeur de point, mais elle n'est définie que
plus tard ici à la ligne 183. Ici, l'ordre est important. Je prends simplement ces deux
lignes et je les mets ici. Nous avons maintenant des ennemis qui marchent
de droite à gauche dans un couloir correct et
se réinitialisent derrière le bord droit. De cette façon, nous pouvons réutiliser
les mêmes ennemis encore et encore, à moins que
je ne décide ajouter d'autres fonctionnalités,
comme permettre au joueur détruire des ennemis ou quelque chose
comme ça. Nous allons voir. Encore une fois, vous n'êtes pas
obligé de faire cette partie. Je suis juste en train de tester notre code. Je crée donc 30 ennemis. fait d'avoir autant d'ennemis
me donne une meilleure idée de la façon dont ils se réinitialisent et je peux détecter les problèmes
potentiels plus rapidement. Tout
semble bien fonctionner. Ce serait une forêt très
dangereuse. Heureusement pour nos créatures
naissantes, le jeu final ne comportera pas tels
essaims d'ennemis, à moins que
vous ne vouliez créer une
vague périodique d'ennemis comme celui-ci. En tant que jeu et
mécanique, le joueur doit se préparer et éviter. Nous pouvons faire tellement de choses en
termes de conception de jeux ici Je
vous donne simplement les outils et techniques et je
vous montre certaines de mes idées. N'hésitez pas à développer ce jeu
avec vos idées créatives. Une fois le cours terminé, revenons à trois ennemis. heure actuelle. Les ennemis
volent simplement à travers la forêt sans
interagir avec quoi que ce soit. Tout d'abord, je veux qu'ils réagissent à obstacles
solides et
que le joueur ait déjà du code
qui utilise cette méthode de mise à jour des informations sur la classe EKG. Je peux littéralement utiliser le
même bloc de code et le
placer dans la
méthode de mise à jour de la classe ennemie. Cela transformera les ennemis,
traitera les obstacles et les joueurs deviendront des objets solides et
impossibles et ils
glisseront autour d'eux. Nous utilisons la
méthode de mise à jour interne de la classe ennemie, et nous passons
l'ennemi comme objet a, joueur et les obstacles
comme objet B. Et ici, nous disons ajuster position de a en
fonction de la position de B. Le joueur et les obstacles
seront solides et dominants dans
cette interaction, et les ennemis seront
bousculés autour d'eux. Ce simple
enregistrement en cas de collision
créera également une intelligence
artificielle très basique. Comme vous pouvez le voir, les
ennemis marchent de droite à gauche
dans la zone de jeu. Et ils
se glissent automatiquement vers intérieur
et évitent les obstacles et le joueur, ils
l'ont évité de cette façon, nous pouvons également utiliser le joueur
pour repousser les ennemis, même manière que nous pouvons
pousser le x J'ajuste la vitesse de l'ennemi. Si j'ajoute x à la matrice d'
objets de collision d'une classe ennemie, x deviendra également un obstacle solide et
impossible
pour les ennemis. Et les ennemis
devront les contourner. Cela peut être une bonne
chose
selon la façon dont vous
concevez votre jeu. Au fait, je veux que
mon jeu soit, je voulais en fait
supprimer le x d'ici. Au lieu de cela, je passe à la classe
et à la méthode de mise à jour interne, j'ajouterai des ennemis aux objets de
collision. Ici. Cela fera des œufs un chemin pour
vérifier la méthode des collisions. Et les ennemis seront solides, les objets
impossibles, car les ennemis
pousseront le x. Si je le fais de cette façon, nous avons implémenté de
nombreuses fonctionnalités. Je vais donc laisser le code
source de cette étape dans la section
ressources ci-dessous, vous pouvez le télécharger et le
comparer à vos fichiers. Si vous codez seul.
J'espère que tu t'amuses bien.
23. Cours de Larva: Ici, entre les classes d'œufs
et les classes ennemies. Et je crée une nouvelle
classe que j'appelle, par exemple larve. Je veux que x ait une minuterie cachée et
qu'après un certain intervalle de temps, chaque œuf éclose
en une larve plus petite. Cette larve va essayer de se
cacher dans la forêt. Et notre travail en tant que joueur est
de le protéger en le rapprochant de la zone de sécurité ou en
éloignant les ennemis de celle-ci. Le constructeur de
la classe des larves sera légèrement
différent car je veux que chaque larve apparaisse à la même position que l'œuf d'où
provient l'œuf éclos. Nous allons donc lui transmettre une référence à l'
objet principal du jeu comme d'habitude, mais nous lui transmettrons également les coordonnées
x et y. Maintenant, je convertis tous ces
arguments en propriétés de classe. Je dois nommer ces coordonnées
x et y, collision et collision, pourquoi ces variables seront impliquées
dans la détection des collisions. Nous devons donc les nommer de
la même manière que les autres objets de notre jeu de
physique, afin pouvoir utiliser notre méthode réutilisable de vérification et de
collision et d'impliquer ces
larves
dans la boucle du jeu de physique. Nous aurons également besoin d'un rayon de
collision ici, disons 30 pixels pour le moment. Vous pouvez télécharger l'image de la larve
dans la description de la vidéo. J'ai ajouté ici un identifiant de larve et un point de larve source PNG. Il s'agit d'une feuille de calcul
à deux cadres. Dans ce rôle, nous
avons une larve audacieuse et celle-ci a un peu de
duvet derrière le cou, juste pour lui donner une certaine variété
visuelle. Le duvet a plus de
sens si vous savez ce que deviennent
ces nouveau-nés
lorsqu'ils sont adultes. J'intègre l'
image de la larve dans le projet utilisant get element
by ID, comme ceci. Largeur et hauteur
d'un seul cadre. Maintenant, la largeur du sprite est de 150 pixels, hauteur du
sprite est également de
150 pixels. Si vous êtes débutant,
je vous suggère fortement suivre mon code à la lettre
et d'utiliser les mêmes images. Amusant. Une fois le
projet terminé, il sera plus facile d'apporter
vos propres modifications personnalisées. Changer le code au fur
et à mesure tout en suivant ce tutoriel n'est pas une
bonne idée. À moins que vous ne
soyez un développeur
JavaScript expérimenté qui apporte vos propres modifications avant
la fin du projet, nous allons le rendre plus difficile à déboguer. Nous aurons également besoin des coordonnées
Sprite X et Sprite Y de l'image de la
feuille de calcul. Chaque larve devra dessiner et
mettre à jour des méthodes. Comme d'habitude. La méthode Draw prendra
les contextes comme argument. Dans le site, nous appelons image intégrée dans un tiroir et nous lui transmettons l'image que nous voulons dessiner et les coordonnées
x et y
où la dessiner. Je veux que chaque larve remonte
vers la sécurité de
la forêt de champignons. Cette zone ouverte est pleine d' ennemis et elle est très dangereuse. Vitesse, pourquoi
la vitesse verticale sera une valeur aléatoire, 1-2, par exemple, nous avons défini le sprite X et le Sprite. Pourquoi des propriétés qui déterminent où la
feuille de sprite sera dessinée. Mais comme ils devront
se déplacer à chaque fois que les larves se déplacent, je dois
les mettre à jour encore et
encore à l'aide de la méthode de mise à jour interne. Sprite X correspondra à une collision
x moins la moitié de sa largeur. sprite y sera la collision
y moins la moitié de la hauteur. Je cache cette image avec du CSS. Nous lui avons donné un identifiant de larve.
24. Couvertures d'œufs: Nous avons donc une classe que nous pouvons
utiliser comme modèle pour
créer une larve chaque
fois qu'un œuf éclot Écrivons l'éclosion d'un œuf en logique, nous devrons
aider nos variables. Le chronomètre passera de
zéro à l'intervalle d'éclosion. Cela comptera des millisecondes. Disons que je veux que
l'œuf éclose au bout de cinq millisecondes après 5 s. Dans la méthode de mise à jour, nous gérons les collisions
dans cette zone. Et ici, nous nous
occuperons de l'éclosion. Si le délai d'éclosion que nous venons définir est supérieur à un intervalle d'
éclosion, nous faisons autre chose. Nous continuons à augmenter le temps d'
éclosion en fonction du temps delta. Compter et accumuler
en millisecondes. Le terme Delta sera transmis à la méthode de mise à jour
ici à la ligne 159. Cette méthode de mise à jour le
recevra ici. Rendu intérieur. Nous avons calculé la valeur du temps delta
avant la boucle d'animation intérieure temps
delta contient le nombre de millisecondes qui se sont
écoulées entre cette image d'animation et l'image
d'animation précédente. chronomètre accumule donc ce temps delta en millisecondes
entre les images. Si le temps d'éclosion est
supérieur à l'intervalle d'éclosion, nous supprimerons l'œuf et
le remplacerons par une larve. Ici, je crée une propriété
appelée marquée pour suppression. Ici, nous avons défini la valeur True
pour suppression. Je peux enregistrer et
supprimer ces objets marqués pour suppression pour chaque image
d'animation. Il serait peut-être un peu
plus efficace de
restructurer notre effacement uniquement lorsque quelque chose est réellement marqué. appellerons donc ici
une méthode personnalisée. Je vais appeler, par exemple,
supprimer les objets d'un jeu. Ici, dans la classe de jeu
principale, je vais définir cette méthode. Jusqu'à présent, nous ne
marquons que X pour suppression. Donc, chaque fois que cette méthode s'exécute, je prends le tableau entier et j'appellerai la méthode de
filtrage de tableau intégrée dessus. Ou une méthode de filtrage
créera simplement une copie de ce tableau. Mais ce nouveau tableau
filtré ne contiendra
que les éléments qui passent la vérification fournie
dans la fonction de rappel. Dans ce cas, la vérification sera je veux uniquement que le tableau X
contienne des éléments
dont la
propriété de suppression est définie sur false. Si un élément marqué
pour suppression est défini sur vrai, il sera filtré
hors du tableau. C'est ce que l'on appelle la syntaxe de
la fonction de flèche ES6. Je dis de prendre les éléments
d'un tableau un par un, attribuer à chacun un nom de
variable temporaire. Et sur chacun de ces objets, vérifiez s'ils sont marqués pour
suppression. La propriété est fausse. point d'exclamation signifie faux. Si la case marquée pour suppression
sur cet œuf est vraie, cet œuf sera filtré
hors de ce nouveau tableau. Et cette nouvelle
matrice filtrée est affectée à la radiographie d'origine et remplace. Suis-je en train de trop expliquer ? Et encore une fois,
enregistrons ce point
X du jeu de points sur la console pour voir si x est
supprimé et ajouté. Oui, cela fonctionne parfaitement. Lorsque nous sommes en mode debug, je veux que le chronomètre du Hajj soit visible sous la forme d'un chiffre
flottant au-dessus chaque œuf
dans la méthode de dessin que j'appelle
ici la méthode FiltText intégrée. Cette méthode nécessite au
moins trois arguments, le texte que nous voulons dessiner et les coordonnées x et
y pour le dessiner. La modification de la taille de police, plutôt que de changer la taille de la
police à chaque fois que la méthode de dessin
s'exécute sur chaque œuf, je vais la configurer ici, à la
dixième ligne, lors du chargement de la première page. Il s'agit d'une technique
d'optimisation puissante. La police fait partie d'un état et les modifications
fréquentes d'un état
peuvent affecter les performances. Propriétés du Canvas définies
telles que FillStyle, largeur de ligne , style de
trait et phonation dans un bloc de code qui s'exécute le moins
possible. idéal, évitez d'
utiliser une méthode qui s'exécute 60 fois par seconde sur plusieurs
objets en même temps. Bien que dans certains cas
, cela puisse être inévitable. Tout ce que je veux dire ici, c'est que si vous pouvez définir les propriétés du canevas
sur la première page, charger comme ceci, tout ce
code ne s'exécutera qu'une seule fois. J'ai dit que j'
aimais les 40 pixels. Helvética. J'aurais également pu définir la police Canvas ici
dans cette méthode de dessin. Mais comme je l'ai dit, cette
ligne de code s'exécuterait 60 fois par seconde
sur chaque œuf actif. Cela représente un grand nombre d'
opérations qui peuvent être facilement évitées en faisant
ce que je viens de dire. Ij dimer est ce nombre
ridicule avec tant de chiffres après
la virgule décimale. Nettoyons tout ça. Je crée une variable d'assistance
appelée display timer. Ici, nous allons
formater un
peu ce nombre avant de
le dessiner. Je peux, par exemple utiliser une minuterie et appeler une méthode
intégrée ou fixe. Javascript
en méthode fixe convertit un nombre en chaîne et arrondit la chaîne à un
nombre de décimales spécifié. En fait, je veux
le zéro décimal. Je veux juste voir
les millisecondes. J'utilise cette variable de
minuterie d'affichage ici pour réellement la dessiner. Je peux ajuster la
position verticale du texte, peut-être en fonction d'
un rayon de collision comme celui-ci. Ici, je vais placer la ligne de
texte au centre. Cela alignera les minuteries
et x horizontalement. Agréable. Je voulais pousser les chronomètres
encore plus haut au-dessus des œufs. Peut-être même plus.
Allons-y avec 2,5. Au lieu de millisecondes, je veux
juste voir les secondes. Je ferme donc le compte à rebours entre parenthèses et je
le multiplie par 0,001. Maintenant, c'est plus lisible. Nous pouvons voir le nombre de
secondes au-dessus de chaque œuf. Faisons
éclore chaque œuf au bout de 3 s. Bien. Lorsque l'œuf éclot, il est éliminé par
la méthode du filtre. la classe de jeu principale, je crée une propriété
appelée hatchlings, Dans la classe de jeu principale,
je crée une propriété
appelée hatchlings,
et je la définis d'abord
sur un tableau vide. Chaque fois qu'un œuf éclot, nous introduisons une nouvelle larve
dans ce réseau. Ici, sur la ligne 190, je peux voir que la larve attend gibier et des coordonnées x et y. Donc, quand un œuf éclot, je l'apporte à la gamme Game Dot Hatchlings et
j'y insère de nouvelles larves. Je le passe à Distort Game. Et je lui transmets les
coordonnées x et y de ces
œufs qui ont éclos Je
retire ce journal de console. Dans la méthode de rendu,
j'utilise l'opérateur de propagation ou pour
transformer les nouveau-nés en objets de jeu, en
tableaux, afin qu'ils puissent être
triés, dessinés et mis à jour. Parfait, nous progressons. Maintenant que nous pouvons voir à quoi ressemblent
nos nouveau-nés, nous pouvons passer à la
classe des larves et nettoyer tout cela. Tout d'abord, nous vérifierons si
la larve se met en sécurité. Ils sont en sécurité
dès qu'ils atteignent cette
zone de champignons et de buissons où ils peuvent se cacher. Donc, si la collision y est
inférieure à cette marge supérieure de
points du jeu de points, si la larve dépasse ce point, nous pouvons définir la valeur True pour
suppression. Nous allons supprimer cette larve parce que nous ne
voulons plus la dessiner. Et nous appellerons supprimer les objets
du jeu en ligne 350 insights, méthode de
suppression de l'objet du jeu. Je fais la même chose que
nous avons fait pour x, filtre le tableau des nouveau-nés. Et si un objet larvaire
de ce tableau dont propriété est
marquée pour suppression est définie true, filtrez-le. Juste pour consulter les objets du jeu dans le
journal de notre console. Chaque fois que nous retirons un œuf
ou une larve, je reçois une erreur. Et c'est parce que ce doit
être ce jeu de points à supprimer des objets de
jeu, car cette méthode appartient à notre classe de jeu principale. Je veux que tu dessines
des cercles de collision sur les nouveau-nés. Je copie ce bloc
de code de la classe ennemie. Et je viens de le coller ici parce que nos classes ont les mêmes conventions
de dénomination pour leurs propriétés. Il est facile de réutiliser
du code comme celui-ci. heure actuelle, nous sommes en train
de dessiner la feuille de calcul complète
pour chaque larve. Je voulais recadrer une
seule image à partir de la coordonnée zéro-zéro deux. Cela a l'air d'une largeur éclatante et de
cette hauteur de sprite à points. Et nous voulons dessiner
cette
image recadrée à la position
sprite, sprite y. Et nous devons lui donner une
largeur et une hauteur comme celles-ci. Neuf arguments. Je voulais positionner l'image de la
feuille de calcul de la larve par rapport
à son cercle de
collision. J'essaie -50. Oui, ça va marcher. Je veux que le cercle de collision soit aligné avec le
bas de son corps. Je pense que c'est ce qui aura le
plus de sens visuel lorsque vous interagissez avec
les environnements de jeu et les personnages. Je supprime ce
journal de console sur la ligne 362.
25. Sprites et collisions Larva: feuille de calcul Larva
comporte deux cadres, mais nous
ne dessinons que celui du haut. Réduisons ce cadre de manière aléatoire. Y sera une valeur aléatoire de 0 à 2. Et comme il
n'y a pas de ligne 1.5,
nous avons par exemple besoin d'entiers, de nombres entiers
sans décimales. Je l'intègre donc dans Math.floor. Cette ligne de code
nous donnera zéro ou un, car Math.floor
arrondira la valeur jusqu'à l'entier
inférieur le plus proche. Le cadre X sera toujours nul jusqu'à la fin
du cours où je vous donnerai une
feuille de calcul avancée. Pour l'animation. Nous utiliserons frame x
times sprite avec ici comme source x l'argument transmis
à la méthode draw image. Et nous devons également
définir une source. Pourquoi la combinaison des
coordonnées x et y de la source déterminera la zone de
la feuille de calcul dans laquelle nous
sommes recadrés à partir de source Y sera encadrée par
y fois la hauteur du sprite. Agréable. Puisque frame why est randomisé
pour être égal à zéro ou à un. Certains nouveau-nés utilisent l'
image du sprite de la ligne zéro, tandis que
d'autres utilisent l'
autre de la première ligne. collisions entre les nouveau-nés et les objets
du jeu
seront traitées ici. Je vais ici dans la méthode de
mise à jour d'une classe et je copie
ce bloc de code, nous y apporterons quelques modifications, mais la plupart seront les mêmes. Nous pourrions donc tout aussi bien le
copier ne pas avoir à
écrire tout cela. Encore une fois. Je le colle ici dans la
méthode de mise à jour sur la classe Larva. Je retirerai les ennemis
des objets en collision car les ennemis auront un type d'interaction différent. Ainsi, la larve
évitera automatiquement le joueur et les obstacles. Et nous pouvons également utiliser
le joueur pour déplacer les
larves de cette manière, ce qui sera une mécanique de jeu
importante. collisions avec des ennemis
seront gérées ici. Je prends un tableau d'ennemis et
j'appelle chacun d'entre eux. Pour chaque objet ennemi, je les appellerai ennemi, par exemple pour chacun d'entre eux, appelez cette fonction de rappel. En gros, je veux dire si cette larve et cet ennemi que nous sommes actuellement en train de traverser à vélo avec
cette méthode ForEach entrent en collision. Une façon de vérifier facilement
si deux objets du jeu entrent en collision est d'utiliser notre méthode de
vérification et de collision personnalisée. Encore une fois, je veux vérifier la
collision entre cette larve. Nous appartenons à la classe des larves
et à chaque ennemi individuel. Comme cette méthode s'exécute pour chaque méthode, nous savons que notre méthode de
vérification par collision personnalisée renvoie un tableau de valeurs. Cela nous donne la distance de collision,
certains rayons, DX et DY. Je ne veux ici que le
premier argument, le collagène, qui sera vrai ou
faux selon que cette larve
et cet ennemi entrent en collision ou non. Check Collision
renvoie un tableau et je veux que l'état de collision soit
vrai ou faux. Je veux que le premier élément de l'index du tableau soit zéro, comme ceci. Nous utilisons donc ici
la structuration pour extraire les cinq variables
individuelles de la méthode Check Collision. Ici, j'accède directement à la première valeur avec l'indice zéro car je n'ai pas
besoin des autres. Si je n'ai pas besoin ces autres valeurs en
cas de
collision entre une larve et un ennemi , c'est parce qu'
il n'y aura pas bousculades ni de physique. La larve va juste être mangée. J'ai donc dit « marqué pour
suppression » sur cette larve. Object à vrai. Je vais également appeler
Supprimer les objets du jeu pour filtrer cette larve hors
du réseau de nouveau-nés. Je vais également suivre le
nombre de nouveau-nés que nous avons perdus
à cause du dégoût et de la variabilité. Ce jeu à points qui a perdu nouveau-nés sera
augmenté d'un point. Et ici, lorsque nous
vérifions si la Floride déplace la sécurité de
la forêt de champignons, nous augmentons le score d'un point. Donc, si nous protégeons la larve
par position et x, en repoussant les ennemis
ou en poussant larve vers la forêt. Si la larve
atteint sa hauteur dans les buissons, nous obtenons un point. Si la larve est mangée, nouveau-nés
perdus
augmentera d'une unité. Ici, dans notre classe de jeu principale nous créons ces propriétés. Le score sera
initialement fixé à zéro et les nouveau-nés perdus seront également
initialement fixés à zéro.
26. Gagner des points de score: Je peux utiliser les journaux de la console
ou quelque chose comme
ça pour vérifier si le code que
nous venons d'écrire fonctionne, mais nous avions quand même besoin que ce texte soit
affiché au joueur. Donc, ici, nous allons
dessiner le texte du statut du jeu. Encore une fois. Nous utiliserons la méthode de remplissage de texte intégrée au
cannabis, qui attend le
texte que nous voulons dessiner et les coordonnées x et y
où le dessiner ? Je veux dessiner le mot score aux coordonnées 25 horizontalement
et verticalement. Le problème que nous avons
actuellement est que je veux que ce texte
soit aligné à gauche. Et si vous vous souvenez
du texte ci-dessus, qui indique que ce chronomètre est aligné au centre, je devrai isoler ce
FiltText appelé en l'insérant entre des méthodes Canvas sécurisées et des méthodes de restauration
intégrées. Ensuite, je peux régler l'
alignement du texte sur la gauche. Et j'appelle une restauration. Les méthodes de sauvegarde et de restauration fonctionnent ensemble et nous
les utilisons lorsque nous voulons appliquer des paramètres spécifiques uniquement à un certain appel de dessin sur le canevas sans affecter
le reste de notre projet. Je sauvegarde l'état du canevas. J'ai réglé l'alignement du texte sur la gauche, qui n'affectera que
cet appel FiltText où nous dessinons le score
, puis la méthode de restauration réinitialisera toutes sortes de paramètres
à ce qu'ils étaient. Safe a été appelé. Dans ce cas, il
ne reviendra à la ligne
X de la gauche au centre
. C'est logique. C'est une technique très utile, surtout si vous souhaitez redimensionner et faire pivoter vos dessins sur toile. Je le fais dans
d'autres classes, par exemple dans ma classe de
fractale de codage créatif, si vous voulez en savoir
plus à ce sujet. Maintenant, le score est aligné à gauche et les chronomètres situés au-dessus des œufs
sont alignés au centre. Parfait. J'ai ajusté le texte pour le dessiner, je veux dire marquer l'espace entre
deux points
entre guillemets , plus cette
variable de score par points pour le rendre dynamique. Maintenant que les nouveau-nés se mettent en
sécurité et se cachent dans la forêt, nous pouvons voir notre score
augmenter en mode débuggage. Je veux aussi pouvoir
voir les nouveau-nés perdus. Donc, si ce jeu
à débugger est vrai, je copie cette ligne de code. Le texte indiquera perdu plus ce point pour la variable «
hatchlings perdus ». En fait, nous sommes dans la classe
du jeu, donc je dois dire
juste ce point de débogage. Oui, je change la
coordonnée verticale ici. Et maintenant, en mode débuggage, nous pouvons également suivre le
nombre de nouveau-nés qui ont été mangés nombre de nouveau-nés qui sont
entrés en collision avec des ennemis.
27. Effets de particules: Parfois, la larve éclot rapidement et se nourrit
trop vite, ou parfois la larve
disparaît très près bord supérieur alors que l'
ennemi se trouve à proximité. Il se peut donc qu'il ne soit pas clair à
100 % s'il a réussi à se mettre en
sécurité ou s'il a été mangé. J'aimerais ajouter un effet visuel
supplémentaire qui nous
aidera à rendre notre
jeu clair et facile à lire. Je voulais ajouter deux types
d'effets de particules. Lorsque la larve atteint la hauteur
des buissons, elle interrompt un essaim
de lucioles qui se
trouvaient sur les branches et
elles s'envolent dans les airs. Un joueur voit ces lucioles. Ils savent que la larve est sans danger. Si la Floride se fait dévorer, j'essaierai de
créer un mouvement de particules différent et
très distinct. Donc, s'il y a de nombreux
objets de jeu dans la même zone, nous pouvons toujours savoir ce qui
se passe en observant type de particules
qui s'en
échappent. Je profiterai également de cette
occasion pour
parler du sous-classement en JavaScript Nous aurons une
classe de particules parente qui contiendra toutes les propriétés et méthodes partagées entre tous les types de
particules. Il s'agit d'une classe dite
parent, également appelée classe de superclasse. Firefly étend cette classe
de particules. Il s'agit d'une classe pour enfants, également appelée sous-classe. Nous aurons également une
classe que j'appelle spark qui étend la
classe de particules comme celle-ci. Nous avons une classe pour parents
et deux classes pour enfants. Les classes enfants hériteront
automatiquement des propriétés et des méthodes
de la classe parent, ce qui nous évitera
des répétitions inutiles. Écrivons le code et
parlons-en un peu plus au
fur et à mesure. Le constructeur de la
classe de particules parent
s'attendra à la position X et
Y du jeu, car les lucioles et les étincelles
s'
envoleront toujours à partir de la position où
la larve a disparu. Et ajoutons une
autre couleur, par exemple, ici. Peut-être que je veux qu'un type de
particule soit doré et un autre bleu, selon l'endroit où cette
particule a été créée dans notre base de code. Je vais te montrer ce que je veux dire. Je convertis tous ces arguments en propriétés de classe comme d'habitude. Je dis de prendre la couleur qui a été
transmise en argument ici et de l'enregistrer en tant que propriété scalaire sur cette instance
de classe de particules. Vous savez comment cela fonctionne maintenant, rayon sera une valeur
aléatoire de 5 à 15. Mais je l'intègre dans Math.floor
pour n'autoriser que les entiers, donc pas de décimales. Si nous créons
de nombreuses particules, vous remarquerez une grande
différence de performance lorsque nous utilisons des
valeurs aléatoires comme celles-ci, par rapport à
la définition du rayon
initial une valeur fixe de, disons dix pixels
pour toutes les particules. attribution aléatoire des
valeurs d'un objet lorsque la création de plusieurs objets coûte très cher en termes de
performances. Vous pouvez améliorer les
performances de votre jeu en évitant
autant que possible Math.random. Si vous le savez, vous
allez créer de nombreuses copies de cet objet
en particulier. Je sais que nous allons
créer de nombreuses particules. Nous n'avons qu'un seul objet pour le joueur, donc là, cela n'a pas
vraiment d'importance. Il n'est créé qu'une seule fois. Mais au cours de notre jeu, nous allons probablement créer
des milliers de particules. Une façon d'éviter cela serait
d'utiliser une technique appelée regroupement
d'objets. Vous créez un pool d'objets
particulaires ne les dessinez et vous ne les
utilisez qu'en cas de besoin. En termes de performances, ce sera bien
mieux que d'en
créer constamment de nouveaux
et de les supprimer. La vitesse x sera une valeur aléatoire comprise entre moins trois
et plus trois. Cela signifie que certaines particules se
déplaceront vers la droite dans la direction positive sur
l'axe horizontal des X, tandis que d'autres
se déplaceront vers la gauche si leur vitesse x est
une valeur négative. Pour la vitesse verticale, il s'
agira d'une valeur aléatoire comprise entre 0,5 et 2,5 pixels
par image d'animation. Je veux utiliser un peu de trigonométrie pour faire
tourner,
flotter et tourbillonner les particules . Nous aurons donc besoin d'une valeur d'
angle au départ, je l'ai mise à zéro. V. La vitesse de l'angle
déterminera rapidité avec laquelle
la valeur de cet angle augmente. Je vais vous montrer exactement comment l'utiliser dans une
minute. Ne t'inquiète pas. Le a sera une valeur aléatoire entre ces deux
très petits nombres. Nous allons supprimer les particules
qui se déplacent hors de l'écran. Au départ, j'ai dit qu'ils étaient
destinés à
être supprimés en raison faux drames qui porteront de
faux drames qui porteront également sur la classe de
particules parent. Il sera donc partagé pour toutes les
Fireflies et toutes les Sparks. Je veux m'assurer que les
modifications apportées à un état que nous
effectuons ici restent isolées de
cette particule en particulier. J'ai donc regroupé le code de
dessin entre les méthodes Canvas
intégrées
sécurisées et restaurées. Nous avons attribué FillStyle à cette couleur de
point à partir de la ligne 3/3. J'appelle commencer un chemin
pour commencer une nouvelle forme. La méthode d'arc intégrée
prendra l'horizontale, point
central, la verticale, le point
central, rayon, l'angle de départ et l'angle final. Je veux que tu dessines
un cercle complet. Ainsi, de zéro à math.pi
fois et math.pi fois deux, on obtient une valeur en radians et
elle est convertie en 360 degrés. boucle est bouclée. Nous devons utiliser des valeurs en radians ici lorsque nous
les transmettons à la méthode arc. Ensuite, j'appelle fill pour remplir
la couleur de la largeur du chemin. Et je vais aussi le caresser
car dans notre jeu, tout a ce
style d'art vectoriel avec des contours noirs. Je veux que les particules correspondent
à cela. De plus, Firefly
ne contiendra que la méthode de mise à jour. Idem pour Spark plus tard lorsque nous
appellerons la méthode draw sur la classe Firefly. Comme cette classe
étend les particules, JavaScript recherchera
automatiquement méthode de
dessin et le constructeur dans la classe de particules
parente. Cela
nous évitera de répéter le code. Je n'ai pas besoin de définir
deux fois le
constructeur et la méthode de dessin si c'est partagé pour
les lucioles et pour les étincelles, nous ne pouvons
le définir qu'une seule fois dans la classe parent et le
JavaScript le trouvera,
il sera hérité. Les lucioles auront un mouvement
unique, je pense qu'elles flottent vers le haut et
se balancent, de gauche à droite, ce qui est très facile à mettre en œuvre. Tout d'abord, nous allons
augmenter l'angle de VA, la vitesse
angulaire pour
chaque image d'animation. Ensuite, nous augmenterons la
collision x de la vitesse x. Comme la vitesse x peut être
positive ou négative, ils peuvent commencer à
tourner à gauche ou à droite manière aléatoire. La collision y
sera moins égale à la vitesse. Pourquoi ? Parce que je veux qu'ils
flottent dans la direction négative
sur l'axe vertical Y. Si une luciole se déplace complètement
vers le haut et qu'elle est cachée au-dessus du bord
supérieur de la zone de jeu. Donc, s'il s'agit d'
une collision, le point central est inférieur à zéro moins son rayon. Nous avons indiqué que la suppression était marquée comme étant
« vrai », et nous appellerons «
supprimer des objets du jeu ». Dans la classe de jeu principale, je crée
une propriété appelée particules. Ce sera un tableau qui
contiendra tous les objets particulaires actuellement
actifs. Je transforme les particules en objets de
jeu afin qu' elles puissent être triées,
dessinées et mises à jour. Dans Supprimer les objets du jeu, j'ajoute une ligne de code supplémentaire pour filtrer les objets particulaires dont la propriété marquée pour
suppression est définie sur true comme ceci. Essayons de créer
des particules. Je vais les créer
ici en classe de larve. Dans ce bloc de code qui s'exécute lorsque la larve atteint sa hauteur
dans la forêt, nous obtenons un point. Je veux qu'un essaim de lucioles
s'envole des buissons. Je prends ce réseau de particules aux
allures de jeu haut de gamme, et j'y insère une nouvelle
Firefly. Je me souviens que les constructeurs de
classes de particules attendent pour les arguments, une référence à l'objet principal du
jeu, comme d'habitude. Je le transmets donc
à ce jeu de points de Larva Constructor. x et y de départ initiaux de cette particule
seront les dernières
positions X et Y de la larve que nous venons supprimer et la couleur
sera rouge, par exemple juste pour le tester. Super, nous avons des particules rouges
avec des contours blancs. Si j'en veux plus d'une, je viens de créer une boucle à quatre. Disons que je veux trois
lucioles à chaque fois. Je vais changer de couleur en jaune. Voyons à quoi cela ressemble. Les belles particules
ont besoin d'un trait noir. Je peux le définir dans la
méthode de dessin sur chaque particule. Mais dans ce projet,
je n'utilise pas un trait pour beaucoup d'autres choses. Je peux simplement régler le
trait sur noir dans le monde entier ici, sur la ligne 9, ce qui sera plus efficace en termes de
performances. Cela donnera également des traits
noirs pour les cercles de
collision pendant que
nous sommes en mode debug. Mais je ne
pense pas vraiment que ce soit un problème. Ça pourrait être encore
mieux comme ça.
28. Mouvement des particules: Les lucioles ont un mouvement très basique vers le haut vers la gauche et la droite. Nous n'utilisons pas cet angle. Nous augmentons
sans cesse sur la ligne 327. Un moyen simple de faire en sorte que
quelque chose fasse des allers-retours est de transmettre chaque
augmentation de la valeur de l'angle à la méthode du
sinus ou du cosinus de Masdar. Lorsque votre code est comme ça, va, l'augmentation de l'angle pour chaque image d'animation
déterminera la vitesse de balancement. Et cette vitesse x
déterminera la courbe, le rayon, la distance parcourue, gauche et à droite, par le mouvement. Parfait. Chaque fois que la
larve hauteur dans la forêt, nous obtenons un point et nous en obtenons confirmation en observant
cet effet de luciole. Je veux que les étincelles aient un aspect
différent, de sorte que, au cas où larve et l'ennemi
seraient cachés derrière des
obstacles ou quelque chose comme ça, vous puissiez toujours voir que
la larve a été mangée fonction de l'
effet de particules qui s'y produit. Ici, je vais définir une méthode de mise à jour différente
avec un code différent à l'intérieur. Firefly et Spark sont donc
toutes deux des classes enfants de la particule mère
.
Elles héritent toutes deux du code du constructeur de
classes de particules. Elles partagent également
leur méthode de dessin,
mais chacune aura
une méthode de mise à jour unique dans Elles partagent également
leur méthode de dessin, mais chacune aura
une laquelle nous gérons le mouvement. Je vais à nouveau augmenter l'angle en fonction de la vitesse
angulaire VA, mais je vais le ralentir. Ainsi, multipliée par 0,5, la position
horizontale sera
moins égale au cosinus maîtrisé. Nous lui transmettons cette
valeur d'angle
toujours croissante pour la cartographier le long
d'une courbe en cosinus. Et nous définissons le
rayon de cette courbe en utilisant la vitesse x. La
collision y sera égale au
signe de la méthode et je lui transmets la même valeur d'angle et rayon de la courbe
est la valeur de la vitesse y. Nous remontons à la classe des larves. Et ici, si la Floride entre en collision avec un ennemi, nous le supprimons. Et je voulais créer
un tourbillon de particules. Je vais simplement copier ce
bloc de code que nous avons utilisé pour créer trois lucioles
et je le copie ici. Dans ce cas, nous voulons créer trois étincelles et
la couleur sera bleue. Comment puis-je m'y prendre ? Maintenant, je dois pousser la
larve devant un médecin, voir ce qui se passe
quand elle est mangée. Super, on a des étincelles bleues et une sorte de mouvement
circulaire. Juste à des fins de test, je créerai des étincelles même lorsque larves atteignent la hauteur, en toute sécurité, afin que l'animation se produise
automatiquement plus souvent sans que j'aie
à les poursuivre. J'ai besoin de le voir pour
pouvoir ajuster le mouvement. Que pouvons-nous faire avec
ces particules d'olive ? Vous pouvez faire tellement de
mouvements différents si facilement. Par exemple, faisons-les rétrécir. Si vous essayez de dessiner
un cercle en utilisant la méthode de l' arc dont le
rayon est inférieur à zéro, vous obtiendrez une erreur. Nous devons donc être
très prudents à cet égard. Je dis que si le rayon
est supérieur à 0,1, continuez à réduire le rayon
d'une petite valeur. Cette valeur doit être inférieure à 0,1 pour nous assurer que nous ne
pouvons pas descendre en dessous de zéro. De plus, si vous vous souvenez
bien, nous ne retirons les anciennes
particules que si elles dépassent le bord supérieur de Canvas et les
particules tourbillonnantes ne le font jamais. Donc, j'ai besoin d'une autre
condition. Si le rayon est inférieur à
0,2, par mesure de sécurité, il est marqué
pour suppression vrai et appelle la méthode de suppression des objets
du jeu. Super, ça a l'air intéressant. Je veux qu'ils soient
explorés des deux côtés. Je ne l'ai pas mentionné auparavant
car il n'est pas
nécessaire de bien comprendre la
trigonométrie pour ce cours. Sinus et cosinus et travaillez
ensemble pour tracer une trajectoire circulaire. Si nous leur donnons les mêmes valeurs, regardez ce qui se passe si j'
échange le sinus et le cosinus. Tout ce que vous devez comprendre à
propos du sinus et du cosinus à des
fins d'animation, c'est
que si vous les passez, valeur de l'angle augmente
toujours. Et lorsque vous associez
ces valeurs aux positions
verticales et horizontales de votre objet, vous obtenez un mouvement
circulaire. La meilleure façon d'obtenir
un peu de clarté est de jouer avec les valeurs
essayées pour le déchiffrer, ajuster le code et de
voir ce qui se passe. Ne vous inquiétez pas pour bien
comprendre la trigonométrie aujourd'hui, elle peut être compliquée pour les débutants et sa maîtrise prend
un certain temps. Je dessine 30
particules ici pour me donner une meilleure idée du
mouvement qui se produit. Et si des cas extrêmes apparaissent, il
faut en tenir compte. Tu n'es pas obligée de le faire. Je recommande de
n'utiliser que trois particules par terme pour des raisons de
performance Vous pouvez voir que les étincelles sont des
sortes d'
explosions tourbillonnantes. Je l'aime bien. Le mouvement est très
différent de celui des lucioles. Je leur donne une couleur jaune ici, et je vais recommencer
à utiliser des lucioles. Voyons à quoi ça ressemble. Nous savons donc comment étendre classe
JavaScript pour
éviter les répétitions de code Nous avons créé une
classe de particules parente et une classe secondaire, Firefly, qui indique
au joueur que des larves
ont réussi à se cacher dans la forêt en
perturbant un essaim d' insectes en
pleine croissance qui
flottent vers le haut. Et lorsque la larve est
mangée par un ennemi, elle se transforme en un tourbillon d' étincelles
magiques qui
rétrécissent lentement et disparaissent. Je vais en revenir à trois
lucioles ici. Et ici en bas. Créons trois
étincelles, ou peut-être cinq, car elles rétrécissent si
rapidement et sont souvent masquées par des obstacles
et d'autres objets du jeu. Nous voulons nous assurer qu'ils se font
remarquer lorsqu'ils apparaissent. J'aimerais également permettre au joueur de déplacer
les x
vers la forêt pour
marquer des points immédiatement Je veux que X
éclore instantanément lorsque nous les
poussons assez haut
dans la zone de sécurité, cet œuf se transformera
automatiquement en larve et en
lucioles instantanément. Et nous obtiendrons un point. Je peux le faire ici, sur la
ligne 179, où nous vérifierons si chronomètre de
Hodge est supérieur à l'intervalle entre le
clapier et
redevenir une larve Je veux que ce
bloc de code fonctionne également si l'œuf a été poussé
vers la zone de sécurité. Si une collision en
position verticale y est inférieure à ce
jeu de points (marge supérieure en pointillés). Pour le tester, je devrais peut-être
augmenter l'intervalle d'éclosion. Sinon, ces œufs
éclosent trop vite. Je vois un œuf ici, pas ici, et je l'
enfonce dans la moelle. OK, maintenant on y va. Il a éclos instantanément alors que le temps d'
éclosion n'était que 7 s. J'essaie à nouveau avec cet œuf, et oui, cela fonctionne et nous obtenons
également des points
pour cela. Parfait.
29. Peaux ennemis randomisés: Je repousse de nombreux
ennemis différents pour toi. Vous savez comment nous avons
un seul fichier image avec plusieurs types d'obstacles. Je
vous ai également préparé de
nombreux gains de crapauds qui joueront le rôle
d'ennemis dans notre jeu. J'ai eu beaucoup de plaisir à créer différentes variations et à imaginer quels types de capacités
spéciales et de mouvements spéciaux
ils pouvaient avoir. Disons que pour
des raisons de performance, nous voulons utiliser uniquement un ensemble d'images
statiques pour les ennemis. Nous
les animerons également plus tard. Si c'est
ce que vous souhaitez dans la
version finale du jeu, tout sera animé. Toutes les images du projet peuvent être téléchargées à partir de la section
des ressources ci-dessous. Comme d'habitude, je vous offre toutes ces illustrations de
jeu premium gratuitement. Ce cours est conçu pour
vous donner la valeur maximale possible. N'hésitez pas à utiliser
ces ressources artistiques pour vos propres projets
si vous le souhaitez. J'intègre donc cette feuille de calcul contenant quatre cadres pour les
types d'ennemis au projet. L'identifiant correspond à des crapauds et la source
est dirigée vers le point PNG. Je le cache avec du CSS comme d'habitude. Dans script.js, dans le constructeur de classes
ennemies, nous créons deux variables auxiliaires qui nous aideront à
naviguer dans la feuille de calcul et à recadrer une image aléatoire pour chaque objet
ennemi, l'image x. Nous allons parcourir la
feuille de calcul horizontalement. Et il sera initialement
mis à zéro pour que MY navigue verticalement et
il commence également à zéro. J'aurai besoin de la version la
plus longue de méthode
Draw Image pour définir l'image
que je
voulais dessiner, la source x, y, largeur et la
hauteur de la
source afin de
spécifier la zone rectangulaire que
je voulais recadrer à partir de l'image source
et de la destination. Destination. Pourquoi la
destination avec et la hauteur de la destination pour définir pourquoi nous avons placé
cette image
recadrée sur le canevas de
destination. Neuf arguments au total. Image pour dessiner une zone de recadrage. Et où placer
cette image recadrée. Commençons par recadrer
uniquement le cadre supérieur gauche. Nous recadrons donc à partir de la
coordonnée zéro à zéro, deux coordonnées, un sprite
avec une peau de sprite. Cette feuille de calcul
ne comporte qu'une seule colonne, donc le cadre x restera à zéro. Je veux recadrer un cadre
vertical au hasard. Donc, expliquez pourquoi
la zone de recadrage sera à la hauteur du sprite, poussant le début de la zone de
recadrage ici, étant donné ce cadre,
pour vraiment le voir, je dois utiliser la nouvelle
image avec un identifiant de crapauds. Donc, pour être clair, zéro fois la hauteur du sprite nous
donnera ce cadre. Ce cadre
sera découpé en deux fois la hauteur du sprite. La valeur que nous transmettons à une source. La méthode Pourquoi dessiner une image déterminera où commencer le recadrage
à partir de la verticale. Au lieu de cette valeur
codée en dur, nous pouvons utiliser frame. Pourquoi ? Maintenant, quand je donne un cadre, pourquoi une valeur différente ? Cela nous donne différents types d'
ennemis. Je veux que chaque objet
ennemi soit attribué au hasard à l'une de ces images
lors de sa création. Nous avons donc quatre lignes,
Math.random multiplié par quatre. Et si je l'enveloppe dans Math.floor cadre y sera
soit zéro, soit un, deux
ou trois. Je remplacerai également la source X par une trame à points sur disque x fois sprite. Cela
deviendra pertinent un peu plus tard lorsque je
vous donnerai la prochaine feuille de calcul. Pour l'instant, laissons le
cadre x à zéro. Ce serait également bien de réattribuer
l'image au hasard
à chaque fois, puis déplacer hors de l'écran et de la réinitialiser. Nous utilisons donc toutes les images
disponibles. Je place simplement l'image y au hasard, comme ceci pour y parvenir. Pour tester rapidement cette vitesse ou augmenter la vitesse de l'ennemi
à une valeur aléatoire, 5 à 8 pixels par image d'animation. Les ennemis se réinitialisent
et les images changent de
manière aléatoire à
chaque réinitialisation. Parfait. Revenons
à une vitesse plus basse. J'ai réglé x à cinq, étant donné que nous utilisons des images statiques pour les ennemis à ce stade, les
dessiner coûte très peu cher
en termes de performances Peut-être pourrais-je également augmenter
le nombre d' ennemis à cinq. Cela commence à
avoir l'air vraiment bien.
30. Gagnez et perdez l'état: Je voulais afficher
un message de victoire et de
défaite sur
la classe de jeu principale J'ai créé une propriété que j'
appelle par exemple le score gagnant. À des fins de test,
je l'ai réglé à cinq. Nous allons tirer au sort les messages gagnants et
perdants ici. Si le score est supérieur ou
égal au score gagnant, je l'emballerai dans un coffre-fort
et je le restaurerai pour restreindre certains
paramètres de tirage. Nous n'utiliserons désormais que deux messages de
victoire ou de défaite. Je souhaite dessiner une couche
semi-transparente pour indiquer que le jeu est terminé, et aussi pour rendre le message plus contrasté par
rapport à l'arrière-plan. J'ai donc dit FillStyle
pour bloquer les zéros, zéros, l'opacité de 0,0, 0,5. Ensuite, nous allons dessiner ce rectangle
noir semi-transparent sur toute
la toile,
de la coordonnée 00 à la largeur et à la
hauteur de la zone de jeu. Exécutons ce code pour le tester. Lorsque nous atteindrons le score trois, nous devrions obtenir la couche
semi-transparente hollandaise. Oui. Une fois ce rectangle dessiné, je vais changer FillStyle
en blanc pour m'assurer que le texte contraste avec le
fond sombre. J'ai réglé l'alignement du texte au centre. Nous aurons un
message principal en gros caractères et un message secondaire
en caractères plus petits. Je vais simplement les définir comme
des variables principales. Et la valeur de
ces messages
dépendra de la qualité
de notre jeu. Dans tous les cas, ce message ne
s'affichera que lorsque le score sera supérieur ou égal
au score gagnant. Mais disons que si
nous avons bien joué et nous ne perdons que cinq nouveau-nés
ou moins, nous recevrons un message gagnant. Si nous en perdons plus de cinq, nous recevrons un message perdant. Le but du jeu est de
pousser des œufs, des maillons et des ennemis
pour nous assurer en
protéger le plus possible. Donc, si nous jouons bien, disons un
message, jouons un peu avec les mots. Vous pouvez écrire ce que vous voulez comme message gagnant ou
perdant ici. Donc, si nous obtenons le message principal en grosses lettres
sur l'écran, nous dirons cible et
quelques points d'exclamation. Le
message secondaire, plus petit, dira : « Vous tirez sur les intimidateurs ». Si nous perdons, le
message principal indiquera, secondaire plus petit de
Borlaug
indiquera que vous avez perdu. De plus, nous afficherons une valeur de variable
dynamique pour montrer combien de nouveau-nés ont été mangés. Et le coma des nouveau-nés. Ne soyez pas un jeu d'enfant. Il s'agit d'un jeu de physique
qui consiste à bousculer les choses. Nous devons apprendre à mieux pousser. J'utilise une bonne vieille concaténation de
chaînes pour construire ce message
dynamique serait
encore mieux d'utiliser
un modèle de littéraux ici, si vous connaissez la syntaxe JavaScript
moderne. Maintenant, nous voulons réellement
dessiner ces messages. Le message
de grande taille sera, par exemple, 130 pixels. Helvética. La méthode Filttext
prendra le texte que nous voulons dessiner dans le message 1 et les coordonnées x
et y seront au milieu
du
canevas horizontalement et verticalement, comme ceci. Le second message sera
plus petit pour les pixels. Helvética. Filttext affichera également le
message 2 au milieu
du cannabis. Encore un
objectif FiltText : nous indiquerons l'espace des scores
finaux et nous y afficherons la valeur du
score final, plus un point pour
terminer la phrase. Et une autre phrase dira : appuyez sur R pour vous cogner à nouveau. Je veux vous montrer
comment implémenter une
fonctionnalité de redémarrage très simple. Chaque fois que nous appuyons sur la
lettre R sur le clavier, je la dessine également au milieu verticalement
et horizontalement. Maintenant, je dois espacer
ces messages qu'ils ne soient pas dessinés
les uns sur les autres. J'ajuste la position
verticale du
message d' un par -20 pixels, le
déplaçant vers
le haut dans le sens négatif
sur l'axe vertical Y. Le message 2 sera plus
30, en le poussant vers le bas. Le message trois sera plus 80. Voyons à quoi cela ressemble. Oui, cet espace
est bien meilleur. Nous avons notre message gagnant. Lorsque le score est
supérieur au score gagnant, nous avons dit game over à true. Sur l'objet principal du jeu, je définis le jeu par rapport à la propriété et, au départ, je le définis sur false. La chose la plus simple que nous
puissions faire ici est de figer l'animation lorsque Game Over
se produit. Je peux le faire, par exemple , ici, je dis ne diffuser que
l'image d'animation suivante. Si la fin de la partie est fausse, lorsque la fin de partie devient vraie, la partie se fige. J'ai dit score de victoire à
un, juste pour les tests. Et il affichera un message
gagnant ou perdant. Et ça va geler comme ça. Je descends à la ligne 519
et je supprime ce passage. J'aimerais que le jeu continue
de fonctionner, mais nous allons faire en sorte que le nouveau X cesse apparaître et j'
empêcherai les ennemis de se réinitialiser. Ils flottent donc hors de
l'écran et y restent. Ainsi, chaque fois que
la partie sera terminée, les objets qui se trouvent
déjà dans la zone de jeu termineront simplement l'
action qu'ils sont en train de faire, mais de nouveaux objets n'apparaîtront
plus. Nous finirons simplement de jouer derrière le message gagnant
ou perdant, mais le nouveau x n'
apparaîtra plus et les ennemis s'
arrêteront et entreront. Le joueur sera toujours
interactif et nous pouvons toujours le déplacer dans
le monde vide du jeu. Comment mettre
cela en œuvre ? C'est simple. Tout d'abord, supposons qu' un message de
victoire ou de défaite apparaisse et il
nous reste encore des œufs qui
éclosent .
Nous nous assurerons de
marquer des points uniquement si la fin de la
partie est fausse. Lorsque Game Over aura lieu, nouveau-nés apparaîtront
toujours sur les x restants, mais quoi qu'il arrive, cela n'
affectera plus nos points de score.
Sur la classe ennemie. Je veux que les ennemis soient réinitialisés uniquement si la fin de partie est fausse, comme ça, quand GameOver se produira,
et cela leur permettra terminer leur
déplacement dans la zone de jeu, mais ils ne seront plus
réinitialisés vers la droite. Ainsi, de nouveaux ennemis cesseront d'arriver. Ici, nous
voulons ajouter un nouveau x
au jeu uniquement si la fin de la partie est fausse, si message de
victoire ou de défaite
apparaît, si le x existant, nous allons quand même terminer de hacher, mais le nouveau x cessera d'apparaître. Nous allons le tester. J'ai un message gagnant. Il me reste quelques œufs, mais ces nouveau-nés n'augmentent
plus notre score. Il nous reste quelques ennemis, mais ils quittent lentement l'écran et ne
reviennent pas. Le joueur reste interactif et nous pouvons toujours le déplacer. Parfait. Je voulais tester
le message de relâchement Plutôt que de pousser
intentionnellement des
nouveau-nés devant les
ennemis pour qu'ils se fassent manger, je vais simplement
définir manuellement les nouveau-nés perdus, les dix ici sur la ligne 380. Oui, nous recevons un message perdant. C'est génial. J'ai dit plus touchez
les liens pour revenir à zéro. L'ajout d'une police personnalisée est facile. Vous pouvez choisir la
police de votre choix. Je vais accéder à Google Fonts. Des milliers de
polices y sont disponibles. Je souhaite utiliser cette police
inspirée des bandes dessinées appelée bankers. Je clique ici pour sélectionner la police, et je clique ici, ce qui générera du
code que je pourrai utiliser pour inclure cette
police dans mon projet. Je copie ces trois balises de liens
et je les colle ici dans l'en-tête de
mon fichier HTML d'index, en attendant
mes feuilles de style
personnalisées, afin que la police soit
disponible à partir de là. Ensuite, je copie la règle CSS. Je l'utilise ici. Dans le cas de ce projet, je peux simplement appliquer cette
famille de polices à tous les éléments. Vous pouvez être
plus précis et ne l'appliquer qu'à l'élément de
toile. Par exemple , la police est
désormais
disponible dans notre projet. Donc, ici, à la dixième ligne, j'ai dit toile pleine de banquiers de
40 pixels. Cela affectera le
texte qui affiche score et les chronomètres
au-dessus des œufs à éclore. Nous voulons également définir des
banquiers ici et ici Si nous voulons l'utiliser
pour les messages de fin de partie,
allons-y rapidement quand la partie sera terminée . Ça a l'air mieux, n'est-ce pas ? Parce que nous utilisons Safe and Restore. Écoutez, tout ce que je fais dans
cette zone restera limité au
message Game Over est Canvas. Les ombres sont coûteuses en termes de
performances et certains navigateurs ne les
gèrent pas bien, mais si je les limite à
ce bout de texte, tout ira bien. Essayons-le. Nous devons définir la distance
horizontale entre la forme et l'ombre. Il peut s'agir d'une valeur positive ou
négative selon que vous souhaitez placer l'ombre
à gauche ou à droite. décalage d'ombre y peut également
être positif ou négatif. Il déterminera la position
verticale de l'ombre par rapport
à sa forme d'origine. La couleur de l'ombre sera noire. Nous pouvons également définir le flou des
ombres si nous le souhaitons. Celui-ci est facultatif, je vais
donc le laisser sur zéro
par défaut, ce qui
signifie plus noble. Gardez à l'esprit que les
ombres ne seront dessinées si la couleur de l'ombre est définie sur
une valeur non transparente. Et si au moins l'une des
propriétés de flou d'ombre, décalage d'
ombre X ou de décalage d'ombre y est définie sur une valeur différente de zéro. Les ombres mettent le
texte en valeur et le font ressortir un peu plus de
l'arrière-plan. J'ai encore dit « bébés perdus »
à dix, juste pour comprendre le message de relâchement. À quoi cela ressemble avec une
nouvelle police et de nouvelles ombres. Super, ça a l'air super. J'ai dit de remettre la soie dentaire à zéro pour les
nouveau-nés.
31. Redémarrer le jeu: Nous avons ce message
ici qui dit appuyer sur R pour vous heurter à nouveau, ce qui signifie que vous devez appuyer sur R
pour redémarrer le jeu. Ce que je vais vous montrer
est le moyen le plus simple d'
implémenter la
fonctionnalité de redémarrage du jeu dans la classe des joueurs. Je crée une
méthode personnalisée que j'appelle, par exemple redémarrer. À l'intérieur, je veux définir propriétés des
joueurs telles qu' elles sont au début d'une nouvelle partie. Jetons un coup d'œil à
ce que nous avons ici. Je veux que le joueur revienne
à la position initiale. Nous allons réinitialiser la collision
x et la raison de la collision ? Nous nous assurerons également que image du
sprite se déplace
en même temps que le cercle de collision. Je vais donc avoir besoin de ces
deux lignes de code. La méthode de redémarrage
du jeu ramènera donc la zone de collision
du joueur et la feuille de sprite du joueur
à leur position de départ. Nous descendons ici vers
la classe de jeu principale et ici, dans l'écouteur d'événements Key
Down, je dis que si la touche qui a été enfoncée est notre méthode de redémarrage des appels
sur une classe de jeu comme celle-ci. Je définis cette méthode ici. Et ici, nous allons remettre toutes les propriétés à
leur état initial. Cela sera
différent d'un projet à l'autre. Nous venons d'écrire cette base de code afin de la connaître
et comprendre ce qui doit
être modifié pour le jeu revienne
à son état initial. Tout d'abord, nous appellerons la méthode de
redémarrage que
nous venons de définir sur
la classe du joueur. Nous allons le tester. Je déplace le joueur et lorsque j'appuie sur la lettre
R sur le clavier, joueur revient à sa position de départ.
Jusqu'ici, tout va bien. Nous pouvons utiliser une
technique similaire pour donner au joueur la possibilité
de revenir en arrière. Par exemple, nous avons simplement défini l'état
et la position de x et n est n nouveau-nés
tels qu'ils étaient, disons il y a 5 s. Cela pourrait nous donner un gameplay
intéressant. Quoi qu'il en soit, nous voulions
relancer le jeu. Donc, ici, dans le constructeur, je vérifie ce qui doit changer. Je sais que je vais devoir réinitialiser
le contenu de mes tableaux. Je prends des obstacles, des x, des ennemis, des nouveau-nés
et des particules. Et j'ai dit tout cela
pour revenir à des tableaux vides comme celui-ci. Je le teste. OK, donc quand j'appuie sur R, cela se produit et je dois
réexécuter la méthode init pour
recréer les ennemis et obstacles depuis que nous les avons supprimés. Oui, maintenant, lorsque je redémarre, les obstacles se régénèrent à des positions
aléatoires et nous générons
également de nouveaux ennemis. Je peux voir que je dois également
réinitialiser la position actuelle de
la souris. Je prends cette
souris
à points et je la règle sur ces
valeurs de départ, donc je peux simplement la copier. J'ai également remis le score à zéro et j'ai également perdu des nouveau-nés. Je dois également régler le jeu
sur False pour m'
assurer que x continue d'apparaître et que les
ennemis continuent de se réinitialiser. Nous allons le tester. Je joue. Je gagne la partie. J'appuie sur le côté de l'artère. Je joue. Quand je le redimensionne, je joue, je gagne, j'ai
l'air de fonctionner. Très bien. J'ai dit score de
victoire à 30. OK, je passe un peu de temps à tester le gameplay et il y a encore
quelques
points que nous pouvons ajuster. Comme vous le savez, nous pouvons activer et désactiver le mode de débogage en appuyant lettre D. Je suis ici sur
notre classe de larves personnalisée. J'aimerais que nos liens
Larva Hatch interagissent avec x dans la méthode de
mise à jour classe
Larva. J'ai utilisé l'opérateur de
propagation pour étendre x dans un tableau d'
objets de collisions. Cela
rendra le X solide impossible à surmonter
et les nouveau-nés devront ramper autour d'eux. Cela rendra le
jeu un peu plus difficile et le joueur
devra
s'impliquer davantage pour
éliminer le x et s'
assurer que les nouveau-nés atteignent la
zone de sécurité le plus rapidement possible. Parfois, les nouveau-nés
peuvent même se retrouver coincés entre plusieurs
œufs et des obstacles. Et si nous ne les libérons pas à temps, ils seront dévorés par les ennemis. Sinon, je peux
supprimer X d'ici. Je passe à la classe d'œufs
et à la méthode de mise à jour des informations. Dans un cours, je vais étendre nouveau-nés à un tableau d'objets en
collision. Cela, en revanche, facilitera le jeu,
car non seulement
les nouveau-nés seront capables de
pousser le x à l'écart. Ils placent également
parfois le x
devant eux, plus près
de la zone de sécurité. Vous pouvez choisir vous-même ce que vous
voulez faire ici, selon
que vous voulez que votre jeu soit facile ou plus difficile
à ce stade, vous connaissez assez bien ce
code. Donc, si vous le souhaitez, vous pouvez prendre une certaine liberté et ajuster le
gameplay comme vous le souhaitez. Je veux également que les
cercles de collision des nouveau-nés
correspondent mieux à la feuille de sprites
-40 ici. Cela fonctionnera bien Je pense que pour mieux
aligner le bas des cercles de collision
là où se trouve le bas du corps des nouveau-nés. Je veux que ces
zones de collision correspondent le plus possible à l'œuvre d'art. Nous sommes maintenant en mode debug, mais gardez à l'esprit que
le jeu est
censé être joué avec des cercles de
collision cachés. Lorsque le mode de débogage est désactivé. Vous pouvez utiliser la
même technique pour mieux aligner les cercles de
collision sur ennemis avec la petite ombre au sol sous chaque ennemi. Je le ferai dans
une minute car dans la prochaine leçon, nous nous concentrerons
sur l'ajout de nouveaux types d'ennemis. Je vais également vous donner les feuilles de calcul de tous les
personnages et nous ajouterons de nombreuses
animations à ce projet. J'ai eu tellement de plaisir à concevoir ces créatures et à
les faire bouger. J'espère qu'il vous plaira. J'ai remarqué un petit
avantage, lorsque nous recevons un message de fin de partie
et ennemis
restants mangent des nouveau-nés restants. Les variables relatives aux nouveau-nés perdus
continuent d'augmenter. Nous devons nous assurer que la valeur des nouveau-nés
perdus reste la même après l'affichage du message Game
Over. Je n'exécuterai donc ce
bloc de code que si la fin de la partie est fausse. Cela rendra également
les nouveau-nés
vulnérables pendant le
jeu à l'écran. Si vous ne le souhaitez pas, vous pouvez appliquer cette instruction
if uniquement à une ligne de code qui
augmente le nombre de nouveau-nés perdus. Si la fin du jeu est fausse, nouveau-nés
perdus sont plus, plus.
32. Élargir la classe ennemie: OK, plusieurs types d'ennemis. Je souhaite créer deux
classes pour enfants qui s'étendent. Classe ennemie parent. La peau dorée sera
cette peau verte visqueuse, scan de l'
écorce sera le bois
creux avec des bois,
des pointes et des feuilles. Nous travaillons sur le thème de
la forêt magique. Je me suis donc amusée à
dessiner des créatures sur celui-ci. Encore une fois, nous étendons la classe
JavaScript ici. Nous le faisons pour éviter les répétitions à
froid. Toutes les propriétés et
méthodes partagées par
tous les types d'ennemis appartiendront à
la classe endémique parente. Seules
les propriétés spécifiques à
chaque type d' ennemi
seront incluses dans les classes enfants. Vous pouvez télécharger toutes
ces versions premium ou les ressources dans la section
projet ci-dessous. Nous allons commencer par ajouter
huit scans d'aboiement différents. Que pensez-vous de trop de
mes créations ? Je voulais que celui-ci soit en bois et qu'il soit creux à l'intérieur, mais que la lumière sorte des yeux et
de la bouche, un peu comme une citrouille d'Halloween. Je cache l'image avec du CSS. J'ai également remplacé l'image
du crapaud. Au début, nous avions quatre personnages
dessus. Il existe désormais huit versions
différentes. Beaucoup de mots, de boue, d'
yeux et de tentacules. qui concerne la classe ennemie principale, je peux voir que le constructeur s'attend à ce que
le jeu soit un argument. Je veux exécuter le constructeur
sur la classe ennemie mère et y ajouter un peu de matière
depuis la classe de skin TO. Principalement les propriétés
qui ne seront spécifiques qu'au type d'ennemi de la peau du crapaud. Ainsi, dans le constructeur de la
classe enfant, nous nous attendrons à ce que le
jeu soit un argument. Ensuite, nous devons d'abord exécuter constructeur sur la classe ennemie
parent, également appelée superclasse. Nous appelons constructeur de superclasse. Et nous transmettons la référence, l'objet principal du jeu
, car nous savons ce qui est attendu
ici à la ligne 264. Toutes ces propriétés
seront spécifiques uniquement à l' habillage NMAI car
l'image sera différente. La taille des sprites, ainsi que leur largeur
et leur hauteur,
dépendront également de la taille de ce sprite. Et la collision x utilise
la largeur et sa formule. J'ai donc supprimé tout cela, basant sur la classe pour
enfants ici. Ces propriétés auront donc une valeur différente pour
chaque classe enfant. Ils ne seront pas partagés. Je vais copier ce bloc de code
et le mettre sur Bark Skin. Ici, nous devrons
ajuster les valeurs. La largeur du sprite est ici de 183 pixels. La hauteur du sprite sera de 280, largeur et hauteur
d'un seul cadre. Cet ennemi sera plus grand. Cette image à points
sera l'identifiant de Barack. Lui avons-nous donné un index HTML ? Ce sont donc les propriétés
communes à toutes les classes ennemies. Ils partageront également ce
tiroir et cette méthode de mise à jour. Les propriétés des classes enfants seront uniques pour
chaque type d'ennemi Nous avons deux types d'ennemis. Je voudrais
ajouter l'un ou l'autre au hasard. Je m'occupe de l'ajout d'
ennemis ici dans la méthode d'ajout de lavement
sur la classe de jeu de domaine. Ici, je peux dire
que si
Math.random est inférieur à 0,5, Math.random appelé seul Math.random appelé seul de cette manière renverra
un nombre
aléatoire supérieur ou égal
à zéro et inférieur à un. On peut donc dire que
ce sera moins de 0,5 et environ 50
% des cas. S'il est inférieur à 0,5, nous ajouterons une nouvelle peau
de crapaud à notre réseau d'ennemis. Sinon, dans les 50
% restants,
nous vendrons de la peau de daim neuve. Agréable. Maintenant, nous ajoutons aléatoirement
les deux types d'ennemis. image x est définie sur zéro, nous n'obtenons
donc que les
images de la première colonne. Je veux que ce soit zéro ou un. Donc Math.random multiplié par deux
dans Math.floor comme ça. Maintenant, nous avons toutes les images. Je vais également vous montrer comment
animer ces feuilles de calcul, mais cela augmentera les performances du
jeu, car les
illustrations des personnages que j'ai
choisi d' car les
illustrations des personnages que j'ai utiliser pour
ce projet sont très détaillées et
les images sont assez grandes. Certaines
techniques d'optimisation peuvent être utilisées pour l'animation de
sprites, mais cela dépasse le cadre de ce cours adapté aux débutants. Nous en
reparlerons un peu plus bientôt. Lorsque les ennemis se réinitialisent, nous sommes aléatoirement dans l'image
y, mais pas x.
Faisons-le en copiant la ligne 270 et en la plaçant ici dans
ce bloc d'instruction if. Maintenant que nous sommes entièrement aléatoires dans l'image lorsque les ennemis
réinitialisent leur position, je peux placer ces lignes
qui ont aléatoirement x et l'image y dans une méthode de mise à jour
partagée. Parce que mes deux
types d'ennemis ont le même nombre d' images pour les lignes et les deux colonnes. Si chaque feuille de sprite ennemie avait un
nombre d'images différent, je devrais étendre
cette méthode de mise à jour. chaque sous-classe NMS, nous ajoutons et
supprimons des objets
tels que des particules, des
nouveau-nés et des x. Il est toujours bon de vérifier
nos objets pour nous assurer que
les anciens objets été correctement supprimés et que nous
n'avons pas un tableau qui ne s'
agrandit pas à l'infini. Je pourrais l'enregistrer sur console dans
ma méthode de mise à jour, par exemple, mais exécuter un
journal de console comme celui-ci, 60 fois par seconde, coûte très cher en termes de
performances. Nous pourrions simplement enregistrer
des objets r sur console à la demande chaque fois que nous
appuyons sur un bouton de notre écouteur d'événements
Key Down Je dis que si nous appuyons sur
C sur le clavier, console enregistre
ces objets de jeu à points. Maintenant, je peux jouer au jeu et temps en temps, j'appuie sur
C pour vérifier si le tableau des objets
du jeu ne contient que
les bons objets actuellement
actifs dans le jeu. Si vous remarquez, par exemple,
qu'il
augmente sans cesse et qu'il contient de
plus en plus de particules. Nous savons que nous ne supprimons pas correctement
les anciens
objets particulaires. Tout semble bon dans ce cas.
33. Mode plein écran simple: Ainsi, dans notre jeu, nous pouvons appuyer sur la lettre
D pour activer et désactiver le mode de débogage, la lettre
R pour redémarrer le jeu, C pour créer un journal de console personnalisé. Et je vais également
vous montrer comment activer et désactiver un
mode plein écran très simple en
appuyant sur la lettre F. Nous vous
appellerons pour discuter de la méthode, par exemple passer en plein écran. Nous allons le définir ici
sur la classe de jeu principale. Javascript possède une fonctionnalité de
plein écran native. Cette API intégrée contient un ensemble de méthodes
qui nous permettent de
présenter un élément spécifique et tous ses descendants en mode plein écran, en supprimant tous les éléments de
l'interface utilisateur du navigateur et les autres applications
de l'écran. Lorsque j'appelle un élément
en plein écran du document point comme
celui-ci, il renvoie l'élément
actuellement présenté
en mode plein écran. S'il renvoie la valeur null, cela signifie que le
mode plein écran n'est actuellement pas utilisé. Donc, je veux dire que si nous ne sommes actuellement pas utilisés en mode
plein écran sur cette page, je souhaite passer en mode
plein écran. La méthode de demande en plein écran affichera l'élément auquel elle est appelée
en mode plein écran. Dans ce cas, je voulais
afficher l'intégralité de la page Web. Donc document, qui représente l'élément de
document DOD de la page Web, qui représente l'
élément racine du document, en l'occurrence la balise HTML. Je veux qu'il mette en plein écran
l'ensemble de la page Web à partir du code de son élément racine
pour quitter le mode plein écran. C'est simple, donc nous disons
simplement « sinon » si le document sort du plein écran, Exécuter, le document qui quitte le mode
plein écran. C'est un peu bizarre,
mais ça va marcher. Pendant ce temps, toute
la page Web tournera. Fullscreen Canvas n'
occupera pas toute la largeur de l'écran. Nous déplaçons le
joueur à l'aide de la souris, nous devons
donc faire attention à la
façon dont nous redimensionnons Canvas dans ce projet, car les coordonnées de la
souris sont calculées d'une certaine manière. Si je donne une largeur
dynamique à Canvas avec du CSS, il commencera à
nous donner de mauvaises coordonnées. Dans le navigateur Google Chrome. Si je passe en plein écran comme ça et que je zoome pour que le
jeu couvre tout l'écran, les coordonnées de la
souris seront
toujours calculées correctement et le gain
sera jouable. Vous pouvez le tester par
vous-même en appuyant sur F pour passer en plein écran,
puis en maintenant la touche
Ctrl enfoncée et en appuyant sur les touches plus ou moins pour
zoomer avant et dézoomer. Sur Mac, nous utilisons plutôt
la touche Commande. Nous sommes sur le point d'animer
les feuilles de calcul. Ces images sont
volumineuses et cela mettra à rude épreuve les
performances de l'ordinateur lorsque nous
commencerons à les parcourir
très rapidement sur chaque objet
animé actif Vous pouvez enregistrer
la base de code telle qu'elle est actuellement et
continuer dans une copie de ce dossier afin de conserver des bases de code statiques et entièrement animées
et de les comparer côte à côte en termes de
les performances de votre machine. C'est à vous de décider. Je laisserai également le code
source complet de cette étape
du projet disponible en
téléchargement dans la section
des ressources ci-dessous Le dossier contenant le code
source complet de cette étape s'appelle code
source version 5.
34. Animation complète de la feuille de sprite: Il est temps d'animer complètement
la feuille de sprite du joueur. Nous utilisons déjà
la feuille de sprites, mais nous ne recadrons que
la première image chaque ligne pour faire pivoter le joueur
dans différentes directions. Nous avons ici des variables auxiliaires, où une image x tournera
sur la même ligne de gauche à droite en boucle dans
cette animation particulière. Et l'image y
déterminera la ligne que nous animons. Dans le cas d'une
feuille de sprite, le
même personnage est
orienté dans des directions différentes sur différentes rangées . Nous utilisons la méthode draw pour dessiner cette feuille de calcul sur Canvas. Nous utilisons la version la
plus longue avec une image à neuf arguments que
nous voulons dessiner. Ensuite, nous définissons la zone de recadrage à l'aide des quatre arguments suivants. Source x, y,
largeur et hauteur de la source. Et les quatre derniers arguments définissent où, sur la
destination du cannabis, nous plaçons cette image recadrée sur la destination x, destination. Pourquoi largeur de destination
et hauteur de destination ? Je l'ai expliqué à quelques reprises dans ce cours parce qu'
il est très important comprendre si vous souhaitez utiliser l'image de dessin pour
une animation de sprite. Nous avons déjà une fonctionnalité
qui permet de remplacer l'image y par une ligne différente en fonction de l'endroit où le joueur doit se trouver. Tout ce que j'ai à faire maintenant pour être
complètement animé, c'est de faire image X passe de l'image zéro à l'image maximale
encore et encore. Nous allons gérer l'animation des sprites ici
dans la méthode de mise à jour. Et nous réutiliserons également ce code
pour d'autres objets. Nous aurons besoin d'une autre
propriété d'assistance appelée max frame. La feuille Sprite comporte
58 images par ligne. C'est une énorme image
de feuille de calcul. Nous allons le parcourir découpant différentes
images pour créer une illusion de mouvement
et d'animation. Laisse-moi te montrer. C'est facile Si l'image x
est inférieure à l'image maximale, je souhaite que l'image x augmente d'
une unité au fur et à mesure que la méthode de mise à jour
s'exécute encore et encore. Cela se déplacera sur la ligne d'animation
de gauche à droite. Lorsqu'il atteint la fin de l'image, x n'est plus
inférieur à l'image maximale. Sinon, l'instruction s'exécutera. Il remettra l'image x à zéro afin qu'elle
puisse recommencer. C'est ça Nous sommes en
train d'animer le joueur. J'essaie de me balader, tourner le joueur dans toutes les directions
possibles pour voir si tout va bien. Maintenant, notre joueur est bel et
bien vivant. Lorsque vous préparez
votre feuille de calcul vous pouvez créer correctement des illustrations de jeu, comme je l'ai préparé pour vous. L'animer avec
du code est très simple. Tout ce dont vous avez besoin est ce
simple bloc de code.
35. animation complète de la feuille sprite: Je copie ce bloc de code. Je vais le réutiliser en classe de larves. Je passe à la classe des larves. Ici. Nous aurons également besoin de la propriété
maximale d'assistance au cadre. Dans ce cas, le nombre maximum d'images est de 38. feuille de calcul Larva comporte
38 images par ligne. Comme d'habitude, vous pouvez télécharger toutes les feuilles de calcul dans
la section des ressources. Je le place dans mon dossier Projet et je l'intègre
au projet ici. L'identifiant sera une larve,
soulignera le sprite et source sera le même point de
larve (sprite point PNG). Dans script.js, je pointe cette propriété d'image à points
vers ce nouvel identifiant. Il compte 38 images par rangée. Et encore une fois, je veux alterner entre l'image zéro
et l'image maximale. J'ai copié cette
animation de sprite appelée blog à partir de la méthode de mise à jour de
la classe du joueur, et je l'ai collée ici. C'est très simple, il
n'est donc pas nécessaire d'apporter des modifications. Si l'image x est
inférieure à l'image maximale, continuez à augmenter l'image x d'une unité. Sinon, remettez à
zéro l'image x pour qu'elle puisse recommencer. Toutes les feuilles de calcul sont
configurées de telle sorte que la dernière image et la première image se connectent dans une boucle d'animation continue. Ainsi, en les repassant
encore et encore, vous créerez une séquence
d'animation fluide. Vous pouvez maintenant voir nos nouveau-nés ramper avec leur Antonio,
vaciller de haut en bas.
Ce
sont des corps spongieux qui se déplacent alors qu'ils rampent vers la sécurité
d'une forêt de champignons. Parfait.
36. animation complète de la feuille sprite: J'ai également préparé
des feuilles de calcul d'animation pour les ennemis. Je lui donne un identifiant de skin d'écorce et identifiant sera bark skin point PNG. Le slime vert.
L'un sera l'identifiant de la peau
adulte et la source
de la peau PNG. Dans un skin Hyde Park avec CSS. Aussi dit à la peau. Et le sprite larvaire. Nous allons à nouveau copier
ce bloc de code. Il est important de remarquer comment sont organisées les
feuilles de calcul de
ces ennemis. Nous devons tenir compte du fait que
lorsque nous écrivons notre code, je peux voir que nous avons quatre types de crapauds et quatre types
pour les peaux foncées, chaque type étant sur une ligne distincte. Dans ce cas, nous savons
que l'image y
contrôlera le
type d'ennemi affiché. image X
parcourra à nouveau cette ligne d'animation
, donnant vie à cette créature. Il est également important
de noter que j'ai la même structure pour
les sprites fourre-tout et pour les sprites
à la peau foncée. Les deux ont quatre rangées, 38 images par rangée. Je peux donc gérer l'animation sur la classe ennemie parent,
car la logique
sera partagée pour les deux sous-classes d'
animus. J'ai dit image x à zéro ici. Expliquez pourquoi nous allons choisir
au hasard
l'un des quatre
ennemis disponibles à animer. Le cadre maximum sera de 38. Dans la méthode de mise à jour, j'ai géré l'animation des
sprites ici, je colle le bloc de code que j'ai copié. Tout d'abord, je voulais
utiliser une feuille de calcul sur la peau de crapaud ici et de la peau d'écorce
ici comme celle-ci. Lorsque vous voyez un problème d'
animation comme celui-ci,
cela signifie généralement que la
taille d'image que nous avons définie est incorrecte. Les cadres se glissent donc
un peu. Les skins foncés
s'animent correctement. Je vérifie la taille d'un nombre incalculable d'habillages, et je constate que l'
image unique de la feuille de calcul 154 pixels de large et
238 pixels de haut. Vous obtenez la largeur d'un seul
cadre en divisant la largeur de la feuille de calcul entière
par le nombre de colonnes, par le nombre de cadres par ligne. Et vous obtiendrez la hauteur d'
un seul cadre en divisant la hauteur de l'
ensemble de la feuille de calcul par le nombre de lignes. Parfait, nous animons les nouveau-nés du joueur et
huit types d'ennemis différents. Nous voyons des
cercles de collagène, mais le jeu est
censé être joué avec le mode de débogage désactivé. Nous devons nous assurer
que les zones de collision correspondent aux petites ombres qui se trouvent
sous notre char et à celles de nos ennemis, car je veux qu'elles
soient parfaites au pixel près. Et les peaux de crapauds, de cannes et de chevreuils ont
des tailles de sprites différentes. Je ne peux pas
décaler Sprite X et Sprite. Pourquoi ici dans la méthode de
mise à jour partagée selon une certaine valeur et alignez les
deux à partir
du même endroit. Dans une situation comme celle-ci, je souhaite commenter cette ligne
et étendre cette méthode de mise à jour à chaque sous-classe afin de lui donner valeurs
légèrement différentes
pour chaque type d'élément. Pour le faire aussi simplement. On torts can, une sous-classe
qui étend classe parent
de la superclasse
NME, que nous appelons update. Si je définissais simplement la
mise à jour comme
ceci, cette méthode serait prioritaire
et
remplacerait complètement la méthode du même nom
dans la classe parent. n'est pas vraiment ce que je veux. Je veux que le code contenu dans méthode de
mise à jour de la classe
ennemie soit exécuté. Et je voulais
ajouter du code personnalisé spécifique uniquement à la classe de skin de
crapaud ici
dans cette
méthode de mise à jour sur une classe enfant. Je le fais en utilisant le super mot clé
représentant le parent. Et puis mon cours. Ici, je
dis d'exécuter tout le code dans la méthode de mise à jour sur le parent, puis la
classe sur la superclasse. Ensuite, je veux prendre
cette ligne de code, et cette ligne n'
exécutera que quatre scans toed. J'essaie plus 50. Mon objectif est d'aligner cercle de
collision sur
la petite ombre au sol sous
les ennemis
flottants
le plus possible Nous avons cassé des skins
parce que la valeur Y de leur sprite
n'est pas mise à jour pour le moment, nous allons corriger ce problème dans une minute. Tout d'abord, je veux
m'aligner vers la hauteur -100. OK, que diriez-vous de la hauteur de
l'ennemi divisée par deux -100 ? Cela se rapproche de plus en plus de
ce que je veux. Peut-être -90. Oui. Lorsque j'appuie sur le d pour activer
et désactiver le mode de débogage, je peux constater que les skins de Little Ground
Shadow Undertone s'alignent très étroitement sur la zone du cercle de
collision. Parfait. Je copie ce bloc de code et je le place ici sur nos skins Bark. Ici, je vais faire -100. C'est ainsi que vous étendez
une méthode qui existe sur une classe parent comme cette méthode de
mise à jour que nous avons ici. Et pour chaque sous-classe, nous appelons d'abord le code dans la méthode de
mise à jour de la
classe parent à partir de la ligne 302. Ensuite, nous pouvons y ajouter du code
supplémentaire qui ne sera unique qu'à
cette sous-classe particulière. L'utilisation de cette technique peut donner chaque type d'ennemi un schéma de mouvement
différent, un comportement
différent, des attaques
différentes, des animations différentes, etc. Vous pouvez télécharger le dossier de code source
final que j'ai appelé
code source version 6 dans la section des ressources
ci-dessous et le comparer à votre propre code si vous
rencontrez des problèmes. Il est maintenant temps pour vous d'ajouter
des fonctionnalités supplémentaires. Essayez peut-être de consulter mes autres classes de développement de
jeux où nous
appliquons la gestion des sons ou des états et les utilisons pour ce jeu. Découvrez la collection
d'actifs artistiques bonus disponible dans la section
des ressources ci-dessous Je vais laisser de nombreuses œuvres d'art
dans plusieurs formats avec pièces
séparées afin
que vous puissiez les mélanger et vous amuser
si vous le souhaitez. Merci d'avoir passé
du temps avec moi. J'espère que tu as
beaucoup de valeur aujourd'hui. Bravo pour avoir terminé le
projet. Je te verrai plus tard.
37. Projet bonus (optionnel): Créez des environnements de
jeu animés
pour des personnages
contrôlés par clavier directionnel, obstacles positionnés
au hasard et des ressources artistiques environnementales. Créons des jeux
en utilisant du HTML, du
CSS et du Javascript sans framework ni bibliothèque. Comme d'habitude, si je dessine tous mes éléments interactifs
sur un seul élément du canevas superposition peut être un défi Nous pouvons utiliser la méthode de
tri par tableau intégrée pour réorganiser objets
du jeu en fonction leur coordonnée verticale y
et les dessiner dans cet ordre Avec cette astuce simple en place, nous pouvons avoir un
personnage de joueur qui contourne les obstacles d'une manière
visuellement logique. Créons un jeu à partir de
zéro et découvrons le développement Front and Y et la programmation
orientée objet.
38. Mise en place de projet bonus: Nous travaillerons avec trois
fichiers en index HTML. Je crée une page Web
simple et générique et je lui donne un titre. Je lie une feuille de style CSS, je crée un élément HTML à cinq
canevas avec un identifiant de canevas un, et je lie un fichier de script GS. Je crée un dip avec l'identifiant d' un emballage et j'
y mets de la toile. Je crée une balise d'image
avec une superposition Source, une superposition Alt et une superposition ID Vous pouvez télécharger
tous les actifs artistiques dans la description de la vidéo dans
la section des fichiers de projet. Je vous propose également
toutes les pièces séparées en haute résolution afin que
vous puissiez composer vos propres images
d'arrière-plan uniques. Si vous voulez obtenir le conseil d'optimisation
numéro un, utilisez du CSS brut. Pour les grandes images de fond, je peux
tout dessiner et animer sur du cannavas J'ai l'habitude de le faire aujourd'hui. Je veux vous montrer comment
combiner le CSS et méthode de dessin d'image
sur toile
pour maximiser les performances. Cela vous évitera d'avoir à
dessiner ces grandes images sur le canevas encore et encore pour
chaque animation Et cela améliorera les
performances de nos jeux. Les transformations CSS utilisent le GPU. Ils sont plus rapides et leur
balisage est plus simple car CSS contient de nombreux mots clés
intégrés ce qui facilite grandement
les transitions animées Peut-être que pour votre jeu, vous avez besoin que tout soit
dessiné sur toile. Mais aujourd'hui, je vais
le combiner avec du CSS pour tirer pleinement parti des
outils et techniques proposés l'environnement de développement Web
frontal.
39. Améliorer les mondes de jeu: Intalsias. Je donne à Canvas une image d'
arrière-plan, vous pouvez la télécharger dans
la description de la vidéo ou vous pouvez créer
votre propre arrière-plan à partir des éléments individuels
que
je fournis. Comme vous pouvez le voir, nous avons
créé deux couches. œuvres d'art de fond sur lesquelles notre personnage
sera dessiné, et quelques images superposées, des feuilles et de l'herbe,
figureront devant notre scène forestière Le personnage du joueur
pourra se cacher derrière eux. À moins que nous ne
définissions la largeur et la hauteur du canevas, valeur par défaut
sera toujours de 300 fois 150 pixels. Nous lui donnerons la bonne
taille avec le script Java dans une minute pour révéler l'illustration d'arrière-plan
complète. J'aurais également pu mettre cette image de fond
sur l'élément wrapper. Je donne une bordure à l'
élément principal de l'emballage. Mon navigateur est zoomé pour que je puisse tout afficher à l'écran Les images que je vous présente
aujourd'hui sont optimisées pour une résolution de
1 280 fois 720
pixels Le jeu que nous sommes en train de créer
est assez vaste. Vous pouvez ajuster les
tailles si vous le souhaitez. Si vous êtes
débutant, ce serait peut-être une bonne idée de suivre exactement
mon code, utiliser les mêmes tailles
et les mêmes images,
et de n'apporter des modifications qu'une fois que l'ensemble du
projet aura fonctionné Je veux centrer le récipient, donc je lui donne une position absolue. Vous pouvez voir que l'emballage ne part pas
du coin supérieur gauche Il existe des
marges et des garnitures par défaut pour garantir que notre page s'affiche de la même manière dans tous les
navigateurs Je vais effectuer une réinitialisation globale de
tous les éléments de la page
et je définis la marge à zéro, remplissage à zéro et la
taille de la boîte dans la zone de bordure Pour m'assurer que
les éléments de rembourrage et bordure sont inclus dans sa largeur et sa hauteur
totales, je souhaite centrer le
rapidive au milieu de
la page verticalement Je lui ai déjà donné
une position absolue. Maintenant, je peux lui donner 50 % du haut, 50 % à gauche et transformer, traduire -50 %, 50 %. Je dois également
aligner la superposition Je lui donne la position
absolue en haut à 50 % à gauche 50 % de transformation de
traduction -50 % à 50 % Cela l'alignera exactement
sur le dessus de l'emballage Il y a bien d'autres
choses que nous pouvons faire ici. Par exemple, ajoutons deux
autres images
au projet. Je crée une image appelée
leaves underscore left. Je lui donne le même
ancien attribut et identifiant. Vous pouvez télécharger
toutes ces images dans la description de la vidéo, je crée une autre image appelée leaves underscore,
non ? Comme ça. Elles auraient
pu n'être qu'une partie de l'image de superposition principale, mais je veux qu'elles soient
animées et interactives Comme nous l'avons dit,
les transformations CSS sont traitées par le GPU. Profitons-en pour rendre
notre univers
de jeu un peu
plus vivant et interactif. Les CSS font du travail pour nous. Il n'est pas
nécessaire de tout dessiner sur toile. Tout va très
bien se
mélanger et notre jeu
sera superbe. Je cible les feuilles de gauche en position supérieure
à 50 pixels, la position de gauche
à -100 feuilles droite sera positionnée à
-150 pixels derrière le bord droit, ici
sur l'emballage principal Réglez Overflow sur Masqué, pour découper et masquer
tout ce qui se trouve
en dehors du conteneur de jeu principal Nous pouvons faire tellement de
choses avec elle maintenant. Par exemple, nous pouvons faire bouger les
feuilles. Lorsque nous survolons la toile, nous ne sommes qu'un observateur silencieux qui
se cache dans les buissons Éloignons un peu
les feuilles pour que nous puissions voir. Lorsque je survole le canevas, je souhaite appliquer du
CSS aux feuilles de gauche Je vais changer leur position
gauche, et je vais les faire pivoter
de plus de 15 degrés. Cette déclaration CSS ne
fonctionnera pas. Cela fonctionnerait si leaves left était un enfant d'un
élément canvas, mais ce n'est pas le cas. Si nous regardons ici, nous pouvons voir
qu'ils sont frères et sœurs. Ils sont au même
niveau dans l'élément trois et ils partagent tous les deux le même
emballage en tant que parent Pour appliquer quelque chose
aux feuilles restantes,
lorsque vous passez le curseur sur le canevas,
nous devons utiliser ce que l'on appelle
le sélecteur nous devons utiliser ce que l'on appelle général des frères et sœurs sélecteur général de frères et sœurs
sélectionne tous les éléments qui sont les frères et sœurs suivants
d'un élément spécifié Si je regarde la structure de nos
éléments, nous avons une image de superposition
d'
éléments de toile directement au-dessus Cela empêche en fait le déclenchement
de l'événement hover sur le canevas Je veux que
l'image de superposition soit au-dessus, mais je veux qu'elle soit invisible
pour toutes les interactions avec la souris Pour que je puisse interagir avec le
canevas qui se trouve en dessous. Je peux le faire en définissant la propriété des événements du
pointeur la superposition sur une valeur différente heure actuelle, le canevas ne se trouve que
dans cette petite zone, mais nous le
redimensionnerons bientôt pour remplir tout
le conteneur afin de
tester le survol. Pour l'instant, je dois déplacer ma souris sur la
petite zone du canevas. Ici, cela fonctionne au survol, j'ai réglé la position gauche
à -150 pixels Je vais donner aux feuilles
un peu de temps de transition pour qu'elles s'animent réellement Essayons 0,3 seconde. Sympa. Je fais la même
chose pour les feuilles, non ? Je lui donne également une certaine transition, peut-être juste 0,2 seconde. Ils ne sont donc pas
complètement synchronisés. Nous pouvons faire tellement de choses. Par exemple, appliquez une animation d'
images clés pour donner l'impression que les feuilles
bougent sous l'effet du vent. Je l'appellerai wobble. À 0 %, il
commencera au sommet des 50 pixels. Nous aurons un
point d'arrêt de 50 % à 55 pixels. Et à 100 %, il
reviendra à 50. Nous pouvons l'appliquer en donnant à
leaves left la propriété d'animation. C'est ce que nous appelons vacillement. Le timing va s'assouplir. La durée de la boucle d'animation
sera de 1,5 seconde. Comme ça, comme ça, ça ne fonctionnera qu'une seule fois, mais je veux une boucle infinie,
je ne vois aucun mouvement. Réglons cela à
65 pixels, non ? Je dois m'assurer que j'ai la bonne syntaxe pour les images-clés. Ce point-virgule doit être là, nous avons des feuilles qui
bougent dans le vent Essayons 56 pixels. Je copie cette ligne et je
l'applique également aux feuilles, non ? Je veux les désynchroniser. boucle sur celui-ci
durera 1,6 seconde, comme nous l'avons fait avec la superposition Je dois définir les événements
du pointeur sur aucun sur les deux feuilles pour m'
assurer qu'ils ne
bloquent pas les événements de la souris sur le canevas qui se trouve en dessous. C'est ainsi que nous pouvons
dessiner et améliorer une partie de votre
scène de jeu avec du CSS. C'est une bonne pratique
en matière de performance. Si votre projet le permet, n'hésitez pas à l'utiliser plus souvent.
40. Installation de JavaScript: Nous allons également dessiner quelques
images avec Javascript, principalement notre personnage Alber animé
contrôlé par clavier Lorsque nous travaillons avec
des images en Javascript, nous devons toujours nous assurer que l'image est complètement chargée et disponible avant que le code qui dépend de cette
image ne soit exécuté. Dans le cas contraire, nous aurons un message d'erreur. Il existe de nombreuses façons de le faire. Nous pouvons utiliser des promesses ou
un moyen très simple consiste à
encapsuler tout le code Javascript
dans l'écouteur d'événements de chargement L'événement Load est déclenché lorsque
la page entière est chargée, y compris toutes les ressources
dépendantes telles que les feuilles de style et les images. De cette façon, je peux simplement
placer ma feuille de calcul en
tant qu' élément IMG normal
dans l'index HTML, et Javascript
attendra que cette image se charge dans la fonction de
rappel anonyme Ici, j'ai installé mon canevas. Nous avons besoin d'une référence à
l'élément canvas, une variable constante que j'appelle
canvas et je veux pointer
Javascript vers
cet élément canvas que nous avons
créé à Javascript vers
cet élément canvas que nous avons la ligne
12 dans l'index HGML, nous lui avons donné un identifiant de canvas one Nous n'avons pas vraiment besoin d'utiliser
get element by ID ici, car tous les navigateurs créent
automatiquement des variables
Javascript pour
tous les éléments dotés d'un identifiant. Le nom de cette variable automatique
est toujours le même que l'ID. C'est une bonne chose pour le bogue, mais comme les navigateurs placent toutes ces variables dans
l'espace de noms global, il est facile de les
remplacer accidentellement Il vaut mieux utiliser get
element by ID, comme ceci. Le contexte Ctx est canvas point get context two D pour générer
une instance de l'API Canvas Two D intégrée qui contient état du
canevas et les
deux méthodes de dessin L'
élément wrapper parent a été défini sur 1 280 fois 720 pixels Assurons-nous que l'
élément du canevas est de la même taille. Cela révélera l'illustration d'arrière-plan
complète. Qu'est-ce que tu en penses ? Comme je l'ai dit, je partagerai également des pièces individuelles avec
vous en haute résolution. Vous pouvez
les mélanger et créer vos propres
environnements de jeu uniques si vous le souhaitez. Toutes les ressources artistiques que je partage dans cette vidéo sont libres de droits. Ils ont été conçus et dessinés
par moi ou par des artistes que j'ai engagés. Vous pouvez les modifier et les
utiliser comme bon vous semble. Je vais commenter les
animations CSS sur les lignes 39.31. Je pense que ce
sera moins distrayant Nous avons
maintenant du
code Java à faire pour donner vie à notre
personnage animé. Suivons les principes de programmation orientée
objet aujourd'hui et divisons notre code en classes
individuelles. Chaque classe aura des
responsabilités différentes et nous
les ferons communiquer et travailler ensemble pour créer
le produit final. Classe personnalisée que j'appelle par exemple, le gestionnaire de
saisie
gérera les entrées au clavier Lorsqu'une touche est pressée
sur un clavier, cette classe la
traite, transforme et stocke cette valeur afin qu' elle puisse être utilisée par d'autres classes. Class Owl Bear sera notre personnage d'animation
principal. Le joueur pourra le
contrôler à l'aide du clavier. L'objet de classe sera utilisé
comme plan pour créer des
arbres, des buissons et de l'herbe générés de
manière aléatoire Une fois que nous les aurons placés
dans le monde du jeu, nous apprendrons à les
organiser de manière à ce qu' ils soient dessinés devant
et derrière le joueur, en fonction de la position actuelle du joueur
. C'est très important car
sans cela, dans un jeu comme
celui-ci , dessiner un joueur au-dessus de tout n'aurait aucun
sens visuel. Nous avons besoin d'une certaine logique pour que
le joueur puisse contourner ces deux obstacles en D et je vais vous montrer un moyen
simple de le faire. Enfin, nous aurons besoin d'
un jeu de classe que j'appelle jeu. C'est là que toute la logique de toutes les classes
est réunie. Ce sera le
cerveau principal de notre base de code. Le constructeur de classe
créera une instance d'
une classe pour nous sur la base d'un
plan que nous définirons Définissons un plan
pour notre classe de jeu principale. Je veux que ces cours soient
autonomes et modulaires. Nous allons le transmettre
avec la hauteur de la zone de jeu comme
arguments comme celui-ci. Nous les convertissons en propriétés
de classe. Nous prenons la largeur et la hauteur comme arguments du
constructeur de classe et nous les convertissons propriétés de
largeur et de hauteur sur cette instance de classe de jeu Pour créer une instance
de classe de jeu, je crée une variable constante. J'appelle par exemple game, et j'utilise le nouveau mot-clé. Le nouveau mot clé dans
le script Java est utilisé pour créer une instance d'un objet
doté d'une fonction constructeur nouveau mot-clé
recherchera une classe portant ce nom et
déclenchera son constructeur Le constructeur créera un
nouvel objet de script Java vide et définira automatiquement son prototype dans les coulisses Il liera ce mot-clé pour pointe vers cet objet nouvellement
créé et il attribuera à l'objet
toutes les propriétés et valeurs telles que nous les définissons
dans le plan ici Jusqu'à présent, notre objet de jeu n'
aura que des propriétés de largeur
et de hauteur. Dans ce cas, je peux voir
que ces propriétés sont attendues sous forme de valeurs transmises
de l'extérieur. Nous faisons cela pour que nos cours restent autonomes et modulaires. Je lui transmets la
largeur du canevas à partir de la quatrième ligne. Comme pour la hauteur
de la toile à partir de la ligne cinq comme hauteur. Comme je veux que le jeu
soit de la même taille que le canevas, je veux que la zone de jeu utilise
tout l'élément du canevas. C'est ainsi que vous
créez une classe dans script
Java et
une instance de cette classe. Comment utiliser cette classe pour créer un objet basé sur
le plan de classe Consolidons la
variable de jeu de la ligne 26 pour vérifier si tout s'
est bien passé Je peux voir que la
variable de jeu stocke une référence pointant vers un objet de jeu avec des
propriétés de
hauteur et de largeur parfaitement définies sur les
bonnes valeurs. Si vous rencontrez des erreurs lors écriture de votre base de code
orientée objet, vous pouvez toujours configurer
vos objets de
cette manière et vérifier si toutes ces
propriétés ont des valeurs Si vous voyez « non défini » ici, vous savez qu'il y a un problème dans votre code et vous pouvez suivre cette valeur dans votre base de
code pour trouver le problème
41. Commandes de clavier: La classe de gestionnaire d'entrée est là
pour suivre
les touches du clavier lorsqu'elles sont pressées
et relâchées par l'utilisateur Et il les convertira en
valeurs utilisables par d'autres objets de notre
base de code et les stockera. Je lui donne également un constructeur. C'est ainsi que nous allons faire communiquer
nos objets entre eux. gestionnaire de saisie attendra une référence pointant vers l'objet principal du jeu
comme argument L'objet entier qu'il
contient convertit cette référence
en une propriété de classe, comme ce jeu passé argument, est converti en propriété
de jeu. Sur cette instance
de gestionnaire d'entrée, objets de
classe du script Java
sont des types de données de référence Je ne crée pas une copie
de l'objet du jeu ici, je crée simplement une
variable qui pointe vers un espace de mémoire où l'objet de jeu
principal est stocké. C'est génial car lorsque
les valeurs des objets de jeu sont mises à jour, ces modifications sont immédiatement visibles à partir de cette référence au jeu de
points. Ici, dans la classe de jeu principale, je crée une propriété
appelée « point last key input handle class » qui mettra
à jour cette valeur sur la classe à jour cette valeur sur la jeu au fur et à mesure que les touches sont
enfoncées et relâchées. Au départ, je l'
ai dit à Undefined. Aujourd'hui, nous allons en apprendre davantage sur les commandes
du clavier
et nous ne conserverons que la dernière touche
enfoncée ou relâchée en mémoire. C'est tout ce dont nous avons besoin pour contrôler, quatre directions sur
le personnage. Si je voulais suivre
les pressions sur plusieurs touches, je créerais plutôt un
tableau ici. Et j'ajouterais et
supprimerais des clés à partir de là. Je l'ai déjà fait et je le
ferai peut-être plus tard
dans cette série. En fonction de la complexité et de la
précision
des commandes du clavier dont nous aurons besoin. Je souhaite également
créer automatiquement une instance de gestionnaire de saisie lorsque je
crée l'objet du jeu Mettons ici une console
qui indique que le gestionnaire d'entrées a été créé dans le constructeur de
classe de jeu Je crée une propriété
appelée cette entrée. Je l'ai défini comme un nouveau gestionnaire de
saisie comme celui-ci. À la huitième ligne, je peux voir que constructeur de la classe du gestionnaire
d'entrées attend une référence à
l'objet principal du jeu Ici, je crée une instance de gestionnaire
d'entrée dans cette classe de jeu Je lui passe ce mot clé. Ce mot clé utilisé
dans une classe de jeu pointe vers l'ensemble de la classe de
jeu elle-même. Il représente l'objet
dans lequel il a été défini. Bien parce que je mets ce code dans le
constructeur de classe de jeu lorsque je crée une instance de classe de
jeu sur la ligne 31, il crée également
automatiquement une instance de classe de
gestionnaire d'entrée pour Cela l'enregistrera sous forme de propriété de saisie de
points dans
la classe de jeu principale elle-même. Je peux confirmer que le
gestionnaire de saisie a été créé car je vois cette
console ici. Il s'agit d'un
moyen simple de connecter
vos classes et de les faire fonctionner ensemble pour
créer un jeu complet. Il est également très modulaire, ce qui vous permet d'
ajouter ultérieurement plus de fonctionnalités et de classes à
votre jeu si vous le souhaitez. Comme nous le voyons avec cette console, tout le code contenu dans le constructeur de
classe est automatiquement exécuté
lorsqu'une instance de cette classe est créée Ce code ne doit pas toujours
être simplement défini dans les propriétés
de classe. Nous pouvons mettre n'importe quel code ici. Dans ce cas, je souhaite
appliquer automatiquement les écouteurs d'événements Lorsqu'une instance de classe de
descripteur d'entrée est créée, je les mettrai simplement ici. Nous écouterons
l'événement key down dans la fonction de rappel Je vais exécuter une
fonction de
rappel consolo si l'écouteur d'événements en
Javascript a accès à objet d'événement
généré automatiquement qui
contient tous les détails sur
l'événement qui contient tous les détails sur
l'événement Je peux lui attribuer un nom de
variable ici, la convention est généralement
une lettre comme celle-ci. Je l'ai déjà fait, donc je sais que cet objet d'
événement généré automatiquement possède une propriété appelée clé qui nous
donne le nom de la
touche qui a été pressée touche console, je dois cliquer sur Canvas
pour m'assurer qu'il est sélectionné Et lorsque j'appuie sur
quelque chose sur
le clavier, les noms des touches
sont imprimés dans la console. Aujourd'hui, nous allons nous concentrer sur les flèches
directionnelles. Donc flèche gauche, flèche droite, flèche bas et flèche haut. Je souhaite enregistrer ces valeurs
clés dans dernière propriété clé de la ligne
28 de l'objet principal du jeu. Nous avons une référence à
l'objet principal du jeu ici à la neuvième ligne. Mais lorsque je consulte
ce jeu depuis l'écouteur d'événements,
nous remarquons que
la référence
renvoie une valeur indéfinie C'est parce que cette fonction de
rappel oublie qu'elle a été initialement définie ici dans la méthode du
constructeur sur la classe du gestionnaire d'entrée Je veux que la fonction se souvienne, je veux limiter sa portée de manière à ce qu' une référence à ce mot-clé représentant
dans ce cas cet objet de gestionnaire d'entrée ainsi qu' accès à cette
propriété de jeu soient disponibles
depuis cette fonction de
rappel sur
l'écouteur d'événements enfoncé
chaque fois que cet écouteur d'événements s' écouteur d'événements s'exécute
Later Je veux m'assurer que cette
fonction n'oublie jamais qu'elle a été initialement définie à l'
intérieur d'un objet Je peux utiliser la méthode de
liaison Javascript pour le faire, ou je peux simplement utiliser la fonction ES à
six flèches. Oui, les fonctions à six flèches
ne lient pas leur propre fonction, mais elles héritent
de celle de la portée parent C'est ce que nous appelons le cadrage lexical. La portée de la fonction de flèche dépendra toujours de l'endroit dans
notre base de code où elle a été initialement définie par rapport à sa portée
lexicale d'origine Dans notre cas, il a été défini ici dans cette méthode de
constructeur Il aura donc toujours accès
à cette propriété du jeu de points et à toutes les autres propriétés que nous pourrions définir dans
ce constructeur Plus tard, lorsque je
refactoriserai cette fonction
de rappel en une fonction étroite, nous pourrons consolo did Et on voit qu'il pointe
vers l'objet principal du jeu. Et toutes ses propriétés y sont visibles, y
compris la dernière clé, si je consolo la dernière
valeur clé de la ligne 28, elle est
initialement
définie sur undefined Nous prenons la propriété clé de objet de l'
événement et je la
lui assigne comme ceci. Désormais, la propriété de
la dernière touche de la classe de jeu principale garde
toujours une trace de la
dernière touche pressée. J'ai également besoin de savoir quand
la dernière clé a été publiée. Je crée un autre écouteur d'événements, cette fois pour l'événement key up Nous stockons maintenant le nom de la dernière touche qui a été
enfoncée ou relâchée. Le problème est qu'il
enregistre simplement le nom de la clé. J'ai besoin de savoir si cette touche
a été enfoncée ou relâchée. Je vais concaténer la lettre
majuscule P à l'intérieur événement
key down pour indiquer que la touche correspondant à ce
nom a été pressée J'ajouterai ensuite un R majuscule
devant le nom de clé dans l'événement keyup afin que nous sachions que cette
clé a été publiée Maintenant que nous obtenons ces
valeurs dans la console, vous pouvez voir la valeur
de ce gamet à points La dernière propriété clé est en train de changer. Nous appuyons sur la flèche
ici et nous relâchons
la flèche juste ici. Je peux retirer la console. D'accord. Maintenant que nous savons que cela fonctionne sur l'objet principal du jeu, nous avons défini la dernière
propriété clé et nous avons créé une instance de la classe de gestionnaire
d'entrée Au fur et à mesure que la classe de gestionnaire d'entrée
est initialisée, nous appliquons une touche vers le bas et activons les
écouteurs d'événements Cela mettra à jour
dynamiquement dernière propriété clé afin
que notre objet de jeu et tous les objets qui y sont connectés
sachent toujours quelle touche a été
enfoncée ou relâchée. Nous utiliserons ces valeurs pour
contrôler le personnage du joueur, l'ourson hibou.
Définissons-le ici.
42. Personnage de joueur: Tout d'abord, nous devons
le connecter à l'objet principal du jeu. Nous nous assurons qu'il
attend une référence à l'objet du jeu en
tant qu'argument, nous le convertissons en propriété de
classe comme d'habitude. Commençons par lui donner une largeur
et une hauteur de 100 pixels. Sa position initiale
sera de 200 pixels à partir du bord gauche et à
200 pixels du haut. Je lui donne une méthode de dessin
pour le dessiner sur toile. Il attendra le contexte
comme argument pour
spécifier l' élément du canevas sur lequel nous voulons dessiner. Prenez cette variable de contexte et j' appelle la méthode du
rectangle Phil intégrée. Le rectangle Phil attend une largeur et une hauteur x, y. Je lui transmets donc les propriétés
du constructeur Owl Bear. Nous voulons d'abord dessiner un rectangle
noir représentant le
hibou,
comme nous l' avons fait avec la classe
Input Handler Je souhaite créer automatiquement une instance de l' objet
Owl Bear Lorsque je crée une instance
de la classe de jeu principale, je l'instancie ici dans constructeur de
classe et je l'assigne à une
propriété J'appelle ce hibou un
ours sur la ligne 20, je vois qu'il s'attend à
du gibier comme argument Je lui passe ce mot clé parce que nous sommes dans cette classe de jeu. classe de jeu aura une
méthode spéciale que j'appelle render pour
mettre à jour et dessiner tous les objets
du jeu sur le canevas. Je prends Oil Bear de la ligne 42 et j'appelle sa méthode de
dessin associée de la ligne 27. Cette méthode attend
le contexte comme argument, qui est ce CTX
de la troisième ligne Je dois le transmettre. J'appellerai toujours cela le contexte. Il sera attendu comme argument par la méthode de rendu
principale, nous le transmettons à la
méthode draw sur Owl Bear. Je prends un jeu, j'appelle sa méthode de
rendu à partir de la ligne 44, et je lui passe CTX à partir de la ligne
trois comme argument auquel un contexte de nom de
variable
sera attribué et transmis si nécessaire Parfait. Nous
dessinons notre ourson hibou. Cela ressemble à un
simple carré noir car c'est ce que
nous avons défini ici dans la méthode draw on owl bear
class. Faisons en sorte que ça bouge. Je lui donne une méthode de mise à jour personnalisée pour chaque image d'animation. Je veux que X augmente d'un, en le faisant marcher vers la droite. Nous devons réellement
appeler cette méthode depuis le rendu interne de
la classe de jeu. Ici, je supprime cette console
pour voir réellement le mouvement Nous devons appeler cette méthode de
mise à jour encore et encore. appeler depuis le
rendu une seule fois lors du chargement de la première page, comme nous le
faisons ici, n'
animera rien. Nous aurons besoin d'une boucle d'animation. Je crée une fonction personnalisée. J'appelle par exemple
animate inside. J'ai lancé cet appel de rendu. Pour le faire en boucle, j'appelle la méthode du cadre d'animation de
demande intégrée . Cette méthode mettra à jour
notre page Web avant la prochaine peinture en exécutant
un code dans une fonction, nous le passons en argument Si je lui passe animate le
nom de sa fonction parent, cela créera une boucle d'animation
sans fin Animate est appelé. Il appelle Render pour dessiner et
mettre à jour notre demande d'ourson hibou. Le cadre d'animation
déclenchera à nouveau l'animation, sorte que le cycle se répétera cadre d'animation de la demande se trouve sur l'objet de fenêtre représentant
la fenêtre du navigateur. Mais on peut aussi l'appeler
directement comme ça. Sans mettre
window.devant. Il est préférable d'utiliser un cadre
d'animation de demande pour l'animation plutôt que d'utiliser une demande d'intervalle
défini. L'image d'animation ajuste les
images par seconde au taux de rafraîchissement de
votre écran et génère
également automatiquement
un horodatage Nous en aurons peut-être besoin plus tard pour
déclencher l'animation. J'appelle simplement animate. Comme si ce gentil joueur se déplaçait vers la droite,
il laissait des traces Nous devons nous assurer de supprimer tous les dessins du canevas entre
chaque boucle d'animation. Je le fais en appelant la méthode intégrée du
rectangle clair. Je souhaite effacer l'ensemble du
canevas à partir de la coordonnée 002, largeur du
canevas et de la hauteur du canevas. Nous avons maintenant un carré noir
en mouvement représentant le personnage
du joueur. Parfait. Il se déplace
vers la droite car ici, dans la
méthode de mise à jour de la classe Alber, qui est notre joueur,
nous augmentons position
horizontale x d'une
pour chaque image d'animation Je lui donne une propriété
que j'appelle vitesse X. Au départ, je l'ai mise à zéro. Nous aurons également besoin de la vitesse Y, la vitesse
verticale pour les mouvements
de haut en bas. N'oubliez pas que nous sommes en train de créer un personnage contrôlé par clavier capable de marcher dans
quatre directions. Je vais augmenter ce point x la valeur actuelle de la vitesse x.
Par exemple, cette coordonnée verticale
y
du hibou augmentera de la valeur de la vitesse Y. C'est génial car
je peux lui donner valeur positive pour
un
déplacement vers la droite, une valeur négative pour un
déplacement vers la gauche Je peux le faire bouger
plus rapidement en
lui donnant une valeur plus élevée
par image d'animation. Ici, ce nombre correspond aux
pixels par image d'animation. Une valeur positive de la vitesse Y
fera descendre le joueur. Une valeur négative le
fera monter. Une valeur positive en X et en Y le fera descendre, n'est-ce pas ? Nous pourrions facilement l'utiliser pour des mouvements dans
huit directions. Comme vous pouvez le voir
ici à la ligne sept, nous avons la classe Input handle
qui capture les saisies au clavier. Il transforme les noms des touches
par défaut pour indiquer si la touche
a été enfoncée ou relâchée. En pré-attente ou en
R devant le nom
réel de la clé. Il enregistre la valeur
de la dernière touche qui a été pressée ou relâchée
ici à la ligne 46. À l'intérieur de ce point, dernière
propriété clé de la classe de jeu principale. Parce que je fais référence
à l'ensemble de cette classe de jeu lorsque
je crée Alber on line 48 L'objet Alber a accès à la dernière valeur clé grâce à cette référence au jeu de points
ici sur la ligne 21 Je peux dire que si ce jeu fonctionne, dernière touche est la flèche gauche. Si vous appuyez sur la flèche gauche, réglez la vitesse x sur moins un pour
que le personnage se déplace vers la gauche dans le
sens négatif sur l'axe horizontal x. Si je clique sur le canevas et que j'
appuie sur la flèche gauche, nous nous déplaçons parfaitement. Lorsque je relâche la touche, le
joueur ne s'arrête pas là. Je peux constater que nous saisissons la valeur pour la presse et les communiqués. Je peux dire L, régler la
vitesse x à zéro.
Maintenant, nous pouvons nous déplacer vers la gauche
et nous pouvons nous arrêter. Je pourrais également créer
une méthode de réglage de vitesse qui, chaque fois qu'
elle est appelée, définira la vitesse x et la vitesse Y. Celles-ci lui seront transmises
en tant qu'arguments Nous prenons ces arguments et nous mettons à jour les
propriétés de classe à partir de la ligne 26.27. Maintenant, je peux remplacer cette
ligne par cette vitesse définie Et je lui donne moins un pour
la vitesse x et zéro pour la vitesse y. Dans l'instruction L, j'ai réglé les vitesses horizontale et
verticale à zéro. Il est préférable d'avoir une variable de vitesse maximale
globale plutôt que de coder en dur
un et moins un ici. Si cette vitesse
doit être dynamique, joueur peut bénéficier d'une augmentation de vitesse
temporaire. Ou peut-être que le joueur se déplace plus lentement en rampant
et en rôdant Pour ce faire, nous définissons la propriété de vitesse
maximale. Nous le fixons à trois pixels
par image d'animation, et nous le remplaçons ici. Développons cette déclaration. Je vais également vérifier
L si la
dernière touche de ce point est enfoncée avec la droite
R, comme ceci. Dans ce cas, nous réglons la vitesse x sur plus la vitesse maximale y sur zéro. Nous pouvons maintenant nous déplacer
à gauche et à droite et nous arrêtons de bouger lorsque la touche
RO est relâchée. Perfectionnez un autre bloc L if. Faites attention à la
syntaxe et aux crochets. Il est très facile de
rater un crochet et casser toute la
base de code en procédant ainsi. Lorsque nous appuyons sur la touche R, nous appelons « set speed ». Nous réglons la vitesse x à zéro
et la vitesse Y à moins vitesse
maximale parce que nous
voulons nous déplacer vers le haut dans le sens négatif
sur l'axe vertical Y. Nous faisons un autre L si nous bloquons si dernière touche est d'appuyer sur
la flèche vers le bas comme ceci. Nous réglons la vitesse x à zéro et
la vitesse y à la vitesse maximale. Nous pouvons également nous déplacer vers la gauche, droite, le haut et le bas. Je veux m'assurer que le
joueur ne peut pas quitter le canevas. Je dois définir des limites
horizontales. Si la
position horizontale x du joueur est inférieure à zéro
, remettez-la à zéro, c'est la limite gauche. Sinon, si la
position horizontale des joueurs est
supérieure à celle de ce jeu avec la
largeur de la zone de jeu, ce jeu vient d'ici. De là, nous naviguons
vers cette propriété. À la ligne 64, la position
actuelle du joueur est supérieure à la largeur
de
la partie moins la largeur du joueur
définie à la ligne 22. Cela signifie que le bord droit du rectangle du joueur touche
le bord droit du canevas. Assurez-vous que le joueur ne peut plus
se déplacer vers
la droite. Ainsi, je vais augmenter la vitesse du joueur à dix
pixels par image d'animation. Vous pouvez désormais vous déplacer vers la gauche et
vers la droite pour tester les
limites horizontales. Les limites verticales
seront légèrement différentes car
dans notre monde de jeu, le terrain s'arrête là. Je ne veux pas que le joueur traverse
cette zone à moins qu'il ne s'agisse
d'une créature volante. Je suppose que ce hibou est
définitivement trop lourd pour voler. Je me demande s'il existe des espèces
rares de chouettes volantes Nous les rechercherons peut-être
plus tard dans la série Nous avons cette zone en haut où je ne veux pas que le joueur
puisse marcher. Je crée une propriété de classe
appelée top margin. Au départ, je l'
ai réglé sur 200 pixels. Mettons-le ici. Ici, nous allons définir des limites
verticales. Supposons que si ce point y
est inférieur à zéro, y est égal à zéro. Cela créera
une limite ici. Le joueur ne peut pas dépasser
le bord supérieur du canevas. En fait, je veux que
la limite soit plus basse parce que toutes
ces œuvres d'art environnementales, je dis zéro, plus cette marge de
doop dans le jeu comme celle-ci Je peux supprimer zéro plus ici. Bien sûr, la
limite supérieure est maintenant là, 200 pixels du bord supérieur. Nous pouvons nous promener, mais nous ne
pouvons plus monter ici. Parfait, cela aura
plus de sens visuel lorsque le joueur est un
véritable personnage animé, pas simplement un carré noir, nous y arriverons rapidement. La limite inférieure est simple
si la position verticale
Y du joueur est supérieure à la hauteur du jeu moins la
hauteur du joueur. Cela signifie que le bas du rectangle du joueur touche
le bord inférieur des canavas Ne le laissez pas descendre
plus bas comme ça. Nous allons le tester. Oui, nous
avons les quatre limites. Parfait. Transformons ce
simple rectangle noir en feuille de calcul animée à quatre
caractères
43. 4 feuilles de sprite directionnelles: Je commence par ajouter image
de feuille de calcul dans l'
index HTML comme ceci Nous procédons de cette façon parce que tout notre Javascript se trouve
dans l'écouteur d'événements de chargement Si je place ma feuille de calcul ici, Javascript attendra que
ces images soient complètement chargées et disponibles avant
de commencer à les animer Vous pouvez télécharger toutes les ressources artistiques
du projet dans la
section des ressources du projet ci-dessous. Je lui ai donné une idée, sortons-le de son emballage comme ça Vous pouvez voir que nous avons huit lignes
d'animation dans
la feuille de calcul, quatre directions,
et chaque direction comporte un ralenti et une boucle de marche Nous examinerons cela
plus en détail dans une minute, masquerons l'image
elle-même avec du CSS. Nous voulons le dessiner avec
le script Java sur canevas. Vous pouvez voir que tout le code se trouve dans l'écouteur d'événements de chargement Tout ce code contenu ne
sera exécuté que
lorsque Owl Bear et toutes les
autres images auront été
complètement chargées ici
, dans lorsque Owl Bear et toutes les
autres images auront été le constructeur classe Alber, qui est notre personnage de contrôle
du joueur Nous ajouterons une
référence pointant vers cette image de feuille de calcul
en tant que propriété de classe Je l'appelle cette image, et je l'ai définie comme égale à une
variable appelée al bear. Cette variable
n'a pas été déclarée par nous, mais tous les navigateurs
créent automatiquement des références, variables
globales
générées automatiquement pour tous les éléments dotés d'un identifiant Cet élément possède un identifiant. Nous savons donc que notre navigateur automatiquement généré une variable
globale pour celui-ci. Normalement, nous
utiliserions get element by ID ici à la ligne 29,
mais ce n'est pas obligatoire. Le seul problème est qu'il
s'agit d'une variable globale. Alors que nous intégrons des variables
globales dans nos classes en
ce moment, ces variables risquent
constamment d'être écrasées
accidentellement Nous allons juste tester si cela fonctionne. Quoi qu'il en soit, je prends le contexte faisant référence à la variable CTX
de la troisième ligne J'appelle la méthode d'image de
dessin intégrée à Canvas. Draw image attend au
moins trois arguments. Je lui passe cette variable
globale générée automatiquement qui a été créée à partir de
l'identifiant des éléments comme image que nous voulons dessiner. Et je passe ce point x à partir de la
ligne 24 et ce point y à partir de la ligne 25 pour indiquer au script
Java où
nous voulons dessiner l'image sur le canevas. Nous dessinons maintenant la feuille de calcul
complète à ces coordonnées x et y. Nous pouvons nous déplacer à
l'aide des touches fléchées. En raison de la logique que
nous avons écrite plus tôt, il est plus sûr d'utiliser get
element by ID ici. Alors allons-y. J'utilise
cette image à points ici. OK, ça marche toujours. Bien pratique pour animer
n'importe quelle feuille de calcul, nous devons connaître les dimensions d' une seule image d'animation
dans cette feuille Je vais les mettre dans
des variables distinctes. J'appelle le
premier sprite width, et je l'ai réglé sur 200 pixels. La hauteur du sprite sera
également de 200 pixels. Si vous utilisez une
autre feuille de sprites, vous pouvez calculer la
largeur du sprite en divisant la largeur de l'ensemble de la feuille
de sprites par le
nombre hauteur du sprite est la hauteur de l'image complète de la feuille de sprites divisée par le nombre de lignes Dans ce cas, les propriétés de largeur et de
hauteur
seront les mêmes que celles de
largeur et de hauteur du sprite Mais les
séparer peut être une bonne pratique, car
nous pouvons ensuite utiliser mise à l'échelle ou
la randomisation des tailles ici sans affecter ces valeurs qui doivent
toujours rester les mêmes Pour recadrer correctement les cadres
individuels de la feuille de sprites, Draw
Image est disponible en trois versions La première version
attend trois arguments, nous venons de le faire
ici à la ligne 35. La deuxième version
prend cinq arguments, quatrième et
cinquième arguments
facultatifs définissent la largeur et la hauteur de l'image et l'image sera étirée ou comprimée pour
s'adapter à ces dimensions. Maintenant, je comprime l'
intégralité de la feuille de calcul massive dans une zone de 200
fois 200 pixels La troisième version de la méthode draw
image attend neuf arguments pour nous donner le meilleur contrôle sur l'
image que nous voulons dessiner. C'est la version que nous devons
utiliser pour animer notre feuille de calcul Ces neuf arguments sont
l'image que nous voulons dessiner. Source x, source
Y, largeur de source et hauteur de source, la zone que
nous voulons recadrer à
partir de l'image source. Les quatre derniers arguments
sont appelés destination X, destination Y,
largeur de destination et hauteur de destination. Cela définira l'endroit
sur le canevas sur lequel nous
voulons dessiner cette image recadrée Disons que je veux juste
recadrer le cadre en haut à
gauche. Je vais recadrer de la
coordonnée 00 à la largeur du sprite. Et
les valeurs de hauteur des sprites que nous avons définies exactement de la même taille qu' une seule image dans
notre feuille de calcul, dans ce cas 200
fois 200 pixels Bien, nous utilisons la méthode de
dessin d'image pour recadrer un seul cadre. Je peux multiplier la largeur du
sprite ici par un nombre et la
hauteur du sprite ici également Maintenant, j'ai un moyen de contourner la feuille de sprite d'une
image à l'autre. C'est 1100 ? Est-ce que c'est
1200 ? Est-ce un cadre ? Ce numéro navigue
horizontalement. Cet autre chiffre déterminera quelle ligne de la
feuille de sprites nous nous trouvons Vous pouvez voir que nous pouvons passer à une ligne d'animation différente chaque fois que je change ce numéro. Je vais mettre ces valeurs dans Class Properties Frame X qui gérera la navigation horizontale par
sprites Le cadre Y sera destiné à la navigation
verticale avec des sprites. Encore une fois, lorsque le cadre X
et le cadre Y ont la valeur 00, nous affichons le cadre
en haut à gauche. Je peux modifier ces valeurs pour parcourir
la feuille de calcul. Maintenant que nous avons compris comment
ces arguments ont été transmis à la méthode du dessin pour
recadrer des cadres individuels, nous pouvons réellement animer
notre feuille de calcul et donner vie à ce puissant
hibou Commençons par simplement animer une seule ligne pour chaque image
d'animation. Si l'image X est
inférieure au nombre maximum d'images, dans ce cas, le nombre d'images maximum sera le nombre d'
images par ligne, 30. Si l'image X est inférieure à 30, continuez à augmenter l'
image X d'un L, ce qui signifie qu'elle est égale
ou supérieure à 30, remettez l'image X à zéro
pour qu'elle puisse recommencer à tourner. Bien, nous animons cette ligne, car ici nous réglons l'
image Y sur trois Si je le mets à zéro, nous animons cette ligne Si je change ce numéro, nous animons différentes lignes Nous voulons échanger ces
lignes d'animation en fonction de deux choses. Dans quelle direction marche
le joueur Marche-t-il
ou se tient-il simplement debout ? Si nous avions un personnage complexe
doté de multiples attaques
, etc., je suggère de créer
un schéma de conception d'états comme je
l'ai fait dans la classe des coureurs
infinis. Dans ce cas, la logique du mouvement
et de l'animation est suffisamment
simple pour être gérée ici dans la méthode de mise à jour. Nous pourrons toujours l'étendre à un modèle de design d'état plus tard si nous décidons d'ajouter
d'autres mouvements de joueurs. Laissez-moi vous montrer que
nous définissons ici la
vitesse du joueur en fonction des quatre touches fléchées
qui ont été enfoncées vers la gauche, la droite, le haut ou le bas. Copions ce bloc de code. Faites très attention
aux crochets,
il est facile d'en manquer un
et de déchiffrer votre code. Si vous vous souvenez,
ici, nous gardons trace des touches qui ont été
enfoncées et relâchées. Les touches enfoncées
commencent par un P majuscule, les touches
relâchées
commencent par une majuscule R. Comment faire ? Je
pense que cela devrait fonctionner. Lorsque nous appuyons sur la touche flèche gauche, nous voulons animer cette ligne Ce cadre de points y est égal à trois lignes d'
animation qui marchent vers la gauche. Lorsque nous relâchons la flèche
gauche comme ceci, nous définissons le cadre y22 Nous voulons simplement rester les bras croisés
vers la gauche. Nous allons le tester. Je dois régler la vitesse sur
00 lorsque nous publierons ici. C'est mieux quand on
appuie sur la flèche, non ? Je veux animer la
marche, c'est vrai .
Cette ligne, ce
cadre à points, compte cinq Je copie ce LF, en faisant attention
aux crochets. Nous passons à R ici lorsque nous
relâchons la flèche, touche droite. Nous avons réglé la vitesse sur 00. Et nous avons réglé le cadre
Y24, Idle, à droite. Animation. Parfait. Nous avons un personnage qui peut
marcher à gauche et à droite,
et la logique que nous venons d'écrire naviguer
correctement
dans la feuille de calcul Nous marchons et
nous sommes debout. Le joueur est animé
et
réagit correctement aux
entrées du clavier. Bon travail. Faisons-le également pour les mouvements
verticaux, de haut en bas. Lorsque nous appuyons sur la flèche vers le haut, nous voulons que le joueur
s'éloigne
du cadre de la caméra par sept. Je copie ce bloc de code. Lorsque nous relâchons la flèche vers le haut, nous animons l'image par six et nous réglons la vitesse sur 00 Nous pouvons marcher à gauche, juste en haut. Lorsque nous appuyons sur la flèche vers le bas, nous voulons animer le cadre Y un. Je copie ce bloc de code. Lorsque nous relâchons la flèche vers le bas, nous animons l'image Y zéro
et nous réglons la vitesse sur zéro Nous marchons et animons
dans quatre directions. Nous alternons correctement
entre l'animation debout et animation de
marche pour
chacune de ces directions travail incroyable pour créer
une idée
de profondeur donnant l'
impression que le joueur s' éloigne et se
dirige vers la caméra. En montant et en descendant, je le fais bouger un
peu plus lentement sur cet axe. Regarde à quel point ça fait une
différence. On a l'impression qu'il
y a plus de profondeur, comme si l'arrière-plan était plus éloigné de la caméra que
le premier plan Nous marchons à une
vitesse normale, à gauche, non ? Mais de haut en bas, nous
marchons un peu plus lentement. Changeons la vitesse maximale à cinq. C'est une grosse et lourde créature. Il devrait se déplacer plus lentement. Je commente
le rectangle noir, nous n'en avons pas besoin pour le moment. J'aime vraiment ça. Nous avons une base pour de nombreux jeux
différents. Tout ce dont vous avez besoin maintenant, ce sont
vos idées créatives. On peut faire tellement de
choses différentes avec ça. Au fur et à mesure que vous en apprendrez davantage sur Java Script Canvas
et le développement de jeux, il deviendra de
plus en plus facile de transformer ces idées en une base de code
fonctionnelle. Laisse-moi t'en montrer plus. J'espère que tu en retires
de la valeur aujourd'hui. Faites-moi savoir dans les commentaires
si vous apprenez quelque chose nouveau, car nous n'
utilisons que la dernière touche enfoncée ou relâchée pour
contrôler le personnage du joueur. Il existe un problème
courant lorsque nous marchons
dans une direction, disons que je marche à droite, j'appuie sur la flèche gauche. Le joueur tourne à gauche et ce n'
est qu'alors que je relâche la flèche droite. La dernière touche est relâchée vers la droite, ce qui obligera le joueur à
s'arrêter brièvement avant que le joueur ne continue à marcher à gauche
en maintenant
enfoncé la touche gauche. Vous pouvez essayer et vous
constaterez que nous aurons ce problème dans n'importe quelle
direction, marchez quelque part. Et lorsque vous appuyez sur une touche de direction
différente avant de relâcher
la précédente, le joueur
s'arrête un moment avant continuer à
se déplacer dans
cette nouvelle direction. Résoudre ce problème est facile. Lorsque nous relâchons la flèche vers la gauche. Nous voulons que ce code ne s'exécute que si la vitesse des
joueurs est inférieure à zéro. Arrêtez le joueur et
faites-le tourner au ralenti vers
la gauche uniquement si la
vitesse du joueur actuel est inférieure à zéro, si le joueur se
déplace actuellement vers la gauche De cette façon, nous ne pouvons passer au ralenti à
gauche qu'en
marchant à gauche. Lorsque nous relâchons la flèche droite, nous voulons uniquement arrêter la vitesse de déplacement et
animer le ralenti, n'est-ce pas ? Si le joueur se
déplace actuellement vers la droite, si sa vitesse x est
supérieure à zéro. Je dois également supprimer
cette déclaration L ici. Et maintenant, nous résolvons le problème
pour les mouvements à gauche et à droite. Faisons la même chose
pour les mouvements de haut en bas. N'exécutez ce code que lorsque
nous relâchons la flèche vers le haut et en même temps, la vitesse de déplacement des
joueurs y est inférieure à zéro lorsque nous
relâchons la flèche vers le bas. N'exécutez ce code que si en même temps
la vitesse
Y est supérieure à zéro. Uniquement lorsque le joueur
descend vers la caméra. Maintenant, nous nous déplaçons et le pépin a
disparu. Bravo.
44. Comment commander FPS: Si je règle la vitesse maximale sur
deux joueurs, les mouvements sont lents, mais l'
animation du sprite diffuse des images si vite que le joueur
marche sur la lune Les pieds s'animent d'
une manière qui ne
correspond pas à la vitesse de déplacement
et cela donne une très mauvaise apparence Pour résoudre
ce problème, vous pouvez
contrôler manuellement la vitesse d'animation de la feuille de
sprites heure actuelle, nous ne diffusons une nouvelle
image d'animation par boucle. Chaque fois qu'une image
d'animation de demande est appelée. Créons une fonctionnalité qui nous permettra
de définir manuellement images par seconde par seconde pour la vitesse d'animation
de notre feuille de sprites Cela peut être fait
globalement et nous pouvons définir des FPS pour l'ensemble du jeu. Ou comme je vais vous le montrer maintenant, vous pouvez définir le FPS individuellement
pour l'objet du joueur. Peut-être aurons-nous des ennemis plus tard qui auront des feuilles de sprites
différentes Et nous souhaiterions peut-être que
ces feuilles
de sprites soient animées à une vitesse
différente Par défaut, le cadre
d'animation de la demande s'ajuste automatiquement
au rafraîchissement de l'écran. Tarif. Notre jeu
fonctionnera plus rapidement pour des écrans à taux de
rafraîchissement élevé Comme ces nouveaux écrans de jeu, nous pouvons contrôler
que si nous voulons demander une image d'animation, elle possède
une fonctionnalité spéciale générer un horodatage à chaque fois qu'elle appelle une fonction d'animation et de transmettre cet horodatage comme argument à la fonction
d'
animation qu'elle Utilisons-le pour compter les
millisecondes entre les images afin de pouvoir définir nos propres images
FBS J'ai créé une variable
que j'ai appelée la dernière fois, elle se trouvera en dehors de la boucle
d'animation comme celle-ci. Au départ, je l'ai mis à zéro. Il contiendra la valeur de horodatage de la boucle d'animation
précédente Ainsi, nous pouvons comparer les horodatages
actuels et anciens et déterminer le nombre de
millisecondes écoulées La valeur est appelée temps delta. temps delta est le nombre de millisecondes qui se sont écoulées entre l'horodatage de
cette boucle d'animation et l'horodatage de la boucle d'animation
précédente Pour calculer le temps delta, nous savons que nous devons
comparer ces horodatages horodatage de la boucle
précédente sera conservé dans la dernière variable horaire ici Dans un premier temps, nous l'avons mis à zéro avant de commencer à
générer des horodatages Comme je l'ai dit, le cadre
d'animation de la demande transmet argument d'
horodatage
généré automatiquement à la fonction Si vous êtes débutant,
imaginez qu'il est généré et
transmis ici comme ça. Au moment où l'image d'animation de la
demande déclenche cette fonction, nous attribuons un nom de variable à cet
horodatage généré automatiquement Ici, je vais simplement l'appeler timestamp orthographié avec une majuscule S. Commentons cela
et consoloquons l' Juste pour que je puisse voir quel
format nous obtenons, vous pouvez voir que
c'est en millisecondes La première valeur est littéralement
le nombre de secondes écoulées depuis
le début de la boucle, 45678 C'est l'horodatage que je supprime. L'heure delta de la console
est l'horodatage
de cette boucle d'animation moins la
dernière fois indiquée sur la ligne 113,
qui
contiendra de cette boucle d'animation moins la
dernière fois indiquée sur la ligne 113, toujours une valeur pour horodatage de la boucle d'animation
précédente Une fois que nous avons calculé le temps delta, nous avons défini la dernière heure sur l'horodatage. Ainsi, ce nouvel horodatage
issu de cette boucle peut être utilisé comme ancienne valeur d'horodatage dans la
prochaine boucle d'animation suivante Nous avons maintenant l'heure delta. Il nous indique le nombre de
millisecondes nécessaires à
notre ordinateur pour diffuser
une image d'animation Mon écran se rafraîchit à
environ 60 images par seconde. Mon temps delta est d'environ
16,6 millisecondes. C'est parfait. Obtenez-vous le même delta ou
obtenez-vous une valeur complètement
différente ? Faites-le moi savoir dans un commentaire. Cela dépendra
du taux de rafraîchissement de votre écran et en partie également de la puissance
de votre machine. Les machines les plus faibles
auront un temps delta plus élevé. Vous pouvez voir qu'ici les premières valeurs de temps delta ne
sont aucune, pas un nombre. Comme nous exécutons animate pour la première fois
ici dans la première boucle, cet horodatage n'est pas défini Aucun appel
d'image
d'animation de demande n'a été généré automatiquement auparavant . Pour que nous puissions résoudre ce problème, je dois
m'assurer de passer le premier horodatage ici,
juste pour éviter un non, pas une valeur numérique
dans la boucle initiale. Sinon, cela pourrait
nous poser des problèmes ultérieurement en fonction de la manière dont vous souhaitez
utiliser vos valeurs de temps delta. L'horodatage initial sera égal à zéro. Vous pouvez voir que
les valeurs sont omniprésentes au début,
mais elles se stabilisent ensuite rapidement aux alentours de
16,6 au fur et à mesure que notre
boucle d'animation se répète C'est l'idéal. Je
supprime la console, je transmets cette valeur de temps delta
à la méthode de rendu sur la classe de jeu Je m'assure que cette valeur
est attendue ici et je peux la transmettre n'
importe où dans notre jeu. Maintenant, partout où nous en avons besoin. Je le passe à la méthode de mise à jour sur classe
Alber car
nous voulons utiliser temps
delta pour contrôler les images
FPS par seconde
d'animation de sprites Là, je passe le temps
delta pour mettre à jour méthode et je dois m'
assurer que c'est prévu. Ici, à la ligne 44, nous sommes
maintenant
dans la classe Alber et nous pouvons utiliser la valeur
du temps delta ici pour tellement de choses
différentes Pour contrôler le nombre d'images par seconde de l'animation des
sprites, je vais créer trois variables
auxiliaires, les propriétés de
classe, le
FPS sera Essayons d'animer 30 images par seconde et voyons à
quoi cela ressemble L'intervalle entre les images sera de 1 000
millisecondes divisé par 30. Cela déterminera le nombre de
millisecondes qui doivent s'écouler
avant de passer à l'
image suivante de la feuille de sprites Le Frame Timer sera le compteur. Il accumulera le temps
delta encore et encore au fur et à mesure que notre boucle
d'animation se déroulera Lorsqu'il atteint la valeur
et l'intervalle d'images, lorsque suffisamment de millisecondes se
sont accumulées, nous déclenchons certaines
actions périodiques Dans ce cas, nous diffuserons
la prochaine image d'animation. La même technique peut également être utilisée pour ajouter un nouvel
ennemi au jeu ou pour un autre événement
que vous souhaitez voir se produire dans un intervalle
spécifique. Il s'agit d'une
technique importante à comprendre. Écrivons la logique et expliquons-la lorsque nous verrons le code. Ce ne sont que quelques lignes. Je veux uniquement exécuter
ce code qui échange entre les images de sprites lorsque
suffisamment de millisecondes Si le délai d'images est
supérieur à l'intervalle d'images, animez
uniquement
la feuille de sprites Sinon, continuez à augmenter le
délai d'image par delta. Ce code animera la
feuille de calcul à partir d'ici. Lorsque cela se déclenche,
nous remettons également chronomètre à zéro
afin qu'il puisse être à
nouveau pris en compte pour le
prochain événement périodique dans la boucle d'animation.
Nous calculons le temps delta, Nous calculons le temps delta la différence entre
l'horodatage de la actuelle et celle de la boucle
d'animation précédente. temps delta est le nombre
de millisecondes nécessaires notre ordinateur pour traiter
une image d'animation Le temporisateur d'images commence
à zéro et ajoute plus de
temps delta au fur et à mesure que la boucle d'animation s'exécute jusqu'à ce qu'il soit
supérieur à l'intervalle d'images. L'intervalle d'images est le
point d'arrêt qui, lorsqu'
il est atteint, déclenche notre événement périodique Lorsque nous l'atteignons, nous gérons animation des
sprites et nous
remettons le chronomètre à zéro afin qu'il puisse être compté à nouveau pour la prochaine image d'animation
diffusée périodiquement Je sais que c'était beaucoup, mais cette technique
est très importante. Il deviendra
facile à comprendre lorsque vous l'utiliserez plus souvent. Croyez-moi maintenant, le personnage
s'anime plus lentement, juste à cause de l'échange de sprites et non de la
vitesse de déplacement réelle sur la Vous pouvez vraiment voir
que lorsque je règle le
FPS à deux images par seconde, il glisse toujours facilement sur le
canevas à 60 images par seconde. Mais nous limitons la rapidité avec laquelle les images suivantes sont diffusées dans des
feuilles de sprites J'espère que cela fait clairement la
différence. Je peux essayer d'autres valeurs comme FPS. Je dois expérimenter
un peu et
trouver la bonne valeur
qui permettra au lex se déplacer à la vitesse
naturelle lorsque le joueur se déplace
sur le terrain gazonné. 50, c'est encore un peu dérapant. 60, nous ne prenons
pas en compte les valeurs
restantes du temps delta
chaque fois que nous déclenchons
notre événement périodique Même si j'ai dit 60 FPS, le FPS réel
serait inférieur à cela. Pour les besoins d'un projet comme celui-ci, c'est parfaitement bien. Nous avons une valeur que nous pouvons augmenter ou diminuer pour contrôler l'animation des
sprites Il remplit bien son objectif. Je peux simplifier cette
ligne de code et utiliser opérateur
ternaire pour écrire tout
cela sur une seule ligne Laissez-moi vous montrer que c'est facile. L'opérateur ternaire est le seul opérateur Java Script
à trois opérandes Nous l'utiliserons comme une
simple instruction d'une ligne
si nous avons une
condition à évaluer. Nous vérifions si l'image X est
inférieure à la trame maximale. S'il s'agit d'un point d'interrogation, augmentez le cadre X d'un, L remettez le cadre X à zéro. Maintenant, cette seule
ligne de code fait la même chose que cette instruction L if
multiligne. Vous pouvez utiliser l'une ou l'autre des syntaxes.
Je voulais juste te montrer.
45. Objets de jeu positionnés aléatoirement: Créons des
objets et
distribuons-les au hasard dans
le monde du jeu. Je crée une classe, je l'appelle objet. Comme d'habitude, il s'attend une référence à l'objet principal du
jeu à partir de la ligne 111 comme argument indiquant que nous avons accès à
toutes les propriétés importantes. À partir de là, nous convertissons cette
référence en propriété de classe. Comme nous l'avons fait avant. Méthode Draw, nous attendrons
le contexte comme argument. À l'intérieur, nous appelons
la méthode de dessin d'image intégrée. Je veux vous montrer comment étendre les classes et
tirer parti de l'héritage, qui est l'un des
grands principes de la programmation orientée objet. Comment pouvons-nous l'utiliser pour
réduire la répétition du code. Je crée une classe
appelée Busch qui étend la classe d'objets
à partir de la ligne 102 Il aura également un
constructeur. Je crée une autre classe. J'appelle plante
encore une plante, j'appelle herbe. Nous avons la classe d'objet principale. Nous avons trois classes, Bush, plant et Grass, qui
étendent cette classe d'objets. L'objet est appelé classe
parent, également appelée superclasse Bush, Plant et Grass
sont des cours pour enfants, également appelés sous-classes. Si j'utilise une propriété ou une méthode dans l'une de ces classes
enfants, cette propriété n'est pas
définie dans cette sous-classe Le script Java va le
rechercher automatiquement sa classe parent, sur l'objet. De cette façon, je ne peux définir
cette méthode de dessin qu'en une seule fois. Et toutes les
classes enfants qui étendent cette classe parent y auront
automatiquement accès, elles héritent de cette méthode Nous pouvons faire quelque chose de similaire
avec les propriétés du constructeur en utilisant le super mot-clé que je vais vous montrer dans une minute. classe Object contiendra
toutes les propriétés et méthodes partagées entre
toutes les classes enfants. Busch, Plant et Grass
contiendront des propriétés spécifiques uniquement à
cette sous-classe particulière Par exemple, chaque sous-classe
aura une image différente, mais toutes passeront cette image
différente à
la même méthode de dessin à partir de 907. Faisons-le. Avant de pouvoir utiliser
ce mot clé dans le constructeur de la classe
enfant, je dois déclencher
le constructeur sur sa classe parent Quand je dis super comme ça ici, cela signifie que je veux exécuter un constructeur du parent de
cette classe La classe parent est également
appelée superclasse. À la ligne cent trois, je peux voir que le constructeur
de classe d'objets attend le jeu comme argument Je transmets cette
référence en même temps
que je la convertit également en
propriété de classe sur la classe Bush. Comme cela, dans la
méthode de dessin d'image partagée que je lui ai transmise l'image didot x et dis.yi peuvent également lui donner la
largeur dist et Si je veux redimensionner les
images comme vous pouvez le voir, aucune d'entre elles n'est
présente dans ce cours. Je veux que chaque sous-classe
ait une image différente, et nous devons connaître la taille de cette image pour calculer
sa position aléatoire Je vais devoir mettre
toutes ces propriétés sur chaque sous-classe séparément. Commençons par
Bush. Cette image à points sera un document
obtenu par élément par identifiant. Ici, dans l'index HTML, je dois créer cet élément d'
image comme d'habitude, vous pouvez télécharger les images dans la
section des ressources du projet ci-dessous. Je l'ai mis ici, l'identifiant sera Bush, un
autre avec un identifiant
de plante comme celui-ci. Le dernier sera du
grass dans le style CSS. J'utilise leurs identifiants pour
masquer ces images. Nous voulons les dessiner sur une toile, et non comme de véritables
éléments d'image sur la page Web. L'identifiant est Bush. Je duplique ce code d'identification. Ici, ce sera prévu
et ici, de l'herbe. J'essaie de garder le
nom simple et propre. Je ne veux pas vraiment
redimensionner les images, mais si nous voulons laisser l'
option de mise à l'échelle ouverte, il vaut
peut-être mieux que je définisse propriétés de largeur et de masquage d'image séparément. Même si, à ce stade, ils
auront la même valeur. Je redimensionne déjà les images pour qu'elles soient de
la même taille que celles que nous allons
dessiner sur Canvas, ce qui est une bonne pratique. L'image de Bush est de 216 à 100 pixels. Je pourrais également définir
ces propriétés sur une ligne comme celle-ci.
C'est à vous de décider. position horizontale sera une valeur aléatoire comprise entre zéro et la largeur de la zone de jeu moins la largeur de
l'image elle-même. Cela
nécessitera probablement quelques ajustements. Voyons voir, la position verticale en y ne
partira pas de zéro, elle partira de la marge supérieure. Et à partir de là, une valeur aléatoire comprise entre zéro et la hauteur de la zone de
jeu moins la hauteur de l'
image moins la marge supérieure. Je pense que lorsque nous
commencerons à les dessiner, nous verrons si je dois
apporter des ajustements ici. Nous allons le tester. Dans
la classe de jeu principale, je crée une propriété
appelée Number of Plants. Créons dix objets végétaux
positionnés de manière aléatoire. Je crée une méthode initialisée
qui ne s'exécutera qu'une seule fois lors du chargement de la première page et qui positionnera aléatoirement
les objets à l'intérieur Je crée une boucle à quatre boucles. Il sera exécuté dix fois. Chaque fois qu'il fonctionne,
nous créons une plante. Je crée ici un
tableau vide qui contiendra tous les objets de la plante. Chaque fois que les quatre boucles s'exécutent, je prends ce tableau de plantes, moi, nouvel objet Bush
à l'intérieur de la ligne 111, je peux voir que le constructeur de
classe Bush attend le jeu comme argument Je lui passe ce mot clé parce que nous sommes dans cette classe de
jeu ici. Après avoir créé une instance
de la classe de jeu 160, je peux appeler cette méthode d'initialisation Il fonctionnera et
remplira le tableau des plantes avec dix
instances aléatoires de la classe Bush Si je veux
les afficher sur le canevas, je dois appeler
leur méthode de dessin. Je vais le faire depuis le rendu interne. Je prends des plantes et pour chaque objet
végétal du tableau, j'appelle leur méthode de
dessin associée à partir de la ligne 106. Cette méthode s'attend à un contexte. Je transmets cette référence
contextuelle. Super, je dessine dix buissons positionnés
au hasard. Je vais ici, je vais copier toutes ces propriétés spécifiques à la classe Bush, et je les copie ici
dans la classe plant. Je vérifie que la largeur de l'image est de
212 pixels, la hauteur de 118. Je le copie à nouveau, et la largeur de
l'herbe sera 103 et la hauteur de 183 pixels. Bien, nous avons défini une classe d'objet
parent dans laquelle nous pouvons placer toutes les
propriétés et méthodes partagées, ainsi que trois sous-classes appelées Bush Plant et Grass qui
étendent la classe parent Pour vérifier rapidement si
ces classes fonctionnent, je peux simplement échanger le
nom de la classe ici à la ligne 168. L'herbe fonctionne, l'
usine fonctionne. Comment
les répartir aléatoirement et contrôler quelle partie de ces dix plantes générées
aléatoirement sera constituée de buissons, herbes ou d'objets végétaux Un moyen simple de le faire
est de créer une variable. Ici, j'appelle
par exemple randomiser. Il sera égal
à mathodtrandom. Nous savons qu'un code
aléatoire méthot comme
celui-ci renvoie à lui seul une valeur aléatoire 0 à 1. Disons que je veux environ 30 % de ces objets soient des instances de la classe plant Je dis que si random Ize
est inférieur à 0,3 L, si randomize est inférieur à
0,6 lorsque les mathématiques sont
aléatoires entre 0,3 et 0,6, nous créons une
instance de la classe Bush L, ce qui signifie que lorsque Maat lance
aléatoirement entre 0,6 et un, nous créons Cela ne fonctionne pas
parce que cela
doit se trouver à l'intérieur de la
boucle
à quatre, car nous voulons lancer chaque fois que nous
créons un nouvel objet, non une seule fois
pour les dix objets.
46. Superposition et ordre de dessin dans des jeux 2D: Parfait. Nous étendons
une classe pour créer trois objets de jeu différents
positionnés aléatoirement. Bon travail. Comme vous pouvez le constater, la façon dont ces objets sont
positionnés et la façon dont le jeu se superpose n'ont pas vraiment
de sens visuel hibou est dessiné d'abord
sur la ligne 162, puis toutes les plantes sont dessinées, après les plantes
soient toujours au-dessus d'un ours Si je l'échange, les plantes sont toujours
derrière l'ours. Puisque nous dessinons tout sur le même élément du canevas, ce qui est dessiné en
premier est derrière, et ce qui a été dessiné après
se trouve en haut devant. Je souhaite dessiner des objets dans un ordre précis en fonction de
leur position verticale. Plus précisément, en fonction de la position verticale
de leur bord inférieur. Parce que chaque objet a une hauteur différente,
il faut s'assurer qu'ils sont alignés d'une manière
logique et visuelle. Et pour que notre personnage
puisse
les contourner et être devant
et derrière les objets. cas échéant,
nous essayons de
simuler un monde virtuel dans lequel les plantes poussent
depuis le sol. Et où ce hibou
marche
sur un sol solide en tout temps, même lorsqu'il marche de haut en bas. La superposition doit
correspondre visuellement à cela. C'est en fait très
facile à réaliser. Je dois juste m'assurer
que tous ces objets, donc tous les ours et tous les objets
végétaux, sont dans le même ensemble. Pour que je puisse les trier en
fonction de leur position verticale. Je crée un autre tableau
appelé objets de jeu. Chaque fois que la méthode de rendu s'exécute, je mets un objet Alber à l'intérieur J'ai réparti tous les objets
des plantes en bas âge dans cet opérateur de propagation en
réseau. telle utilisation nous permet d' étendre un tableau
à un autre. Dans ce cas, cela n'a pas
beaucoup de sens de le faire chaque fois que la méthode de rendu est activée
pour chaque image d'animation. Comme nous n'avons qu'Alber
et dix plantes statiques, nous aurions pu utiliser cette méthode d'
initialisation interne Il serait
logique de le faire périodiquement pour construire
ce tableau encore et encore. Si d'autres objets
sont ajoutés et
supprimés à maintes reprises, par
exemple des ennemis ou
des bonus qui vont et viennent. Nous avons maintenant Alber, les dix plantes au même
niveau dans le même tableau Je peux prendre ce tableau pour chaque objet du tableau d'objets
du jeu. J'appelle leur méthode de dessin. Lorsque nous faisons cela et que nous combinons différents types d'objets
dans un seul tableau, nous devons nous assurer que
tous ces objets ont
réellement des méthodes de dessin
définies dans leurs classes. Attention aux crochets
Ici, je peux supprimer ce code. Je vais devoir appeler la
méthode de mise à jour et lui transmettre le delta time. Sinon, je vais supporter, je ne bougerai pas et je n'
animerai pas. Quand j'appelle Update comme ça, nous dessinons et mettons à jour tous les ours. Lorsque j'essaie de dessiner et de
mettre à jour la première plante
sur dix, elle est dessinée, mais il n'y a
aucune méthode de mise à jour à exécuter, nous obtenons
donc une erreur. Je dois ajouter une méthode de mise à jour sur la classe d'
objet pour que
ce code s'exécute. Nous ne mettons pas vraiment
à jour les objets, mais ici nous pouvons avoir
quelques animations. Par exemple, les buissons et l'herbe peuvent bouger lorsque le
joueur les touche, ce code sera géré
dans cette méthode de mise à jour. Je vais laisser ce champ vide pour le moment. Nous avons maintenant la même
chose qu'avant, mais tous les éléments qui doivent
être superposés dynamiquement sont dessinés et mis à jour depuis
le tableau d'objets du jeu. Tous les ours sont les premiers du tableau. C'est pourquoi il est
dessiné avant les plantes. Des plantes sont dessinées dessus. Si je les échange, les plantes sont derrière et l'aulber
est dessiné en dernier sur le dessus Parce que c'est l'
ordre dans lequel chaque méthode parcourt le tableau d'objets
du jeu. Pour définir leurs méthodes de dessin, nous voulons trier Alber et les dix plantes de ce tableau en fonction de leur coordonnée
verticale y, mais pas en fonction de leur limite supérieure
mais de leur limite inférieure Comme nous avons des objets
de hauteurs différentes, nous pouvons le faire en utilisant la méthode de tri par tableau intégrée
. La méthode de tri trie les
éléments d'un tableau place et renvoie la
référence au même tableau. Maintenant trié, il prend
un argument optionnel. Nous appelons une fonction de comparaison, dans laquelle nous pouvons définir une logique
décrivant l'ordre de tri. Si nous ne définissons pas de condition de
tri, par défaut, tous les éléments du tableau
sont simplement convertis en chaînes et triés en fonction des
caractères, des valeurs Unicode. A est le premier élément
de comparaison, B représente le deuxième
élément. Pour la comparaison, méthode de
tri comparera
automatiquement chaque élément du tableau
à tous les autres éléments. Pour les trier en
fonction de nos besoins. Nous voulons que la
condition de tri compare la limite inférieure de chaque
élément dessiné sur le canevas. C'est donc la position verticale y
plus sa hauteur. Comme ça. Je dis de trier tous les éléments
par ordre croissant en fonction leur position verticale et de
leur hauteur Une fois le tableau trié, nous dessinons des plantes et un hibou
dans cet ordre sur toile Et maintenant, tout a un
sens visuel. Nous pouvons contourner les obstacles et nous pouvons constater que le personnage du
joueur et les plantes sont désormais toujours correctement
dessinés devant ou derrière. Vous pouvez étendre ce jeu
de différentes manières, créer des champignons qui poussent dans zone
jouable pour faire grandir le hibou pendant
qu'il les mange Vous pouvez également lui faire éviter dangereux ennemis ou
contourner des obstacles épineux Je vous suggère de créer une copie
de cette base de code et l'
utiliser comme base pour
différentes expériences de jeu.