Page 1 sur 1

Gestion de la visibilité sur un plateau hexadécimal

Posté : 12 juin 2005, 22:55
par naholyr
Salut,

Je tente de développer un algo pour gérer la visibilité sur un plateau héxadécimal. Dans un premier temps déjà, je code le plateau hexa comme un plateau carré classique, en décalant une colonne sur deux.

Pour déterminer si un obstacle se trouve entre deux cases je procède comme suit :

Code : Tout sélectionner

D = droite passant par les centres des deux cases. Si D coupe un des 4 côtés de l'obstacle: -> Oui Sinon: -> Non Fin.
Ainsi pour savoir si une case Y est visible depuis une case X :

Code : Tout sélectionner

Pour chaque case C de la zone carrée définie par [X,Y]: Si C est un obstacle: Si C est entre X et Y: -> Oui Fin. Fin. Fin. -> Non
Et comme ça je calcule la visibilité. J'ai codé le tout en Javascript avant de le porter en Php, donc pour le moment mon problème traite de JS.

Démo ici : http://naholyr.free.fr/XHR/map.html
L'obstacle en (6,5) est non déplaçable.
Pour déplacer le "personnage" il suffit de cliquer sur une case.

Globalement ça marche, mais j'ai quelques bugs:
- si on place le personnage en (5,1) ou en (7,1) il y a une case visible en plein milieu de la zone cachée.
- si on place le personnage en (4,1) ça passe à deux cases.
- plus étrange encore, si on le place en (8,1) ça se passe normalement, alors que la symétrie devrait provoquer le même problème en (4,1) qu'en (8,1).

Tout le code JS est dans la source de la page (layerAccess.js n'est pas en cause), c'est développé en objet, donc relativement lisible, mais j'ajouterai les commentaires que je n'ai pas encore mis si ça peut aider.

Si quelqu'un a un début d'idée sur la provenance de ces bugs étranges, je suis preneur :)

Posté : 12 juin 2005, 23:02
par albat
J'ai aussi remarqué que (5,6) et (5,7) fonctionnent bien tandis que (7,6) et (7,7) omettent (4,1).
(7,7) omet également (2,1), me semble-t-il...

Posté : 12 juin 2005, 23:11
par naholyr
(7,7) omet également (2,1), me semble-t-il...
Pour celui-là ce n'est pas évident de savoir si c'est normal ou non, donc j'ignore pour l'instant.

Tu penses que ça pourrait venir d'erreurs d'arrondis ?

Posté : 12 juin 2005, 23:16
par albat
Je ne suis pas rentré dans le détail de ton code, mais je trouve ce sujet très intéressant.
Dès que j'aurai un p'tit moment cette semaine, je jetterai un oeil à ton algorithme. Promis !
Histoire de voir s'il me reste quelque chose de mon DEUG de maths... :langue:

Posté : 12 juin 2005, 23:17
par naholyr
Histoire de voir s'il me reste quelque chose de mon DEUG de maths... :langue:
Ben j'ai fait 3 classes : Point, Droite, Segment. Avec des méthodes contient(), appartient(), intersection(). Normalement c'est niveau première hein :langue:
Je me demande si cela peut venir d'erreurs d'arrondis (2/3 qui devient 0.66666666 par ex.)... Je vais tenter de faire une version avec une classe "Fraction", mais là ça va devenir lourd :?

Posté : 12 juin 2005, 23:31
par naholyr
C'est confirmé : problème d'arrondi !
Pour le cas du perso en (5,1) et de la case (7,8 ) visible en pleine zone d'ombre :
visible([7,8], [5,1]) ?
surLaDroite(5,4,y=3.5x+-737.5)
pos=[250,200]
s = y=200
((y=200)<[250,200];[300,200]>)x(y=3.5x+-737.5) = [object Object]
((y=200)<[250,200];[300,200]>) contient [267.85714285714283,199.9999999999999] ?NON!
s = x=300
((x=300)<[300,200];[300,250]>)x(y=3.5x+-737.5) = [object Object]
((x=300)<[300,200];[300,250]>) contient [300,312.5] ?Peut-être...NON!
s = y=250
((y=250)<[300,250];[250,250]>)x(y=3.5x+-737.5) = [object Object]
((y=250)<[300,250];[250,250]>) contient [282.14285714285717,250.0000000000001] ?NON!
s = x=250
((x=250)<[250,250];[250,200]>)x(y=3.5x+-737.5) = [object Object]
((x=250)<[250,250];[250,200]>) contient [250,137.5] ?Peut-être...NON!
-> False
Si je traduis la partie en rouge de mon message de debug, ça veut dire "Le segment défini par les points (250,200) et (300,200) (inclus dans la droite y=200) contient-il le point (267.85714285714283,199.99999999999999) ?". Forcément non, puisque 199.9999999999999 n'est pas égal à 200 :evil: :evil: :evil:
(quelques lignes plus bas on a le même, version 250 < 250.0000000000000001)

Je suis bon pour recoder le tout avec une classe fraction :cry:

Posté : 12 juin 2005, 23:33
par albat
(7,7) omet également (2,1), me semble-t-il...
Pour celui-là ce n'est pas évident de savoir si c'est normal ou non, donc j'ignore pour l'instant.
Tu as raison. (2,1) n'a pas à être sélectionné pour (7,7).
Tout comme (10,1) ne l'est pas pour (5,7).

Mais (1,10) doit-il l'être pour (7,2) ? :?:

Posté : 12 juin 2005, 23:35
par albat
C'est confirmé : problème d'arrondi !
(...)
Je suis bon pour recoder le tout avec une classe fraction :cry:
Les problèmes de calcul en virgule flottante sont un grand classique
des langages de programmation.
PHP n'échappe pas à la règle. :cry:

Ne peux-tu pas arrondir tes résultats après chaque calcul ?
Certes, ce n'est pas élégant mais ça t'évitera peut-être de tout refaire... ;)

Posté : 12 juin 2005, 23:36
par naholyr
Mais (1,10) doit-il l'être pour (7,2) ? :?:
ça se joue à un poil de fion (pour être poli). Si tu prends une règle, tu vois que le segment défini par les centres des cases (1,10) et (7,2) passe par le coin topleft de l'obstacle.

Je paufinerai l'algo après pour qu'il soit un peu plus laxiste, surtout que c'est censé représenter un plateau hexadécimal, donc quand c'est juste un bout de coin comme ça qui bloque, en version hexa ce coin sera raboté, et ne devrait donc pas gêner.

Posté : 12 juin 2005, 23:49
par naholyr
Ne peux-tu pas arrondir tes résultats après chaque calcul ?
Certes, ce n'est pas élégant mais ça t'évitera peut-être de tout refaire... ;)
Difficile, quand j'ai une droite qui a pour formule y=34/67x+123/45 par exemple, il faut bien que je me trimballe la version exacte, car si j'arrondis une première fois c'est déjà mort pour la suite. J'aurais du y penser dès le début de toute façon ;)

Puis si j'arrondis, je me retrouverai tot ou tard avec les mêmes problèmes.

Dans le doute j'ai tenté les deux : en arrondissant au début (directement sur les attributs), c'est la cata :langue:
Par contre, si j'arrondis au dernier moment j'obtiens un bon résultat, mais je reste méfiant...

Voici la version avec arrondis : http://naholyr.free.fr/XHR/mapArrondi.html

Posté : 12 juin 2005, 23:55
par Cyrano
Je viens d'essayer : en (4,1), il y a carrément une tranchée dans la zone d'ombre : le relief ? ;)

Posté : 13 juin 2005, 10:07
par naholyr
Je viens d'essayer : en (4,1), il y a carrément une tranchée dans la zone d'ombre : le relief ? ;)
Faut lire tout le thread :P
Je mettrais bien un [Résolu] mais cette histoire d'arrondis ça m'embête un peu, j'aimerais être sûr que c'est bien une solution.

Posté : 14 juin 2005, 00:28
par naholyr
Bon c'est à peu près reglé. De façon empirique je vais admettre que le fait d'arrondir au dernier moment rend les calculs justes.

Après ajout du rabotage (j'ignore une partie des coins de l'obstacle qui sont visibles) j'obtiens quelque chose de plus réaliste : reste à fignoler le choix de la valeur de rabotage (pour le moment 20% de la largeur de l'obstacle).

http://naholyr.free.fr/XHR/mapArrondiRabot.html

et [Résolu]

Posté : 14 juin 2005, 10:22
par albat
Conserver les fractions, arrondir les résultats finaux (sinon les résultats intermédiaires)...
je peine à trouver une aute solution... :-k