User prompt
make the player spawning 15,15 coordinates and screen has to centre it for looking player
User prompt
i cannot seeing the player fix it for screen
User prompt
i cannot see the play on center of screen make it fix
User prompt
make - `player.subTileX = 15` - `player.subTileY = 15`
User prompt
make player can move
User prompt
make player move for one movement one is center of tile
User prompt
the player doesnt move
User prompt
make that player always move to center of tiles it means one movement is one tile
User prompt
make biome more smaller and so be many on map
User prompt
the player cannot move its looking like teleporting but not moving fix it
User prompt
optimize that game
User prompt
the player has to be in center of screen for showing himself
User prompt
make that player spawning in 15,15 coordinates
User prompt
i cant see on my screen fix it
User prompt
make tiles a bit bigger
User prompt
the player has to be in center of screen on top of tile fix it
User prompt
i cannot see the player fix it
User prompt
i cant see the player on screen
User prompt
make a bit closer each tiles like 1 pixel
User prompt
make sure that tiles are connected each other i mean no black dots and make player spawinin center of the map
User prompt
creatures and player would can crossing each other forcatching fix that
User prompt
i canr see the player on top of tiles
User prompt
make bigger world size
User prompt
make 2 times bigger that tiles size
User prompt
Make more biome on map and add some different biome like streer urban
/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1", { discoveredCreatures: {}, playerPosition: { x: 10, y: 10 }, unlockedAreas: { starter: true } }); var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Collection class to manage discovered creatures var Collection = Container.expand(function () { var self = Container.call(this); // Collection components self.visible = false; self.background = null; self.scrollContainer = null; self.closeButton = null; // Initialize collection screen self.init = function () { // Create darkened background self.background = self.attachAsset('grassTile', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); self.background.alpha = 0.9; self.background.tint = 0x000000; // Create scroll container for creatures self.scrollContainer = new Container(); self.addChild(self.scrollContainer); self.scrollContainer.x = 50; self.scrollContainer.y = 200; // Add title var titleText = new Text2('CREATURE COLLECTION', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 1024; titleText.y = 50; self.addChild(titleText); // Create close button self.closeButton = self.attachAsset('dpadButton', { anchorX: 0.5, anchorY: 0.5, x: 1900, y: 100 }); self.closeButton.interactive = true; // Add X to close button var closeText = new Text2('X', { size: 60, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.x = 1900; closeText.y = 100; self.addChild(closeText); // Hide initially self.visible = false; return self; }; // Show collection screen and populate with discovered creatures self.show = function () { self.visible = true; // Clear existing creatures while (self.scrollContainer.children.length > 0) { self.scrollContainer.removeChild(self.scrollContainer.children[0]); } // Get discovered creatures from storage var discoveredCreatures = storage.discoveredCreatures || {}; var creatureCount = Object.keys(discoveredCreatures).length; // Show count var countText = new Text2('DISCOVERED: ' + creatureCount + ' / 90', { size: 50, fill: 0xFFFFFF }); countText.anchor.set(0.5, 0); countText.x = 1024; countText.y = 150; self.addChild(countText); // Create grid of discovered creatures var gridX = 0; var gridY = 0; var itemsPerRow = 5; var cellSize = 380; // First add "undiscovered" placeholders for all possible combinations var allTypes = ['bug', 'dark', 'dragon', 'electric', 'fairy', 'fighting', 'fire', 'flying', 'ghost', 'grass', 'ground', 'ice', 'normal', 'poison', 'psychic', 'rock', 'steel', 'water']; var allRarities = ['common', 'uncommon', 'rare', 'epic', 'legendary']; for (var t = 0; t < allTypes.length; t++) { for (var r = 0; r < allRarities.length; r++) { var type = allTypes[t]; var rarity = allRarities[r]; var key = type + '-' + rarity; // Calculate grid position gridX = (allRarities.length * t + r) % itemsPerRow; gridY = Math.floor((allRarities.length * t + r) / itemsPerRow); // Create cell container var cell = new Container(); cell.x = gridX * cellSize; cell.y = gridY * cellSize; self.scrollContainer.addChild(cell); if (discoveredCreatures[key]) { // Discovered creature var creatureGraphic = LK.getAsset(type + 'Creature', { anchorX: 0.5, anchorY: 0.5, x: cellSize / 2, y: cellSize / 2 - 40 }); // Apply rarity styling var rarityColor = 0xFFFFFF; if (rarity === 'uncommon') rarityColor = 0x00FF00; if (rarity === 'rare') rarityColor = 0x0000FF; if (rarity === 'epic') rarityColor = 0xFF00FF; if (rarity === 'legendary') rarityColor = 0xFFD700; // Make rarer creatures slightly larger var scale = 1.0; if (rarity === 'uncommon') scale = 1.1; if (rarity === 'rare') scale = 1.2; if (rarity === 'epic') scale = 1.3; if (rarity === 'legendary') scale = 1.5; creatureGraphic.scale.set(scale, scale); cell.addChild(creatureGraphic); // Add info text var infoText = new Text2(type.toUpperCase() + '\n' + rarity.toUpperCase(), { size: 30, fill: 0xFFFFFF }); infoText.anchor.set(0.5, 0); infoText.x = cellSize / 2; infoText.y = cellSize / 2 + 40; cell.addChild(infoText); } else { // Undiscovered creature (shadow) var undiscoveredGraphic = LK.getAsset(type + 'Creature', { anchorX: 0.5, anchorY: 0.5, x: cellSize / 2, y: cellSize / 2 }); undiscoveredGraphic.alpha = 0.2; undiscoveredGraphic.tint = 0x000000; cell.addChild(undiscoveredGraphic); // Add question mark var questionText = new Text2('?', { size: 60, fill: 0x999999 }); questionText.anchor.set(0.5, 0.5); questionText.x = cellSize / 2; questionText.y = cellSize / 2; cell.addChild(questionText); } } } }; // Hide collection screen self.hide = function () { self.visible = false; }; return self; }); // Game dimensions and settings // Creature class for encounters var Creature = Container.expand(function () { var self = Container.call(this); // Creature properties self.type = 'normal'; // Default type self.rarity = 'common'; // Default rarity self.gridX = 0; self.gridY = 0; self.captured = false; // Rarity colors self.rarityColors = { common: 0xFFFFFF, uncommon: 0x00FF00, rare: 0x0000FF, epic: 0xFF00FF, legendary: 0xFFD700 }; // Type to biome mapping self.typeBiomeMap = { bug: 'forest', dark: 'mountain', dragon: 'mountain', electric: 'grass', fairy: 'forest', fighting: 'mountain', fire: 'desert', flying: 'grass', ghost: 'mountain', grass: 'grass', ground: 'desert', ice: 'mountain', normal: 'grass', poison: 'forest', psychic: 'grass', rock: 'mountain', steel: 'street', water: 'water' }; // Initialize creature with specific type, rarity, and position self.init = function (type, rarity, gridX, gridY) { self.type = type || self.getRandomType(); self.rarity = rarity || self.getRandomRarity(); self.gridX = gridX; self.gridY = gridY; // Create creature graphic var creatureGraphics = self.attachAsset(self.type + 'Creature', { anchorX: 0.5, anchorY: 0.5 }); // Apply rarity visual effect (glow or color) var rarityColor = self.rarityColors[self.rarity] || 0xFFFFFF; // Add glow effect for rare+ creatures if (self.rarity !== 'common') { // Make rarer creatures slightly larger var scale = 1.0; if (self.rarity === 'uncommon') scale = 1.1; if (self.rarity === 'rare') scale = 1.2; if (self.rarity === 'epic') scale = 1.3; if (self.rarity === 'legendary') scale = 1.5; creatureGraphics.scale.set(scale, scale); } // Position creature self.x = self.gridX * TILE_SIZE + TILE_SIZE / 2; // Center of tile self.y = self.gridY * TILE_SIZE + TILE_SIZE / 2; // Center of tile return self; }; // Generate a random creature type, weighted by biome self.getRandomType = function (biome) { // Default types for each biome var biomeTypes = { grass: ['normal', 'grass', 'bug', 'flying', 'electric', 'psychic'], water: ['water', 'ice', 'flying'], desert: ['ground', 'fire', 'rock'], forest: ['bug', 'grass', 'poison', 'fairy'], mountain: ['rock', 'fighting', 'dragon', 'dark', 'ghost', 'ice'], street: ['steel', 'electric', 'poison', 'normal', 'fighting'] }; // Get types for the provided biome, or use all types var types = biome ? biomeTypes[biome] : Object.keys(self.typeBiomeMap); // Select random type from available options return types[Math.floor(Math.random() * types.length)]; }; // Generate a random rarity based on configured probabilities self.getRandomRarity = function () { var rand = Math.random(); if (rand < 0.65) return 'common'; if (rand < 0.85) return 'uncommon'; if (rand < 0.95) return 'rare'; if (rand < 0.99) return 'epic'; return 'legendary'; }; // Animate creature during encounter self.animate = function () { // Bounce animation var originalY = self.y; // Use tween to create a bouncing effect tween(self, { y: originalY - 20 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { y: originalY }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { // Repeat animation self.animate(); } }); } }); }; // Stop animations self.stopAnimation = function () { tween.stop(self, { y: true }); }; return self; }); // Directional pad control for player movement var DPad = Container.expand(function () { var self = Container.call(this); // DPad components self.padBase = null; self.upButton = null; self.downButton = null; self.leftButton = null; self.rightButton = null; // Initialize dpad with buttons self.init = function () { // Create base of DPad self.padBase = self.attachAsset('dpad', { anchorX: 0.5, anchorY: 0.5 }); // Create directional buttons self.upButton = self.createButton(0, -65); self.downButton = self.createButton(0, 65); self.leftButton = self.createButton(-65, 0); self.rightButton = self.createButton(65, 0); // Position the entire DPad in the bottom left of the screen self.x = 200; self.y = 2500; return self; }; // Create a directional button at relative x,y from center self.createButton = function (relX, relY) { var button = self.attachAsset('dpadButton', { anchorX: 0.5, anchorY: 0.5, x: relX, y: relY }); button.interactive = true; return button; }; return self; }); // Encounter class to handle creature encounters var Encounter = Container.expand(function () { var self = Container.call(this); // Encounter state self.active = false; self.creature = null; self.captureRing = null; self.captureTarget = null; self.targetSpeed = 5; self.targetDirection = 1; self.captureAttempts = 0; self.maxAttempts = 3; // Initialize encounter screen self.init = function () { // Darkened background var bg = self.attachAsset('grassTile', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); bg.alpha = 0.7; bg.tint = 0x000000; // Initially hidden self.visible = false; return self; }; // Start encounter with a specific creature self.startEncounter = function (creature) { self.active = true; self.visible = true; self.creature = creature; self.captureAttempts = 0; // Add creature to encounter screen self.addChild(creature); creature.x = 1024; // Center horizontally creature.y = 1000; // Position in upper portion of screen // Make creature interactive to allow clicking directly on it creature.interactive = true; creature.down = function () { self.attemptCapture(); }; // Start creature animation creature.animate(); // Create capture interface self.createCaptureInterface(); // Play encounter sound LK.getSound('encounter').play(); }; // Create the capture ring and target interface self.createCaptureInterface = function () { // Capture ring self.captureRing = self.attachAsset('captureRing', { anchorX: 0.5, anchorY: 0.5, x: 1024, // Center horizontally y: 1800 // Lower portion of screen }); // Moving target self.captureTarget = self.attachAsset('captureTarget', { anchorX: 0.5, anchorY: 0.5, x: 964, // Start position (left side of ring) y: 1800 // Same Y as ring }); // Capture button var captureButton = self.attachAsset('grassTile', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2200, width: 300, height: 100 }); captureButton.tint = 0xFF0000; // Capture button text var captureText = new Text2('CAPTURE', { size: 60, fill: 0xFFFFFF }); captureText.anchor.set(0.5, 0.5); captureText.x = 1024; captureText.y = 2200; self.addChild(captureText); // Capture button event captureButton.interactive = true; captureButton.down = function () { self.attemptCapture(); }; // Leave button var leaveButton = self.attachAsset('grassTile', { anchorX: 0.5, anchorY: 0.5, x: 1700, y: 2200, width: 300, height: 100 }); leaveButton.tint = 0x888888; var leaveText = new Text2('LEAVE', { size: 60, fill: 0xFFFFFF }); leaveText.anchor.set(0.5, 0.5); leaveText.x = 1700; leaveText.y = 2200; self.addChild(leaveText); leaveButton.interactive = true; leaveButton.down = function () { // End encounter immediately, treat as fail/escape self.endEncounter(); }; // Info text about the creature var infoText = new Text2('TYPE: ' + self.creature.type.toUpperCase() + '\n' + 'RARITY: ' + self.creature.rarity.toUpperCase() + '\n' + 'ATTEMPTS: ' + (self.maxAttempts - self.captureAttempts) + ' REMAINING', { size: 50, fill: 0xFFFFFF }); infoText.anchor.set(0.5, 0); infoText.x = 1024; infoText.y = 2300; self.addChild(infoText); }; // Update function for moving the target self.update = function () { if (!self.active || !self.captureTarget) return; // Move target back and forth across the ring self.captureTarget.x += self.targetSpeed * self.targetDirection; // Reverse direction at edges if (self.captureTarget.x > 1084) { // Right edge of ring self.targetDirection = -1; } else if (self.captureTarget.x < 964) { // Left edge of ring self.targetDirection = 1; } // Make target move faster based on creature rarity var speedMultiplier = 1; if (self.creature) { if (self.creature.rarity === 'uncommon') speedMultiplier = 1.2; if (self.creature.rarity === 'rare') speedMultiplier = 1.5; if (self.creature.rarity === 'epic') speedMultiplier = 1.8; if (self.creature.rarity === 'legendary') speedMultiplier = 2.2; } self.targetSpeed = 5 * speedMultiplier; }; // Attempt to capture the creature self.attemptCapture = function () { // Play capture sound LK.getSound('capture').play(); self.captureAttempts++; // Check if target is in center zone (successful capture) var distanceFromCenter = Math.abs(self.captureTarget.x - 1024); var successZone = 15; // Size of "perfect" zone // Adjust success zone based on rarity (harder for rarer creatures) if (self.creature.rarity === 'uncommon') successZone = 13; if (self.creature.rarity === 'rare') successZone = 10; if (self.creature.rarity === 'epic') successZone = 8; if (self.creature.rarity === 'legendary') successZone = 5; var captured = distanceFromCenter <= successZone; if (captured) { // Success! self.captureSuccess(); } else if (self.captureAttempts >= self.maxAttempts) { // Failed after max attempts self.captureFail(); } else { // Update attempts remaining text var remainingText = self.children.filter(function (child) { return child instanceof Text2 && child.y === 2300; })[0]; if (remainingText) { remainingText.setText('TYPE: ' + self.creature.type.toUpperCase() + '\n' + 'RARITY: ' + self.creature.rarity.toUpperCase() + '\n' + 'ATTEMPTS: ' + (self.maxAttempts - self.captureAttempts) + ' REMAINING'); } } }; // Handle successful capture self.captureSuccess = function () { // Play success sound LK.getSound('success').play(); // Add to collection if (!storage.discoveredCreatures) { storage.discoveredCreatures = {}; } var creatureKey = self.creature.type + '-' + self.creature.rarity; storage.discoveredCreatures[creatureKey] = true; // Show success message var successText = new Text2('CAPTURED!', { size: 100, fill: 0x00FF00 }); successText.anchor.set(0.5, 0.5); successText.x = 1024; successText.y = 1400; self.addChild(successText); // Flash screen LK.effects.flashScreen(0x00FF00, 500); // End encounter after delay LK.setTimeout(function () { self.endEncounter(); }, 1500); }; // Handle failed capture self.captureFail = function () { // Show fail message var failText = new Text2('ESCAPED!', { size: 100, fill: 0xFF0000 }); failText.anchor.set(0.5, 0.5); failText.x = 1024; failText.y = 1400; self.addChild(failText); // Flash screen LK.effects.flashScreen(0xFF0000, 500); // End encounter after delay LK.setTimeout(function () { self.endEncounter(); }, 1500); }; // End the current encounter self.endEncounter = function () { if (self.creature) { self.creature.stopAnimation(); } self.active = false; self.visible = false; // Remove all children while (self.children.length > 0) { self.removeChild(self.children[0]); } self.creature = null; self.captureRing = null; self.captureTarget = null; // Reinitialize for next encounter self.init(); // Also set encounterActive to false so game resumes if (typeof encounterActive !== "undefined") { encounterActive = false; } }; return self; }); // GameMap represents the entire game map with different biomes var GameMap = Container.expand(function () { var self = Container.call(this); self.mapWidth = 60; // Number of tiles horizontally (max size, increased) self.mapHeight = 60; // Number of tiles vertically (max size, increased) self.tileSize = 240; // Size of each tile in pixels (increased to match TILE_SIZE) self.tiles = []; // 2D array to hold all map tiles // Biome generation parameters self.biomeTypes = ['grass', 'water', 'desert', 'forest', 'mountain', 'street']; self.biomeSeeds = []; // Points from which biomes spread // Initialize map with biomes self.initMap = function () { // Create empty 2D array for tiles for (var y = 0; y < self.mapHeight; y++) { self.tiles[y] = []; for (var x = 0; x < self.mapWidth; x++) { self.tiles[y][x] = null; } } // Place biome seeds self.placeBiomeSeeds(); // Generate biomes from seeds self.generateBiomes(); // --- Flood fill to ensure all tiles are connected (no black dots) --- var visited = []; for (var y = 0; y < self.mapHeight; y++) { visited[y] = []; for (var x = 0; x < self.mapWidth; x++) { visited[y][x] = false; } } // Start flood fill from center of map var startX = Math.floor(self.mapWidth / 2); var startY = Math.floor(self.mapHeight / 2); var startBiome = self.tiles[startY][startX]; var queue = [{ x: startX, y: startY }]; visited[startY][startX] = true; while (queue.length > 0) { var pos = queue.shift(); var dirs = [{ dx: 1, dy: 0 }, { dx: -1, dy: 0 }, { dx: 0, dy: 1 }, { dx: 0, dy: -1 }]; for (var d = 0; d < dirs.length; d++) { var nx = pos.x + dirs[d].dx; var ny = pos.y + dirs[d].dy; if (nx >= 0 && nx < self.mapWidth && ny >= 0 && ny < self.mapHeight && !visited[ny][nx]) { // Only connectable if not "dark" if (self.tiles[ny][nx] !== "dark") { visited[ny][nx] = true; queue.push({ x: nx, y: ny }); } } } } // Any tile not visited is unreachable, so set it to the most common neighbor biome for (var y = 0; y < self.mapHeight; y++) { for (var x = 0; x < self.mapWidth; x++) { if (!visited[y][x]) { // Find most common neighbor biome (not dark) var biomeCount = {}; for (var dy = -1; dy <= 1; dy++) { for (var dx = -1; dx <= 1; dx++) { var nx = x + dx; var ny = y + dy; if (nx >= 0 && nx < self.mapWidth && ny >= 0 && ny < self.mapHeight && (dx !== 0 || dy !== 0)) { var b = self.tiles[ny][nx]; if (b && b !== "dark") { if (!biomeCount[b]) biomeCount[b] = 0; biomeCount[b]++; } } } } // Pick the most common neighbor biome, fallback to "grass" var maxCount = 0; var bestBiome = "grass"; for (var b in biomeCount) { if (biomeCount[b] > maxCount) { maxCount = biomeCount[b]; bestBiome = b; } } self.tiles[y][x] = bestBiome; } } } // Create tiles based on biome map self.createTiles(); return self; }; // Place seed points for biome generation self.placeBiomeSeeds = function () { // Place one seed for each biome for (var i = 0; i < self.biomeTypes.length; i++) { var seed = { x: Math.floor(Math.random() * self.mapWidth), y: Math.floor(Math.random() * self.mapHeight), biome: self.biomeTypes[i] }; self.biomeSeeds.push(seed); } }; // Generate biomes from seed points using a simple distance-based algorithm self.generateBiomes = function () { for (var y = 0; y < self.mapHeight; y++) { for (var x = 0; x < self.mapWidth; x++) { // Find closest biome seed var closestDist = Number.MAX_VALUE; var closestBiome = 'grass'; // Default for (var i = 0; i < self.biomeSeeds.length; i++) { var seed = self.biomeSeeds[i]; var dist = Math.sqrt(Math.pow(x - seed.x, 2) + Math.pow(y - seed.y, 2)); // Add some randomness to make borders less regular dist += Math.random() * 3 - 1.5; if (dist < closestDist) { closestDist = dist; closestBiome = seed.biome; } } self.tiles[y][x] = closestBiome; } } // Add some randomness and blending between biomes self.refineBiomes(); }; // Add more natural transitions between biomes with street patterns self.refineBiomes = function () { // Create a deep copy of tiles array var tempTiles = []; for (var y = 0; y < self.mapHeight; y++) { tempTiles[y] = []; for (var x = 0; x < self.mapWidth; x++) { tempTiles[y][x] = self.tiles[y][x]; } } // Create street grid patterns // Find street biome seed var streetSeedX = -1; var streetSeedY = -1; for (var i = 0; i < self.biomeSeeds.length; i++) { if (self.biomeSeeds[i].biome === 'street') { streetSeedX = self.biomeSeeds[i].x; streetSeedY = self.biomeSeeds[i].y; break; } } // If we have a street seed, create grid pattern around it if (streetSeedX >= 0 && streetSeedY >= 0) { // Create street grid - horizontal and vertical streets var streetRadius = 8; // Size of urban area var streetGridSpacing = 3; // Distance between streets for (var y = Math.max(0, streetSeedY - streetRadius); y < Math.min(self.mapHeight, streetSeedY + streetRadius); y++) { for (var x = Math.max(0, streetSeedX - streetRadius); x < Math.min(self.mapWidth, streetSeedX + streetRadius); x++) { // Check if within street biome core radius var distToSeed = Math.sqrt(Math.pow(x - streetSeedX, 2) + Math.pow(y - streetSeedY, 2)); if (distToSeed <= streetRadius) { // Street grid pattern: create roads at regular intervals if (x % streetGridSpacing === 0 || y % streetGridSpacing === 0) { self.tiles[y][x] = 'street'; } // Building blocks between streets else if (self.tiles[y][x] === 'street') { // Determine building type based on position in grid - some variety within urban areas if ((x + y) % 2 === 0) { self.tiles[y][x] = 'street'; // Keep as urban (tall buildings) } else { // Mix with nearby biomes occasionally for parks, etc. if (Math.random() < 0.3) { var nearbyNonStreetBiome = ''; // Look for any non-street biome nearby for (var ny = y - 1; ny <= y + 1; ny++) { for (var nx = x - 1; nx <= x + 1; nx++) { if (ny >= 0 && ny < self.mapHeight && nx >= 0 && nx < self.mapWidth) { if (self.tiles[ny][nx] !== 'street' && self.tiles[ny][nx] !== undefined) { nearbyNonStreetBiome = self.tiles[ny][nx]; break; } } } if (nearbyNonStreetBiome) break; } // If found nearby non-street biome, use it, otherwise keep as street if (nearbyNonStreetBiome) { self.tiles[y][x] = nearbyNonStreetBiome; } } } } } } } } // Now apply regular biome smoothing for (var y = 1; y < self.mapHeight - 1; y++) { for (var x = 1; x < self.mapWidth - 1; x++) { // Skip street grid areas var distToStreetSeed = streetSeedX >= 0 ? Math.sqrt(Math.pow(x - streetSeedX, 2) + Math.pow(y - streetSeedY, 2)) : Number.MAX_VALUE; if (distToStreetSeed <= streetRadius && (x % streetGridSpacing === 0 || y % streetGridSpacing === 0)) { continue; // Skip street grid lines } // Count neighboring biomes var biomeCount = {}; for (var ny = y - 1; ny <= y + 1; ny++) { for (var nx = x - 1; nx <= x + 1; nx++) { // Check that neighbor coordinates are valid if (ny >= 0 && ny < self.mapHeight && nx >= 0 && nx < self.mapWidth) { var neighborBiome = tempTiles[ny][nx]; if (neighborBiome) { if (!biomeCount[neighborBiome]) { biomeCount[neighborBiome] = 0; } biomeCount[neighborBiome]++; } } } } // Random chance to convert to most common neighbor if (Math.random() < 0.4) { var mostCommon = tempTiles[y][x]; var maxCount = 0; for (var biome in biomeCount) { if (biomeCount.hasOwnProperty(biome) && biomeCount[biome] > maxCount) { maxCount = biomeCount[biome]; mostCommon = biome; } } self.tiles[y][x] = mostCommon; } } } }; // Create actual tile objects based on the biome map self.createTiles = function () { for (var y = 0; y < self.mapHeight; y++) { for (var x = 0; x < self.mapWidth; x++) { var biomeType = self.tiles[y][x]; var tile = new MapTile().initTile(biomeType, x, y); self.addChild(tile); } } }; // Get tile at grid coordinates self.getTileAt = function (gridX, gridY) { // Ensure coordinates are within bounds if (gridX < 0 || gridX >= self.mapWidth || gridY < 0 || gridY >= self.mapHeight) { return null; } // Find the tile in the children for (var i = 0; i < self.children.length; i++) { var tile = self.children[i]; if (tile.gridX === gridX && tile.gridY === gridY) { return tile; } } return null; }; return self; }); // MapTile represents a single tile in the game grid var MapTile = Container.expand(function () { var self = Container.call(this); self.biomeType = 'grass'; // Default biome self.tileSize = 240; // Increased to match TILE_SIZE self.hasCreature = false; self.explored = false; self.x = 0; self.y = 0; self.gridX = 0; self.gridY = 0; // Initialize the tile with a specific biome self.initTile = function (biomeType, gridX, gridY) { self.biomeType = biomeType; self.gridX = gridX; self.gridY = gridY; self.x = gridX * self.tileSize - gridX * 1; self.y = gridY * self.tileSize - gridY * 1; // Get the appropriate tile asset based on biome var assetId = self.biomeType + 'Tile'; // Create a container to hold 4 quadrant images self.quadrantTiles = []; for (var qy = 0; qy < 2; qy++) { for (var qx = 0; qx < 2; qx++) { var quad = self.attachAsset(assetId, { anchorX: 0, anchorY: 0, width: self.tileSize / 2 + 2, // Add 2px overlap to eliminate black dots height: self.tileSize / 2 + 2, // Add 2px overlap to eliminate black dots x: qx * self.tileSize / 2 - (qx > 0 ? 1 : 0), y: qy * self.tileSize / 2 - (qy > 0 ? 1 : 0) }); quad.alpha = 0.9; self.quadrantTiles.push(quad); } } // Add fog overlay for undiscovered tiles self.fogOverlay = self.attachAsset('grassTile', { anchorX: 0, anchorY: 0, width: self.tileSize, height: self.tileSize }); self.fogOverlay.alpha = 0.7; self.fogOverlay.tint = 0x222222; self.fogOverlay.visible = true; // Random chance to spawn a creature based on biome (further reduced for less frequent spawning) if (Math.random() < 0.02) { self.hasCreature = true; var indicator = self.attachAsset('encounterIndicator', { anchorX: 0.5, anchorY: 0.5, x: self.tileSize / 2, y: self.tileSize / 2 }); indicator.alpha = 0.7; } return self; }; // Mark tile as explored self.explore = function () { if (!self.explored) { self.explored = true; // Hide fog overlay if present if (self.fogOverlay) { self.fogOverlay.visible = false; } // Add to explored areas in storage var exploredKey = self.gridX + "," + self.gridY; if (!storage.exploredTiles) storage.exploredTiles = {}; storage.exploredTiles[exploredKey] = true; } }; return self; }); // MiniMap class to show explored areas var MiniMap = Container.expand(function () { var self = Container.call(this); // MiniMap components self.mapBackground = null; self.playerMarker = null; self.tileMarkers = []; self.mapSize = 300; self.scale = 0.1; // How much of the full map to show // Initialize minimap self.init = function () { // Create background self.mapBackground = self.attachAsset('minimap', { anchorX: 0, anchorY: 0, width: self.mapSize, height: self.mapSize }); // Create player marker self.playerMarker = self.attachAsset('minimapMarker', { anchorX: 0.5, anchorY: 0.5, x: self.mapSize / 2, y: self.mapSize / 2 }); // Position minimap in top right corner self.x = 2048 - self.mapSize - 20; self.y = 20; return self; }; // Update minimap with current player position and explored tiles self.update = function (player, gameMap) { // Check if player and gameMap are defined if (!player || !gameMap) return; // Update player marker position var centerX = self.mapSize / 2; var centerY = self.mapSize / 2; // Position marker relative to center self.playerMarker.x = centerX; self.playerMarker.y = centerY; // Clear existing tile markers for (var i = 0; i < self.tileMarkers.length; i++) { self.removeChild(self.tileMarkers[i]); } self.tileMarkers = []; // Add markers for visible tiles around player var visibleRadius = Math.floor(self.mapSize / (2 * 10)); // 10px per tile for (var y = player.gridY - visibleRadius; y <= player.gridY + visibleRadius; y++) { for (var x = player.gridX - visibleRadius; x <= player.gridX + visibleRadius; x++) { var tile = gameMap.getTileAt(x, y); if (tile && tile.explored) { // Create marker with biome color var color = 0x33cc33; // Default grass if (tile.biomeType === 'water') color = 0x3399ff; if (tile.biomeType === 'desert') color = 0xe6cc99; if (tile.biomeType === 'forest') color = 0x006600; if (tile.biomeType === 'mountain') color = 0x999999; if (tile.biomeType === 'street') color = 0x666666; var marker = new Container(); var markerGraphics = LK.getAsset('grassTile', { anchorX: 0, anchorY: 0, width: 10, height: 10 }); markerGraphics.tint = color; marker.addChild(markerGraphics); // Position marker relative to player marker.x = centerX + (x - player.gridX) * 10; marker.y = centerY + (y - player.gridY) * 10; self.addChild(marker); self.tileMarkers.push(marker); } } } }; return self; }); // Player character with integrated vision logic var Player = Container.expand(function () { var self = Container.call(this); // Player properties self.gridX = 10; // Starting X position on grid (max map) self.gridY = 10; // Starting Y position on grid (max map) self.moveSpeed = 0.2; // Movement animation speed self.moving = false; self.lastGridX = 10; self.lastGridY = 10; self.visionRadius = 2; // Reduced vision radius in blocks // New: sub-tile position (0=left, 1=right for X; 0=up, 1=down for Y) self.subTileX = 0; self.subTileY = 0; // New: quadrant label self.quadrantLabel = null; // Initialize player with graphics self.init = function () { var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Add quadrant label self.quadrantLabel = new Text2('', { size: 40, fill: 0xffff00 }); self.quadrantLabel.anchor.set(0.5, 1); self.quadrantLabel.x = 0; self.quadrantLabel.y = -90; self.addChild(self.quadrantLabel); // Load position from storage if available if (storage.playerPosition) { self.gridX = storage.playerPosition.x; self.gridY = storage.playerPosition.y; self.lastGridX = self.gridX; self.lastGridY = self.gridY; // Always force subTileX and subTileY to 0 (center) self.subTileX = 0; self.subTileY = 0; } // Update position based on grid coordinates self.updatePosition(); return self; }; // Move player to specific grid coordinates self.moveToGrid = function (newGridX, newGridY, newSubTileX, newSubTileY) { if (self.moving) return; // Don't interrupt current movement // Default sub-tile values if not provided if (typeof newSubTileX === "undefined") newSubTileX = 0; if (typeof newSubTileY === "undefined") newSubTileY = 0; // Clamp sub-tile values if (newSubTileX < 0) newSubTileX = 0; if (newSubTileX > 1) newSubTileX = 1; if (newSubTileY < 0) newSubTileY = 0; if (newSubTileY > 1) newSubTileY = 1; // Store last position for comparison self.lastGridX = self.gridX; self.lastGridY = self.gridY; // Prevent movement onto dark (black) blocks if (typeof gameMap !== "undefined") { var targetTile = gameMap.getTileAt(newGridX, newGridY); if (targetTile && targetTile.biomeType === "dark") { // Block movement, do not update grid position return; } } // Update grid and sub-tile position self.gridX = newGridX; self.gridY = newGridY; self.subTileX = newSubTileX; self.subTileY = newSubTileY; // Save position to storage storage.playerPosition = { x: self.gridX, y: self.gridY, subTileX: self.subTileX, subTileY: self.subTileY }; // Animate movement and update vision after movement finishes self.moving = true; // Move to the correct sub-tile center var offsetX = TILE_SIZE / 4 + self.subTileX * TILE_SIZE / 2; var offsetY = TILE_SIZE / 4 + self.subTileY * TILE_SIZE / 2; var targetX = self.gridX * TILE_SIZE + offsetX; var targetY = self.gridY * TILE_SIZE + offsetY; // Animate vision update to be much faster than player movement var visionTweenDuration = 200; // Vision moves even faster for better centering var playerTweenDuration = 350; // Player moves slightly faster for better responsiveness // Start vision tween first if (typeof gameMap !== "undefined" && typeof self.updateVision === "function") { // Animate a dummy property to trigger vision update visually var visionObj = { progress: 0 }; tween(visionObj, { progress: 1 }, { duration: visionTweenDuration, easing: tween.easeOut, onUpdate: function onUpdate() { // Update vision during tween for smooth effect self.updateVision(gameMap); } }); } // Then animate player movement tween(self, { x: targetX, y: targetY }, { duration: playerTweenDuration, // Slower movement (player is slower than vision) easing: tween.easeOut, onFinish: function onFinish() { self.moving = false; // Only update vision after movement is complete for optimized vision if (typeof gameMap !== "undefined") { self.updateVision(gameMap); } } }); // Always clear quadrant label since player is always at center if (self.quadrantLabel) self.quadrantLabel.setText(''); // Call onQuadrantChange with 'CENTER' label for compatibility if (typeof self.onQuadrantChange === "function") { self.onQuadrantChange(self.gridX, self.gridY, self.subTileX, self.subTileY, 'CENTER'); } }; // Update position based on current grid coordinates (no animation) self.updatePosition = function () { // Position player at the center of the correct sub-tile var offsetX = TILE_SIZE / 4 + self.subTileX * TILE_SIZE / 2; var offsetY = TILE_SIZE / 4 + self.subTileY * TILE_SIZE / 2; self.x = self.gridX * TILE_SIZE + offsetX; self.y = self.gridY * TILE_SIZE + offsetY; // Hide player sprite if on dark (black) block if (typeof gameMap !== "undefined") { var tile = gameMap.getTileAt(self.gridX, self.gridY); if (tile && tile.biomeType === "dark") { self.visible = false; } else { self.visible = true; // Mark this tile as discovered if not already if (tile && !tile.explored) { tile.explore(); } } } else { self.visible = true; } // No longer force sub-tile to 0 (center) when updating position // Only update vision if not moving, to optimize vision updates if (!self.moving && typeof gameMap !== "undefined" && typeof self.updateVision === "function") { self.updateVision(gameMap); } // Always clear quadrant label since player is always at center if (self.quadrantLabel) self.quadrantLabel.setText(''); // Call onQuadrantChange with 'CENTER' label for compatibility if (typeof self.onQuadrantChange === "function") { self.onQuadrantChange(self.gridX, self.gridY, self.subTileX, self.subTileY, 'CENTER'); } // Ensure player is always above the tile and centered after update if (typeof game !== "undefined" && self.parent !== game) { game.addChild(self); } self.scale.set(gameMap.scale.x, gameMap.scale.y); self.visible = true; }; // Update vision: show/hide tiles based on a smaller vision angle, and save seen tiles as memory self.updateVision = function (gameMap) { // Vision area: always center player in the middle of the vision area for optimized movement var visionRadius = 3; // Reduced from 5 to 3 for smaller vision var minX = Math.max(0, self.gridX - visionRadius); var maxX = Math.min(MAP_WIDTH - 1, self.gridX + visionRadius); var minY = Math.max(0, self.gridY - visionRadius); var maxY = Math.min(MAP_HEIGHT - 1, self.gridY + visionRadius); for (var y = 0; y < MAP_HEIGHT; y++) { for (var x = 0; x < MAP_WIDTH; x++) { var tile = gameMap.getTileAt(x, y); if (tile) { // Calculate distance from player - properly centered now var dx = Math.abs(x - self.gridX); var dy = Math.abs(y - self.gridY); // Only show tiles within a diamond-shaped vision area (Manhattan distance <= visionRadius) if (dx + dy <= visionRadius) { tile.visible = true; // Mark as explored and save to memory if (!tile.explored) { tile.explored = true; var exploredKey = x + "," + y; if (!storage.exploredTiles) storage.exploredTiles = {}; storage.exploredTiles[exploredKey] = true; } // Hide fog overlay if present (only for tiles currently in vision) if (tile.fogOverlay) { tile.fogOverlay.visible = false; } // --- Show both spawned and despawned creatures in vision --- // In vision area: show both spawned and despawned creatures // Remove all faded indicators first to avoid duplicates for (var c = tile.children.length - 1; c >= 0; c--) { if (tile.children[c].assetId === 'encounterIndicator' && tile.children[c].alpha === 0.25) { tile.removeChild(tile.children[c]); } } // If a creature is currently spawned, mark that this tile has ever had a creature if (tile.hasCreature) { tile._everHadCreature = true; } // Show indicator for spawned creature if (tile.hasCreature) { // If no indicator present, add one var hasIndicator = false; for (var c = 0; c < tile.children.length; c++) { if (tile.children[c].assetId === 'encounterIndicator' && tile.children[c].alpha === 0.7) { hasIndicator = true; break; } } if (!hasIndicator) { var indicator = tile.attachAsset('encounterIndicator', { anchorX: 0.5, anchorY: 0.5, x: tile.tileSize / 2, y: tile.tileSize / 2 }); indicator.alpha = 0.7; } } // Show faded indicator for despawned creature (if ever had creature, but not currently spawned) if (tile._everHadCreature && !tile.hasCreature) { var alreadyFaded = false; for (var c = 0; c < tile.children.length; c++) { if (tile.children[c].assetId === 'encounterIndicator' && tile.children[c].alpha === 0.25) { alreadyFaded = true; break; } } if (!alreadyFaded) { var fadedIndicator = tile.attachAsset('encounterIndicator', { anchorX: 0.5, anchorY: 0.5, x: tile.tileSize / 2, y: tile.tileSize / 2 }); fadedIndicator.alpha = 0.25; } } // --- End show both spawned and despawned creatures in vision --- } else { // Out of vision: hide all encounter indicators (spawned and despawned) in foggy/unvision area for (var c = tile.children.length - 1; c >= 0; c--) { if (tile.children[c].assetId === 'encounterIndicator') { tile.removeChild(tile.children[c]); } } // Hide all creatures in foggy area: do not show any indicators or creatures tile.visible = true; // Show fog overlay for out-of-vision tiles if (tile.fogOverlay) { tile.fogOverlay.visible = true; } } } } // Called whenever the player moves to a new quadrant of a tile self.onQuadrantChange = function (gridX, gridY, subTileX, subTileY, label) { // Example: you can add your own logic here to check which quadrant the player is in // For example, trigger something if in DOWN LEFT // gridX, gridY: tile coordinates // subTileX, subTileY: 0 or 1 (0=left/up, 1=right/down) // label: string label of the quadrant }; // Example: log which quadrant the player is in // console.log("Player is at tile (" + gridX + "," + gridY + ") in quadrant: " + label); // You can add more logic here, e.g.: // if (subTileX === 0 && subTileY === 1) { /* DOWN LEFT */ } // if (subTileX === 1 && subTileY === 0) { /* UP RIGHT */ } // etc. } ; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Sounds // Encounter indicator // UI elements // Creatures by elemental type // Map tiles // Player character // Storage for saving game progress // Tween for animations // Game dimensions and settings // JSON helper functions for parsing and stringifying function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function parseJSON(str) { var result = {}; if (typeof str === 'string') { try { var pairs = str.slice(1, -1).split(','); for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].trim().split(':'); var key = pair[0].replace(/["']/g, '').trim(); var value = pair[1].trim(); if (value.startsWith('[') && value.endsWith(']')) { result[key] = parseJSONArray(value); } else if (value.startsWith('{') && value.endsWith('}')) { result[key] = parseJSON(value); } else if (value === 'true') { result[key] = true; } else if (value === 'false') { result[key] = false; } else if (!isNaN(value)) { result[key] = Number(value); } else { result[key] = value.replace(/["']/g, ''); } } } catch (e) { console.log('Error parsing JSON: ', e); } } return result; } function parseJSONArray(str) { var result = []; if (typeof str === 'string') { try { var items = str.slice(1, -1).split(','); for (var i = 0; i < items.length; i++) { var item = items[i].trim(); if (item.startsWith('[') && item.endsWith(']')) { result.push(parseJSONArray(item)); } else if (item.startsWith('{') && item.endsWith('}')) { result.push(parseJSON(item)); } else if (item === 'true') { result.push(true); } else if (item === 'false') { result.push(false); } else if (!isNaN(item)) { result.push(Number(item)); } else { result.push(item.replace(/["']/g, '')); } } } catch (e) { console.log('Error parsing JSON array: ', e); } } return result; } function stringifyJSON(obj) { if (Array.isArray(obj)) { var items = []; for (var i = 0; i < obj.length; i++) { items.push(stringifyJSON(obj[i])); } return '[' + items.join(',') + ']'; } else if (_typeof(obj) === 'object' && obj !== null) { var pairs = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { pairs.push('"' + key + '":' + stringifyJSON(obj[key])); } } return '{' + pairs.join(',') + '}'; } else if (typeof obj === 'string') { return '"' + obj.replace(/"/g, '\\"') + '"'; } else { return String(obj); } } var TILE_SIZE = 240; // Increased from 200 to 240 for bigger tiles var MAP_WIDTH = 60; // Increased from 30 to 60 for a bigger world var MAP_HEIGHT = 60; // Increased from 30 to 60 for a bigger world // Initialize game objects var gameMap = game.addChild(new GameMap().initMap()); gameMap.scale.set(1.5, 1.5); // Place player at 0,0 and ensure 0,0 is a grass tile with player in up left quadrant // Set new tile size to 240 for all tiles TILE_SIZE = 240; if (gameMap.tiles && gameMap.tiles[0] && gameMap.tiles[0][0]) { gameMap.tiles[0][0] = "grass"; // Also update the MapTile object if already created var tileObj = gameMap.getTileAt(0, 0); if (tileObj) { tileObj.biomeType = "grass"; tileObj.tileSize = TILE_SIZE; // Optionally update the tile graphics if needed } } // Spawn player at 15,15 coordinates var playerStartX = 15; var playerStartY = 15; var playerStartSubTileX = 0; var playerStartSubTileY = 0; // Ensure 15,15 is a valid tile (set to grass if not) if (gameMap.tiles && gameMap.tiles[15] && gameMap.tiles[15][15]) { gameMap.tiles[15][15] = "grass"; var tileObj = gameMap.getTileAt(15, 15); if (tileObj) { tileObj.biomeType = "grass"; tileObj.tileSize = TILE_SIZE; } } storage.playerPosition = { x: playerStartX, y: playerStartY, subTileX: playerStartSubTileX, subTileY: playerStartSubTileY }; var player = new Player().init(); player.gridX = playerStartX; player.gridY = playerStartY; player.lastGridX = playerStartX; player.lastGridY = playerStartY; player.subTileX = playerStartSubTileX; player.subTileY = playerStartSubTileY; player.updatePosition(); // After initial position, center the view so player is in the center of the screen and on top of the tile centerViewOnPlayer(); // Ensure player is always above all map tiles and scaled to match map player.scale.set(gameMap.scale.x, gameMap.scale.y); // Always add player after gameMap so it is above all tiles if (player.parent !== game) { game.addChild(player); } player.visible = true; // Explicitly set player visible in case it was hidden // Mark starting tile as explored and discovered var startTile2 = gameMap.getTileAt(playerStartX, playerStartY); if (startTile2 && !startTile2.explored) { startTile2.explore(); } var dpad = game.addChild(new DPad().init()); var minimap = game.addChild(new MiniMap().init()); var encounter = game.addChild(new Encounter().init()); var collection = game.addChild(new Collection().init()); // Collection button (top right corner) var collectionButton = game.attachAsset('dpadButton', { anchorX: 0.5, anchorY: 0.5, x: 1900, y: 150 }); collectionButton.interactive = true; // Collection button icon var collectionText = new Text2('COL', { size: 30, fill: 0xFFFFFF }); collectionText.anchor.set(0.5, 0.5); collectionText.x = 1900; collectionText.y = 150; game.addChild(collectionText); // Game stats text display var statsText = new Text2('Collected: 0/90\nExplored: 0%', { size: 40, fill: 0xFFFFFF }); statsText.anchor.set(0, 0); statsText.x = 150; statsText.y = 50; game.addChild(statsText); // Game variables var encounterActive = false; var exploredCount = 0; var totalTiles = MAP_WIDTH * MAP_HEIGHT; // Update stats display function updateStats() { var discoveredCount = Object.keys(storage.discoveredCreatures || {}).length; var exploredPercent = Math.floor(exploredCount / totalTiles * 100); statsText.setText('Collected: ' + discoveredCount + '/90\n' + 'Explored: ' + exploredPercent + '%'); } // Center the game view on player function centerViewOnPlayer() { // Calculate offset to center player // Player should be visually centered on the screen, and appear on top of the tile // 1024,1366 is the center of the screen (2048x2732) // Player's anchor is 0.5,0.5 so its center is at player.x, player.y // The map should be offset so that the player's center aligns with the screen center var offsetX = 1024 - player.x; var offsetY = 1366 - player.y; gameMap.x = offsetX; gameMap.y = offsetY; // Also ensure player is visually above the tile and at the correct z-order if (player.parent !== game) { game.addChild(player); } // Make sure player is at the correct scale and visible player.scale.set(gameMap.scale.x, gameMap.scale.y); player.visible = true; } // Handle player movement from DPad (move exactly 1 block per input) dpad.upButton.down = function () { if (!encounterActive && !player.moving) { // Move up by half a tile (decrease Y by 0.5) if (player.gridY > 0 || player.gridY === 0 && player.subTileY > 0) { var newGridY = player.gridY; var newSubTileY = player.subTileY - 1; if (newSubTileY < 0) { newGridY -= 1; newSubTileY = 1; } player.moveToGrid(player.gridX, newGridY, player.subTileX, newSubTileY); } } }; dpad.downButton.down = function () { if (!encounterActive && !player.moving) { // Move down by half a tile (increase Y by 0.5) if (player.gridY < MAP_HEIGHT - 1 || player.gridY === MAP_HEIGHT - 1 && player.subTileY < 1) { var newGridY = player.gridY; var newSubTileY = player.subTileY + 1; if (newSubTileY > 1) { newGridY += 1; newSubTileY = 0; } player.moveToGrid(player.gridX, newGridY, player.subTileX, newSubTileY); } } }; dpad.leftButton.down = function () { if (!encounterActive && !player.moving) { // Move left by half a tile (decrease X by 0.5) if (player.gridX > 0 || player.gridX === 0 && player.subTileX > 0) { var newGridX = player.gridX; var newSubTileX = player.subTileX - 1; if (newSubTileX < 0) { newGridX -= 1; newSubTileX = 1; } player.moveToGrid(newGridX, player.gridY, newSubTileX, player.subTileY); } } }; dpad.rightButton.down = function () { if (!encounterActive && !player.moving) { // Move right by half a tile (increase X by 0.5) if (player.gridX < MAP_WIDTH - 1 || player.gridX === MAP_WIDTH - 1 && player.subTileX < 1) { var newGridX = player.gridX; var newSubTileX = player.subTileX + 1; if (newSubTileX > 1) { newGridX += 1; newSubTileX = 0; } player.moveToGrid(newGridX, player.gridY, newSubTileX, player.subTileY); } } }; // Always start the player centered in the vision area player.gridX = playerStartX; player.gridY = playerStartY; player.lastGridX = playerStartX; player.lastGridY = playerStartY; player.updatePosition(); // Handle collection button collectionButton.down = function () { if (!encounterActive) { collection.show(); } }; // Handle collection close button collection.closeButton.down = function () { collection.hide(); }; // Track last player position to detect changes var lastPlayerGridX = player.gridX; var lastPlayerGridY = player.gridY; // Main game update loop // Throttle update to 44FPS (every ~23ms) var lastUpdateTime = 0; game.update = function () { var now = Date.now(); if (lastUpdateTime && now - lastUpdateTime < 23) { return; } lastUpdateTime = now; // --- Creature spawn/despawn logic --- // We'll use a global array to track visible creatures on the map if (typeof mapCreatures === "undefined") { mapCreatures = []; mapCreatureTiles = []; mapCreatureLabels = []; mapCreatureMax = 6; // Max creatures on map at once (reduced for harder spawning) mapCreatureSpawnCooldown = 0; } // Despawn creatures sometimes (randomly, or if their tile is explored) for (var i = mapCreatures.length - 1; i >= 0; i--) { var tile = mapCreatureTiles[i]; // Despawn if tile is explored or random chance if (!tile || tile.explored || Math.random() < 0.01) { // Remove label if present if (mapCreatureLabels[i]) { tile && tile.removeChild(mapCreatureLabels[i]); mapCreatureLabels.splice(i, 1); } // Remove indicator if present if (tile && tile.hasCreature) { tile.hasCreature = false; // Remove encounterIndicator for (var j = 0; j < tile.children.length; j++) { if (tile.children[j].assetId === 'encounterIndicator') { tile.removeChild(tile.children[j]); break; } } } mapCreatures.splice(i, 1); mapCreatureTiles.splice(i, 1); continue; } } // Spawn new creatures sometimes, up to max if (mapCreatures.length < mapCreatureMax && mapCreatureSpawnCooldown <= 0) { // Try to spawn a new creature var tries = 0; while (tries < 10 && mapCreatures.length < mapCreatureMax) { var gx = Math.floor(Math.random() * MAP_WIDTH); var gy = Math.floor(Math.random() * MAP_HEIGHT); var tile = gameMap.getTileAt(gx, gy); // Only spawn on tiles that are not explored, not dark, not already with a creature, and are crossable by the player // Crossable: not water, not dark, not mountain (if you want to restrict more, add more biomeType checks) var crossable = tile && tile.biomeType !== "dark"; // Optionally, restrict further: e.g. not water, not mountain // crossable = crossable && tile.biomeType !== "water" && tile.biomeType !== "mountain"; if (tile && !tile.explored && !tile.hasCreature && crossable) { // Mark tile as having a creature tile.hasCreature = true; // Add indicator var indicator = tile.attachAsset('encounterIndicator', { anchorX: 0.5, anchorY: 0.5, x: tile.tileSize / 2, y: tile.tileSize / 2 }); indicator.alpha = 0.7; // Pick a random type for this biome var cType = new Creature().getRandomType(tile.biomeType); mapCreatures.push(cType); mapCreatureTiles.push(tile); // No type label writing for bug ground type mapCreatureLabels.push(null); } tries++; } // Add a much longer cooldown so we don't spawn every frame (increased for much less frequent spawning) mapCreatureSpawnCooldown = 180 + Math.floor(Math.random() * 120); // 3-5s } else { mapCreatureSpawnCooldown--; } // --- End creature spawn/despawn logic --- // Skip updates if in an active encounter if (encounterActive) { encounter.update(); return; } // Check if collection is visible if (collection.visible) { return; } // Center view on player centerViewOnPlayer(); // Update minimap minimap.update(player, gameMap); // Vision update is now handled after player movement for optimization // Check if player has moved to a new tile if (player.gridX !== lastPlayerGridX || player.gridY !== lastPlayerGridY) { // Get the current tile var currentTile = gameMap.getTileAt(player.gridX, player.gridY); if (currentTile) { // Mark tile as explored if it's new if (!currentTile.explored) { currentTile.explore(); exploredCount++; updateStats(); } // Prevent encounters on dark (black) blocks if (currentTile.biomeType !== "dark" && currentTile.hasCreature) { // Always trigger encounter if player and creature cross encounterActive = true; // Create creature based on biome var creatureType = new Creature().getRandomType(currentTile.biomeType); var creature = new Creature().init(creatureType, null, player.gridX, player.gridY); // Start encounter with this creature encounter.startEncounter(creature); // Remove creature from tile currentTile.hasCreature = false; // Remove indicator from tile for (var i = 0; i < currentTile.children.length; i++) { var child = currentTile.children[i]; if (child.assetId === 'encounterIndicator') { currentTile.removeChild(child); break; } } // Remove label if present (from mapCreatureLabels) if (typeof mapCreatureTiles !== "undefined") { for (var k = mapCreatureTiles.length - 1; k >= 0; k--) { if (mapCreatureTiles[k] === currentTile) { if (mapCreatureLabels[k]) { currentTile.removeChild(mapCreatureLabels[k]); mapCreatureLabels.splice(k, 1); } mapCreatures.splice(k, 1); mapCreatureTiles.splice(k, 1); break; } } } } } // Update last position lastPlayerGridX = player.gridX; lastPlayerGridY = player.gridY; } }; // End throttled update // Listen for encounter end var checkEncounterInterval = LK.setInterval(function () { if (encounterActive && !encounter.active) { encounterActive = false; updateStats(); } }, 100); // Initialize stats updateStats(); // Initial centering centerViewOnPlayer(); // Fix: Only reveal vision area at game start, not the whole map if (typeof player !== "undefined" && typeof gameMap !== "undefined" && typeof player.updateVision === "function") { player.updateVision(gameMap); } // Vision mask overlay removed to fix black screen issue
===================================================================
--- original.js
+++ change.js
@@ -1302,18 +1302,18 @@
/****
* Game Code
****/
-// JSON helper functions for parsing and stringifying
-// Game dimensions and settings
-// Tween for animations
-// Storage for saving game progress
-// Player character
-// Map tiles
-// Creatures by elemental type
-// UI elements
-// Encounter indicator
// Sounds
+// Encounter indicator
+// UI elements
+// Creatures by elemental type
+// Map tiles
+// Player character
+// Storage for saving game progress
+// Tween for animations
+// Game dimensions and settings
+// JSON helper functions for parsing and stringifying
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
@@ -1416,38 +1416,22 @@
tileObj.tileSize = TILE_SIZE;
// Optionally update the tile graphics if needed
}
}
-// Spawn player in the center of the map on a valid tile
-var centerX = Math.floor(MAP_WIDTH / 2);
-var centerY = Math.floor(MAP_HEIGHT / 2);
-var playerStartX = centerX;
-var playerStartY = centerY;
+// Spawn player at 15,15 coordinates
+var playerStartX = 15;
+var playerStartY = 15;
var playerStartSubTileX = 0;
var playerStartSubTileY = 0;
-var tile = gameMap.getTileAt(centerX, centerY);
-// If center is not valid, search outward in a spiral for the nearest valid tile
-if (!tile || tile.biomeType === "dark" || tile.biomeType === "water" || tile.biomeType === "mountain" || tile.hasCreature || tile.explored) {
- var found = false;
- var maxRadius = Math.max(MAP_WIDTH, MAP_HEIGHT);
- for (var r = 1; r < maxRadius && !found; r++) {
- for (var dx = -r; dx <= r && !found; dx++) {
- for (var dy = -r; dy <= r && !found; dy++) {
- if (Math.abs(dx) !== r && Math.abs(dy) !== r) continue; // Only check perimeter
- var nx = centerX + dx;
- var ny = centerY + dy;
- var t = gameMap.getTileAt(nx, ny);
- if (t && t.biomeType !== "dark" && t.biomeType !== "water" && t.biomeType !== "mountain" && !t.hasCreature && !t.explored) {
- playerStartX = nx;
- playerStartY = ny;
- found = true;
- }
- }
- }
+// Ensure 15,15 is a valid tile (set to grass if not)
+if (gameMap.tiles && gameMap.tiles[15] && gameMap.tiles[15][15]) {
+ gameMap.tiles[15][15] = "grass";
+ var tileObj = gameMap.getTileAt(15, 15);
+ if (tileObj) {
+ tileObj.biomeType = "grass";
+ tileObj.tileSize = TILE_SIZE;
}
}
-playerStartSubTileX = 0;
-playerStartSubTileY = 0;
storage.playerPosition = {
x: playerStartX,
y: playerStartY,
subTileX: playerStartSubTileX,
water tile just water and top viewing. In-Game asset. 2d
dpad. In-Game asset. 2d. High contrast. No shadows
red button square. In-Game asset. 2d. High contrast. No shadows
grass tile on top viewing. In-Game asset. 2d. High contrast. No shadows
Mountain tile on top viewing. In-Game asset. 2d
sand tile on top viewing. In-Game asset. 2d. High contrast. No shadows
forest tile on top viewing. In-Game asset. 2d. No shadows
square grass tile on top viewing. In-Game asset. 2d. High contrast. No shadows
urban tile on viewing. In-Game asset. 2d
street tile on top viewing. In-Game asset. 2d. High contrast
street tile on top viewing with street way. In-Game asset. 2d
street tile on top viewing with street way horizontal. In-Game asset. 2d. High contrast. No shadows
make creature image for grass elemental name is sproutle. In-Game asset. 2d. High contrast. No shadows
make creature image for rock elemental name is boulder but dont write name on image. In-Game asset. 2d. High contrast. No shadows
make creature image for electrical elemental name is voltix but dont write name on image. In-Game asset. 2d. High contrast. No shadows
player human viewing on behind of him with all of body. In-Game asset. 2d
make a cube but like a pokeball and change the colour of original and make it the basic one make with purple and yellow but do diffrently. In-Game asset. 2d. High contrast. No shadows
make a cube but like a pokeball and make it the legendary one make with red and golden and blue but do diffrently. In-Game asset. 2d. High contrast. No shadows
make a cube but like a pokeball and make it for rare one make with grey and silver and white but do diffrently. In-Game asset. 2d. High contrast. No shadows
make a cube but like a pokeball and make it for uncommon one make with green and white and bronze but do diffrently. In-Game asset. 2d. High contrast. No shadows