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