JeuWeb - Crée ton jeu par navigateur
Algorithme d'ombre - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Algorithme d'ombre (/showthread.php?tid=3119)

Pages : 1 2


RE: Algorithme d'ombre - jo_link_noir - 16-10-2008

ah oui, désolé, une chose que j'avais pas pensé '^^

tu remplace le 2ème if du foreach par :
Code PHP :
<?php 
if($values[0] <= $angle AND $angle <= $values[1] AND $values[1] - $values[0] <= 180
OR ($values[0] >= $angle OR $angle >= $values[1]) AND $values[1] - $values[0] > 180) {
$cacher = true;
//case cacher, pas la peine de continuer à chercher
break;
}
je posterais plus tard -ou demain- quelques explications pour que tu comprennes mieux sont fonctionnement


RE: Algorithme d'ombre - phenix - 16-10-2008

Citation :je posterais plus tard -ou demain- quelques explications pour que tu comprennes mieux sont fonctionnement

Oui, sa m'aiderais grandement, j'aime pas spécialement prendre un truc et l'ajouté sans en comprendre un minimum le fonctionnement Wink


RE: Algorithme d'ombre - jo_link_noir - 17-10-2008

Fonction angle -> pour connaître en degrés la position de l'obstacle par rapport à l'origine, ça va de 0 à 360. Bon, pour ce qu'elle fait je pense pas qu'il y a de problème. Pas la peine non plus d'expliquer le code de la fonction, c'est de la trigo, j'ai eu du mal à la faire, alors si en plus j'explique ça va être horrible ^^

$c_obstacle pas de problème je pense. C'est sous la forme [x,y] => type
avec x et y les positions de l'obstacle et type, ce que tu veux, là on s'en sert pas.

Jx jy, les positions du joueur

jusque là, rien de bien compliquer, maintenant on va voir comment trouver ce que cache un obstacle.
Ce bout de code
Code PHP :
<?php 
/*calcule l'angle que cache un obstacle et ça distance par rapport au joueur.
rajoute dans $angle_obstacle sous la forme array(angle_min, angle_max, distance)*/
foreach($c_obstacle as $coord=>$type){
list(
$x,$y) = explode(",", $coord);
$x -= $jx;
$y -= $jy;
/*definit l'angle de chaque coin de la case
(0.5 => l'obstacle prend toute la case la diffence entre le centre et un bord est de 0.5;
0.45=> l'obstacle prend 90% de la case la case la diffence entre le centre et un bord est de 0.45)*/
$angle_coin = array(
angle($x+0.45, $y+0.45),
angle($x+0.45, $y-0.45),
angle($x-0.45, $y-0.45),
angle($x-0.45, $y+0.45)
);

//on selectionne l'angle min et max de l'obstacle,
//l'ombre se situe entre les 2 valeurs
$angle_obstacle[] = array(
min($angle_coin), //angle min
max($angle_coin), //angle max
sqrt($x*$x + $y*$y) //distance
);
}
Un foreach pour boucler sur tout les obstacles, ce qui permet au final de savoir l'angle qu'il cache

On récupère les coordonnées de l'obstacle et on leur enleve la position du joueur. Ca permet de simplifier les calcules en simulant le joueur en position 0,0.

[Image: cercle_trigo_u1224271543.gif]


Maintenant ce qui nous intéresse est l'angle que cache l'obstacle (en gris) :

[Image: exemple1_u1224271543.gif]

à vu de nez c'est entre 40 et 70 degrés. on va calculer l'angle de tous les coins pour sélectionner celui qui est le plus grand (angle_max) et le plus petit (angle_min). Tous ce qui sera entre, est dans l'ombre.

Les angles des 4 coins sont 40,45,45 et 70 degrés. Avec les fonctions min et max, on sélectionne bien angle_min (40) et angle_max (70).
On enregistre ces valeurs avec en plus la distance du joueur par rapport à l'obstacle. La distance permet de savoir quand un obstacle est dépasser, et donc qu'une case est peut-être dans l'ombre.

Je vais essayer d'expliquer un peu ces lignes (surtout les -/+ 0.45)
Code PHP :
<?php 
$angle_coin
= array(
angle($x+0.45, $y+0.45),
angle($x+0.45, $y-0.45),
angle($x-0.45, $y-0.45),
angle($x-0.45, $y+0.45)
);
Dans t'as carte pour ce déplacer d'une case à l'autre, on fait -1x, +1x, -1y ou +1y, on se retrouve alors au centre d'une autre case. Une case fait 100% de ça largeur (logique) soit 1, la différence entre un bord et le centre est le est de 50%, soit 0.5.
Et donc, pour calculer la position d'un coin par rapport au joueur, on ajoute -/+0.5 à la position de l'obstacle.
En mettant 0.5 toutes les cases qui sont cacher à moitié seront cacher. Pour moi, une case visible à moitié n'est pas vraiment cacher, alors j'ai diminuer ce chiffre, ce qui a également pour effet de diminuer l'angle que cache l'obstacle. Dans ce cas, toutes les cases visible à moins de 45% seront cacher donc 0.45.
Après tu peux imaginer qu'un arbre fait 2/3 (66%) de la case, ces 4 coins (quand on représente l'arbre par un carrer) seront décaler de 1/3 (33%) en x et y du centre. Son ombre est moins large qu'une tour qui prend la place de toutes la case.

la différence en mettant 50% (0.5) ou 45% (0.45)

[Image: cadrillage05_u1224271543.gif]
[Image: cadrillage045_u1224271543.gif]

Maintenant on passe à l'affichage, comment savoir si ma case est cacher
Code PHP :
<?php 
for($y=1;$y<=25;$y++){
for(
$x=1;$x<=25;$x++){
//variable qui définit si la case doit être cacher ou pas (true => cacher)
$cacher = false;

//regarde si la case est cacher par un obstacle
foreach($angle_obstacle as $values){
//zone d'ombre à porter (pas obligatoireent sur la case en traitetement)
if($values[2] < sqrt(pow($x-$jx, 2) + pow($y-$jy, 2))) {
$angle = angle($x-$jx,$y-$jy);
//verifie si la zone d'ombre est bien sur la case en cours de traitement
if($values[0] < $angle AND $angle < $values[1] AND $values[1] - $values[0] <= 180
OR ($values[0] > $angle OR $angle > $values[1]) AND $values[1] - $values[0] > 180) {
$cacher = true;
//case cacher, pas la peine de continuer à chercher une zone d'ombre
break;
}
}
}

//on affiche une jolie carte pleine de couleur :-°
if(isset($c_obstacle["$x,$y"]))
echo
'<span style="color:red">O </span>';
elseif(
true === $cacher)
echo
'<span style="color:black">A </span>';
elseif(
$jx == $x AND $jy == $y)
echo
'<span style="color:green">P </span>';
else
echo
'<span style="color:gray">C </span>';
}
echo
'<br />';
}

le problème c'est le foreach, comment ça fonctionne ?
Pour chaque case, on regarde si un obstacle est dépasser ou à portée (1er if). Dans ce cas peut-être qu'une case est cacher, on ne sais pas encore.
C'est là qu'appairait le second if. En gros si angle_min_obstacle < angle_case_vérifier (en prenant comme point, le milieu de la case cette fois) < angle_max_obstacle, alors la case est cacher. Ce qui veut dire, si le centre de ma case passe dans l'ombre d'un obstacle, on la cache.
«$values[0] < $angle AND $angle < $values[1]»

Le problème vient dans ce cas

[Image: exeption_u1224271543.gif]

L'angle min est 45, l'angle max, 315. Avec la première condition, on va cacher toute les cases orange, ce n'est pas bon, il nous faut les cases grisées. Pour ça il faut stopper la première partie du if, en disant, si l'angle cacher dépasse 180° on arrête. 180° correspond à une ligne, si ça dépasse 180, de l'ombre ce retrouve avant l'obstacle et ce n'est pas normal.
«AND $values[1] - $values[0] <=180»

Dans le cas contraire
«AND $values[1] - $values[0] > 180»

on fait angle_min > angle_case ou angle_case > angle_min
«OR ($values[0] > $angle OR $angle > $values[1])»

voilà, en espérant que ça d'aide


RE: Algorithme d'ombre - phenix - 18-10-2008

Oui, merci beaucoup, sa m'aide a comprendre un peu plus le fonctionnement. J'avais du mal a voir comment la trigo pouvait intervenir dans un tableau X/Y.


RE: Algorithme d'ombre - zeppelin - 18-10-2008

franchement un gros applaudissement de ma part pour j-12, c'est limite un tuto que tu nous a pondu la :-p

grand merci pour tant d'engagement, même si je n'utilise pas de cartes sur mon jeu, ton boulot reste remarquable! ;-)


RE: Algorithme d'ombre - ancephalopode - 11-02-2011

Salut les gars...

Je cherchais, j'ai trouvé !

Un grand merci.
J'ai implémenté la transparence des Objets (style une table dont les pieds ne cache pas tout tout de suite), en réduisant le Delta entre Perso et Objet bloquant le passage. Sachant que 0 = pas de transparence, 1 = transparence faible (pieds de chaise, grille serrée), 2 = transparence médium (pied de table, gros barreaux aux fenêtre), 3 = grande transparence (les vitres médiévales, un voilage). Bref, up to you.
Comme ceci en modifiant dans le Foreach les lignes suivantes :

list($x,$y)a = explode(",", $coord);
if($x>$jx){
$x -= ($jx-$type);
}
elseif($x<$jx){
$x -= ($jx+$type);
}
elseif($x==$jx){
$x -= ($jx);
}
if($y>$jy){
$y -= ($jy-$type);
}
elseif($y<$jy){
$y -= ($jy+$type);
}
elseif($y==$jy){
$y -= ($jy);
}


Tous cela fonctionne bien.

Cool of you !


RE: Algorithme d'ombre - niahoo - 11-02-2011

Est-ce vraiment important de gérer l'angle de vue ?
Dans la pluspart des RTS ou autres jeux en vue iso, c'est certes moins réaliste de voir une pleine zone plutot que de gérer les angles de vue, mais c'est plus sympa. À moins que ce ne soit qu'une question d'habitude ?

Avez vous des exemples de jeux avec une gestion de l'angle de vue que je teste ?