/**** * 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(); } } }); }; self.setEnabled = function (enabled) { self.enabled = enabled; buttonGraphic.alpha = enabled ? 1.0 : 0.5; }; 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) { if (textDisplay.style) { textDisplay.style.fill = color; } else { textDisplay.style = { fill: color }; } } else { if (textDisplay.style) { textDisplay.style.fill = "#ffffff"; } else { textDisplay.style = { fill: 0xFFFFFF }; } } 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 };
/****
* 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();
}
}
});
};
self.setEnabled = function (enabled) {
self.enabled = enabled;
buttonGraphic.alpha = enabled ? 1.0 : 0.5;
};
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) {
if (textDisplay.style) {
textDisplay.style.fill = color;
} else {
textDisplay.style = {
fill: color
};
}
} else {
if (textDisplay.style) {
textDisplay.style.fill = "#ffffff";
} else {
textDisplay.style = {
fill: 0xFFFFFF
};
}
}
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
};