Le but de ce tutoriel est d'enseigner la programmation de jeux 2D et le langage C à travers des exemples. L'auteur avait l'habitude de programmer des jeux au milieu des années 80 et a été concepteur de jeux chez MicroProse pendant un an dans les années 90. Bien qu'une grande partie de cela ne soit pas pertinente pour la programmation des grands jeux 3D d'aujourd'hui, pour les petits jeux occasionnels, cela servira d'introduction utile.
Implémentation de Snake
Des jeux comme le serpent où des objets se déplacent sur un champ 2D peuvent représenter les objets du jeu soit dans une grille 2D, soit comme un tableau d'objets à une dimension. "Objet" signifie ici tout objet de jeu, pas un objet tel qu'il est utilisé dans la programmation orientée objet.
Commandes de jeu
Les touches se déplacent avec W = haut, A = gauche, S = bas, D = droite. Appuyez sur Echap pour quitter le jeu, sur f pour basculer la fréquence d'images (cela n'est pas synchronisé avec l'affichage, donc peut être rapide), sur la touche de tabulation pour basculer sur les informations de débogage et sur p pour les mettre en pause. Quand il est en pause, la légende change et le serpent clignote,
Dans le serpent, les principaux objets du jeu sont
- Le serpent
- Pièges et fruits
À des fins de gameplay, un ensemble de pièces contiendra chaque objet de jeu (ou partie pour le serpent). Cela peut également aider lors du rendu des objets dans le tampon d'écran. J'ai conçu les graphiques du jeu comme suit:
- Corps de serpent horizontal - 0
- Corps de serpent vertical - 1
- Tête dans 4 rotations à 90 degrés 2-5
- Queue en 4 rotations à 90 degrés 6-9
- Les courbes de changement de directions. 10-13
- Apple - 14
- Fraise - 15
- Banane - 16
- Piège - 17
- Afficher le fichier graphique du serpent snake.gif
Il est donc logique d'utiliser ces valeurs dans un type de grille défini comme bloc [WIDTH * HEIGHT]. Comme il n'y a que 256 emplacements dans la grille, j'ai choisi de le stocker dans un tableau à une dimension. Chaque coordonnée sur la grille 16 x16 est un entier de 0 à 255. Nous avons utilisé des pouces afin que vous puissiez agrandir la grille. Tout est défini par #defines avec WIDTH et HEIGHT tous les deux 16. Comme les graphiques de serpent sont de 48 x 48 pixels (GRWIDTH et GRHEIGHT #defines), la fenêtre est initialement définie comme 17 x GRWIDTH et 17 x GRHEIGHT pour être juste légèrement plus grande que la grille.
Cela a des avantages en termes de vitesse de jeu car l'utilisation de deux index est toujours plus lente qu'un, mais cela signifie qu'au lieu d'ajouter ou de soustraire 1 des coordonnées Y du serpent pour se déplacer verticalement, vous soustrayez LARGEUR. Ajoutez 1 pour vous déplacer vers la droite. Cependant, étant sournois, nous avons également défini une macro l (x, y) qui convertit les coordonnées x et y au moment de la compilation.
Qu'est-ce qu'une macro?
# définir l (X, Y) (Y * LARGEUR) + X
La première ligne est l'index 0-15, la 2e 16-31 etc. Si le serpent est dans la première colonne et se déplace vers la gauche, la vérification pour toucher le mur, avant de se déplacer vers la gauche, doit vérifier si la coordonnée% WIDTH == 0 et pour la coordonnée du mur droit% WIDTH == WIDTH-1. Le% est l'opérateur du module C (comme l'arithmétique d'horloge) et renvoie le reste après la division. 31 div 16 laisse un reste de 15.
Gérer le serpent
Il y a trois blocs (tableaux int) utilisés dans le jeu.
- serpent [], un tampon en anneau
- shape [] - Contient les index graphiques Snake
- dir [] - Maintient la direction de chaque segment du serpent, y compris la tête et la queue.
Au début du jeu, le serpent est long de deux segments avec une tête et une queue. Les deux peuvent pointer dans 4 directions. Pour le nord, la tête est indexée 3, la queue est 7, pour la tête est 4, la queue 8, pour la tête sud 5 et la queue 9, et pour l'ouest, la tête 6 et la queue 10. Alors que le serpent est long de deux segments, la tête et la queue sont toujours séparées de 180 degrés, mais après la croissance du serpent, elles peuvent être de 90 ou 270 degrés.
Le jeu commence avec la tête orientée au nord à l'emplacement 120 et la queue orientée au sud à 136, à peu près au centre. À un léger coût d'environ 1 600 octets de stockage, nous pouvons obtenir une amélioration de la vitesse discernable dans le jeu en maintenant les emplacements du serpent dans le tampon d'anneau de serpent [] mentionné ci-dessus.
Qu'est-ce qu'un tampon tampon?
Un tampon en anneau est un bloc de mémoire utilisé pour stocker une file d'attente de taille fixe et doit être suffisamment grand pour contenir toutes les données. Dans ce cas, c'est juste pour le serpent. Les données sont poussées à l'avant de la file d'attente et retirées à l'arrière. Si l'avant de la file d'attente atteint la fin du bloc, il s'enroule. Tant que le bloc est suffisamment grand, l'avant de la file d'attente ne rattrapera jamais l'arrière.
Chaque emplacement du serpent (c'est-à-dire la seule coordonnée int) de la queue à la tête (c'est-à-dire vers l'arrière) est stocké dans le tampon en anneau. Cela donne des avantages en termes de vitesse car peu importe la durée de vie du serpent, seuls la tête, la queue et le premier segment après la tête (si elle existe) doivent être modifiés au fur et à mesure de ses mouvements.
Le stocker à l'envers est également bénéfique car lorsque le serpent reçoit de la nourriture, le serpent se développera lors de son prochain déplacement. Cela se fait en déplaçant la tête d'un emplacement dans le tampon en anneau et en modifiant l'ancien emplacement de la tête pour devenir un segment. Le serpent est composé d'une tête, de segments 0-n), puis d'une queue.
Lorsque le serpent mange de la nourriture, la variable atefood est définie sur 1 et vérifiée dans la fonction DoSnakeMove ()
Déplacer le serpent
Nous utilisons deux variables d'index, headindex et tailindex pour pointer vers les emplacements head et tail dans le tampon en anneau. Ceux-ci commencent à 1 (headindex) et 0. Ainsi, l'emplacement 1 dans le tampon en anneau contient l'emplacement (0-255) du serpent sur la carte. L'emplacement 0 contient l'emplacement de la queue. Lorsque le serpent se déplace d'un emplacement vers l'avant, le tailindex et le headindex sont incrémentés de un, enveloppant à 0 lorsqu'ils atteignent 256. Alors maintenant, l'emplacement de la tête est l'endroit où se trouve la queue.
Même avec un serpent très long qui serpente et alambiqué disons 200 segments. seuls le headindex, le segment à côté de la head et le tailindex changent chaque fois qu'il se déplace.
Remarque à cause du chemin SDL fonctionne, nous devons dessiner le serpent entier à chaque image. Chaque élément est dessiné dans le tampon de trame puis retourné pour qu'il s'affiche. Cela a cependant un avantage en ce sens que nous pourrions dessiner le serpent en déplaçant doucement quelques pixels, pas une position de grille entière.