Forums Développement Multimédia

Aller au contenu

Exercice 02 - Taquin en javascript

jeux video javascript

10 réponses à ce sujet

#1 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 27 July 2015 - 22:26 PM

Bonjour tout le monde :)

C'est parti pour le deuxième exercice, cette fois c'est le TAQUIN et ça se passe par ici :

Image attachée: taquin.jpg

Le tuto Javascript : http://forums.mediab...exercice_taquin
Le tuto Actionscript : http://forums.mediab...ice_-_le_taquin

Bonne lecture et comme d'hab, n'hésitez pas à me faire part de vos remarques, questions, conseils,...

#2 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 01 October 2015 - 13:39 PM

Un petit coucou en passant…


J'ai d'abord bien avancé sur le pong, mais je ne l'ai pas fini (manque le mouvement de la balle pendant l'entre-jeu)… surtout par manque d'intérêt au pong en lui même. Je suis en effet assez rapidement venu tâter du taquin qui m'intéressait bien plus et je me suis ensuite retrouvé piégé.
J'ai pas mal galéré, recommencé 4 fois avant d'arriver à un résultat presque satisfaisant.

Voici donc ma version, évolution du tuto de Mr Spi : http://ftp.i10.fr/_a..._didier/taquin/
(testée uniquement sous Safari et Firefox)


Fonctionnalités ajoutées :
– Choix du nombre de tuiles
– Choix de l'image (parmi une sélection)
– Rendu en relief à la volée (pour la facilité d'ajouter des photos sans les retoucher)
– Possibilité de déplacer plusieurs tuiles d'un coup
– Disparition du relief lors de la résolution du taquin
– Possibilité de rejouer

Ça n'a vraiment pas été simple.
Je mesure maintenant que je suis certainement capable de faire pas mal de choses mais :
– ma productivité en souffre beaucoup. Même si ça ne peut que s'améliorer, je vois mal comment arriver au même niveau qu'en AS3 avec les briques à ma disposition.
– je trouve le code très dur à relire, difficile à synthétiser. Rien que l'accès aux objets, fonctions et variables quand on travaille dans l'esprit Classes, c'est l'horreur. Du coup, j'utilise beaucoup de variables à 1 ou 2 lettres, ça allège mais pour la relecture plus tard, c'est coton. Bref, je me cherche encore sur la façon de composer le code, de trouver des alignements qui donnent du sens. Peut-être que ça viendra…
– Il me manque ENORMEMENT de fonctions, que ce soit de dessin, de cadrage des Bitmap, de modes de fondu, d'optimisation du rendu graphique. Là, c'est simple : rien n'est optimisé, je redessine la totalité du jeu à chaque frame événement, c'est brutal. Et là, je ne vois pas vraiment de progression possible, à part déléguer le problème à une librairie externe, mais bon, je suis accro au 'from scratch' :-/

Sinon, si le code vous intéresse : j'ai un peu poussé sur ce tuto l'exploitation des images façon découpage en 'sprite', bien sûr pour l'image sur le taquin mais également pour construire le relief, les ombres et le cadre du taquin lui même.
J'ai construit ça autour d'une pseudo liste d'affichage simplifiée, façon AS3 (c'est pour l'instant très limité, mais je vais peut-être y bosser un peu). Vous trouverez donc des codes pour encadrer des zones de tailles différentes à partir d'un seul et unique fichier image contenant les coins du cadre.

Pour la version de Monsieur Spi, elle à le mérite d'aller droit au but, ce qui permet de ne pas s'y perdre (à part sur l'algorithme du mélange des pièces, voir note en bas de page) et, comme pour le pong, ça donne toutes latitudes pour y ajouter des fonctionnalités et mettre rapidement la main à la pâte.
Encore merci, Monsieur…


NB : pour l'algo du mélange du tuto, je crois qu'il ne marche pas. Et j'ai eu beau chercher à le comprendre, je n'ai pas réussi complètement. Il se pourrait que la faisabilité soit rompue quand tu relances un cycle si tu trouves une des pièces non mélangée.
J'ai eu moins de souci, parce que j'ai implémanté le déplacement de plusieurs tuiles à la fois. Du coup, dans mon algo de mélange, je peux tirer une position aléatoire (x,y) et m'y rendre à partir de la tuile vide (i,j) en jouant 2 coups : la tuile (x,j) puis la tuile(x,y). Ça fonctionne également en passant par (i,y), on a le choix. Pour mélanger plus, on tire plus de positions aléatoires… J'ai aussi forcé le mouvement vers les coins pour assurer un meilleur mélange.
Voilà.

Code source dispo pour ceux qui veulent : Fichier joint  taquin.zip   931.56 Ko   133 téléchargement(s)

#3 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 01 October 2015 - 17:00 PM

Hello Didier,

Merci pour tes retours ;)
Jolies évolutions, chapeau.

Pour ce qui est de la productivité et des outils à dispo, pour les prochains je vais essayer de commencer à passer par des libs et des frameworks qui vont simplifier un peu et ajouter pas mal d'outils, je pense notamment à EaselJS ou CreateJs qui se rapprochent beaucoup de l'AS avec cette fois une liste d'affichage, un stage, des classes et des objets, bref ça comble beaucoup de choses que nous avions pris l'habitude d'utiliser mais qui ne sont pas foutues pareil en JS.

Pour l'algo du mélange, je vais voir pour essayer d'être plus clair, j'avoue que c'est un peu tordu mais ça m'a toujours donné de bons résultats, mais si ça se trouve tu as raison et ça ne fais pas ce que je pense que ça fait, je vais me relire un peu ce soir et je t'en dirais plus.


[EDIT] > je viens de me relire pour l'algo, voici grossièrement comment ça fonctionne (faut que je relise plus attentivement) :

Fais une première boucle sur toutes les pièces pour trouver la pièce vide, on l'enregistre.
Refais une boucle sur toutes les pièces
----Vérifie si la pièce en cours n'est pas la pièce vide et que la pièce en cours a sa propriété "depart" encore vierge
----Tire une direction aléatoire (parmi 4)
----Vérifie si le déplacement est possible, si c'est le cas déplace la pièce (et note la comme déplacée "depart")
Refais une boucle sur toutes les pièces
----Vérifie si tu trouve une pièce dont la propriété "depart" est encore vierge (=pièce non mélangée)
----Si c'est le cas sort de la fonction (qui sera relancée au prochain cycle du timer)
Sinon arrête de mélanger (stoppe le timer)

Voilà en gros comment ça marche, le but étant de mélanger toutes les pièces, donc de boucler jusqu'à ce que l'on soit passé par toutes les pièces. La condition de sortie se fait sur le "return", alors que l'arrêt du mélange se fait par l'arrêt du timer si tout a été mélangé.

#4 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 02 October 2015 - 10:01 AM

OK.
Dans la théorie, ça devrait fonctionner, même si l'algo est un peu lourd.
Dans la pratique, ça à l'air de marcher sur la version Flash, testée 5 fois.
Sur la version Javascript, une fois sur deux le taquin ne peut pas être résolu…

#5 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 02 October 2015 - 17:25 PM

Ha ?
Bon je m'y recolle ce weekend pour vérifier ça, l'algo me semble bon pourtant, sans doute une erreur de ma part lors de la conversion.
Tu verrais quoi comme algo plus light pour le mélange ?

#6 dcz.switcher

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 2533 messages

Posté 03 October 2015 - 09:47 AM

Salut à tous,

Même si je suis plutôt discret et c'est peu de le dire, je viens régulièrement faire un tour.

Pour le code, pourquoi ne pas passer à l'ES6 ? c'est très proche de la syntaxe as3 et avec typescript, vous pouvez même le rendre compatible ES4 et donc avec les navigateurs actuels
http://www.typescriptlang.org/

Sinon, je découvre depuis hier Unity et leur implémentation de javascript pour le script est vraiment proche de l'as3 et ES6 ... que du bon !
"Ce que l'on conçoit bien s'énonce clairement et les mots pour le dire arrivent aisément"

embryon de site

#7 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 03 October 2015 - 10:06 AM

Coucou dcz.switcher,

Je compte utiliser les exercices pour tester divers frameworks, donc oui je pense qu'il sera possible de tester Typescript.
Pour le prochain je fais le test avec EaselJS

#8 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 05 October 2015 - 15:52 PM

Hello.
Un peu tard, désolé…

Pour l'algo, j'y vois plusieurs lourdeurs qui me semblent travailler pour rien. En même temps, je suis d'accord qu'on n'est pas sur du code nécessitant une optimisation pointue, c'est plus par coquetterie :

1
- tire une direction aléatoire -> vérification si la direction est possible -> si elle ne l'est pas, on recommence tout un cycle (pour rien). Au pire, tirer une autre direction éviterait de relancer un cycle pour rien, non ?

2
- déplacement de la tuile vide == échange avec une tuile. Si cette dernière avait déjà été mélangée, il y a aura toujours au moins une pièce non mélangée, donc on vérifie pour rien… Par contre, je n'ai pas d'idée comme ça pour optimiser le principe.

3
- quand il n'y a plus qu'une tuile non mélangée, elle peut-être très loin de la tuile vide et on a sans doute un nombre important de tirages aléatoires (en théorie ça pourrait être infini) avant de passer par une configuration ou la tuile vide est ) côté de cette dernière tuile, et là, pas de chance, ou peut encore tirer une autre direction (1 chance sur 4)…

L'algo qui me semble le plus 'light' devrait être du genre :
- ranger toutes les tuiles dans un autre tableau que celui à mélanger
- mélanger ce tableau
- pour chaque tuile (t) du tableau :
---- déplacer la tuile vide (tv) verticalement jusqu'à ce que tv.ligne == t.ligne (*)
---- déplacer la tuile vide (tv) horizontalement jusqu'à ce que tv.colonne == t.colonne(*)
Tu sais que tu auras un nombre de mouvements maximum de ( (C + L - 2 ) * (C * L - 1).
Ou C et L sont le nombre de lignes et de colonnes.

J'étais parti pour cet algo (un peu modifié puisque je peut bouger des groupes de tuiles) et je n'ai pas réussi (du coup, je me suis contenté d'un tirage aléatoire de positions, mais je vais peut être me le retenter). Ceci pour dire que je ne garantie pas la qualité du mélange obtenu vu que je n'ai pas vu l'algo à l'oeuvre, mais je pense que ça devrait le faire. (**)

Pour comparaison, ça serait pas mal que tu mette un compteur sur ta boucle timer avant et après pour qu'on voit la différence ?

(*) La seule difficulté, c'est de vérifier s'il faut augmenter ou diminuer la valeur de tv.colonne et de tv.ligne. Dans mon code, j'ai géré ça en prenant le temps de calculer un pas. C'est pas très simple (c'est un peu pour ça que je te conseille de gérer d'abord verticalement car dans ce cas, la position (id) dans le tableau est supérieur ou inférieur te donne le sens. Une fois qu'on est sur la même ligne, on peut faire la même chose pour la position horizontale, sinon, danger)

(**) En fait, même pas trop mélangé, un taquin reste dur à faire si on ne retrouve pas le chemin à l'identique. C'est un peu comme un Rubick's Cube pas trop mélangé : on fini de mélanger soi même en plaçant les premières îèces ;-)

#9 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 05 October 2015 - 16:13 PM

Up

Je viens de tester (c'est plus facile maintenant que le reste du code est propre).

En fait, ça ne mélange pas beaucoup. Pour améliorer le mélange, j'ai été obligé de stocker (L * C) fois chaque position, ce qui donne (C + L - 2 ) * (C * L - 1) * L * C mouvements :D. Ça m'intéresse vraiment de voir si c'est beaucoup plus efficace que ta méthode… ou pas du tout.

#10 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 05 October 2015 - 16:39 PM

Coucou,

Citation

1
- tire une direction aléatoire -> vérification si la direction est possible -> si elle ne l'est pas, on recommence tout un cycle (pour rien). Au pire, tirer une autre direction éviterait de relancer un cycle pour rien, non ?

Pas faux, sauf si aucune direction n'est possible.
Vu qu'on tire les pièces par ordre du tableau en fait on peut se retrouver avec des pièces qui ne bougent pas.
Pour optimiser il faudrait en fait tirer les 4 pièces voisines de la pièce vide et en choisir une.

Citation

2
- déplacement de la tuile vide == échange avec une tuile. Si cette dernière avait déjà été mélangée, il y a aura toujours au moins une pièce non mélangée, donc on vérifie pour rien… Par contre, je n'ai pas d'idée comme ça pour optimiser le principe.

Pas tout à fait d'accord là dessus, vu qu'on mélange tant que toutes les tuiles n'ont pas été mélangées, la pièce non mélangée ne le sera donc plus lorsqu'on commence la partie.

Citation

3
- quand il n'y a plus qu'une tuile non mélangée, elle peut-être très loin de la tuile vide et on a sans doute un nombre important de tirages aléatoires (en théorie ça pourrait être infini) avant de passer par une configuration ou la tuile vide est ) côté de cette dernière tuile, et là, pas de chance, ou peut encore tirer une autre direction (1 chance sur 4)…

Là par contre je suis tout à fait d'accord, c'est vrai que du coup le mélange peut durer un sacré moment, surtout si on a beaucoup de pièces, il faudrait utiliser un pathfinding pour faire remonter la pièce vide près de la dernière pièce à mélanger (tout en continuant de suivre un chemin de mélange). D'ailleurs ça devrait même être applicable dès qu'on a moins de 3 pièces.

Citation

Pour comparaison, ça serait pas mal que tu mette un compteur sur ta boucle timer avant et après pour qu'on voit la différence ?

Oui je vais monter ça, une petite boucle de tests ;)

Je suis en train d'écrire le Memory en parallèle, j'aimerai bien me débarrasser des petits jeux avant de pouvoir attaquer les plus gros avec EaselJS.

#11 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 05 October 2015 - 17:01 PM

2
On est d'accord je crois (vu que tu es d'accord avec le 3), c'est juste que je ne le dis pas bien.

Si je reprends l'algo :
- recherche s'il y a une pièce non mélangée -> On trouve la pièce A
- choix aléa d'une direction autour de la case vide -> Tombe sur la pièce B, qui est déjà une pièce mélangée (ou pas, mais dans mon exemple, oui) (en fait, ça n'a pas d'importance)
- on permute la pièce vide et la pièce B
- fin de la fonction de rappel
Au nouveau cycle :
- recherche s'il y a une pièce non mélangée -> On trouvera encore la pièce A puisque le nombre de pièces mélangées n'a pas changé
C'est cette dernière ligne qui, pour moi, est de l'ordre du travail inutile. Peut être qu'en ayant un compteur de pièces mélangées, ça srait mieux non ?

Début du mélange :
var nombre_pieces_non_melangées = C * L -1:

Le cycle :
Si nombre_pieces_non_melangées > 0 : choix aléa d'une pièce ( B ) autour de la case vide
Si B n'était pas mélangée : B est mélangée et nombre_pieces_non_melangées -= 1;

Ça évite de re-parcourrir le tableau inutilement, je crois.



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)