Code edit (1 edits merged)
Please save this source code
User prompt
Mines & Monsters: RPG Sweeper
Initial prompt
I want to create a minesweeper game but with RPG elements. Instead of bombs there will be monsters, and each monser will have HP and Damage. Player will also have HP and Damage and will earn experience points when killing enemies. Player can choose when to use exp to level up and recover their hp.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // EmptyTile: Represents a safe tile (no monster) var EmptyTile = Container.expand(function () { var self = Container.call(this); self.revealed = false; self.adjacentMonsters = 0; self.cover = self.attachAsset('emptyTileCover', { anchorX: 0.5, anchorY: 0.5 }); self.bg = self.attachAsset('emptyTileBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0 // Hidden until revealed }); self.adjText = new Text2('', { size: 48, fill: "#fff" }); self.adjText.anchor.set(0.5, 0.5); self.adjText.alpha = 0; self.addChild(self.adjText); self.reveal = function () { if (self.revealed) return; self.revealed = true; self.cover.alpha = 0.2; self.bg.alpha = 1; if (self.adjacentMonsters > 0) { self.adjText.setText(self.adjacentMonsters + ''); self.adjText.alpha = 1; } }; return self; }); // MonsterTile: Represents a monster hidden under a tile var MonsterTile = Container.expand(function () { var self = Container.call(this); // Monster stats self.hp = 1; self.maxHp = 1; self.damage = 1; self.exp = 1; self.revealed = false; self.defeated = false; // Visuals self.cover = self.attachAsset('monsterTileCover', { anchorX: 0.5, anchorY: 0.5 }); self.monster = self.attachAsset('monsterTileMonster', { anchorX: 0.5, anchorY: 0.5, alpha: 0 // Hidden until revealed }); // Show monster stats as text (hidden until revealed) self.statText = new Text2('', { size: 48, fill: "#fff" }); self.statText.anchor.set(0.5, 0.5); self.statText.alpha = 0; self.addChild(self.statText); // Reveal the monster self.reveal = function () { if (self.revealed) return; self.revealed = true; self.cover.alpha = 0.2; self.monster.alpha = 1; self.statText.setText('HP:' + self.hp + '\nDMG:' + self.damage); self.statText.alpha = 1; }; // Mark as defeated self.defeat = function () { self.defeated = true; self.monster.alpha = 0.3; self.cover.alpha = 0.1; self.statText.setText('DEFEATED'); self.statText.alpha = 1; }; return self; }); // Player: Holds player stats and methods var Player = Container.expand(function () { var self = Container.call(this); self.maxHp = 10; self.hp = 10; self.damage = 2; self.exp = 0; self.level = 1; self.expToLevel = 5; // Level up: spend exp to increase stats or heal self.levelUp = function (choice) { if (self.exp < self.expToLevel) return false; self.exp -= self.expToLevel; self.level += 1; self.expToLevel = Math.floor(self.expToLevel * 1.5); if (choice === 'hp') { self.maxHp += 3; self.hp = self.maxHp; } else if (choice === 'damage') { self.damage += 1; } else if (choice === 'heal') { self.hp = self.maxHp; } return true; }; // Take damage self.takeDamage = function (amount) { self.hp -= amount; if (self.hp < 0) self.hp = 0; }; // Gain exp self.gainExp = function (amount) { self.exp += amount; }; // Heal self.heal = function (amount) { self.hp += amount; if (self.hp > self.maxHp) self.hp = self.maxHp; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x22223a }); /**** * Game Code ****/ // --- Game Constants --- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } var GRID_COLS = 8; var GRID_ROWS = 10; var TILE_SIZE = 180; var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * TILE_SIZE) / 2); var GRID_OFFSET_Y = 300; var MONSTER_COUNT = 12; // --- Asset Initialization --- // --- Game State --- var player = new Player(); var grid = []; // 2D array [row][col] var tileObjs = []; // Flat array of all tile objects for easy iteration var monstersLeft = MONSTER_COUNT; var revealedTiles = 0; var totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT; var gameOver = false; // --- GUI Elements --- var hpText = new Text2('', { size: 80, fill: 0xFF6666 }); hpText.anchor.set(0, 0); LK.gui.top.addChild(hpText); var dmgText = new Text2('', { size: 80, fill: "#fff" }); dmgText.anchor.set(0, 0); LK.gui.top.addChild(dmgText); var expText = new Text2('', { size: 80, fill: 0xFFE066 }); expText.anchor.set(0, 0); LK.gui.top.addChild(expText); var levelText = new Text2('', { size: 80, fill: 0xA3E635 }); levelText.anchor.set(0, 0); LK.gui.top.addChild(levelText); var monstersLeftText = new Text2('', { size: 60, fill: "#fff" }); monstersLeftText.anchor.set(1, 0); LK.gui.topRight.addChild(monstersLeftText); var levelUpBtn = new Text2('LEVEL UP', { size: 70, fill: "#fff", font: "Impact" }); levelUpBtn.anchor.set(0.5, 0.5); levelUpBtn.alpha = 0.7; levelUpBtn.visible = false; LK.gui.bottom.addChild(levelUpBtn); var levelUpChoiceBtns = []; var levelUpChoices = [{ label: "Max HP +3 & Heal", value: "hp" }, { label: "Damage +1", value: "damage" }, { label: "Heal to Max", value: "heal" }]; for (var i = 0; i < levelUpChoices.length; i++) { var btn = new Text2(levelUpChoices[i].label, { size: 60, fill: "#fff", font: "Impact" }); btn.anchor.set(0.5, 0.5); btn.visible = false; btn.alpha = 0.9; LK.gui.bottom.addChild(btn); levelUpChoiceBtns.push(btn); } // --- Helper Functions --- function updateGUI() { hpText.setText('HP: ' + player.hp + '/' + player.maxHp); hpText.x = 120; hpText.y = 20; dmgText.setText('DMG: ' + player.damage); dmgText.x = 120; dmgText.y = 120; expText.setText('EXP: ' + player.exp + '/' + player.expToLevel); expText.x = 120; expText.y = 220; levelText.setText('LVL: ' + player.level); levelText.x = 400; levelText.y = 20; monstersLeftText.setText('Monsters: ' + monstersLeft); monstersLeftText.x = -120; monstersLeftText.y = 20; // Show level up button if enough exp if (!gameOver && player.exp >= player.expToLevel) { levelUpBtn.visible = true; levelUpBtn.alpha = 1; } else { levelUpBtn.visible = false; } } // Returns true if (row, col) is inside grid function inBounds(row, col) { return row >= 0 && row < GRID_ROWS && col >= 0 && col < GRID_COLS; } // Get all adjacent tile positions function getAdjacent(row, col) { var adj = []; for (var dr = -1; dr <= 1; dr++) { for (var dc = -1; dc <= 1; dc++) { if (dr === 0 && dc === 0) continue; var nr = row + dr, nc = col + dc; if (inBounds(nr, nc)) adj.push([nr, nc]); } } return adj; } // Reveal empty tiles recursively (flood fill) function revealEmptyTiles(row, col) { var tile = grid[row][col]; if (tile.revealed) return; tile.reveal(); revealedTiles++; if (tile.adjacentMonsters === 0) { var adj = getAdjacent(row, col); for (var i = 0; i < adj.length; i++) { var _adj$i = _slicedToArray(adj[i], 2), nr = _adj$i[0], nc = _adj$i[1]; var t = grid[nr][nc]; if (t instanceof EmptyTile && !t.revealed) { revealEmptyTiles(nr, nc); } } } } // Reveal all monsters (on game over) function revealAllMonsters() { for (var i = 0; i < tileObjs.length; i++) { var t = tileObjs[i]; if (t instanceof MonsterTile && !t.revealed) { t.reveal(); } } } // --- Board Generation --- function generateBoard() { // Clear previous for (var i = 0; i < tileObjs.length; i++) { tileObjs[i].destroy(); } grid = []; tileObjs = []; monstersLeft = MONSTER_COUNT; revealedTiles = 0; totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT; gameOver = false; // Place monsters var monsterPositions = []; while (monsterPositions.length < MONSTER_COUNT) { var r = Math.floor(Math.random() * GRID_ROWS); var c = Math.floor(Math.random() * GRID_COLS); var key = r + ',' + c; var found = false; for (var i = 0; i < monsterPositions.length; i++) { if (monsterPositions[i][0] === r && monsterPositions[i][1] === c) { found = true; break; } } if (!found) monsterPositions.push([r, c]); } // Build grid for (var row = 0; row < GRID_ROWS; row++) { grid[row] = []; for (var col = 0; col < GRID_COLS; col++) { var isMonster = false; for (var i = 0; i < monsterPositions.length; i++) { if (monsterPositions[i][0] === row && monsterPositions[i][1] === col) { isMonster = true; break; } } var tile; if (isMonster) { tile = new MonsterTile(); // Randomize monster stats a bit tile.maxHp = tile.hp = 1 + Math.floor(Math.random() * (1 + player.level)); tile.damage = 1 + Math.floor(Math.random() * (1 + Math.floor(player.level / 2))); tile.exp = 1 + Math.floor(Math.random() * 2); } else { tile = new EmptyTile(); } tile.x = GRID_OFFSET_X + col * TILE_SIZE + TILE_SIZE / 2; tile.y = GRID_OFFSET_Y + row * TILE_SIZE + TILE_SIZE / 2; game.addChild(tile); grid[row][col] = tile; tileObjs.push(tile); } } // Set adjacent monster counts for empty tiles for (var row = 0; row < GRID_ROWS; row++) { for (var col = 0; col < GRID_COLS; col++) { var tile = grid[row][col]; if (tile instanceof EmptyTile) { var adj = getAdjacent(row, col); var count = 0; for (var i = 0; i < adj.length; i++) { var _adj$i2 = _slicedToArray(adj[i], 2), nr = _adj$i2[0], nc = _adj$i2[1]; if (grid[nr][nc] instanceof MonsterTile) count++; } tile.adjacentMonsters = count; } } } } // --- Game Logic --- function handleTileDown(x, y, obj) { if (gameOver) return; // Find which tile was pressed for (var i = 0; i < tileObjs.length; i++) { var tile = tileObjs[i]; if (tile.revealed) continue; if (tile.cover && tile.cover.alpha > 0.1) { // Check if (x, y) is inside tile var dx = x - tile.x; var dy = y - tile.y; if (Math.abs(dx) < TILE_SIZE / 2 && Math.abs(dy) < TILE_SIZE / 2) { // Reveal tile if (tile instanceof EmptyTile) { revealEmptyTiles(Math.floor((tile.y - GRID_OFFSET_Y) / TILE_SIZE), Math.floor((tile.x - GRID_OFFSET_X) / TILE_SIZE)); updateGUI(); // Win check if (revealedTiles >= totalSafeTiles) { LK.showYouWin(); gameOver = true; revealAllMonsters(); } } else if (tile instanceof MonsterTile) { // Reveal monster and start battle tile.reveal(); // Player attacks first tile.hp -= player.damage; LK.effects.flashObject(tile.monster, 0xffe066, 300); if (tile.hp <= 0) { tile.defeat(); monstersLeft--; player.gainExp(tile.exp); updateGUI(); // Win check if (monstersLeft <= 0) { LK.showYouWin(); gameOver = true; } } else { // Monster counterattacks player.takeDamage(tile.damage); LK.effects.flashObject(tile.monster, 0xff0000, 300); LK.effects.flashObject(hpText, 0xff0000, 300); updateGUI(); if (player.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); gameOver = true; revealAllMonsters(); } } } break; } } } } // --- Level Up UI --- function showLevelUpChoices() { levelUpBtn.visible = false; for (var i = 0; i < levelUpChoiceBtns.length; i++) { var btn = levelUpChoiceBtns[i]; btn.visible = true; btn.x = 2048 / 2 + (i - 1) * 400; btn.y = -200; btn.alpha = 1; } } function hideLevelUpChoices() { for (var i = 0; i < levelUpChoiceBtns.length; i++) { levelUpChoiceBtns[i].visible = false; } } // --- Event Handlers --- game.down = function (x, y, obj) { // Level up choice? if (levelUpBtn.visible) { // Check if pressed on level up button var btnX = 2048 / 2, btnY = 2732 - 200; if (Math.abs(x - btnX) < 200 && Math.abs(y - btnY) < 80) { showLevelUpChoices(); return; } } // Level up choices for (var i = 0; i < levelUpChoiceBtns.length; i++) { var btn = levelUpChoiceBtns[i]; if (btn.visible) { var bx = 2048 / 2 + (i - 1) * 400; var by = 2732 - 400; if (Math.abs(x - bx) < 200 && Math.abs(y - by) < 80) { // Apply level up player.levelUp(levelUpChoices[i].value); hideLevelUpChoices(); updateGUI(); return; } } } // Otherwise, check tiles handleTileDown(x, y, obj); }; game.update = function () { // Animate level up button if (levelUpBtn.visible) { levelUpBtn.x = 2048 / 2; levelUpBtn.y = 2732 - 200; levelUpBtn.alpha = 0.8 + 0.2 * Math.sin(LK.ticks / 20); } // Animate level up choices for (var i = 0; i < levelUpChoiceBtns.length; i++) { var btn = levelUpChoiceBtns[i]; if (btn.visible) { btn.x = 2048 / 2 + (i - 1) * 400; btn.y = 2732 - 400; btn.alpha = 0.9 + 0.1 * Math.sin(LK.ticks / 15 + i); } } }; // --- Start Game --- generateBoard(); updateGUI();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,533 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// EmptyTile: Represents a safe tile (no monster)
+var EmptyTile = Container.expand(function () {
+ var self = Container.call(this);
+ self.revealed = false;
+ self.adjacentMonsters = 0;
+ self.cover = self.attachAsset('emptyTileCover', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.bg = self.attachAsset('emptyTileBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0 // Hidden until revealed
+ });
+ self.adjText = new Text2('', {
+ size: 48,
+ fill: "#fff"
+ });
+ self.adjText.anchor.set(0.5, 0.5);
+ self.adjText.alpha = 0;
+ self.addChild(self.adjText);
+ self.reveal = function () {
+ if (self.revealed) return;
+ self.revealed = true;
+ self.cover.alpha = 0.2;
+ self.bg.alpha = 1;
+ if (self.adjacentMonsters > 0) {
+ self.adjText.setText(self.adjacentMonsters + '');
+ self.adjText.alpha = 1;
+ }
+ };
+ return self;
+});
+// MonsterTile: Represents a monster hidden under a tile
+var MonsterTile = Container.expand(function () {
+ var self = Container.call(this);
+ // Monster stats
+ self.hp = 1;
+ self.maxHp = 1;
+ self.damage = 1;
+ self.exp = 1;
+ self.revealed = false;
+ self.defeated = false;
+ // Visuals
+ self.cover = self.attachAsset('monsterTileCover', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.monster = self.attachAsset('monsterTileMonster', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0 // Hidden until revealed
+ });
+ // Show monster stats as text (hidden until revealed)
+ self.statText = new Text2('', {
+ size: 48,
+ fill: "#fff"
+ });
+ self.statText.anchor.set(0.5, 0.5);
+ self.statText.alpha = 0;
+ self.addChild(self.statText);
+ // Reveal the monster
+ self.reveal = function () {
+ if (self.revealed) return;
+ self.revealed = true;
+ self.cover.alpha = 0.2;
+ self.monster.alpha = 1;
+ self.statText.setText('HP:' + self.hp + '\nDMG:' + self.damage);
+ self.statText.alpha = 1;
+ };
+ // Mark as defeated
+ self.defeat = function () {
+ self.defeated = true;
+ self.monster.alpha = 0.3;
+ self.cover.alpha = 0.1;
+ self.statText.setText('DEFEATED');
+ self.statText.alpha = 1;
+ };
+ return self;
+});
+// Player: Holds player stats and methods
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ self.maxHp = 10;
+ self.hp = 10;
+ self.damage = 2;
+ self.exp = 0;
+ self.level = 1;
+ self.expToLevel = 5;
+ // Level up: spend exp to increase stats or heal
+ self.levelUp = function (choice) {
+ if (self.exp < self.expToLevel) return false;
+ self.exp -= self.expToLevel;
+ self.level += 1;
+ self.expToLevel = Math.floor(self.expToLevel * 1.5);
+ if (choice === 'hp') {
+ self.maxHp += 3;
+ self.hp = self.maxHp;
+ } else if (choice === 'damage') {
+ self.damage += 1;
+ } else if (choice === 'heal') {
+ self.hp = self.maxHp;
+ }
+ return true;
+ };
+ // Take damage
+ self.takeDamage = function (amount) {
+ self.hp -= amount;
+ if (self.hp < 0) self.hp = 0;
+ };
+ // Gain exp
+ self.gainExp = function (amount) {
+ self.exp += amount;
+ };
+ // Heal
+ self.heal = function (amount) {
+ self.hp += amount;
+ if (self.hp > self.maxHp) self.hp = self.maxHp;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x22223a
+});
+
+/****
+* Game Code
+****/
+// --- Game Constants ---
+function _slicedToArray(r, e) {
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
+}
+function _nonIterableRest() {
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+}
+function _unsupportedIterableToArray(r, a) {
+ if (r) {
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
+ var t = {}.toString.call(r).slice(8, -1);
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
+ }
+}
+function _arrayLikeToArray(r, a) {
+ (null == a || a > r.length) && (a = r.length);
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
+ return n;
+}
+function _iterableToArrayLimit(r, l) {
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
+ if (null != t) {
+ var e,
+ n,
+ i,
+ u,
+ a = [],
+ f = !0,
+ o = !1;
+ try {
+ if (i = (t = t.call(r)).next, 0 === l) {
+ if (Object(t) !== t) return;
+ f = !1;
+ } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
+ } catch (r) {
+ o = !0, n = r;
+ } finally {
+ try {
+ if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return;
+ } finally {
+ if (o) throw n;
+ }
+ }
+ return a;
+ }
+}
+function _arrayWithHoles(r) {
+ if (Array.isArray(r)) return r;
+}
+var GRID_COLS = 8;
+var GRID_ROWS = 10;
+var TILE_SIZE = 180;
+var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * TILE_SIZE) / 2);
+var GRID_OFFSET_Y = 300;
+var MONSTER_COUNT = 12;
+// --- Asset Initialization ---
+// --- Game State ---
+var player = new Player();
+var grid = []; // 2D array [row][col]
+var tileObjs = []; // Flat array of all tile objects for easy iteration
+var monstersLeft = MONSTER_COUNT;
+var revealedTiles = 0;
+var totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT;
+var gameOver = false;
+// --- GUI Elements ---
+var hpText = new Text2('', {
+ size: 80,
+ fill: 0xFF6666
+});
+hpText.anchor.set(0, 0);
+LK.gui.top.addChild(hpText);
+var dmgText = new Text2('', {
+ size: 80,
+ fill: "#fff"
+});
+dmgText.anchor.set(0, 0);
+LK.gui.top.addChild(dmgText);
+var expText = new Text2('', {
+ size: 80,
+ fill: 0xFFE066
+});
+expText.anchor.set(0, 0);
+LK.gui.top.addChild(expText);
+var levelText = new Text2('', {
+ size: 80,
+ fill: 0xA3E635
+});
+levelText.anchor.set(0, 0);
+LK.gui.top.addChild(levelText);
+var monstersLeftText = new Text2('', {
+ size: 60,
+ fill: "#fff"
+});
+monstersLeftText.anchor.set(1, 0);
+LK.gui.topRight.addChild(monstersLeftText);
+var levelUpBtn = new Text2('LEVEL UP', {
+ size: 70,
+ fill: "#fff",
+ font: "Impact"
+});
+levelUpBtn.anchor.set(0.5, 0.5);
+levelUpBtn.alpha = 0.7;
+levelUpBtn.visible = false;
+LK.gui.bottom.addChild(levelUpBtn);
+var levelUpChoiceBtns = [];
+var levelUpChoices = [{
+ label: "Max HP +3 & Heal",
+ value: "hp"
+}, {
+ label: "Damage +1",
+ value: "damage"
+}, {
+ label: "Heal to Max",
+ value: "heal"
+}];
+for (var i = 0; i < levelUpChoices.length; i++) {
+ var btn = new Text2(levelUpChoices[i].label, {
+ size: 60,
+ fill: "#fff",
+ font: "Impact"
+ });
+ btn.anchor.set(0.5, 0.5);
+ btn.visible = false;
+ btn.alpha = 0.9;
+ LK.gui.bottom.addChild(btn);
+ levelUpChoiceBtns.push(btn);
+}
+// --- Helper Functions ---
+function updateGUI() {
+ hpText.setText('HP: ' + player.hp + '/' + player.maxHp);
+ hpText.x = 120;
+ hpText.y = 20;
+ dmgText.setText('DMG: ' + player.damage);
+ dmgText.x = 120;
+ dmgText.y = 120;
+ expText.setText('EXP: ' + player.exp + '/' + player.expToLevel);
+ expText.x = 120;
+ expText.y = 220;
+ levelText.setText('LVL: ' + player.level);
+ levelText.x = 400;
+ levelText.y = 20;
+ monstersLeftText.setText('Monsters: ' + monstersLeft);
+ monstersLeftText.x = -120;
+ monstersLeftText.y = 20;
+ // Show level up button if enough exp
+ if (!gameOver && player.exp >= player.expToLevel) {
+ levelUpBtn.visible = true;
+ levelUpBtn.alpha = 1;
+ } else {
+ levelUpBtn.visible = false;
+ }
+}
+// Returns true if (row, col) is inside grid
+function inBounds(row, col) {
+ return row >= 0 && row < GRID_ROWS && col >= 0 && col < GRID_COLS;
+}
+// Get all adjacent tile positions
+function getAdjacent(row, col) {
+ var adj = [];
+ for (var dr = -1; dr <= 1; dr++) {
+ for (var dc = -1; dc <= 1; dc++) {
+ if (dr === 0 && dc === 0) continue;
+ var nr = row + dr,
+ nc = col + dc;
+ if (inBounds(nr, nc)) adj.push([nr, nc]);
+ }
+ }
+ return adj;
+}
+// Reveal empty tiles recursively (flood fill)
+function revealEmptyTiles(row, col) {
+ var tile = grid[row][col];
+ if (tile.revealed) return;
+ tile.reveal();
+ revealedTiles++;
+ if (tile.adjacentMonsters === 0) {
+ var adj = getAdjacent(row, col);
+ for (var i = 0; i < adj.length; i++) {
+ var _adj$i = _slicedToArray(adj[i], 2),
+ nr = _adj$i[0],
+ nc = _adj$i[1];
+ var t = grid[nr][nc];
+ if (t instanceof EmptyTile && !t.revealed) {
+ revealEmptyTiles(nr, nc);
+ }
+ }
+ }
+}
+// Reveal all monsters (on game over)
+function revealAllMonsters() {
+ for (var i = 0; i < tileObjs.length; i++) {
+ var t = tileObjs[i];
+ if (t instanceof MonsterTile && !t.revealed) {
+ t.reveal();
+ }
+ }
+}
+// --- Board Generation ---
+function generateBoard() {
+ // Clear previous
+ for (var i = 0; i < tileObjs.length; i++) {
+ tileObjs[i].destroy();
+ }
+ grid = [];
+ tileObjs = [];
+ monstersLeft = MONSTER_COUNT;
+ revealedTiles = 0;
+ totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT;
+ gameOver = false;
+ // Place monsters
+ var monsterPositions = [];
+ while (monsterPositions.length < MONSTER_COUNT) {
+ var r = Math.floor(Math.random() * GRID_ROWS);
+ var c = Math.floor(Math.random() * GRID_COLS);
+ var key = r + ',' + c;
+ var found = false;
+ for (var i = 0; i < monsterPositions.length; i++) {
+ if (monsterPositions[i][0] === r && monsterPositions[i][1] === c) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) monsterPositions.push([r, c]);
+ }
+ // Build grid
+ for (var row = 0; row < GRID_ROWS; row++) {
+ grid[row] = [];
+ for (var col = 0; col < GRID_COLS; col++) {
+ var isMonster = false;
+ for (var i = 0; i < monsterPositions.length; i++) {
+ if (monsterPositions[i][0] === row && monsterPositions[i][1] === col) {
+ isMonster = true;
+ break;
+ }
+ }
+ var tile;
+ if (isMonster) {
+ tile = new MonsterTile();
+ // Randomize monster stats a bit
+ tile.maxHp = tile.hp = 1 + Math.floor(Math.random() * (1 + player.level));
+ tile.damage = 1 + Math.floor(Math.random() * (1 + Math.floor(player.level / 2)));
+ tile.exp = 1 + Math.floor(Math.random() * 2);
+ } else {
+ tile = new EmptyTile();
+ }
+ tile.x = GRID_OFFSET_X + col * TILE_SIZE + TILE_SIZE / 2;
+ tile.y = GRID_OFFSET_Y + row * TILE_SIZE + TILE_SIZE / 2;
+ game.addChild(tile);
+ grid[row][col] = tile;
+ tileObjs.push(tile);
+ }
+ }
+ // Set adjacent monster counts for empty tiles
+ for (var row = 0; row < GRID_ROWS; row++) {
+ for (var col = 0; col < GRID_COLS; col++) {
+ var tile = grid[row][col];
+ if (tile instanceof EmptyTile) {
+ var adj = getAdjacent(row, col);
+ var count = 0;
+ for (var i = 0; i < adj.length; i++) {
+ var _adj$i2 = _slicedToArray(adj[i], 2),
+ nr = _adj$i2[0],
+ nc = _adj$i2[1];
+ if (grid[nr][nc] instanceof MonsterTile) count++;
+ }
+ tile.adjacentMonsters = count;
+ }
+ }
+ }
+}
+// --- Game Logic ---
+function handleTileDown(x, y, obj) {
+ if (gameOver) return;
+ // Find which tile was pressed
+ for (var i = 0; i < tileObjs.length; i++) {
+ var tile = tileObjs[i];
+ if (tile.revealed) continue;
+ if (tile.cover && tile.cover.alpha > 0.1) {
+ // Check if (x, y) is inside tile
+ var dx = x - tile.x;
+ var dy = y - tile.y;
+ if (Math.abs(dx) < TILE_SIZE / 2 && Math.abs(dy) < TILE_SIZE / 2) {
+ // Reveal tile
+ if (tile instanceof EmptyTile) {
+ revealEmptyTiles(Math.floor((tile.y - GRID_OFFSET_Y) / TILE_SIZE), Math.floor((tile.x - GRID_OFFSET_X) / TILE_SIZE));
+ updateGUI();
+ // Win check
+ if (revealedTiles >= totalSafeTiles) {
+ LK.showYouWin();
+ gameOver = true;
+ revealAllMonsters();
+ }
+ } else if (tile instanceof MonsterTile) {
+ // Reveal monster and start battle
+ tile.reveal();
+ // Player attacks first
+ tile.hp -= player.damage;
+ LK.effects.flashObject(tile.monster, 0xffe066, 300);
+ if (tile.hp <= 0) {
+ tile.defeat();
+ monstersLeft--;
+ player.gainExp(tile.exp);
+ updateGUI();
+ // Win check
+ if (monstersLeft <= 0) {
+ LK.showYouWin();
+ gameOver = true;
+ }
+ } else {
+ // Monster counterattacks
+ player.takeDamage(tile.damage);
+ LK.effects.flashObject(tile.monster, 0xff0000, 300);
+ LK.effects.flashObject(hpText, 0xff0000, 300);
+ updateGUI();
+ if (player.hp <= 0) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ gameOver = true;
+ revealAllMonsters();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+// --- Level Up UI ---
+function showLevelUpChoices() {
+ levelUpBtn.visible = false;
+ for (var i = 0; i < levelUpChoiceBtns.length; i++) {
+ var btn = levelUpChoiceBtns[i];
+ btn.visible = true;
+ btn.x = 2048 / 2 + (i - 1) * 400;
+ btn.y = -200;
+ btn.alpha = 1;
+ }
+}
+function hideLevelUpChoices() {
+ for (var i = 0; i < levelUpChoiceBtns.length; i++) {
+ levelUpChoiceBtns[i].visible = false;
+ }
+}
+// --- Event Handlers ---
+game.down = function (x, y, obj) {
+ // Level up choice?
+ if (levelUpBtn.visible) {
+ // Check if pressed on level up button
+ var btnX = 2048 / 2,
+ btnY = 2732 - 200;
+ if (Math.abs(x - btnX) < 200 && Math.abs(y - btnY) < 80) {
+ showLevelUpChoices();
+ return;
+ }
+ }
+ // Level up choices
+ for (var i = 0; i < levelUpChoiceBtns.length; i++) {
+ var btn = levelUpChoiceBtns[i];
+ if (btn.visible) {
+ var bx = 2048 / 2 + (i - 1) * 400;
+ var by = 2732 - 400;
+ if (Math.abs(x - bx) < 200 && Math.abs(y - by) < 80) {
+ // Apply level up
+ player.levelUp(levelUpChoices[i].value);
+ hideLevelUpChoices();
+ updateGUI();
+ return;
+ }
+ }
+ }
+ // Otherwise, check tiles
+ handleTileDown(x, y, obj);
+};
+game.update = function () {
+ // Animate level up button
+ if (levelUpBtn.visible) {
+ levelUpBtn.x = 2048 / 2;
+ levelUpBtn.y = 2732 - 200;
+ levelUpBtn.alpha = 0.8 + 0.2 * Math.sin(LK.ticks / 20);
+ }
+ // Animate level up choices
+ for (var i = 0; i < levelUpChoiceBtns.length; i++) {
+ var btn = levelUpChoiceBtns[i];
+ if (btn.visible) {
+ btn.x = 2048 / 2 + (i - 1) * 400;
+ btn.y = 2732 - 400;
+ btn.alpha = 0.9 + 0.1 * Math.sin(LK.ticks / 15 + i);
+ }
+ }
+};
+// --- Start Game ---
+generateBoard();
+updateGUI();
\ No newline at end of file