### Three.js Module Configuration Source: https://github.com/bunkerbewohner/threejs-hex-map/blob/master/examples/random/index.html Configures the RequireJS module loader for Three.js, specifying the base URL for examples and mapping the 'three' module to its build file within the project's node_modules. ```javascript var require = { baseUrl: "../../lib/examples/random", paths: { "three": "../../../node_modules/three/build/three" } } ``` -------------------------------- ### Three.js Module and Path Configuration Source: https://github.com/bunkerbewohner/threejs-hex-map/blob/master/examples/textureswap/index.html This JavaScript configuration object specifies the base URL for loading modules and defines paths for dependencies, particularly for the Three.js library. It's essential for initializing Three.js and its related modules in the project. ```javascript var require = { baseUrl: "../../lib/examples/textureswap", paths: { "three": "../../../node_modules/three/build/three" } } ``` -------------------------------- ### Hex Map Styling with CSS Source: https://github.com/bunkerbewohner/threejs-hex-map/blob/master/examples/random/index.html Provides basic CSS for styling the HTML document, canvas, and overlay elements for the hex map. It ensures the map fills the screen and positions text overlays. ```css html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; } canvas { display: block; height: 100%; background-color: cornflowerblue; } #text, #debug { position: absolute; top: 0; left: 0; width: 100%; padding: 10px 20px; font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; font-size: 1.5em; text-align: center; pointer-events: none; color: white; text-shadow: 0 0 1px black; box-sizing: border-box; } #debug { top: auto; bottom: 0; text-align: left; } ``` -------------------------------- ### Basic CSS for Hex Map Layout Source: https://github.com/bunkerbewohner/threejs-hex-map/blob/master/examples/textureswap/index.html This CSS code sets up the basic layout for the Hex Map, ensuring the canvas takes up the full screen and styling for text overlays and debug information. It manages margins, overflow, and positioning for various elements. ```css html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; } canvas { display: block; height: 100%; background-color: cornflowerblue; } #text { position: absolute; top: 0; left: 0; width: 100%; padding: 10px 20px; font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; font-size: 1.5em; text-align: center; pointer-events: none; color: white; text-shadow: 0 0 1px black; box-sizing: border-box; } #debug { position: absolute; left: 0; top: auto; bottom: 0; text-align: left; } #textures { max-width: 100%; display: flex; flex-direction: row; } #textures > div { flex: 1; margin: 10px; } #textures img { border: 4px solid white; max-width: 100%; height: 200px; height: 15vh; width: auto; pointer-events: none; } ``` -------------------------------- ### Initialize and Render Hex Map with MapView Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Demonstrates initializing the MapView, creating map data with TileData, configuring rendering options including textures and shaders, and loading the map. It also shows how to set camera views and handle tile selection events. ```typescript import { MapView, Grid, TileData, MapMeshOptions } from 'threejs-hex-map'; import { TextureLoader, Color } from 'three'; // Initialize the view with a canvas element const mapView = new MapView('canvas'); // queries for canvas element // Create map data (96x96 tiles centered at 0,0) const mapGrid = new Grid(96, 96); mapGrid.initQR((q, r) => ({ q, r, height: Math.random() * 2 - 1, // -1.0 to 1.0 terrain: 'grass', fog: true, clouds: false, rivers: null, treeIndex: undefined })); // Configure rendering options const textureLoader = new TextureLoader(); const options: MapMeshOptions = { terrainAtlasTexture: textureLoader.load('terrain.png'), terrainAtlas: { textures: { 'grass': { cellX: 0, cellY: 0 }, 'ocean': { cellX: 1, cellY: 0 }, 'mountain': { cellX: 2, cellY: 0 } }, image: 'terrain.png', width: 512, height: 512, cellSize: 64, cellSpacing: 0 }, hillsNormalTexture: textureLoader.load('hills-normal.png'), coastAtlasTexture: textureLoader.load('coast-diffuse.png'), riverAtlasTexture: textureLoader.load('river-diffuse.png'), undiscoveredTexture: textureLoader.load('paper.jpg'), treeSpritesheet: textureLoader.load('trees.png'), treeSpritesheetSubdivisions: 4, transitionTexture: textureLoader.load('transitions.png'), treesPerForest: 50, gridColor: new Color(0x42322b), gridWidth: 0.025, gridOpacity: 0.25 }; // Load the map mapView.load(mapGrid, options); // Set initial camera position and zoom mapView.setZoom(25); mapView.focus(0, 0); // center on tile at (0, 0) // Handle tile selection mapView.onTileSelected = (tile: TileData) => { console.log(`Selected tile at (${tile.q}, ${tile.r}), height: ${tile.height}`); }; // Update tiles dynamically (e.g., reveal fog of war) mapView.onLoaded = () => { const tilesToUpdate = mapGrid.neighbors(0, 0, 5); // 5-tile radius tilesToUpdate.forEach(t => { t.fog = false; t.clouds = false; }); mapView.updateTiles(tilesToUpdate); }; ``` -------------------------------- ### MapMesh: Initialize and Render Hexagonal Terrain Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Demonstrates initializing the MapMesh with tile data and configuration options, then adding it to a Three.js scene. It covers preparing tile data, configuring terrain textures and properties, creating the mesh, and handling the loading process. Includes dynamic updates like toggling the grid and updating tiles for fog of war. ```typescript import { MapMesh, MapMeshOptions, TileData } from 'threejs-hex-map'; import { Scene, TextureLoader, Color } from 'three'; const scene = new Scene(); const textureLoader = new TextureLoader(); // Prepare tile data const tiles: TileData[] = [ { q: 0, r: 0, height: 0.1, terrain: 'grass', fog: false, clouds: false }, { q: 1, r: 0, height: 0.5, terrain: 'hills', fog: false, clouds: false }, { q: 0, r: 1, height: 0.9, terrain: 'mountain', fog: false, clouds: false }, { q: -1, r: 0, height: -0.5, terrain: 'ocean', fog: false, clouds: false } ]; // Configure mesh options const options: MapMeshOptions = { terrainAtlas: { textures: { 'grass': { cellX: 0, cellY: 0 }, 'hills': { cellX: 1, cellY: 0 }, 'mountain': { cellX: 2, cellY: 0 }, 'ocean': { cellX: 3, cellY: 0 } }, image: 'terrain.png', width: 256, height: 64, cellSize: 64, cellSpacing: 0 }, terrainAtlasTexture: textureLoader.load('terrain.png'), hillsNormalTexture: textureLoader.load('hills-normal.png'), coastAtlasTexture: textureLoader.load('coast-diffuse.png'), riverAtlasTexture: textureLoader.load('river-diffuse.png'), undiscoveredTexture: textureLoader.load('paper.jpg'), treeSpritesheet: textureLoader.load('trees.png'), treeSpritesheetSubdivisions: 4, transitionTexture: textureLoader.load('transitions.png'), scale: 1.0, gridColor: new Color(0xffffff), gridWidth: 0.02, gridOpacity: 0.33 }; // Create the mesh const mapMesh = new MapMesh(tiles, options); // Wait for loading to complete mapMesh.loaded.then(() => { console.log('Map mesh loaded successfully'); scene.add(mapMesh); }); // Toggle grid visibility mapMesh.showGrid = false; // Update tiles dynamically (fog of war) const updatedTiles: TileData[] = [ { q: 0, r: 0, height: 0.1, terrain: 'grass', fog: true, clouds: false } ]; mapMesh.updateTiles(updatedTiles); // Hot-swap textures at runtime const newTerrainTexture = textureLoader.load('new-terrain.png'); mapMesh.replaceTextures({ terrainAtlasTexture: newTerrainTexture }); ``` -------------------------------- ### MapView: Camera Control, Zoom, and Tile Interaction Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Explains how to use the MapView class for camera manipulation, including setting zoom levels, focusing the camera on specific tiles, and enabling smooth scrolling. It also details how to pick tiles at specific world positions, handle mouse clicks for selection, and implement keyboard controls for navigation and zoom. ```typescript import MapView from 'threejs-hex-map'; import { Vector3 } from 'three'; const mapView = new MapView('canvas'); // ... load map data ... // Set camera zoom (distance from map) mapView.setZoom(25); // default zoom level mapView.setZoom(50); // zoom out mapView.setZoom(10); // zoom in (min: 8, max: 500 recommended) // Focus camera on specific tile mapView.focus(10, 5); // centers view on tile (10, 5) // Smooth scrolling mapView.setScrollDir(1, 0); // scroll right mapView.setScrollDir(0, 1); // scroll up mapView.setScrollDir(0, 0); // stop scrolling // Get current view center in world coordinates const viewCenter: Vector3 = mapView.getViewCenter(); console.log(`View center: (${viewCenter.x}, ${viewCenter.y})`); // Pick tile at world position const worldPos = new Vector3(10, 5, 0); const pickedTile = mapView.pickTile(worldPos); if (pickedTile) { console.log(`Picked tile: (${pickedTile.q}, ${pickedTile.r})`); mapView.selectTile(pickedTile); } // Handle mouse clicks for tile selection mapView.canvas.addEventListener('click', (e: MouseEvent) => { const worldPoint = mouseToWorld(e, mapView.getCamera()); const tile = mapView.pickTile(worldPoint); if (tile) { mapView.selectTile(tile); } }); // Keyboard controls window.addEventListener('keydown', (e: KeyboardEvent) => { if (e.key === 'ArrowLeft') mapView.setScrollDir(-1, 0); if (e.key === 'ArrowRight') mapView.setScrollDir(1, 0); if (e.key === 'ArrowUp') mapView.setScrollDir(0, 1); if (e.key === 'ArrowDown') mapView.setScrollDir(0, -1); if (e.key === 'q') mapView.setZoom(mapView.getZoom() * 1.1); // zoom out if (e.key === 'e') mapView.setZoom(mapView.getZoom() * 0.9); // zoom in if (e.key === 'g') mapView.mapMesh.showGrid = !mapView.mapMesh.showGrid; }); window.addEventListener('keyup', (e: KeyboardEvent) => { if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) { mapView.setScrollDir(0, 0); } }); // Mouse wheel zoom mapView.canvas.addEventListener('wheel', (e: WheelEvent) => { const delta = Math.max(-1, Math.min(1, e.deltaY)); const newZoom = Math.max(8, Math.min(500, mapView.getZoom() * (1 - delta * 0.025))); mapView.setZoom(newZoom); }); // Custom animation loop callback mapView.setOnAnimateCallback((deltaTimeSeconds: number) => { // Called every frame with time delta console.log(`Frame time: ${deltaTimeSeconds}s`); }); ``` -------------------------------- ### Manage Hexagonal Grid Data with Grid Class Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Illustrates using the Grid class to manage hexagonal tile data. It covers initializing tiles, retrieving specific tiles and neighbors, iterating over tiles using different coordinate systems (QR and IJ), and transforming grid data. ```typescript import { Grid, TileData } from 'threejs-hex-map'; // Create a 64x64 grid const grid = new Grid(64, 64); // Initialize all tiles with a function grid.initQR((q, r) => ({ q, r, height: 0, terrain: 'grass', fog: false, clouds: false })); // Get a specific tile const tile = grid.get(0, 0); console.log(tile); // { q: 0, r: 0, height: 0, ... } // Get neighbors (6 adjacent tiles) const neighbors = grid.neighbors(0, 0); // returns array of up to 6 tiles console.log(`Found ${neighbors.length} neighbors`); // Get neighbors in a range (e.g., 3 tiles away) const nearbyTiles = grid.neighbors(0, 0, 3); // Get exactly 6 surrounding tiles (includes undefined for missing tiles) const surrounding = grid.surrounding(0, 0); // always returns array of 6 items // Iterate over all tiles by Q/R coordinates grid.forEachQR((q, r, existingTile) => { console.log(`Processing tile at (${q}, ${r})`); if (existingTile) { existingTile.height = Math.random(); } }); // Iterate using array indices (i, j) grid.forEachIJ((i, j, q, r, tile) => { console.log(`Array position [${i}, ${j}] = hex coords (${q}, ${r})`); }); // Convert to array const allTiles = grid.toArray(); console.log(`Total tiles: ${allTiles.length}`); // Map to a new grid const heightGrid = grid.mapQR((q, r, tile) => ({ ...tile, height: Math.random() * 2 - 1 })); ``` -------------------------------- ### Hexagonal Coordinate Conversion for Three.js Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Provides functions to convert between hexagonal axial coordinates (q, r) and Three.js world space coordinates. It also includes utilities for converting mouse clicks to world positions and then back to hex coordinates, and for calculating distances between hex tiles. ```typescript import { qrToWorld, mouseToWorld, axialToCube, roundToHex, cubeToAxial, qrDistance } from 'threejs-hex-map'; import { Vector3, Camera } from 'three'; // Convert hex coordinates to world space (default scale = 1.0) const worldPos = qrToWorld(5, 3); // returns Vector3 console.log(`Tile (5,3) is at world position (${worldPos.x}, ${worldPos.y}, ${worldPos.z})`); // With custom scale const scaledPos = qrToWorld(5, 3, 2.0); // doubles the spacing console.log(`Scaled position: (${scaledPos.x}, ${scaledPos.y})`); // Convert mouse click to world position (requires camera and mouse event) const camera: Camera = mapView.getCamera(); canvas.addEventListener('click', (e: MouseEvent) => { const worldPoint = mouseToWorld(e, camera); console.log(`Clicked at world position: (${worldPoint.x}, ${worldPoint.y})`); // Convert world position back to hex coordinates const fracQ = (1.0 / 3 * Math.sqrt(3) * worldPoint.x - 1.0 / 3 * worldPoint.y); const fracR = 2.0 / 3 * worldPoint.y; // Round to nearest hex const cube = axialToCube(fracQ, fracR); const rounded = roundToHex(cube); const axial = cubeToAxial(rounded.x, rounded.y, rounded.z); console.log(`Clicked hex tile: (${axial.q}, ${axial.r})`); }); // Calculate distance between two hex tiles const dist = qrDistance({ q: 0, r: 0 }, { q: 5, r: 3 }); console.log(`Distance from origin to (5,3): ${dist} tiles`); ``` -------------------------------- ### Procedural Hex Map Generation with Noise and Rivers Source: https://context7.com/bunkerbewohner/threejs-hex-map/llms.txt Generates a random hexagonal map using Perlin and simplex noise, with automatic river generation from mountains to water. The height parameter determines terrain type, and the function returns a promise that resolves with the generated grid. Rivers are automatically populated based on terrain height differences. ```typescript import { generateRandomMap, TileData, Height, isWater, isMountain } from 'threejs-hex-map'; // Generate a 128x128 random map const mapPromise = generateRandomMap(128, (q, r, height: Height): TileData => { // Height ranges from -1.0 (deep water) to 1.0 (high mountains) // [-1.00, -0.25) = deep water // [-0.25, 0.00) = shallow water // [ 0.00, 0.25) = flat land // [ 0.25, 0.75) = hills // [ 0.75, 1.00] = mountains let terrain: string; let treeIndex: number | undefined; if (height < 0.0) { terrain = 'ocean'; treeIndex = undefined; } else if (height >= 0.75) { terrain = 'mountain'; treeIndex = undefined; } else if (height >= 0.25) { terrain = 'hills'; treeIndex = Math.random() > 0.5 ? 0 : undefined; } else { // Flat land - vary terrain types if (Math.abs(r) > 50) { terrain = 'snow'; // polar regions treeIndex = 2; } else { terrain = Math.random() > 0.5 ? 'grass' : 'plains'; treeIndex = Math.random() > 0.7 ? 0 : undefined; } } return { q, r, height, terrain, treeIndex, fog: true, clouds: true, rivers: null // automatically populated by river generation }; }); mapPromise.then(grid => { console.log(`Generated map with ${grid.length} tiles`); // Rivers are automatically generated from mountains to water const tilesWithRivers = grid.toArray().filter(t => t.rivers && t.rivers.length > 0); console.log(`Generated ${tilesWithRivers.length} river tiles`); // Each river tile has river data tilesWithRivers.forEach(tile => { tile.rivers.forEach(river => { console.log(`Tile (${tile.q},${tile.r}) has river #${river.riverIndex}, segment #${river.riverTileIndex}`); }); }); }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.