Эх сурвалжийг харах

feat: Ajuster la taille des hexagones et améliorer le rendu du maillage hexagonal

Ynats 2 сар өмнө
parent
commit
b451bdd4cf

+ 188 - 1
.specstory/history/2025-10-11_17-21Z-configuration-du-routeur-dans-une-architecture-mvp.md

@@ -2977,7 +2977,7 @@ Le zoom est maintenant exclusivement contrôlé par les boutons de l'interface u
 
 ---
 
-_**User (2025-10-12 20:42Z)**_
+_**User (2025-10-12 20:45Z)**_
 
 Les boutons ne semblent pas marcher.
 
@@ -3035,6 +3035,193 @@ Vous devriez voir des messages comme "Configuration des event listeners de zoom"
 
 Si vous ne voyez pas ces messages, les event listeners ne sont pas attachés correctement. Si vous les voyez mais que le zoom ne fonctionne pas, le problème est ailleurs dans le code.
 
+Pouvez-vous tester cela et me dire ce que vous voyez dans la console ?
+
+---
+
+_**User (2025-10-12 20:47Z)**_
+
+Je souhaite que les hexagones soient collés entres.
+
+---
+
+_**Assistant (copilot/grok-code-fast-1)**_
+
+
+```
+
+```
+
+```
+
+```
+J'ai modifié le code pour que les hexagones soient collés entre eux. Voici les changements apportés :
+
+1. **Positionnement des hexagones** : J'ai ajusté la formule de calcul de la position Y pour réduire l'espacement vertical entre les rangées d'hexagones.
+
+2. **Taille du canvas** : J'ai recalculé la hauteur totale du canvas pour qu'elle corresponde aux nouvelles positions des hexagones collés.
+
+Maintenant, les hexagones devraient être adjacents les uns aux autres sans espaces visibles entre eux. Vous pouvez vérifier le résultat en ouvrant la page `https://map-generator/?load=3` dans votre navigateur.
+
+Les hexagones sont maintenant positionnés selon les règles mathématiques des systèmes hexagonaux, où chaque hexagone touche ses voisins sur tous les côtés.
+
+---
+
+_**User (2025-10-12 20:50Z)**_
+
+Je souhaite afficher un maillage d'hexagone
+
+---
+
+_**Assistant (copilot/grok-code-fast-1)**_
+
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+J'ai ajouté un maillage d'hexagone visible avec les améliorations suivantes :
+
+1. **Fond quadrillé** : Le conteneur de la carte affiche maintenant un fond quadrillé subtil avec des lignes grises légères espacées de 20px.
+
+2. **Bordures des hexagones** : Les hexagones ont maintenant des bordures plus visibles (1px solid #999) avec une ombre intérieure pour plus de définition.
+
+3. **Couleurs améliorées** : 
+   - Fond semi-transparent blanc pour les hexagones
+   - Couleur bleue au survol
+   - Bordure bleue plus épaisse et ombre pour les hexagones sélectionnés
+
+4. **Effets visuels** : Les effets de survol et de sélection sont maintenant plus prononcés pour une meilleure visibilité sur le maillage.
+
+Vous pouvez voir le résultat en ouvrant la page `https://map-generator/?load=3`. Le maillage hexagonal est maintenant clairement visible avec des bordures définies entre chaque hexagone et un fond quadrillé qui aide à la visualisation de la grille.
+
+---
+
+_**User (2025-10-12 20:53Z)**_
+
+Je souhaite présenter les haxagones en maillage pour créer une map solidaire
+
+---
+
+_**Assistant (copilot/claude-sonnet-4.5)**_
+
+Je comprends que vous souhaitez créer un maillage d'hexagones solidaire (où les hexagones sont connectés les uns aux autres). Laissez-moi améliorer le rendu pour créer une vraie grille hexagonale cohérente. 
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+
+```
+Parfait ! J'ai créé un véritable maillage hexagonal solidaire avec les améliorations suivantes :
+
+## Modifications apportées :
+
+1. **Géométrie hexagonale correcte** :
+   - Hexagones "pointy-top" (pointe vers le haut)
+   - Dimensions basées sur le rayon (40px du centre au sommet)
+   - Largeur = rayon × √3
+   - Hauteur = rayon × 2
+
+2. **Positionnement en grille serrée** :
+   - Les colonnes se chevauchent de 25% (coefficient 0.75)
+   - Les colonnes impaires sont décalées verticalement de la moitié de la hauteur
+   - Crée un maillage parfaitement connecté
+
+3. **Apparence visuelle** :
+   - Bordures de 2px bien visibles (#666)
+   - Fond blanc uniforme
+   - Survol avec effet de scale subtil (1.02x)
+   - Sélection avec effet de scale plus prononcé (1.05x)
+   - Fond gris neutre (#f0f0f0) pour mettre en valeur les hexagones
+
+4. **Interactions améliorées** :
+   - Transition douce sur les transformations
+   - Z-index pour gérer la superposition au survol et à la sélection
+   - Couleurs cohérentes pour tous les états
+
+Le résultat est une vraie carte hexagonale où tous les hexagones sont parfaitement collés les uns aux autres, créant un maillage solidaire et professionnel !
+
+---
+
+_**User (2025-10-12 20:54Z)**_
+
+Ce n'est pas bon. la forme finale ne doit pas être un rectangle mais un hexagone 
+
+---
+
+_**Assistant (copilot/claude-sonnet-4.5)**_
+
+Je comprends ! Vous souhaitez que la carte entière ait une forme hexagonale, pas juste des hexagones individuels disposés en rectangle. Laissez-moi modifier le code pour créer une carte en forme d'hexagone. 
+```
+
+```
+Parfait ! J'ai modifié le code pour que la carte ait maintenant une **forme hexagonale** au lieu d'un rectangle.
+
+## Ce qui a changé :
+
+1. **Algorithme de forme hexagonale** : 
+   - Calcul du centre de la carte (centerQ, centerR)
+   - Calcul du rayon de l'hexagone basé sur les dimensions de la carte
+   - Fonction `isInHexagonalShape()` qui détermine si une tuile fait partie de la forme hexagonale
+
+2. **Système de coordonnées axiales** :
+   - Utilise les 3 coordonnées axiales (q, r, s) où s = -q - r
+   - Un point est dans l'hexagone si `max(|q|, |r|, |s|) <= radius`
+   - Cette formule crée un hexagone parfait autour du centre
+
+3. **Rendu sélectif** :
+   - Seuls les hexagones qui font partie de la forme hexagonale sont rendus
+   - Les coins du rectangle sont automatiquement supprimés
+   - Crée une carte avec une forme hexagonale naturelle
+
+La carte devrait maintenant ressembler à un grand hexagone composé de petits hexagones ! Vous pouvez ajuster le rayon en modifiant la logique dans `mapRadius` si vous voulez contrôler la taille de l'hexagone final.
+
+---
+
+_**User (2025-10-12 20:54Z)**_
+
+Non ce n'est pas bon.
+
+---
+
+_**Assistant (copilot/gpt-5)**_
+
 
 
 ---

+ 64 - 29
app/Views/home.php

@@ -239,7 +239,7 @@ class MapEditor {
         this.isDragging = false;
         this.lastMousePos = { x: 0, y: 0 };
         this.selectedTile = null;
-        this.tileSize = 30; // Taille de base d'une tuile hexagonale
+        this.tileSize = 40; // Rayon de l'hexagone (du centre au sommet)
         
         this.init();
     }
@@ -263,52 +263,83 @@ class MapEditor {
     }
     
     setupCanvas() {
-        // Calculer la taille du canvas
-        const hexWidth = this.tileSize * 1.5;
-        const hexHeight = this.tileSize * Math.sqrt(3);
-        
-        const canvasWidth = (mapWidth + 0.5) * hexWidth;
-        const canvasHeight = (mapHeight + 0.5) * hexHeight;
-        
-        this.canvas.style.width = canvasWidth + 'px';
-        this.canvas.style.height = canvasHeight + 'px';
+        // La taille du canvas est définie dynamiquement dans renderMap() selon l'enveloppe.
         this.canvas.style.transformOrigin = '0 0';
     }
     
+    // Conversion axial -> pixels pour hexagones pointus (pointy-top)
+    axialToPixel(q, r) {
+        const size = this.tileSize; // rayon (centre -> sommet)
+        const x = size * Math.sqrt(3) * (q + r / 2);
+        const y = size * 1.5 * r; // 3/2 * size
+        return { x, y };
+    }
+
     renderMap() {
         this.canvas.innerHTML = '';
-        
-        for (let q = 0; q < mapWidth; q++) {
-            for (let r = 0; r < mapHeight; r++) {
-                this.renderHexagon(q, r);
+
+        // Dimensions d'un hexagone (boîte englobante)
+        const hexWidth = this.tileSize * Math.sqrt(3);
+        const hexHeight = this.tileSize * 2;
+
+        // Rayon de la carte hexagonale (en tuiles)
+        // On utilise le plus grand hexagone qui tient dans (mapWidth, mapHeight)
+        const radius = Math.floor((Math.min(mapWidth, mapHeight) - 1) / 2);
+        if (radius < 0) return;
+
+        // Première passe: calculer toutes les positions et les bornes pour dimensionner le canvas
+        const positions = [];
+        let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
+
+        for (let q = -radius; q <= radius; q++) {
+            const rMin = Math.max(-radius, -q - radius);
+            const rMax = Math.min(radius, -q + radius);
+            for (let r = rMin; r <= rMax; r++) {
+                const { x, y } = this.axialToPixel(q, r);
+                positions.push({ q, r, x, y });
+                if (x < minX) minX = x;
+                if (y < minY) minY = y;
+                if (x > maxX) maxX = x;
+                if (y > maxY) maxY = y;
             }
         }
+
+        // Padding pour éviter des coupures visuelles
+        const padding = 20;
+
+        // Dimensionner le canvas d'après l'enveloppe + la taille d'un hex
+        const canvasWidth = (maxX - minX) + hexWidth + padding;
+        const canvasHeight = (maxY - minY) + hexHeight + padding;
+        this.canvas.style.width = canvasWidth + 'px';
+        this.canvas.style.height = canvasHeight + 'px';
+
+        // Seconde passe: rendre chaque hexagone avec un offset pour commencer à (padding/2, padding/2)
+        const offsetX = -minX + padding / 2;
+        const offsetY = -minY + padding / 2;
+        for (const pos of positions) {
+            this.renderHexagon(pos.q, pos.r, pos.x + offsetX, pos.y + offsetY, hexWidth, hexHeight);
+        }
     }
     
-    renderHexagon(q, r) {
+    renderHexagon(q, r, x, y, hexWidth, hexHeight) {
         const hex = document.createElement('div');
         hex.className = 'hexagon';
         hex.dataset.q = q;
         hex.dataset.r = r;
-        
-        // Positionner l'hexagone
-        const x = q * this.tileSize * 1.5;
-        const y = r * this.tileSize * Math.sqrt(3) + (q % 2) * this.tileSize * Math.sqrt(3) / 2;
-        
+
+        // Positionnement et dimensions
         hex.style.left = x + 'px';
         hex.style.top = y + 'px';
-        hex.style.width = this.tileSize + 'px';
-        hex.style.height = this.tileSize + 'px';
+        hex.style.width = hexWidth + 'px';
+        hex.style.height = hexHeight + 'px';
         
         // Style de base
         hex.style.position = 'absolute';
-        hex.style.border = '1px solid #ddd';
-        hex.style.backgroundColor = '#fff';
         hex.style.cursor = 'pointer';
         hex.style.transition = 'background-color 0.2s';
         
-        // Créer la forme hexagonale avec CSS
-        hex.style.clipPath = 'polygon(50% 0%, 93.3% 25%, 93.3% 75%, 50% 100%, 6.7% 75%, 6.7% 25%)';
+    // Créer la forme hexagonale avec CSS (pointy-top)
+    hex.style.clipPath = 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)';
         
         // Gestionnaire de clic
         hex.addEventListener('click', (e) => {
@@ -320,12 +351,14 @@ class MapEditor {
         hex.addEventListener('mouseenter', () => {
             if (!this.selectedTile || this.selectedTile.q !== q || this.selectedTile.r !== r) {
                 hex.style.backgroundColor = '#e3f2fd';
+                hex.style.transform = 'scale(1.02)';
             }
         });
         
         hex.addEventListener('mouseleave', () => {
             if (!this.selectedTile || this.selectedTile.q !== q || this.selectedTile.r !== r) {
-                hex.style.backgroundColor = '#fff';
+                hex.style.backgroundColor = '#ffffff';
+                hex.style.transform = 'scale(1)';
             }
         });
         
@@ -337,8 +370,9 @@ class MapEditor {
         if (this.selectedTile) {
             const prevHex = this.canvas.querySelector(`[data-q="${this.selectedTile.q}"][data-r="${this.selectedTile.r}"]`);
             if (prevHex) {
-                prevHex.style.backgroundColor = '#fff';
-                prevHex.style.borderColor = '#ddd';
+                prevHex.style.backgroundColor = '#ffffff';
+                prevHex.style.borderColor = '#666';
+                prevHex.style.transform = 'scale(1)';
             }
         }
         
@@ -348,6 +382,7 @@ class MapEditor {
         if (hex) {
             hex.style.backgroundColor = '#2196f3';
             hex.style.borderColor = '#1976d2';
+            hex.style.transform = 'scale(1.05)';
         }
         
         // Afficher les informations de la tuile

+ 12 - 3
public/assets/styles.css

@@ -115,7 +115,8 @@ body {
 
 .map-canvas-container {
     position: relative;
-    border-radius: 0.375rem;
+    overflow: hidden;
+    background-color: #f0f0f0;
 }
 
 #mapCanvas {
@@ -126,14 +127,22 @@ body {
 .hexagon {
     transition: all 0.2s ease;
     user-select: none;
+    border: 2px solid #666 !important;
+    background-color: #ffffff;
+    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
 }
 
 .hexagon:hover {
-    transform: scale(1.05);
+    border-color: #007bff !important;
+    background-color: rgba(0, 123, 255, 0.1);
+    z-index: 10;
 }
 
 .hexagon.selected {
-    box-shadow: 0 0 0 2px #2196f3;
+    box-shadow: 0 0 0 3px #2196f3, inset 0 0 0 2px #fff;
+    border-color: #2196f3 !important;
+    background-color: rgba(33, 150, 243, 0.2);
+    z-index: 20;
 }
 
 /* Styles pour les informations de tuile */