Présentation
Snake, de l’anglais signifiant « serpent », est un jeu vidéo populaire créé au milieu des années 1970, disponible de par sa simplicité sur l’ensemble des plate-formes de jeu existantes sous des noms de clone. Il s’est de nouveau fait connaître dans les années 1990 avec l’émergence du nouveau support de jeu qu’est le téléphone portable. Aujourd’hui, il est toujours aussi populaire et est devenu un classique dans les jeux vidéo.
Le joueur contrôle une longue et fine créature semblable à un serpent, qui doit slalomer entre les bords de l’écran et les obstacles qui parsèment le niveau. Pour gagner chacun des niveaux, le joueur doit faire manger à son serpent un certain nombre de pastilles ou de fruits (de la nourriture en général), allongeant à chaque fois la taille de la bestiole. Alors que le serpent avance inexorablement, le joueur ne peut que lui indiquer une direction à suivre (en haut, en bas, à gauche, à droite) afin d’éviter que la tête du serpent ne touche les murs ou son propre corps, dans ce cas il risque de mourir.
Le niveau de difficulté est contrôlé par l’aspect du niveau (simple ou labyrinthique), le nombre de pastilles à manger, l’allongement du serpent et sa vitesse.
Le code Javascript
// variables
var canvas, ctx, longueur, angle, compteur, ajouteAnneaux, victoire, vitesse, droite, gauche, snake, pomme, posx, posy, stockAnneaux, timer;
var W = 480;
var H = 480;
// charger les images du jeu
var snakeImg = new Image();
var head = new Image();
var pommeImg = new Image();
var fond = new Image();
fond.src = "assets/fond.jpg";
pommeImg.src = "assets/pomme.png";
head.src = "assets/head.png";
snakeImg.src = "assets/anneau.png";
// préparation du jeu
window.onload = function() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
canvas.width = W;
canvas.height = H;
init();
}
// initialisation du jeu
function init() {
snake = {};
pomme = {};
posx = [];
posy = [];
stockAnneaux = [];
longueur = 5;
angle = 0;
compteur = 0;
ajouteAnneaux = 4;
victoire = 140;
vitesse = 10;
droite = 0;
gauche = 0;
for (var i=0; i<longueur; i++) {
stockAnneaux.push({x:0,y:0,width:snakeImg.width,height:snakeImg.height})
}
snake.x = W*.5;
snake.y = H*.5;
snake.width = head.width;
snake.height = head.height;
pomme.x = 30+Math.random()*(W-60);
pomme.y = 30+Math.random()*(H-60);
pomme.width = pommeImg.width;
pomme.height = pommeImg.height;
canvas.setAttribute('tabindex','1');
canvas.focus();
timer = setInterval(main,60);
canvas.addEventListener("keydown", appuie, false);
canvas.addEventListener("keyup", relache, false);
}
// gestion clavier
function appuie(e){
if (e.keyCode == 39) droite = 1;
if (e.keyCode == 37) gauche = 1;
}
// gestion clavier
function relache(e){
if (e.keyCode == 39) droite = 0;
if (e.keyCode == 37) gauche = 0;
}
// boucle principale
function main(){
var i;
var j;
// Direction
angle += (parseInt(droite)-parseInt(gauche))*20;
// Enregistre la position de la tête
posx[0] = snake.x;
posy[0] = snake.y
// Deplace la tête
snake.x += Math.cos(angle*Math.PI/180)*vitesse;
snake.y += Math.sin(angle*Math.PI/180)*vitesse;
// Envoye le dernier anneau en premier
var dernier = longueur-1-compteur++;
if (dernier == 0) compteur = 0;
stockAnneaux[dernier].x = posx[0];
stockAnneaux[dernier].y = posy[0];
// Déplace les anneaux
for (i=longueur-1; i>0; i--) {
posx[i] = posx[i-1];
posy[i] = posy[i-1];
}
// si la tête touche de la nourriture
if (collisions(snake,pomme)) {
// ajoute des anneaux
for (i=0; i<ajouteAnneaux; i++) {
posx[longueur] = posx[longueur-1];
posy[longueur] = posy[longueur-1];
longueur++;
stockAnneaux.push({x:0,y:0,width:snakeImg.width,height:snakeImg.height});
}
// place la pomme ailleurs
pomme.x = 30+Math.random()*(W-60);
pomme.y = 30+Math.random()*(H-60);
// Repositionne le Snake complet (assure la cohésion)
for (i=0; i<longueur; i++) {
stockAnneaux[i].x = posx[i];
stockAnneaux[i].y = posy[i];
}
compteur = 0;
}
// Vérifie si la tête touche un bord
if (snake.x<0 || snake.x>W || snake.y<0 || snake.y>H) finPartie();
// Vérifie si la tête touche un anneau
var point = {x:snake.x+Math.cos(angle*Math.PI/180)*4, y:snake.y+Math.sin(angle*Math.PI/180)*4, width:1, height:1};
for (i =0; i<stockAnneaux.length; i++){
if(collisions(point,stockAnneaux[i])) finPartie();
}
// vérifie si le joueur gagne
if (longueur>=victoire) gagnePartie();
// dessin final
render();
}
// collisions
function collisions(A,B) {
if (A.y+A.height < B.y || A.y > B.y+B.height || A.x > B.x+B.width || A.x+A.width < B.x) return false;
return true;
}
function finPartie(){
alert("Perdu, cliquez pour rejouer.");
clearInterval(timer);
init();
}
function gagnePartie(){
alert("Bravo, cliquez pour rejouer.");
clearInterval(timer);
init();
}
// Dessine le jeu
function render() {
ctx.drawImage(fond,0,0);
ctx.save();
ctx.translate(snake.x + snake.width / 4, snake.y + snake.height / 2);
ctx.rotate(angle*Math.PI/180);
ctx.drawImage(head,-snake.width/4,-snake.height/2);
ctx.translate(-(snake.x + snake.width / 4), -(snake.y + snake.height / 2));
ctx.restore();
for(var i =0; i<stockAnneaux.length;i++){
ctx.drawImage(snakeImg,posx[i],posy[i]);
}
ctx.drawImage(pommeImg,pomme.x,pomme.y);
}
A retenir
L’autre petite chose utile ici c’est la trigonométrie. Pour ceux qui n’en auraient aucune notion, on joue avec des angles et on utilise le sinus et le cosinus de l’angle pour déterminer une direction sur les deux axes (x et y). Il suffit ensuite de multiplier cette direction sur chaque axe par une vitesse donnée et l’objet avance. Attention, dans la plupart des langages de programmation les angles sont exprimés en radians, il nous faut donc opérer une conversion entre les degrés et les radians pour faire nos calculs.
Enfin, dernière petite astuce concernant les graphismes, chaque objet possède un point d’origine ou de pivot, c’est lui qu’on utilise pour placer l’objet, or ce point est la plupart du temps le point situé aux coordonnées 0,0 de l’objet soit son point haut gauche. Afin d’afficher correctement nos objets à l’écran il va nous falloir appliquer une petite correction pour replacer virtuellement ce point au centre de l’objet avant de l’afficher.











test de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lontest de blabla un peu lon
oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla oui ok bla bla