User prompt
hid gui when battle screen is up, both the top and bototm
User prompt
Add animation when ballte screen appears. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add more options, not only attach on battle screen
User prompt
Still seing other elelemtenon ballet screen.
User prompt
Nice! Make sure that when battle screen is up, only battle screen is seen..
User prompt
Lets add a battle system when the player touched on an enemy cell. Instead of just attacking it, let open a new screen where the player can fight it in a turn based battle, like pokemon.
User prompt
make sure upgrades work, since damage is not being increased neither max hp
User prompt
Improve the graphics of the grid cells when covered and uncovered, should stillbe squares, not green circles. Use a dungeon vibe color.
User prompt
Clicking the levle up button choices is not working. lets put the on a overlay an make sure they are clickable
User prompt
I do not see the update level button
User prompt
level up button should be on the top center of the screen
User prompt
When player has enough EXP, they can click the button to level up.
User prompt
when player has enought EXP to level up, enable the button to level up. it should be greyed out when he has not enough hp. On level up, payer will recover all hp.
User prompt
center the grid in the center of the screen
User prompt
Nice! Lets make the intiial grid 8 by 8
User prompt
Better, but its still cut off. Maybe try center them.
User prompt
Better, but I just see the values, the name of them is cut out on the left of the screen
User prompt
Still HP DMG and EXP are not displayed in the bottom of the screen
User prompt
HP DMG and EXP do not appera in the screen now.
User prompt
move hp exp and damage of player to the bottom of the screen
User prompt
when player touches on an enemy, instead of just killing it, open a new overlpa with the fight between the player and the enemy
User prompt
show enemy hp in 0/1 or whatever it is
User prompt
show the monsters hp and daamage
User prompt
Make sure enemies also generate damage to player
User prompt
Rearragne hud and indicators since everything is overlapping.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// BattleScreen: Handles the turn-based combat
var BattleScreen = Container.expand(function () {
var self = Container.call(this);
self.visible = false; // Initially hidden
self.alpha = 0; // Set alpha to 0 for fade-in animation
// Background overlay
self.overlay = self.attachAsset('emptyTileCover', {
width: 2048,
height: 2732,
alpha: 0.8
});
// Monster display
self.monsterDisplay = self.attachAsset('monsterTileMonster', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 200,
scaleX: 2,
scaleY: 2
});
// Monster stats text
self.monsterStatText = new Text2('', {
size: 60,
fill: "#fff"
});
self.monsterStatText.anchor.set(0.5, 0.5);
self.monsterStatText.x = 2048 / 2;
self.monsterStatText.y = self.monsterDisplay.y + self.monsterDisplay.height / 2 + 50;
self.addChild(self.monsterStatText);
// Player stats text (in battle)
self.playerBattleStatText = new Text2('', {
size: 60,
fill: "#fff"
});
self.playerBattleStatText.anchor.set(0.5, 0.5);
self.playerBattleStatText.x = 2048 / 2;
self.playerBattleStatText.y = self.monsterStatText.y + 100;
self.addChild(self.playerBattleStatText);
// Action button (Attack)
self.attackBtn = new Text2('ATTACK', {
size: 80,
fill: "#fff",
font: "Impact"
});
self.attackBtn.anchor.set(0.5, 0.5);
self.attackBtn.x = 2048 / 2;
self.attackBtn.y = 2732 - 300; // Position near bottom
self.addChild(self.attackBtn);
self.attackBtn.down = function () {
if (!self.visible) return;
self.playerTurn();
};
self.currentMonster = null; // Reference to the monster tile being fought
// Start battle
self.startBattle = function (monsterTile) {
self.currentMonster = monsterTile;
self.visible = true;
game.addChild(self); // Add battle screen to game
tween(self, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
}); // Animate appearance
self.updateBattleStats();
self.attackBtn.visible = true;
};
// End battle
self.endBattle = function (win) {
self.visible = false;
self.alpha = 0; // Reset alpha
self.attackBtn.visible = false;
if (win) {
self.currentMonster.defeat();
monstersLeft--;
player.gainExp(self.currentMonster.exp);
updateGUI();
if (monstersLeft <= 0) {
LK.showYouWin();
gameOver = true;
}
} else {
// Player lost, game over is handled in handleTileDown
}
self.currentMonster = null;
self.parent.removeChild(self); // Remove battle screen from game
};
// Update battle stats display
self.updateBattleStats = function () {
if (self.currentMonster) {
self.monsterStatText.setText('Monster HP:' + self.currentMonster.hp + '/' + self.currentMonster.maxHp + ' DMG:' + self.currentMonster.damage);
self.playerBattleStatText.setText('Your HP:' + player.hp + '/' + player.maxHp + ' DMG:' + player.damage);
}
};
// Player's turn
self.playerTurn = function () {
if (!self.currentMonster) return;
self.currentMonster.hp -= player.damage;
LK.effects.flashObject(self.monsterDisplay, 0xffe066, 300);
self.updateBattleStats();
if (self.currentMonster.hp <= 0) {
self.endBattle(true); // Player wins
} else {
LK.setTimeout(self.monsterTurn, 500); // Monster's turn after a delay
}
};
// Monster's turn
self.monsterTurn = function () {
if (!self.currentMonster) return;
player.takeDamage(self.currentMonster.damage);
LK.effects.flashObject(self.monsterDisplay, 0xff0000, 300); // Flash monster indicating it attacked
LK.effects.flashObject(self.playerBattleStatText, 0xff0000, 300); // Flash player stats indicating damage
self.updateBattleStats();
if (player.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
gameOver = true;
revealAllMonsters();
self.endBattle(false); // Player loses
}
};
return self;
});
// 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 + '/' + self.maxHp + ' DMG:' + self.damage);
self.statText.y = -40; // Move stat text above monster graphic
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('HP:0/' + self.maxHp + ' DMG:' + self.damage + '\nDEFEATED');
self.statText.y = -40;
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 = 8;
var TILE_SIZE = 180;
var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * TILE_SIZE) / 2);
var GRID_OFFSET_Y = Math.floor((2732 - GRID_ROWS * TILE_SIZE) / 2);
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;
var battleScreen = new BattleScreen();
// --- GUI Elements ---
var hpText = new Text2('', {
size: 80,
fill: 0xFF6666
});
hpText.anchor.set(0.5, 1); // Anchor to bottom-center
hpText.x = 0; // Center horizontally relative to LK.gui.bottom
hpText.y = -40;
LK.gui.bottom.addChild(hpText);
var dmgText = new Text2('', {
size: 80,
fill: "#fff"
});
dmgText.anchor.set(0.5, 1); // Anchor to bottom-center
dmgText.x = 0; // Center horizontally relative to LK.gui.bottom
dmgText.y = -140;
LK.gui.bottom.addChild(dmgText);
var expText = new Text2('', {
size: 80,
fill: 0xFFE066
});
expText.anchor.set(0.5, 1); // Anchor to bottom-center
expText.x = 0; // Center horizontally relative to LK.gui.bottom
expText.y = -240;
LK.gui.bottom.addChild(expText);
var levelText = new Text2('', {
size: 80,
fill: 0xA3E635
});
levelText.anchor.set(1, 0);
LK.gui.topRight.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;
levelUpBtn.down = function () {
if (!this.visible) return;
showLevelUpChoices();
};
LK.gui.top.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;
// Capture the current choice for this button's event handler
var currentChoice = levelUpChoices[i];
btn.down = function () {
if (!this.visible) return;
player.levelUp(currentChoice.value);
hideLevelUpChoices();
updateGUI();
// If player still has enough EXP, show the level up button again
if (!gameOver && player.exp >= player.expToLevel) {
levelUpBtn.visible = true;
levelUpBtn.alpha = 1;
}
};
LK.gui.bottom.addChild(btn);
levelUpChoiceBtns.push(btn);
}
// --- Helper Functions ---
function updateGUI() {
if (battleScreen.visible) {
hpText.visible = false;
dmgText.visible = false;
expText.visible = false;
levelText.visible = false;
monstersLeftText.visible = false;
levelUpBtn.visible = false;
hideLevelUpChoices();
battleScreen.updateBattleStats(); // Update battle screen stats when visible
return;
} else {
hpText.visible = true;
dmgText.visible = true;
expText.visible = true;
levelText.visible = true;
monstersLeftText.visible = true;
}
hpText.setText('HP: ' + player.hp + '/' + player.maxHp);
hpText.setText('HP: ' + player.hp + '/' + player.maxHp);
hpText.x = 0; // Center horizontally relative to LK.gui.bottom
hpText.y = -40;
dmgText.setText('DMG: ' + player.damage);
dmgText.x = 0; // Center horizontally relative to LK.gui.bottom
dmgText.y = -140;
expText.setText('EXP: ' + player.exp + '/' + player.expToLevel);
expText.x = 0; // Center horizontally relative to LK.gui.bottom
expText.y = -240;
// Move levelText to top right, below monstersLeftText
levelText.setText('LVL: ' + player.level);
levelText.x = -120; // Position relative to LK.gui.topRight
levelText.y = 120;
monstersLeftText.setText('Monsters: ' + monstersLeft);
monstersLeftText.x = -120;
monstersLeftText.y = 20;
// Show level up button if enough exp
if (!gameOver && player.exp >= player.expToLevel && !levelUpChoiceBtns.some(function (btn) {
return btn.visible;
})) {
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;
if (battleScreen.visible) return; // Don't allow tile interaction if battle screen is up
// 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(); // Reveal the monster visually
// Start the battle sequence
battleScreen.startBattle(tile);
}
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 = (i - 1) * 400; // x relative to LK.gui.bottom (which is screen center horizontally)
btn.y = -400; // y relative to LK.gui.bottom (which is screen bottom edge)
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) {
// The click handling for levelUpBtn and levelUpChoiceBtns
// has been moved to their own 'down' event handlers.
// Check for tile interactions
handleTileDown(x, y, obj);
};
game.update = function () {
if (battleScreen.visible) return; // Don't update game elements when battle screen is up
// Animate level up button
if (levelUpBtn.visible) {
levelUpBtn.x = 0; // Centered horizontally relative to LK.gui.top
levelUpBtn.y = 120;
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 = (i - 1) * 400; // x relative to LK.gui.bottom
btn.y = -400; // y relative to LK.gui.bottom
btn.alpha = 0.9 + 0.1 * Math.sin(LK.ticks / 15 + i);
}
}
if (battleScreen.visible) {
for (var i = 0; i < tileObjs.length; i++) {
tileObjs[i].visible = false;
}
} else {
for (var i = 0; i < tileObjs.length; i++) {
tileObjs[i].visible = true;
}
}
};
// --- Start Game ---
generateBoard();
updateGUI(); ===================================================================
--- original.js
+++ change.js
@@ -9,8 +9,9 @@
// BattleScreen: Handles the turn-based combat
var BattleScreen = Container.expand(function () {
var self = Container.call(this);
self.visible = false; // Initially hidden
+ self.alpha = 0; // Set alpha to 0 for fade-in animation
// Background overlay
self.overlay = self.attachAsset('emptyTileCover', {
width: 2048,
height: 2732,
@@ -62,14 +63,21 @@
self.startBattle = function (monsterTile) {
self.currentMonster = monsterTile;
self.visible = true;
game.addChild(self); // Add battle screen to game
+ tween(self, {
+ alpha: 1
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ }); // Animate appearance
self.updateBattleStats();
self.attackBtn.visible = true;
};
// End battle
self.endBattle = function (win) {
self.visible = false;
+ self.alpha = 0; // Reset alpha
self.attackBtn.visible = false;
if (win) {
self.currentMonster.defeat();
monstersLeft--;