Perspective isometrique jeu
Fermé
Marc_spector
Messages postés
28
Date d'inscription
mercredi 11 mai 2022
Statut
Membre
Dernière intervention
14 mai 2022
-
11 mai 2022 à 23:41
yg_be Messages postés 23349 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 26 novembre 2024 - 14 mai 2022 à 21:12
yg_be Messages postés 23349 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 26 novembre 2024 - 14 mai 2022 à 21:12
A voir également:
- Perspective isometrique jeu
- 94 jeu - Télécharger - Puzzle & Réflexion
- Jeu zuma - Télécharger - Jeux vidéo
- Jeu 94 degrés - Télécharger - Divers Jeux
- Logo jeu - Télécharger - Jeux vidéo
- Jeu serpent pomme - Guide
3 réponses
yg_be
Messages postés
23349
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
26 novembre 2024
Ambassadeur
1 554
12 mai 2022 à 08:49
12 mai 2022 à 08:49
bonjour,
Je suppose que ton jeu est affiché en perspective isométrique, mais mémorisé sous forme orthogonale.
Il suffit alors, je pense, de convertir la position de la souris d'isométrique vers orthogonale, puis de faire le test comme tu le montres.
Je suppose que ton jeu est affiché en perspective isométrique, mais mémorisé sous forme orthogonale.
Il suffit alors, je pense, de convertir la position de la souris d'isométrique vers orthogonale, puis de faire le test comme tu le montres.
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié le 12 mai 2022 à 11:11
Modifié le 12 mai 2022 à 11:11
Salut Marc_spector,
Je n'ai jamais fait cela, mais il y a un fil qui devrait t'aider sur le forum Allegro sur la question, en particulier les posts de Neil Roy qui décrit en détails deux procédés dont l'un à base de calcul (et qui repose à la création d'un système de coordonnées virtuel des briques isométriques et des formules de conversion, similaire à ceci), et l'autre qu'elle appelle "mousemap" et qui est intéressant et repose sur la création en mémoire d'une version de l'écran spécialement destinée à la détection de la brique isométrique sous le curseur de la souris, qui réplique l'écran affiché, mais avec des briques dont les couleurs délimitent clairement l'espace occupé par la brique et les espaces adjacents, toutes ces couleurs étant clairement différentes entre elles.
Déterminer sur quelle brique isométrique le curseur se trouve revient à calculer la localisation du sprite selon un formule classique d'un sprite rectangulaire, puis déterminer si on se trouve vraiment sur la figure centrale ou une figure adjacente en fonction de la couleur présente aux coordonnées du curseur.
Elle le décrit comme ceci :
It's a fairly simple technique, just figure out which tile you are clicking on, which tile number is at that location, then check the identical mousemap. You just check the colour at the location your mouse clicked on and go from there. If the colour is red, you clicked on a tile north of the position your mouse is on (actually, north-west, depending on how you draw them). If you clicked on cyan, you go one tile south, blue is north-west etc.
voir : https://www.allegro.cc/forums/thread/617294
Dal
Je n'ai jamais fait cela, mais il y a un fil qui devrait t'aider sur le forum Allegro sur la question, en particulier les posts de Neil Roy qui décrit en détails deux procédés dont l'un à base de calcul (et qui repose à la création d'un système de coordonnées virtuel des briques isométriques et des formules de conversion, similaire à ceci), et l'autre qu'elle appelle "mousemap" et qui est intéressant et repose sur la création en mémoire d'une version de l'écran spécialement destinée à la détection de la brique isométrique sous le curseur de la souris, qui réplique l'écran affiché, mais avec des briques dont les couleurs délimitent clairement l'espace occupé par la brique et les espaces adjacents, toutes ces couleurs étant clairement différentes entre elles.
Déterminer sur quelle brique isométrique le curseur se trouve revient à calculer la localisation du sprite selon un formule classique d'un sprite rectangulaire, puis déterminer si on se trouve vraiment sur la figure centrale ou une figure adjacente en fonction de la couleur présente aux coordonnées du curseur.
Elle le décrit comme ceci :
It's a fairly simple technique, just figure out which tile you are clicking on, which tile number is at that location, then check the identical mousemap. You just check the colour at the location your mouse clicked on and go from there. If the colour is red, you clicked on a tile north of the position your mouse is on (actually, north-west, depending on how you draw them). If you clicked on cyan, you go one tile south, blue is north-west etc.
voir : https://www.allegro.cc/forums/thread/617294
Dal
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié le 12 mai 2022 à 11:52
Modifié le 12 mai 2022 à 11:52
Sinon, avec la réflexion vers laquelle te guide yg_be, je pense que tu n'est pas loin de la solution, surtout si tes formes sont de vrais losanges divisant ta zone rectangulaire en 5 zones, les points aux charnières étant à la moitié de la largeur et hauteur du rectangle:-)
Tu n'as que des triangles à gérer pour savoir si tu es en dehors de la zone centrale et si oui dans lequel des triangles qui la bordent, et dont tu peux connaître les coordonnées facilement :
https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
Tu n'as que des triangles à gérer pour savoir si tu es en dehors de la zone centrale et si oui dans lequel des triangles qui la bordent, et dont tu peux connaître les coordonnées facilement :
https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
>
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
12 mai 2022 à 12:24
12 mai 2022 à 12:24
et tu peux, par exclusion, savoir si tu es dans la zone centrale, ou utiliser le procédé proposé par yg_be dans son post https://forums.commentcamarche.net/forum/affich-37591864-perspective-isometrique-jeu#10 pour le calculer.
Tu peux aussi diviser ton losange en 2 triangles et voir si tu es dans l'un d'eux.
Il y a plein de solutions :-)
Tu peux aussi diviser ton losange en 2 triangles et voir si tu es dans l'un d'eux.
Il y a plein de solutions :-)
Marc_spector
Messages postés
28
Date d'inscription
mercredi 11 mai 2022
Statut
Membre
Dernière intervention
14 mai 2022
>
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
12 mai 2022 à 13:52
12 mai 2022 à 13:52
Merci beaucoup pour votre réponse, je vais essayer les méthodes que vous et yg_be avez proposé en espérant réussir à les coder :)
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
Modifié le 14 mai 2022 à 03:11
Modifié le 14 mai 2022 à 03:11
Salut Marc_spector,
Voici une solution qui fonctionne dès lors que tu disposes des coordonnées d'un sprite (coin supérieur gauche) et des coordonnées de la souris, pour déterminer si la souris est sur le losange au centre du sprite ou sur l'un des côtés et lequel. En divisant le sprite en triangles, on peut tester individuellement les différentes zones du sprite.
Les points n, e, s, w représent les sommets du losange et s1, s2, s3, s4 les coins du sprite, comme ceci :
La fonction
J'ai testé la fonction
Je n'ai pas testé si c'est réellement optimisé sur un exemple réel avec tout le bazard qui va autour dans un vrai jeu :-)
Dal
Voici une solution qui fonctionne dès lors que tu disposes des coordonnées d'un sprite (coin supérieur gauche) et des coordonnées de la souris, pour déterminer si la souris est sur le losange au centre du sprite ou sur l'un des côtés et lequel. En divisant le sprite en triangles, on peut tester individuellement les différentes zones du sprite.
Les points n, e, s, w représent les sommets du losange et s1, s2, s3, s4 les coins du sprite, comme ceci :
#include <stdio.h> #include <stdbool.h> #include <assert.h> #define SPRITE_WIDTH 142 #define SPRITE_WIDTH_HALF SPRITE_WIDTH / 2 #define SPRITE_EIGHT 48 #define SPRITE_EIGHT_HALF SPRITE_EIGHT / 2 struct point { int x; int y; }; enum point_location { INSIDE_DIAMOND, NW, NE, SE, SW, NOT_IN_SPRITE}; struct point n, e, s, w; struct point s1, s2, s3, s4; /* calc functions */ void calc_vertices(struct point * n, struct point * e, struct point * s, struct point * w, struct point * s1, struct point * s2, struct point * s3, struct point * s4, struct point * sprite_corner) { /* determine coordinates of the diamond vertices based on top * left sprite coordinates and store them in: n, e, s, w * points */ n->x = sprite_corner->x + SPRITE_WIDTH_HALF; n->y = sprite_corner->y; e->x = sprite_corner->x + SPRITE_WIDTH; e->y = sprite_corner->y + SPRITE_EIGHT_HALF; s->x = sprite_corner->x + SPRITE_WIDTH_HALF; s->y = sprite_corner->y + SPRITE_EIGHT; w->x = sprite_corner->x; w->y = sprite_corner->y + SPRITE_EIGHT_HALF; /* determine coordinates of the bounding box for the sprite * starting from top left and store them clockwise in: * s1, s2, s3, s4 */ *s1 = *sprite_corner; s2->x = sprite_corner->x + SPRITE_WIDTH; s2->y = sprite_corner->y; s3->x = sprite_corner->x + SPRITE_WIDTH; s3->y = sprite_corner->y + SPRITE_EIGHT; s4->x = sprite_corner->x; s4->y = sprite_corner->y + SPRITE_EIGHT; } bool is_inside_triangle(struct point * searched_point, struct point * a, struct point * b, struct point * c) { int as_x = searched_point->x - a->x; int as_y = searched_point->y - a->y; bool s_ab = (b->x - a->x) * as_y - (b->y-a->y) * as_x > 0; if ( ((c->x - a->x) * as_y - (c->y-a->y) * as_x > 0) == s_ab) return false; if ( ((c->x - b->x) * (searched_point->y - b->y) - (c->y - b->y) * (searched_point->x - b->x) > 0) != s_ab) return false; return true; } enum point_location location_in_sprite(struct point * searched_point, struct point * sprite_corner) { /* is searched_point inside one of the 2 triangles forming * the diamond? */ if ( is_inside_triangle(searched_point, &n, &e, &w) || is_inside_triangle(searched_point, &e, &s, &w) ) return INSIDE_DIAMOND; /* is searched_point in any of the 4 neighbouring * triangles? */ if ( is_inside_triangle(searched_point, &s1, &n, &w) ) return NW; if ( is_inside_triangle(searched_point, &n, &s2, &e) ) return NE; if ( is_inside_triangle(searched_point, &e, &s3, &s) ) return SE; if ( is_inside_triangle(searched_point, &w, &s, &s4) ) return SW; return NOT_IN_SPRITE; } /* let us test this */ int main(int argc, char* argv[]) { struct point sprite_corner = { .x = 137, .y = 83 }; calc_vertices(&n, &e, &s, &w, &s1, &s2, &s3, &s4, &sprite_corner); /* test INSIDE_DIAMOND (top portion of the diamond) */ { struct point searched_point = { .x = 198, .y = 101 }; assert(location_in_sprite(&searched_point, &sprite_corner) == INSIDE_DIAMOND && ".x = 198, .y = 101 is INSIDE_DIAMOND (top sub-triangle)"); } /* test INSIDE_DIAMOND (lower portion of the diamond) */ { struct point searched_point = { .x = 197, .y = 127 }; assert(location_in_sprite(&searched_point, &sprite_corner) == INSIDE_DIAMOND && ".x = 197, .y = 127 is INSIDE_DIAMOND (lower sub-triangle)"); } /* test NW (North-West of the diamond) */ { struct point searched_point = { .x = 162, .y = 90 }; assert(location_in_sprite(&searched_point, &sprite_corner) == NW && ".x = 162, .y = 90 is NW (North-West of the diamond)"); } /* test NE (North-East of the diamond) */ { struct point searched_point = { .x = 267, .y = 95 }; assert(location_in_sprite(&searched_point, &sprite_corner) == NE && ".x = 267, .y = 95 is NE (North-East of the diamond)"); } /* test SE (South-East of the diamond) */ { struct point searched_point = { .x = 259, .y = 130 }; assert(location_in_sprite(&searched_point, &sprite_corner) == SE && ".x = 259, .y = 130 is SE (South-East of the diamond)"); } /* test SW (South-West of the diamond) */ { struct point searched_point = { .x = 145, .y = 129 }; assert(location_in_sprite(&searched_point, &sprite_corner) == SW && ".x = 145, .y = 129 is SW (South-West of the diamond)"); } /* test NOT_IN_SPRITE (not in any part of the sprite) */ { struct point searched_point = { .x = 15, .y = 19 }; assert(location_in_sprite(&searched_point, &sprite_corner) == NOT_IN_SPRITE && ".x = 15, .y = 19 is NOT_IN_SPRITE (not in any part of the sprite)"); } return 0; }
La fonction
is_inside_triangle()est une adaptation de celle proposée par John Bananas sur le fil SO que j'avais mentionné (là : https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle/9755252#9755252) que j'ai changée afin de gérer le passage de pointeurs et éviter la copie des struct lors du passage en paramètre, sa version étant elle-même une version n'utilisant que des calculs entiers optimisée par rapport celle de Kisielewicz (qui elle même se veut aussi optimisée par rapport aux autres réponses du fil car ne consistant qu'en des additions, soustractions et multiplications et évitant les divisions qui sont plus coûteuses).
J'ai testé la fonction
location_in_sprite()dans un code avec la SDL en envoyant des points aléatoires sur l'image qui sont colorés d'une couleur différente suivant qu'ils tombent sur telle ou telle partie du sprite, que j'ai simulé en dessinant les triangles qui le composent, et cela donne ceci :
Je n'ai pas testé si c'est réellement optimisé sur un exemple réel avec tout le bazard qui va autour dans un vrai jeu :-)
Dal
12 mai 2022 à 09:15
merci de votre réponse
Enfaite pas vraiment, pour afficher mon plateau j'ai crée un sprite pour une "case" faite en perspective et ensuite j'affiche les sprites pour avoir un plateau potable.
12 mai 2022 à 09:28
12 mai 2022 à 09:35
12 mai 2022 à 09:38
12 mai 2022 à 10:11
Je pense que j'ai du mal m'exprimer, en rouge c'est les diagonales du losange, les point magenta sont les coordonnées x et y du coin en haut a gauche dont je parlais. Et en vert j'ai fais une sorte de hitbox pour mon losange. Le problème est que dans la zone hachurée en magenta je ne peux pas savoir si je suis sur la case (0,0) ou (1,0) par exemple vu que c'est le croisement de deux hitbox
J'espère que cette fois-ci j'ai mieux expliqué