This tuto is destined to french users but i think i’ll translate it later…
Bonjour à tous, je vous écris ici mes premiers essais de création d’un jeu en utilisant le formidable ESPLGE (https://corax89.github.io/esp8266Game/index.html)
Space Invaders スペースインベーダー est un jeu vidéo développé par la société japonaise Taito, sorti en 1978 sur borne d’arcade. Il s’agit d’un shoot 'em up fixe. Tomohiro Nishikado à conçu et programmé le jeu en s’inspirant de plusieurs médias populaires de l’époque tels que Breakout ou La Guerre des mondes.
Considéré comme le premier archétype du shoot them up, il est aussi l’un des titres les plus influents et célèbres de l’histoire du jeu vidéo.
Son principe est de détruire des vagues d’aliens au moyen d’un canon laser situé à l’avant d’un vaisseau spatial se déplaçant horizontalement en bas de l’écran. Dans les airs, des rangées d’aliens se déplacent latéralement tout en se rapprochant progressivement du sol et en lançant des missiles.
L’objectif est de détruire avec le canon laser une vague ennemie, qui se compose de cinq lignes de onze aliens chacune, avant qu’elle n’atteigne le bas de l’écran. Le joueur gagne des points à chaque fois qu’il détruit un envahisseur. Le jeu n’autorise qu’un tir à la fois et permet d’annuler ceux des ennemis en tirant dessus. La vitesse et la musique s’accélèrent au fur et à mesure que le nombre d’aliens diminue. L’élimination totale de ces derniers amène une nouvelle vague ennemie plus difficile, et ce indéfiniment. Le jeu ne se termine que lorsque le joueur perd, ce qui en fait le premier jeu sans fin
Les aliens tentent de détruire le canon en tirant dessus pendant qu’ils s’approchent du bas de l’écran. S’ils l’atteignent ou arrivent jusqu’au sol, ils ont réussi leur invasion et le jeu est fini. De temps en temps, une soucoupe spatiale apparaît tout en haut de l’écran et fait gagner des points bonus si elle est détruite. Des bâtiments destructibles, que nous appellerons “Bunkers” permettent au joueur de se protéger des tirs ennemis. Ces défenses se désintègrent progressivement sous l’effet des projectiles adverses et de ceux du joueur. Le nombre de bâtiments n’est pas le même d’une version à l’autre mais il était de 4 dans la versions d’arcade.
Tout d’abord écrivons le Cahier des charges fonctionnel, c’est à dire la liste des fonctionnalités à implémenter et autres spécificités utiles pour comprendre le fonctionnement attendu du jeux. Nous allons reprendre tout une partie des fonctionnalités de l’original mais allons également faire des modifications pour l’adapter à l’Espboy et le faire correspondre à ce que l’on souhaite.
Éléments fondamentaux
L’interface est composée des éléments suivants:
- le vaisseau du joueur; (Fait)
- une rangée de bunker (nous en créerons 3 et non 4 comme dans l’original par rapport à la taille réduite de l’écran); (Fait)
- les vaisseaux ennemis; (Fait)
- les missiles; (Fait)
- les vaisseaux, les bunkers et les missiles sont représentés à l’écran par des sprites. (Fait)
- le nombre de vies restantes du joueur. (Fait)
Déplacement du joueur :
- Le vaisseau du joueur se déplace uniquement horizontalement. (Fait)
- Le vaisseau du joueur ne peut pas sortir de l’écran. (Fait)
- Le déplacement se fait au moyen des touches flèche gauche et flèche droite et il tire lorsque l’on appuie sur le bouton “A” (Fait)
Bloc d’ennemis :
- Les ennemis sont organisés en un bloc est constitué de plusieurs lignes d’ennemis. (Fait)
- Chaque ligne d’ennemis comprend un ou plusieurs vaisseaux du même type. (Fait)
- Le bloc arrive par le haut de la fenêtre et se déplace alternativement de gauche à droite et de droite à gauche. (Fait)
- Le bloc change de direction dès qu’un des vaisseau du bloc arrive au bord de l’écran. (Fait)
- Lorsque le bloc change de direction, il se décale vers le bas. (Fait)
- Lorsque le bloc change de direction, sa vitesse de déplacement augmente. (non implémenté)
Missiles :
- Les missiles se déplacent en ligne droite verticale: de haut en bas si tiré par un ennemis et de bas en haut si c’est un missile du joueur. (Fait)
- Les missiles des ennemis peuvent entrer en collision avec les bunkers, le vaisseau du joueur et le missile du joueur (pas de friendly fire). (Reste à faire: missile / missile)
- Les missiles du joueur peuvent entrer en collision avec les bunkers, les vaisseaux ennemis et les missiles des ennemis.
- Les missiles sont détruits si ils sortent de l’écran. (Fait)
- Les ennemis tirent aléatoirement. (Fait)
- La fréquence de tire des ennemis augmente lorsqu’ils se rapprochent du bas de l’écran.
- Un vaisseau ne peut tirer qu’un seul missile à la fois et doit attendre un certain temps avant de pouvoir tirer à nouveau (le temps du refroidissemnt: cooldown). (Fait)
Vie et mort :
- Le joueur, les ennemis et les missiles possèdent chacun un nombre de vies. (Fait)
- Un élément dont le nombre de vie est inférieur ou égal à zéro est détruit. (Fait)
Collision missile-vaisseau :
- Un missile est en collision avec un vaisseau si un pixel de son sprite est sur un pixel du sprite du vaisseau. (Fait)
- Lorsqu’un missile touche un vaisseau, les nombres de vies du missile et du vaisseau sont décrémentés du nombre de vies du missile et du vaisseau. (Fait)
Collision missile-bunker :
- Un missile est en collision avec un bunker si un pixel de son sprite est sur un pixel du sprite du vaisseau. (Fait)
- S’il y a collision, il y a explosion du missile et les pixels de la partie où à eu lieu l’explosion sont retirés du sprite du bunker: ils deviennent transparents et ne peuvent plus participer à des collisions. (Fait)
- Le nombre de vie du missile est décrémenté. Dans les faits, le missile n’ayant qu’une vie, il est détruit (Fait)
Collision missile-missile :
- Deux missiles qui entre en collision se détruisent mutuellement (Non implémenté)
Victoire et défaite, la première des conditions suivantes qui survient met fin à la partie ou au niveau selon les cas précisés ci dessous:
- Le joueur gagne le niveau s’il détruit tous les vaisseaux ennemis. (Fait)
- Le joueur perd s’il ne lui reste plus de vie. (Fait)
- Un vaisseau touché par un tir Alien perd une vie. N’ayant plus de vie, il est détruit, s’il reste des vies au joueur, on les décrémente pour faire apparaître un nouveau vaisseau (Fait)
- Le joueur perd une vie si les ennemis rentrent en collision avec son vaisseau. (Fait)
- A la fin de la partie, le joueur peut relancer une nouvelle partie (Fait)
Pause :
- Tant que la partie n’est pas terminée le joueur peut mettre le jeu en pause en appuyant sur “B”: pendant la pause tous les déplacements et donc toute la dynamique du jeu est interrompue. (non implémenté)
- Lorsque le jeu est en pause, le joueur peut quitter la pause avec le même bouton B.
Addons
Les addons seront pris en compte uniquement si tous les éléments fondamentaux fonctionnent. Les addons ne sont pas complètements spécifiés et vous êtes libres de développer autour des thèmes proposés ou de proposer de nouveaux thèmes.
Affichage avancé :
- Les sprites des différents éléments sont animés. (Fait)
- Les actions de collisions génèrent des effets visuels (par exemple, explosion). (Fait)
Son :
- Le jeu est accompagné d’une musique en fond sonore. (Fait)
- Les différentes actions produisent l’émission de sons spécifiques. (Fait)
Système de niveaux :
- Le jeu comporte plusieurs niveaux. (Fait)
- La difficulté augmente avec les niveau (Fait)
Scoring
- Le jeu propose un système de high score avec le nom du joueur, son score et le niveau atteint (non implémenté)
- Les aliens rapportent un certain nombre de points en fonctions de leur type. Le type rapportant le plus de point étant celui situé le plus en haut. (Fait)
- La soucoupe rapporte 200 points.(non implémenté)
- Dans la première rangée (celle le plus en bas) les aliens rapportent 10 points, dans la seconde 20 points, 50 points dans la dernière. (Fait)
- Le joueur gagne une vie tous les 500 points
Etape 1: Créer un alien qui va faire des allers-retours à l’écran
Je me rends sur la page de l’IDE, j’ai déjà un code source de chargé. Comme il n’a pas de titre, je ne sais pas du quel il s’agit et ça nous donne un première leçon: nous commenterons notre code…
En attendant, je fais un [CTRL] + [A] puis [Suppr] pour partir d’une feuille blanche
Je veux commencer par créer le sprite d’un Alien, du coup, je clique sur le bouton Sprite (1) puis je règle la largeur et la hauteur du sprite. J’ai choisi un sprite de 8 de large par 8 de haut. Ce qui est la taille standard.
J’ai fais d’autres petites réflexions sur les dimensions mais on verra ça plus tard. Pour le moment, terminons de dessiner notre sprite, puis copions et collons le code dans notre programme.
{
0x00, 0x05, 0x50, 0x00,
0x00, 0x55, 0x55, 0x00,
0x05, 0x55, 0x55, 0x50,
0x55, 0x05, 0x50, 0x55,
0x55, 0x55, 0x55, 0x55,
0x00, 0x50, 0x05, 0x00,
0x05, 0x05, 0x50, 0x50,
0x50, 0x50, 0x05, 0x05
};
Rajoutons tout de suite un peu de commentaires avant ce code
// Tuto space invaders - Part 1: Add a sprite and make it move on the screen
// Invader 8x8
Oui, je pense que c’est une bonne habitude à prendre, j’écris mes commentaires en anglais mais bon, si vous n’êtes pas à l’aise avec l’anglais, vous pouvez les mettre en français.
Nous avons une entête pour notre programme et pour notre sprite. Maintenant, il faut indiquer au programme comment s’appelle notre sprite afin de pouvoir l’appeler plus tard. Je n’ai pas fais compliqué, je l’ai appelé invader. C’est un tableau de caractères qui va recevoir les données que nous avons récupéré de l’éditeur de sprite.
Nous faisons simple pour le moment, sans structure ni objets, on pourra voir ça plus tard…
Reprenons le tuto disponible ici: http://segamiga.com/esplge/doc/#/samples/game_tutorial
On va initialiser les 3 procédures: la procédure init() que nous appellerons au démarrage du programme pour initialiser les valeurs. la procedure step() qui sera exécuté à chaque boucle du jeu et qui contiendra la logique du jeu. La procedure draw qui s’occupera de l’affichage des différents éléments et enfin la procédure principale main() qui est celle appelé au lancement du jeu.
Le squelette du programme est donc:
// global variables
void init(){
// the code at this location will be executed only once when the game starts.
}
void step(){
// code in this place will execute each frame
}
void draw(){
// this is where all objects are drawn
delayredraw(); // waiting for frame drawing
}
void main(){ // required function for any program, execution starts with it
init();
while(1){ // infinite loop
step();
draw();
}
}
On va donc initialiser 2 variables invader_x et invader_y avec la position initiale de l’alien (note invader) et à chaque boucle, on va le faire avancer à la vitesse que nous avons défini.
A chaque fois que le sprite atteindra un des bord, on inversera sa vitesse pour qu’il reparte dans l’autre sens.
En le complétant avec notre programme on obtient:
// Tuto space invaders - Part 1: Add a sprite and make it move on the screen
// define constantes
#define invader_w 8
#define invader_h 8
#define invader_init_speed 2
// Sprites
// Invader 8x8
char invader[] ={
0x00, 0x05, 0x50, 0x00,
0x00, 0x55, 0x55, 0x00,
0x05, 0x55, 0x55, 0x50,
0x55, 0x05, 0x50, 0x55,
0x55, 0x55, 0x55, 0x55,
0x00, 0x50, 0x05, 0x00,
0x05, 0x05, 0x50, 0x50,
0x50, 0x50, 0x05, 0x05
};
// define variables
// invaders variables
int invader_x;
int invader_y;
int invader_speed;
// initialisation of values
void init(){
invader_x = 0;
invader_y = 20;
invader_speed = invader_init_speed;
setframerate(30);
clearscreen();
getsprite(1,invader);
clearscreen();
}
// Step procedure to make the game evolve between each draw
void step(){
invader_x = invader_x + invader_speed;
if (invader_x > 120) invader_speed = -invader_init_speed;
if (invader_x < 0) invader_speed = invader_init_speed;
}
// Draw procedure
void draw(){
putsprite(1, invader_x, invader_y); // Draw the sprite of an invader
delayredraw(); // wait until the frame is drawn.
}
// Main procedure
void main(){
init();
while(1){
step();
draw();
}
}
Et voilà, étape 1 atteinte: notre premier sprite se déplace infiniment de gauche à droite.