User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'textDisplay.style.fill = color;' Line Number: 319
User prompt
Please fix the bug: 'button.setEnabled is not a function' in or related to this line: 'button.setEnabled(skillPointsAvailable > 0);' Line Number: 506
Code edit (1 edits merged)
Please save this source code
User prompt
Monster Gauntlet: Battle RNG
Initial prompt
MG battle RNG
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { playerLevel: 1, victories: 0, skillPoints: 0, attackBonus: 0, defenseBonus: 0, specialBonus: 0, healthBonus: 0 }); /**** * Classes ****/ var ActionButton = Container.expand(function (text, action) { var self = Container.call(this); var buttonGraphic = self.attachAsset('actionButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(text, { size: 50, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.action = action; self.enabled = true; self.setEnabled = function (enabled) { self.enabled = enabled; buttonGraphic.alpha = enabled ? 1.0 : 0.5; }; self.down = function (x, y, obj) { if (!self.enabled) { return; } tween(buttonGraphic, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.up = function (x, y, obj) { if (!self.enabled) { return; } tween(buttonGraphic, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { if (self.action) { self.action(); } } }); }; return self; }); var Dice = Container.expand(function () { var self = Container.call(this); var diceGraphic = self.attachAsset('dice', { anchorX: 0.5, anchorY: 0.5 }); var valueText = new Text2('?', { size: 60, fill: 0x000000 }); valueText.anchor.set(0.5, 0.5); self.addChild(valueText); self.value = 0; self.isRolling = false; self.roll = function (callback) { if (self.isRolling) { return; } self.isRolling = true; LK.getSound('diceRoll').play(); var rollIterations = 10; var currentIteration = 0; function doRoll() { self.value = Math.floor(Math.random() * 6) + 1; valueText.setText(self.value.toString()); currentIteration++; if (currentIteration < rollIterations) { LK.setTimeout(doRoll, 100); } else { self.isRolling = false; if (callback) { callback(self.value); } } } doRoll(); }; self.setValue = function (val) { self.value = val; valueText.setText(val.toString()); }; return self; }); var HealthBar = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('hpBarBg', { anchorX: 0, anchorY: 0 }); var foreground = self.attachAsset('hpBar', { anchorX: 0, anchorY: 0 }); self.maxHealth = 100; self.currentHealth = 100; self.setMaxHealth = function (value) { self.maxHealth = value; self.updateDisplay(); }; self.setCurrentHealth = function (value) { self.currentHealth = Math.max(0, Math.min(self.maxHealth, value)); self.updateDisplay(); }; self.updateDisplay = function () { var ratio = self.currentHealth / self.maxHealth; foreground.scale.x = ratio; }; return self; }); var Monster = Container.expand(function (isPlayer) { var self = Container.call(this); var assetId = isPlayer ? 'playerMonster' : 'enemyMonster'; var monsterGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); var nameText = new Text2(isPlayer ? "Player" : "Enemy", { size: 40, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0); nameText.y = -monsterGraphic.height / 2 - 50; self.addChild(nameText); var healthBar = new HealthBar(); healthBar.y = monsterGraphic.height / 2 + 20; healthBar.x = -healthBar.width / 2; self.addChild(healthBar); self.isPlayer = isPlayer; self.level = 1; self.baseHealth = 100; self.baseAttack = 10; self.baseDefense = 5; self.baseSpecial = 15; self.maxHealth = self.baseHealth; self.currentHealth = self.maxHealth; self.attackPower = self.baseAttack; self.defensePower = self.baseDefense; self.specialPower = self.baseSpecial; self.setName = function (name) { nameText.setText(name); }; self.setLevel = function (level) { self.level = level; if (!self.isPlayer) { // Scale enemy stats based on level self.maxHealth = self.baseHealth + (level - 1) * 20; self.attackPower = self.baseAttack + (level - 1) * 2; self.defensePower = self.baseDefense + (level - 1); self.specialPower = self.baseSpecial + (level - 1) * 3; } else { // Apply player bonuses from storage self.maxHealth = self.baseHealth + storage.healthBonus * 10; self.attackPower = self.baseAttack + storage.attackBonus; self.defensePower = self.baseDefense + storage.defenseBonus; self.specialPower = self.baseSpecial + storage.specialBonus; } self.currentHealth = self.maxHealth; healthBar.setMaxHealth(self.maxHealth); healthBar.setCurrentHealth(self.currentHealth); }; self.takeDamage = function (amount) { self.currentHealth -= amount; if (self.currentHealth < 0) { self.currentHealth = 0; } healthBar.setCurrentHealth(self.currentHealth); // Flash red on damage LK.effects.flashObject(monsterGraphic, 0xff0000, 500); // Shake when hit self.shake(); return self.currentHealth <= 0; // Return true if defeated }; self.heal = function (amount) { self.currentHealth += amount; if (self.currentHealth > self.maxHealth) { self.currentHealth = self.maxHealth; } healthBar.setCurrentHealth(self.currentHealth); }; self.shake = function () { var originalX = self.x; var originalY = self.y; function shakeStep(magnitude) { var offsetX = (Math.random() - 0.5) * 2 * magnitude; var offsetY = (Math.random() - 0.5) * 2 * magnitude; self.x = originalX + offsetX; self.y = originalY + offsetY; } var steps = 10; var currentStep = 0; var maxMagnitude = 20; function doShake() { var magnitude = maxMagnitude * (1 - currentStep / steps); shakeStep(magnitude); currentStep++; if (currentStep < steps) { LK.setTimeout(doShake, 30); } else { self.x = originalX; self.y = originalY; } } doShake(); }; self.down = function (x, y, obj) { // Just for show - adds interactivity by shrinking slightly on press if (self.isPlayer) { tween(monsterGraphic, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); } }; self.up = function (x, y, obj) { if (self.isPlayer) { tween(monsterGraphic, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }; return self; }); var StatUpgradeButton = Container.expand(function (statName, upgradeAction) { var self = Container.call(this); var buttonGraphic = self.attachAsset('actionButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var buttonText = new Text2(statName + " +1", { size: 40, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.upgradeAction = upgradeAction; self.down = function (x, y, obj) { tween(buttonGraphic, { scaleX: 0.75, scaleY: 0.75 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(buttonGraphic, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100, onFinish: function onFinish() { if (self.upgradeAction) { self.upgradeAction(); } } }); }; return self; }); var StatusText = Container.expand(function () { var self = Container.call(this); var textDisplay = new Text2("", { size: 60, fill: 0xFFFFFF }); textDisplay.anchor.set(0.5, 0.5); self.addChild(textDisplay); self.show = function (message, color, duration) { textDisplay.setText(message); if (color) { textDisplay.style.fill = color; } else { textDisplay.style.fill = "#ffffff"; } self.alpha = 1; if (duration) { tween(self, { alpha: 0 }, { duration: duration }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Game state var gameState = "start"; // Possible states: "start", "battle", "playerTurn", "enemyTurn", "diceRoll", "victory", "defeat", "upgrade" var currentDiceRoll = 0; var actionInProgress = false; var skillPointsAvailable = storage.skillPoints; // Game objects var playerMonster; var enemyMonster; var actionDice; var actionButtons = []; var statusText; var upgradeButtons = []; // Initialize the game function initGame() { // Play background music LK.playMusic('battleMusic'); // Create player monster playerMonster = new Monster(true); playerMonster.x = 2048 * 0.25; playerMonster.y = 2732 * 0.5; playerMonster.setName("Your Monster"); playerMonster.setLevel(storage.playerLevel); game.addChild(playerMonster); // Create enemy monster enemyMonster = new Monster(false); enemyMonster.x = 2048 * 0.75; enemyMonster.y = 2732 * 0.5; enemyMonster.setName("Enemy Lvl " + storage.playerLevel); enemyMonster.setLevel(storage.playerLevel); game.addChild(enemyMonster); // Create action dice actionDice = new Dice(); actionDice.x = 2048 * 0.5; actionDice.y = 2732 * 0.4; actionDice.visible = false; game.addChild(actionDice); // Create status text statusText = new StatusText(); statusText.x = 2048 * 0.5; statusText.y = 2732 * 0.3; game.addChild(statusText); // Create action buttons var buttonY = 2732 * 0.75; var buttonSpacing = 350; var attackButton = new ActionButton("Attack", function () { if (!actionInProgress && gameState === "playerTurn") { performPlayerAction("attack"); } }); attackButton.x = 2048 * 0.5 - buttonSpacing; attackButton.y = buttonY; game.addChild(attackButton); actionButtons.push(attackButton); var defendButton = new ActionButton("Defend", function () { if (!actionInProgress && gameState === "playerTurn") { performPlayerAction("defend"); } }); defendButton.x = 2048 * 0.5; defendButton.y = buttonY; game.addChild(defendButton); actionButtons.push(defendButton); var specialButton = new ActionButton("Special", function () { if (!actionInProgress && gameState === "playerTurn") { performPlayerAction("special"); } }); specialButton.x = 2048 * 0.5 + buttonSpacing; specialButton.y = buttonY; game.addChild(specialButton); actionButtons.push(specialButton); // Create upgrade buttons (initially hidden) createUpgradeButtons(); // Create score display var levelText = new Text2("Level: " + storage.playerLevel, { size: 50, fill: 0xFFFFFF }); levelText.anchor.set(1, 0); levelText.x = 2048 - 50; levelText.y = 50; game.addChild(levelText); var victoryText = new Text2("Victories: " + storage.victories, { size: 50, fill: 0xFFFFFF }); victoryText.anchor.set(1, 0); victoryText.x = 2048 - 50; victoryText.y = 110; game.addChild(victoryText); var skillPointsText = new Text2("Skill Points: " + storage.skillPoints, { size: 50, fill: 0xFFFFFF }); skillPointsText.anchor.set(0, 0); skillPointsText.x = 150; skillPointsText.y = 50; game.addChild(skillPointsText); // Start the battle startBattle(); } function createUpgradeButtons() { var startY = 2732 * 0.55; var spacing = 150; var attackUpgrade = new StatUpgradeButton("Attack", function () { if (skillPointsAvailable > 0) { storage.attackBonus++; storage.skillPoints--; skillPointsAvailable--; updateUpgradeButtons(); } }); attackUpgrade.x = 2048 * 0.5; attackUpgrade.y = startY; game.addChild(attackUpgrade); upgradeButtons.push(attackUpgrade); var defenseUpgrade = new StatUpgradeButton("Defense", function () { if (skillPointsAvailable > 0) { storage.defenseBonus++; storage.skillPoints--; skillPointsAvailable--; updateUpgradeButtons(); } }); defenseUpgrade.x = 2048 * 0.5; defenseUpgrade.y = startY + spacing; game.addChild(defenseUpgrade); upgradeButtons.push(defenseUpgrade); var specialUpgrade = new StatUpgradeButton("Special", function () { if (skillPointsAvailable > 0) { storage.specialBonus++; storage.skillPoints--; skillPointsAvailable--; updateUpgradeButtons(); } }); specialUpgrade.x = 2048 * 0.5; specialUpgrade.y = startY + spacing * 2; game.addChild(specialUpgrade); upgradeButtons.push(specialUpgrade); var healthUpgrade = new StatUpgradeButton("Health", function () { if (skillPointsAvailable > 0) { storage.healthBonus++; storage.skillPoints--; skillPointsAvailable--; updateUpgradeButtons(); } }); healthUpgrade.x = 2048 * 0.5; healthUpgrade.y = startY + spacing * 3; game.addChild(healthUpgrade); upgradeButtons.push(healthUpgrade); var continueButton = new ActionButton("Continue", function () { if (gameState === "upgrade") { startBattle(); } }); continueButton.x = 2048 * 0.5; continueButton.y = startY + spacing * 4.5; game.addChild(continueButton); upgradeButtons.push(continueButton); // Hidden initially updateUpgradeButtons(); setUpgradeButtonsVisible(false); } function updateUpgradeButtons() { for (var i = 0; i < upgradeButtons.length - 1; i++) { var button = upgradeButtons[i]; button.setEnabled(skillPointsAvailable > 0); } } function setUpgradeButtonsVisible(visible) { for (var i = 0; i < upgradeButtons.length; i++) { upgradeButtons[i].visible = visible; } } function setActionButtonsVisible(visible) { for (var i = 0; i < actionButtons.length; i++) { actionButtons[i].visible = visible; } } function startBattle() { gameState = "battle"; actionInProgress = false; // Reset monsters for new battle playerMonster.setLevel(storage.playerLevel); enemyMonster.setName("Enemy Lvl " + storage.playerLevel); enemyMonster.setLevel(storage.playerLevel); // Hide upgrade buttons, show action buttons setUpgradeButtonsVisible(false); setActionButtonsVisible(true); // Show battle start message statusText.show("Battle Start!", "#ffff00", 2000); // Start player turn after a delay LK.setTimeout(function () { startPlayerTurn(); }, 2000); } function startPlayerTurn() { gameState = "playerTurn"; statusText.show("Your Turn", "#3498db", 2000); } function performPlayerAction(actionType) { gameState = "diceRoll"; actionInProgress = true; // Play sound based on action LK.getSound(actionType).play(); // Show the dice for roll actionDice.visible = true; actionDice.roll(function (value) { // Process player action based on dice roll currentDiceRoll = value; var actionResult = calculateActionResult(actionType, playerMonster, enemyMonster, value); if (actionType === "attack") { statusText.show("You attacked for " + actionResult + " damage!", "#ff9900"); var defeated = enemyMonster.takeDamage(actionResult); if (defeated) { handleVictory(); return; } } else if (actionType === "defend") { var healAmount = Math.floor(actionResult / 2); statusText.show("You defended! +" + actionResult + " DEF for this turn\n+" + healAmount + " HP", "#2ecc71"); playerMonster.defensePower += actionResult; // Temporary defense boost playerMonster.heal(healAmount); } else if (actionType === "special") { statusText.show("Special attack for " + actionResult + " damage!", "#9b59b6"); var defeated = enemyMonster.takeDamage(actionResult); if (defeated) { handleVictory(); return; } } // Hide dice after action LK.setTimeout(function () { actionDice.visible = false; // Start enemy turn after a delay LK.setTimeout(function () { startEnemyTurn(); }, 1000); }, 1000); }); } function startEnemyTurn() { gameState = "enemyTurn"; statusText.show("Enemy Turn", "#e74c3c", 1000); // Reset temporary defense boost from defend action if (playerMonster.defensePower > playerMonster.baseDefense + storage.defenseBonus) { playerMonster.defensePower = playerMonster.baseDefense + storage.defenseBonus; } // Enemy AI chooses action LK.setTimeout(function () { var actions = ["attack", "special", "defend"]; var weights = [0.6, 0.3, 0.1]; // Weights for action selection if (enemyMonster.currentHealth < enemyMonster.maxHealth * 0.3) { // When low on health, more likely to defend weights = [0.4, 0.2, 0.4]; } var actionIndex = weightedRandomChoice(actions, weights); var actionType = actions[actionIndex]; // Play sound based on action LK.getSound(actionType).play(); // Show dice for enemy roll actionDice.visible = true; actionDice.roll(function (value) { currentDiceRoll = value; var actionResult = calculateActionResult(actionType, enemyMonster, playerMonster, value); if (actionType === "attack") { statusText.show("Enemy attacked for " + actionResult + " damage!", "#ff9900"); var defeated = playerMonster.takeDamage(actionResult); if (defeated) { handleDefeat(); return; } } else if (actionType === "defend") { var healAmount = Math.floor(actionResult / 2); statusText.show("Enemy defended! +" + actionResult + " DEF\n+" + healAmount + " HP", "#2ecc71"); enemyMonster.defensePower += actionResult; // Temporary defense boost enemyMonster.heal(healAmount); } else if (actionType === "special") { statusText.show("Enemy special attack for " + actionResult + " damage!", "#9b59b6"); var defeated = playerMonster.takeDamage(actionResult); if (defeated) { handleDefeat(); return; } } // Hide dice after action LK.setTimeout(function () { actionDice.visible = false; // Start player turn again after a delay LK.setTimeout(function () { actionInProgress = false; startPlayerTurn(); }, 1000); }, 1000); }); }, 1000); } function calculateActionResult(actionType, attacker, defender, diceValue) { var result = 0; if (actionType === "attack") { // Base damage is attacker's attack power + dice roll var baseDamage = attacker.attackPower + diceValue * 2; // Reduce by defender's defense result = Math.max(1, baseDamage - Math.floor(defender.defensePower / 2)); } else if (actionType === "defend") { // Defense value is based on dice roll result = diceValue * 3; } else if (actionType === "special") { // Special attack does more damage but is more dependent on dice roll var baseDamage = attacker.specialPower + diceValue * 4; // Special attacks ignore some defense result = Math.max(1, baseDamage - Math.floor(defender.defensePower / 3)); } return result; } function handleVictory() { gameState = "victory"; actionInProgress = true; LK.getSound('victory').play(); // Hide dice actionDice.visible = false; // Update stats storage.victories++; storage.playerLevel++; storage.skillPoints++; skillPointsAvailable = storage.skillPoints; // Show victory message statusText.show("Victory! +1 Skill Point", "#ffff00"); // Show upgrade screen after delay LK.setTimeout(function () { setActionButtonsVisible(false); setUpgradeButtonsVisible(true); updateUpgradeButtons(); gameState = "upgrade"; statusText.show("Upgrade Your Monster", "#2ecc71"); }, 2000); } function handleDefeat() { gameState = "defeat"; actionInProgress = true; LK.getSound('defeat').play(); // Hide dice actionDice.visible = false; // Show defeat message statusText.show("Defeat!", "#e74c3c"); // End game after delay LK.setTimeout(function () { LK.showGameOver(); }, 2000); } function weightedRandomChoice(items, weights) { var totalWeight = 0; for (var i = 0; i < weights.length; i++) { totalWeight += weights[i]; } var random = Math.random() * totalWeight; var weightSum = 0; for (var i = 0; i < items.length; i++) { weightSum += weights[i]; if (random < weightSum) { return i; } } return 0; // Fallback } // Initialize game initGame(); // Game update loop game.update = function () { // Game logic that needs to run every frame would go here // Currently, all our logic is event-driven }; // Handle mouse/touch events game.move = function (x, y, obj) { // Movement handling if needed }; game.down = function (x, y, obj) { // Handle clicks not caught by other objects }; game.up = function (x, y, obj) { // Handle releases not caught by other objects };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,710 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ playerLevel: 1,
+ victories: 0,
+ skillPoints: 0,
+ attackBonus: 0,
+ defenseBonus: 0,
+ specialBonus: 0,
+ healthBonus: 0
+});
+
+/****
+* Classes
+****/
+var ActionButton = Container.expand(function (text, action) {
+ var self = Container.call(this);
+ var buttonGraphic = self.attachAsset('actionButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var buttonText = new Text2(text, {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ buttonText.anchor.set(0.5, 0.5);
+ self.addChild(buttonText);
+ self.action = action;
+ self.enabled = true;
+ self.setEnabled = function (enabled) {
+ self.enabled = enabled;
+ buttonGraphic.alpha = enabled ? 1.0 : 0.5;
+ };
+ self.down = function (x, y, obj) {
+ if (!self.enabled) {
+ return;
+ }
+ tween(buttonGraphic, {
+ scaleX: 0.9,
+ scaleY: 0.9
+ }, {
+ duration: 100
+ });
+ };
+ self.up = function (x, y, obj) {
+ if (!self.enabled) {
+ return;
+ }
+ tween(buttonGraphic, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ if (self.action) {
+ self.action();
+ }
+ }
+ });
+ };
+ return self;
+});
+var Dice = Container.expand(function () {
+ var self = Container.call(this);
+ var diceGraphic = self.attachAsset('dice', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var valueText = new Text2('?', {
+ size: 60,
+ fill: 0x000000
+ });
+ valueText.anchor.set(0.5, 0.5);
+ self.addChild(valueText);
+ self.value = 0;
+ self.isRolling = false;
+ self.roll = function (callback) {
+ if (self.isRolling) {
+ return;
+ }
+ self.isRolling = true;
+ LK.getSound('diceRoll').play();
+ var rollIterations = 10;
+ var currentIteration = 0;
+ function doRoll() {
+ self.value = Math.floor(Math.random() * 6) + 1;
+ valueText.setText(self.value.toString());
+ currentIteration++;
+ if (currentIteration < rollIterations) {
+ LK.setTimeout(doRoll, 100);
+ } else {
+ self.isRolling = false;
+ if (callback) {
+ callback(self.value);
+ }
+ }
+ }
+ doRoll();
+ };
+ self.setValue = function (val) {
+ self.value = val;
+ valueText.setText(val.toString());
+ };
+ return self;
+});
+var HealthBar = Container.expand(function () {
+ var self = Container.call(this);
+ var background = self.attachAsset('hpBarBg', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ var foreground = self.attachAsset('hpBar', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ self.maxHealth = 100;
+ self.currentHealth = 100;
+ self.setMaxHealth = function (value) {
+ self.maxHealth = value;
+ self.updateDisplay();
+ };
+ self.setCurrentHealth = function (value) {
+ self.currentHealth = Math.max(0, Math.min(self.maxHealth, value));
+ self.updateDisplay();
+ };
+ self.updateDisplay = function () {
+ var ratio = self.currentHealth / self.maxHealth;
+ foreground.scale.x = ratio;
+ };
+ return self;
+});
+var Monster = Container.expand(function (isPlayer) {
+ var self = Container.call(this);
+ var assetId = isPlayer ? 'playerMonster' : 'enemyMonster';
+ var monsterGraphic = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var nameText = new Text2(isPlayer ? "Player" : "Enemy", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ nameText.anchor.set(0.5, 0);
+ nameText.y = -monsterGraphic.height / 2 - 50;
+ self.addChild(nameText);
+ var healthBar = new HealthBar();
+ healthBar.y = monsterGraphic.height / 2 + 20;
+ healthBar.x = -healthBar.width / 2;
+ self.addChild(healthBar);
+ self.isPlayer = isPlayer;
+ self.level = 1;
+ self.baseHealth = 100;
+ self.baseAttack = 10;
+ self.baseDefense = 5;
+ self.baseSpecial = 15;
+ self.maxHealth = self.baseHealth;
+ self.currentHealth = self.maxHealth;
+ self.attackPower = self.baseAttack;
+ self.defensePower = self.baseDefense;
+ self.specialPower = self.baseSpecial;
+ self.setName = function (name) {
+ nameText.setText(name);
+ };
+ self.setLevel = function (level) {
+ self.level = level;
+ if (!self.isPlayer) {
+ // Scale enemy stats based on level
+ self.maxHealth = self.baseHealth + (level - 1) * 20;
+ self.attackPower = self.baseAttack + (level - 1) * 2;
+ self.defensePower = self.baseDefense + (level - 1);
+ self.specialPower = self.baseSpecial + (level - 1) * 3;
+ } else {
+ // Apply player bonuses from storage
+ self.maxHealth = self.baseHealth + storage.healthBonus * 10;
+ self.attackPower = self.baseAttack + storage.attackBonus;
+ self.defensePower = self.baseDefense + storage.defenseBonus;
+ self.specialPower = self.baseSpecial + storage.specialBonus;
+ }
+ self.currentHealth = self.maxHealth;
+ healthBar.setMaxHealth(self.maxHealth);
+ healthBar.setCurrentHealth(self.currentHealth);
+ };
+ self.takeDamage = function (amount) {
+ self.currentHealth -= amount;
+ if (self.currentHealth < 0) {
+ self.currentHealth = 0;
+ }
+ healthBar.setCurrentHealth(self.currentHealth);
+ // Flash red on damage
+ LK.effects.flashObject(monsterGraphic, 0xff0000, 500);
+ // Shake when hit
+ self.shake();
+ return self.currentHealth <= 0; // Return true if defeated
+ };
+ self.heal = function (amount) {
+ self.currentHealth += amount;
+ if (self.currentHealth > self.maxHealth) {
+ self.currentHealth = self.maxHealth;
+ }
+ healthBar.setCurrentHealth(self.currentHealth);
+ };
+ self.shake = function () {
+ var originalX = self.x;
+ var originalY = self.y;
+ function shakeStep(magnitude) {
+ var offsetX = (Math.random() - 0.5) * 2 * magnitude;
+ var offsetY = (Math.random() - 0.5) * 2 * magnitude;
+ self.x = originalX + offsetX;
+ self.y = originalY + offsetY;
+ }
+ var steps = 10;
+ var currentStep = 0;
+ var maxMagnitude = 20;
+ function doShake() {
+ var magnitude = maxMagnitude * (1 - currentStep / steps);
+ shakeStep(magnitude);
+ currentStep++;
+ if (currentStep < steps) {
+ LK.setTimeout(doShake, 30);
+ } else {
+ self.x = originalX;
+ self.y = originalY;
+ }
+ }
+ doShake();
+ };
+ self.down = function (x, y, obj) {
+ // Just for show - adds interactivity by shrinking slightly on press
+ if (self.isPlayer) {
+ tween(monsterGraphic, {
+ scaleX: 0.95,
+ scaleY: 0.95
+ }, {
+ duration: 100
+ });
+ }
+ };
+ self.up = function (x, y, obj) {
+ if (self.isPlayer) {
+ tween(monsterGraphic, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 100
+ });
+ }
+ };
+ return self;
+});
+var StatUpgradeButton = Container.expand(function (statName, upgradeAction) {
+ var self = Container.call(this);
+ var buttonGraphic = self.attachAsset('actionButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+ });
+ var buttonText = new Text2(statName + " +1", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ buttonText.anchor.set(0.5, 0.5);
+ self.addChild(buttonText);
+ self.upgradeAction = upgradeAction;
+ self.down = function (x, y, obj) {
+ tween(buttonGraphic, {
+ scaleX: 0.75,
+ scaleY: 0.75
+ }, {
+ duration: 100
+ });
+ };
+ self.up = function (x, y, obj) {
+ tween(buttonGraphic, {
+ scaleX: 0.8,
+ scaleY: 0.8
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ if (self.upgradeAction) {
+ self.upgradeAction();
+ }
+ }
+ });
+ };
+ return self;
+});
+var StatusText = Container.expand(function () {
+ var self = Container.call(this);
+ var textDisplay = new Text2("", {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ textDisplay.anchor.set(0.5, 0.5);
+ self.addChild(textDisplay);
+ self.show = function (message, color, duration) {
+ textDisplay.setText(message);
+ if (color) {
+ textDisplay.style.fill = color;
+ } else {
+ textDisplay.style.fill = "#ffffff";
+ }
+ self.alpha = 1;
+ if (duration) {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: duration
+ });
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2c3e50
+});
+
+/****
+* Game Code
+****/
+// Game state
+var gameState = "start"; // Possible states: "start", "battle", "playerTurn", "enemyTurn", "diceRoll", "victory", "defeat", "upgrade"
+var currentDiceRoll = 0;
+var actionInProgress = false;
+var skillPointsAvailable = storage.skillPoints;
+// Game objects
+var playerMonster;
+var enemyMonster;
+var actionDice;
+var actionButtons = [];
+var statusText;
+var upgradeButtons = [];
+// Initialize the game
+function initGame() {
+ // Play background music
+ LK.playMusic('battleMusic');
+ // Create player monster
+ playerMonster = new Monster(true);
+ playerMonster.x = 2048 * 0.25;
+ playerMonster.y = 2732 * 0.5;
+ playerMonster.setName("Your Monster");
+ playerMonster.setLevel(storage.playerLevel);
+ game.addChild(playerMonster);
+ // Create enemy monster
+ enemyMonster = new Monster(false);
+ enemyMonster.x = 2048 * 0.75;
+ enemyMonster.y = 2732 * 0.5;
+ enemyMonster.setName("Enemy Lvl " + storage.playerLevel);
+ enemyMonster.setLevel(storage.playerLevel);
+ game.addChild(enemyMonster);
+ // Create action dice
+ actionDice = new Dice();
+ actionDice.x = 2048 * 0.5;
+ actionDice.y = 2732 * 0.4;
+ actionDice.visible = false;
+ game.addChild(actionDice);
+ // Create status text
+ statusText = new StatusText();
+ statusText.x = 2048 * 0.5;
+ statusText.y = 2732 * 0.3;
+ game.addChild(statusText);
+ // Create action buttons
+ var buttonY = 2732 * 0.75;
+ var buttonSpacing = 350;
+ var attackButton = new ActionButton("Attack", function () {
+ if (!actionInProgress && gameState === "playerTurn") {
+ performPlayerAction("attack");
+ }
+ });
+ attackButton.x = 2048 * 0.5 - buttonSpacing;
+ attackButton.y = buttonY;
+ game.addChild(attackButton);
+ actionButtons.push(attackButton);
+ var defendButton = new ActionButton("Defend", function () {
+ if (!actionInProgress && gameState === "playerTurn") {
+ performPlayerAction("defend");
+ }
+ });
+ defendButton.x = 2048 * 0.5;
+ defendButton.y = buttonY;
+ game.addChild(defendButton);
+ actionButtons.push(defendButton);
+ var specialButton = new ActionButton("Special", function () {
+ if (!actionInProgress && gameState === "playerTurn") {
+ performPlayerAction("special");
+ }
+ });
+ specialButton.x = 2048 * 0.5 + buttonSpacing;
+ specialButton.y = buttonY;
+ game.addChild(specialButton);
+ actionButtons.push(specialButton);
+ // Create upgrade buttons (initially hidden)
+ createUpgradeButtons();
+ // Create score display
+ var levelText = new Text2("Level: " + storage.playerLevel, {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ levelText.anchor.set(1, 0);
+ levelText.x = 2048 - 50;
+ levelText.y = 50;
+ game.addChild(levelText);
+ var victoryText = new Text2("Victories: " + storage.victories, {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ victoryText.anchor.set(1, 0);
+ victoryText.x = 2048 - 50;
+ victoryText.y = 110;
+ game.addChild(victoryText);
+ var skillPointsText = new Text2("Skill Points: " + storage.skillPoints, {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ skillPointsText.anchor.set(0, 0);
+ skillPointsText.x = 150;
+ skillPointsText.y = 50;
+ game.addChild(skillPointsText);
+ // Start the battle
+ startBattle();
+}
+function createUpgradeButtons() {
+ var startY = 2732 * 0.55;
+ var spacing = 150;
+ var attackUpgrade = new StatUpgradeButton("Attack", function () {
+ if (skillPointsAvailable > 0) {
+ storage.attackBonus++;
+ storage.skillPoints--;
+ skillPointsAvailable--;
+ updateUpgradeButtons();
+ }
+ });
+ attackUpgrade.x = 2048 * 0.5;
+ attackUpgrade.y = startY;
+ game.addChild(attackUpgrade);
+ upgradeButtons.push(attackUpgrade);
+ var defenseUpgrade = new StatUpgradeButton("Defense", function () {
+ if (skillPointsAvailable > 0) {
+ storage.defenseBonus++;
+ storage.skillPoints--;
+ skillPointsAvailable--;
+ updateUpgradeButtons();
+ }
+ });
+ defenseUpgrade.x = 2048 * 0.5;
+ defenseUpgrade.y = startY + spacing;
+ game.addChild(defenseUpgrade);
+ upgradeButtons.push(defenseUpgrade);
+ var specialUpgrade = new StatUpgradeButton("Special", function () {
+ if (skillPointsAvailable > 0) {
+ storage.specialBonus++;
+ storage.skillPoints--;
+ skillPointsAvailable--;
+ updateUpgradeButtons();
+ }
+ });
+ specialUpgrade.x = 2048 * 0.5;
+ specialUpgrade.y = startY + spacing * 2;
+ game.addChild(specialUpgrade);
+ upgradeButtons.push(specialUpgrade);
+ var healthUpgrade = new StatUpgradeButton("Health", function () {
+ if (skillPointsAvailable > 0) {
+ storage.healthBonus++;
+ storage.skillPoints--;
+ skillPointsAvailable--;
+ updateUpgradeButtons();
+ }
+ });
+ healthUpgrade.x = 2048 * 0.5;
+ healthUpgrade.y = startY + spacing * 3;
+ game.addChild(healthUpgrade);
+ upgradeButtons.push(healthUpgrade);
+ var continueButton = new ActionButton("Continue", function () {
+ if (gameState === "upgrade") {
+ startBattle();
+ }
+ });
+ continueButton.x = 2048 * 0.5;
+ continueButton.y = startY + spacing * 4.5;
+ game.addChild(continueButton);
+ upgradeButtons.push(continueButton);
+ // Hidden initially
+ updateUpgradeButtons();
+ setUpgradeButtonsVisible(false);
+}
+function updateUpgradeButtons() {
+ for (var i = 0; i < upgradeButtons.length - 1; i++) {
+ var button = upgradeButtons[i];
+ button.setEnabled(skillPointsAvailable > 0);
+ }
+}
+function setUpgradeButtonsVisible(visible) {
+ for (var i = 0; i < upgradeButtons.length; i++) {
+ upgradeButtons[i].visible = visible;
+ }
+}
+function setActionButtonsVisible(visible) {
+ for (var i = 0; i < actionButtons.length; i++) {
+ actionButtons[i].visible = visible;
+ }
+}
+function startBattle() {
+ gameState = "battle";
+ actionInProgress = false;
+ // Reset monsters for new battle
+ playerMonster.setLevel(storage.playerLevel);
+ enemyMonster.setName("Enemy Lvl " + storage.playerLevel);
+ enemyMonster.setLevel(storage.playerLevel);
+ // Hide upgrade buttons, show action buttons
+ setUpgradeButtonsVisible(false);
+ setActionButtonsVisible(true);
+ // Show battle start message
+ statusText.show("Battle Start!", "#ffff00", 2000);
+ // Start player turn after a delay
+ LK.setTimeout(function () {
+ startPlayerTurn();
+ }, 2000);
+}
+function startPlayerTurn() {
+ gameState = "playerTurn";
+ statusText.show("Your Turn", "#3498db", 2000);
+}
+function performPlayerAction(actionType) {
+ gameState = "diceRoll";
+ actionInProgress = true;
+ // Play sound based on action
+ LK.getSound(actionType).play();
+ // Show the dice for roll
+ actionDice.visible = true;
+ actionDice.roll(function (value) {
+ // Process player action based on dice roll
+ currentDiceRoll = value;
+ var actionResult = calculateActionResult(actionType, playerMonster, enemyMonster, value);
+ if (actionType === "attack") {
+ statusText.show("You attacked for " + actionResult + " damage!", "#ff9900");
+ var defeated = enemyMonster.takeDamage(actionResult);
+ if (defeated) {
+ handleVictory();
+ return;
+ }
+ } else if (actionType === "defend") {
+ var healAmount = Math.floor(actionResult / 2);
+ statusText.show("You defended! +" + actionResult + " DEF for this turn\n+" + healAmount + " HP", "#2ecc71");
+ playerMonster.defensePower += actionResult; // Temporary defense boost
+ playerMonster.heal(healAmount);
+ } else if (actionType === "special") {
+ statusText.show("Special attack for " + actionResult + " damage!", "#9b59b6");
+ var defeated = enemyMonster.takeDamage(actionResult);
+ if (defeated) {
+ handleVictory();
+ return;
+ }
+ }
+ // Hide dice after action
+ LK.setTimeout(function () {
+ actionDice.visible = false;
+ // Start enemy turn after a delay
+ LK.setTimeout(function () {
+ startEnemyTurn();
+ }, 1000);
+ }, 1000);
+ });
+}
+function startEnemyTurn() {
+ gameState = "enemyTurn";
+ statusText.show("Enemy Turn", "#e74c3c", 1000);
+ // Reset temporary defense boost from defend action
+ if (playerMonster.defensePower > playerMonster.baseDefense + storage.defenseBonus) {
+ playerMonster.defensePower = playerMonster.baseDefense + storage.defenseBonus;
+ }
+ // Enemy AI chooses action
+ LK.setTimeout(function () {
+ var actions = ["attack", "special", "defend"];
+ var weights = [0.6, 0.3, 0.1]; // Weights for action selection
+ if (enemyMonster.currentHealth < enemyMonster.maxHealth * 0.3) {
+ // When low on health, more likely to defend
+ weights = [0.4, 0.2, 0.4];
+ }
+ var actionIndex = weightedRandomChoice(actions, weights);
+ var actionType = actions[actionIndex];
+ // Play sound based on action
+ LK.getSound(actionType).play();
+ // Show dice for enemy roll
+ actionDice.visible = true;
+ actionDice.roll(function (value) {
+ currentDiceRoll = value;
+ var actionResult = calculateActionResult(actionType, enemyMonster, playerMonster, value);
+ if (actionType === "attack") {
+ statusText.show("Enemy attacked for " + actionResult + " damage!", "#ff9900");
+ var defeated = playerMonster.takeDamage(actionResult);
+ if (defeated) {
+ handleDefeat();
+ return;
+ }
+ } else if (actionType === "defend") {
+ var healAmount = Math.floor(actionResult / 2);
+ statusText.show("Enemy defended! +" + actionResult + " DEF\n+" + healAmount + " HP", "#2ecc71");
+ enemyMonster.defensePower += actionResult; // Temporary defense boost
+ enemyMonster.heal(healAmount);
+ } else if (actionType === "special") {
+ statusText.show("Enemy special attack for " + actionResult + " damage!", "#9b59b6");
+ var defeated = playerMonster.takeDamage(actionResult);
+ if (defeated) {
+ handleDefeat();
+ return;
+ }
+ }
+ // Hide dice after action
+ LK.setTimeout(function () {
+ actionDice.visible = false;
+ // Start player turn again after a delay
+ LK.setTimeout(function () {
+ actionInProgress = false;
+ startPlayerTurn();
+ }, 1000);
+ }, 1000);
+ });
+ }, 1000);
+}
+function calculateActionResult(actionType, attacker, defender, diceValue) {
+ var result = 0;
+ if (actionType === "attack") {
+ // Base damage is attacker's attack power + dice roll
+ var baseDamage = attacker.attackPower + diceValue * 2;
+ // Reduce by defender's defense
+ result = Math.max(1, baseDamage - Math.floor(defender.defensePower / 2));
+ } else if (actionType === "defend") {
+ // Defense value is based on dice roll
+ result = diceValue * 3;
+ } else if (actionType === "special") {
+ // Special attack does more damage but is more dependent on dice roll
+ var baseDamage = attacker.specialPower + diceValue * 4;
+ // Special attacks ignore some defense
+ result = Math.max(1, baseDamage - Math.floor(defender.defensePower / 3));
+ }
+ return result;
+}
+function handleVictory() {
+ gameState = "victory";
+ actionInProgress = true;
+ LK.getSound('victory').play();
+ // Hide dice
+ actionDice.visible = false;
+ // Update stats
+ storage.victories++;
+ storage.playerLevel++;
+ storage.skillPoints++;
+ skillPointsAvailable = storage.skillPoints;
+ // Show victory message
+ statusText.show("Victory! +1 Skill Point", "#ffff00");
+ // Show upgrade screen after delay
+ LK.setTimeout(function () {
+ setActionButtonsVisible(false);
+ setUpgradeButtonsVisible(true);
+ updateUpgradeButtons();
+ gameState = "upgrade";
+ statusText.show("Upgrade Your Monster", "#2ecc71");
+ }, 2000);
+}
+function handleDefeat() {
+ gameState = "defeat";
+ actionInProgress = true;
+ LK.getSound('defeat').play();
+ // Hide dice
+ actionDice.visible = false;
+ // Show defeat message
+ statusText.show("Defeat!", "#e74c3c");
+ // End game after delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 2000);
+}
+function weightedRandomChoice(items, weights) {
+ var totalWeight = 0;
+ for (var i = 0; i < weights.length; i++) {
+ totalWeight += weights[i];
+ }
+ var random = Math.random() * totalWeight;
+ var weightSum = 0;
+ for (var i = 0; i < items.length; i++) {
+ weightSum += weights[i];
+ if (random < weightSum) {
+ return i;
+ }
+ }
+ return 0; // Fallback
+}
+// Initialize game
+initGame();
+// Game update loop
+game.update = function () {
+ // Game logic that needs to run every frame would go here
+ // Currently, all our logic is event-driven
+};
+// Handle mouse/touch events
+game.move = function (x, y, obj) {
+ // Movement handling if needed
+};
+game.down = function (x, y, obj) {
+ // Handle clicks not caught by other objects
+};
+game.up = function (x, y, obj) {
+ // Handle releases not caught by other objects
+};
\ No newline at end of file