air-hockey « myDrix
RSS
 

Articles associés au tag ‘air-hockey’

Air Hockey en JS – l’adversaire

10 fév

Après l’ajout du terrain, voici l’ajout de l’adversaire, ainsi que du serveur servant à synchroniser les données entre les deux clients (joueurs).

L’adversaire est un joueur comme le joueur principale, mais il est piloté par une autre source (pas les événements de la souris (ou tactile), mais il s’affiche de la même façon. Je réutilise donc la même classe.
Le serveur va nous servir à transmettre les informations du jeu, d’un joueur à un autre. Ayant commencé à faire mon code en JavaScript, et avec l’arrivé de node.js (depuis quelque temps), je voulais l’essayer, surtout avec le module Socket.io, qui répond tout à fait au besoin présent.

Je ne présenterais pas node.js, ni socket.io, tellement il y a des exemples, tutoriels, … et qu’il est facile de la trouver sur l’Internet en cherchant sur Google.

J’ai écrit un serveur assez simple qui lorsqu’il reçoit des informations d’un joueur les retransmets au second joueur :

var io = require('socket.io').listen(8080);
 
// une partie
function jeu() {
	this.joueur1 = null;
	this.joueur2 = null;
}
 
jeu.prototype.isReady = function() {
	return this.joueur1 !== null && this.joueur2 !== null;
}
 
// le serveur gere plusieurs partie de air hockey
var jeuList = new Array();
 
// tentative d'association de joeur entre eux pour faire une partie
function association(socket) {
	var currentJeux = null;
	for(var i=0;i<jeuList.length;i++) {
		if(!jeuList[i].isReady()) {
			currentJeux = jeuList[i];
		}
	}
 
	if(currentJeux == null) {
		jeuList.push(new jeu());
		currentJeux = jeuList[jeuList.length-1];
	}
 
	if(currentJeux.joueur1 === null){
		currentJeux.joueur1 = socket;
	} else if(currentJeux.joueur2 === null){
		currentJeux.joueur2 = socket;
	}
}
 
// déroulement d'une partie
function eventJeu(currentJeux) {
	currentJeux.joueur1.emit('debutJeu');
	currentJeux.joueur2.emit('debutJeu');
	currentJeux.joueur1.on('Bouge', function(data) {
		currentJeux.joueur2.emit('BougerSeul', data);
	});
	currentJeux.joueur2.on('Bouge', function(data) {
		currentJeux.joueur1.emit('BougerSeul', data);
	});
	currentJeux.joueur1.on('PaletChange', function(data) {
		currentJeux.joueur2.emit('ChangerPalet', data);
	});
	currentJeux.joueur2.on('PaletChange', function(data) {
		currentJeux.joueur1.emit('ChangerPalet', data);
	});
	currentJeux.joueur1.on('disconnect', function() {
		currentJeux.joueur1 = null;
		currentJeux.joueur2.emit('departAdversaire');
	});
	currentJeux.joueur2.on('disconnect', function() {
		currentJeux.joueur2 = null;
		currentJeux.joueur1.emit('departAdversaire');
	});
}
 
function connection(socket){
	association(socket);
	if(jeuList.length > 0 && jeuList[jeuList.length-1].isReady()) {
		eventJeu(jeuList[jeuList.length-1]);
	}
}
 
function deconnection(socket) {
	var deleteIndex = -1;
	for(var i=0;i<jeuList.length;i++) {
		if(jeuList[i].joueur1 === socket) {
			jeuList[i].joueur1 = null;
			jeuList[i].joueur2.emit("departAdversaire");
		}
 
		if(jeuList[i].joueur2 === socket) {
			jeuList[i].joueur2 = null;
			jeuList[i].joueur1.emit("departAdversaire");
		}
 
		if(jeuList[i].joueur1 === null && jeuList[i].joueur2 === null) {
			deleteIndex = i;
		}
	}
	if(deleteIndex > -1)
		jeuList.splice(deleteIndex, 1);
}
 
io.sockets.on('connection', function(socket) {
	connection(socket);
});

Les informations sont les déplacements du joueur, du palet, … c’est tout pour l’instant … mais il pourrait devrait y avoir le score aussi.
La petite subtilité c’est de géré une liste de parties, quand un joueur ce connecte, il est placé dans un partie, le joueur suivant sera dans la même partie. Le troisième joueur commencera une nouvelle partie et attendras une nouvelle connexion

Voici le code du client qui reçoit les événements du serveur :

    socket = io.connect('http://localhost:8080');
    socket.on('debutJeu', function(data) {
	    alert('Debut de la partie!');
    });
    socket.on('BougerSeul', function(data) {
	    adversaire.bougerSeul(data.x, data.y);
    });
    socket.on('ChangerPalet', function(data) {
    	  var newAngle = Math.atan2(data.vy, data.vx);
	  newAngle = 2 * Math.PI - newAngle;
	  ballon.bougera(newAngle, data.force, true);
    });
    socket.on('departAdversaire', function() {
	    alert('votre adversaire est parti');
    });

Cela ne fonctionne pas trop mal pour la synchronisation des joueurs, j’ai du faire quelque adaptations car j’ai considérais que le joueur jouant était forcement en bas. Il à fallu faire un changement sur les coordonnées.

// pour le retour du serveur: affichage en miroir. 
poussoir.prototype.bougerSeul = function(x, y) {
	this.x = env.width - x;
	this.y = env.height - y;
}

Le résultat est testable ici : V3 d’un air-hockey en javascript.
J’ai un peu plus de problème sur le palet, d’un part pour le bon calcul de son angle, et surtout pour la synchro de la direction du palet. Le calcul des collisions se fait sur les deux clients et est synchroniser avec l’autre client à chaque changement de direction du palet (collision). Mais chaque client à son propre timer, qui n’est pas synchroniser. Donc entre un décalage du calcul de collisions et un mauvais report des angles de direction du palet : il fait un peu n’importe quoi.

La correction de ce problème sera une prochaine étape. Ces calculs de trajectoire et mise à jour de la position du palet se sera faite sur le serveur qui emmétra des indications aux clients lors de changement. Et les clients s’occuperont uniquement de l’affichage et de l’input des data de la capture des déplacements du joueur. Mais ceci sera pour la prochaine fois.

Ps : si quelqu’un à envie de rendre le jeu plus jolie, qu’il n’hésite à allez voir sur les sources sur github. De même que toute amélioration technique ou pour consultation

 
2 commentaires

Classé dans code

 

Air Hockey en JS – le terrain

20 jan

Un petit avancement de la V1 mon air hockey, mais qui prend quand même le nom de V2 :p
Un petit avancement car c’est juste un peu de design et quelque légère modification.

Alors les nouveautés :
– Le tour du terrain et la matérialisation des buts. Pour ça j’ai utilise une seconde balise canvas qui est superposé à la première (en dessous de la première) comme ça ce n’est pas nécessaire de redessiner à chaque fois le terrain.terrain air hockey
– Nouveauté pas visuel du tout, le découpage du javascript en plusieurs fichiers, uniquement pour pouvoir le parcourir plus facilement. J’ai essayer de le répartir par fonctionnalité ou classe selon les cas.

– Autre nouveautés c’est les quelque apports pour l’affichage sur mobile par l’utilisation des évènements des écrans tactiles qui exécutent les même fonctions que les évènements de la souris

    document.onmousedown = onStart;
    document.onmouseup = onEnd;
    document.onmousemove = onMove;
 
    document.ontouchstart = onStart;
    document.ontouchend = onEnd;
    document.ontouchmove = onMove;

Il y a aussi un essai d’affichage correct selon la taille de l’écran grâce aux méta du fichier html, mais le résultat n’est pas exploitable, il faudra trouver quelque chose de mieux

<meta name="viewport" content="height=device-height, initial-scale=2.0, user-scalable=yes" >

Sinon j’ai fait quelque petites corrections sur la gestion des collisions.

Autre changement pour la gestion de code cette fois-ci, je l’ai donc mis à disposition sur github sousle doux nom de JSAirHockey. Si le coeur, ou l’envie vous en dis, n’hésitez pas à apporter des modifications, améliorations.

Pour les prochaines fois, ce sera l’ajout d’un adversaire, et/ou la communication avec un serveur node.js

 
1 commentaire

Classé dans code

 

Air hockey en html5 & javascript

03 jan

Aujourd’hui j’essai HeTeMeLe5, enfin j’essai la balise canvas. Oui celle qui permet de faire du dessin (et donc de l’animation) avec du javascript. Du coup j’essai JavaScript, et fait, je le découvre un peu plus réellement, car le JavaScript ce n’est pas vraiment nouveau. Mais jusque là j’en ai une utilisation assez minimaliste, ce qui se traduit par l’utilisation de jquery et quelques plugins pour quelques effets visuels ou appels Ajax.

L’idée c’est aussi de voir ce qu’on peut faire comme code (notamment orienté objet) avec JavaScript.

Dans mon idée écrire du code juste pour essayer c’est un premier pas, essayer de faire un projet (même tout p’tit) ça me parait mieux. L’idée est donc la réalisation d’un jeu de air hockey, si possible où l’on puisse jouer à deux (comme en vrai :p).

Pour faire communiquer mes deux clients (joueurs) il me faudra un serveur. Comme on entend beaucoup parler de node.js en ce moment, on essaiera de faire un serveur avec node.js, ce qui aussi fournira une solution homogène et très certainement nous poussera un peu plus dans JavaScript.

En route pour le 1er jet :
Ça nous donne une vue de haut du plateau (qui n’est pas encore dessiné) avec un rond bleu (frappeur) représentant le joueur et un petit rond rouge représentant le palet. Il est possible de frapper le palet en sélectionnant le rond bleu avec la souris.

Pour l’instant c’est du JavaScript tout simple : une structure de code pour dessiner dans la balise canvas, et le mettre à jour régulièrement

function timeout() {
  draw();
  update();
  if (stopped == false) {
    setTimeout('timeout()', 30);
  }
}

Quelque bout de code pour l’interaction avec la souris. Et voila le tour est jouer, enfin on a un début.

  document.onmousedown = function(event) {....}
 
  document.onmouseup = function(event) {....}
 
  document.onmousemove = function(event) {....}

Le plus compliquer c’est se rappeler les cours de math, voir les fonctions draw() et update() dans le code.Surement qu’un Framework m’aurait un peu aidé…

Après un premier test, ça ne fonctionne pas sur tactile. Ah mais oui, il y a aussi des événements pour le tactile :p

La suite dans un prochain épisode.

 
2 commentaires

Classé dans code