User prompt
Bueno ahora quiero que la generación de los bates que se generan por la roca sea de cada 7 segundos, y que ahora cuando aparezca la roca, toda las demás spawneos de objetos se detenga, para que solo esté la generación de la roca y de los bates que genera la roca ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Quiero que la piedra aguante ahora 50 disparos, y que spawne en medio de la pantalla, y que que se mueva de lado a lado y ya no avance hacia adelante, y que ahora por cada 3 segundos que está la roca aparezcan 10 bates cubriendo todo el escenario de lado a lado ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ahora quiero que cuando se cumpla la condición cada 5 veces, aparezca una piedra que aguante 10 golpes, y que esa piedra de 50 puntos
User prompt
Ahora quiero que cuando los objetos sean destruidos haga una mínima explosión ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Buenísimo, solo que ahora necesito que el cuchillo y el palo aguanten 1 disparo, el bate 2 disparos y la espada 4 disparos
User prompt
Bien ahora quiero qie los objetos tengan más resistencia, que el bate aguante 5 disparos, el palo 3 disparos el cuchillo 3 disparos, y las espada 7 disparos
User prompt
Lo siento, pero necesito que vuelvas a poner el tiempo a 15 segundos
User prompt
A si me falto decir, si se cumple con la condición antes de que se acabe el tiempo se vuelve a resetear la condición, a si y que el tiempo ahora sea de 10 segundos
User prompt
Ahora tambien necesito que haya un temporizador en el qie necesites destruir 5 objetos en 15 segundos, y si no cumples con el tiempo te quitan 20 puntos, si se tienen menos de 20 puntos, y se acaba ese tiempo y no cumples con las condiciones tambien se pierde
User prompt
Ahora necesito que la velocidad de los objetos aumente al doble
User prompt
Ahora necesito que la velocidad del player sea menor
User prompt
Ok gracias, ahora solo necesito que la generación sea más rápida, y sea aleatoriamente, y que el player no pueda disparar tanto, que el límite sean 3 disparos por pantalla, después de que los disparos salgan se podrá volver a disparar
Code edit (1 edits merged)
Please save this source code
User prompt
Dodge & Destroy
Initial prompt
Hola, necesito un juego en el que hayan varios objeto que necesites esquivar, como cuchillos, espadas, bates de béisbol, palos y otros, en donde el player o jugador o protagonista necesite esquivarlo, pero que también pueda destruirlos disparandoles, y por cada objeto que destruya el player disparandole, gane un punto por cada objeto destruido, y el jugador o player solo aguante 3 golpes de esos objetos
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.update = function () {
self.y += self.speed;
};
return self;
});
var FallingObject = Container.expand(function (type) {
var self = Container.call(this);
var objectGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = (Math.random() * 3 + 2) * 2;
self.type = type;
// Set hit points based on object type
if (type === 'bat') {
self.hitPoints = 2;
} else if (type === 'stick') {
self.hitPoints = 1;
} else if (type === 'knife') {
self.hitPoints = 1;
} else if (type === 'sword') {
self.hitPoints = 4;
} else if (type === 'rock') {
self.hitPoints = 25;
}
self.maxHitPoints = self.hitPoints;
self.update = function () {
self.y += self.speed;
self.rotation += 0.05;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset(equippedSkin, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.shootCooldown = 0;
self.updateSkin = function (newSkin) {
self.removeChildren();
playerGraphics = self.attachAsset(newSkin, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
// Pulse effect
self.scaleX = 1 + Math.sin(LK.ticks * 0.2) * 0.2;
self.scaleY = 1 + Math.sin(LK.ticks * 0.2) * 0.2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing', or 'shop'
// Shop variables
var totalEarnings = storage.totalEarnings || 0;
var currentShopSection = 'upgrades'; // Track current shop section
var shopUpgrades = {
doubleDamagePrice: storage.savedDoubleDamage || 100,
unlimitedShootingPrice: storage.savedUnlimitedShooting || 150,
extraLifePrice: storage.savedExtraLife || 200,
fastShootingPrice: storage.savedFastShooting || 120,
shieldPrice: storage.savedShield || 180,
damageUpgradePrice: storage.savedDamageUpgradePrice || 150
};
// Skin system variables
var ownedSkins = storage.ownedSkins || ['player']; // Default skin is always owned
var equippedSkin = storage.equippedSkin || 'player';
var skinPrices = {
player2: 100
};
// Add blue background
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Menu elements
var titleText = new Text2('Dodge & Destroy', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 2 - 200;
game.addChild(titleText);
var playButton = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.x = 2048 / 2;
playButton.y = 2732 / 2 + 100;
game.addChild(playButton);
var shopButton = new Text2('SHOP', {
size: 80,
fill: 0xFFD700
});
shopButton.anchor.set(0.5, 0.5);
shopButton.x = 2048 / 2;
shopButton.y = 2732 / 2 + 200;
game.addChild(shopButton);
var saveButton = new Text2('SAVE', {
size: 60,
fill: 0x00FFFF
});
saveButton.anchor.set(0.5, 0.5);
saveButton.x = 2048 / 2 - 200;
saveButton.y = 2732 / 2 + 300;
game.addChild(saveButton);
var loadButton = new Text2('LOAD', {
size: 60,
fill: 0xFF00FF
});
loadButton.anchor.set(0.5, 0.5);
loadButton.x = 2048 / 2 + 200;
loadButton.y = 2732 / 2 + 300;
game.addChild(loadButton);
// Save confirmation message
var saveMessageText = new Text2('PROGRESS SAVED', {
size: 70,
fill: 0x00FF00
});
saveMessageText.anchor.set(0.5, 0.5);
saveMessageText.x = 2048 / 2;
saveMessageText.y = 2732 / 2 - 100;
saveMessageText.visible = false;
game.addChild(saveMessageText);
// Load confirmation message
var loadMessageText = new Text2('PROGRESS RESTORED', {
size: 70,
fill: 0x00FFFF
});
loadMessageText.anchor.set(0.5, 0.5);
loadMessageText.x = 2048 / 2;
loadMessageText.y = 2732 / 2 - 100;
loadMessageText.visible = false;
game.addChild(loadMessageText);
// Game version text
var versionText = new Text2('Game version: V1.00', {
size: 40,
fill: 0xFFFFFF
});
versionText.anchor.set(0, 1);
versionText.x = 120;
versionText.y = 2732 - 20;
game.addChild(versionText);
// Shop UI elements (initially hidden)
var shopTitle = new Text2('SHOP', {
size: 100,
fill: 0xFFD700
});
shopTitle.anchor.set(0.5, 0.5);
shopTitle.x = 2048 / 2;
shopTitle.y = 300;
shopTitle.visible = false;
game.addChild(shopTitle);
var coinsText = new Text2('Coins: ' + totalEarnings, {
size: 60,
fill: 0xFFFFFF
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 2048 / 2;
coinsText.y = 400;
coinsText.visible = false;
game.addChild(coinsText);
// Shop upgrades
var upgrade1Text = new Text2('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade1Text.anchor.set(0.5, 0.5);
upgrade1Text.x = 2048 / 2;
upgrade1Text.y = 600;
upgrade1Text.visible = false;
game.addChild(upgrade1Text);
var upgrade2Text = new Text2('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade2Text.anchor.set(0.5, 0.5);
upgrade2Text.x = 2048 / 2;
upgrade2Text.y = 700;
upgrade2Text.visible = false;
game.addChild(upgrade2Text);
var upgrade3Text = new Text2('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade3Text.anchor.set(0.5, 0.5);
upgrade3Text.x = 2048 / 2;
upgrade3Text.y = 800;
upgrade3Text.visible = false;
game.addChild(upgrade3Text);
var upgrade4Text = new Text2('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade4Text.anchor.set(0.5, 0.5);
upgrade4Text.x = 2048 / 2;
upgrade4Text.y = 900;
upgrade4Text.visible = false;
game.addChild(upgrade4Text);
var upgrade5Text = new Text2('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade5Text.anchor.set(0.5, 0.5);
upgrade5Text.x = 2048 / 2;
upgrade5Text.y = 1000;
upgrade5Text.visible = false;
game.addChild(upgrade5Text);
var upgrade6Text = new Text2('+1 Damage - Price: 150 coins', {
size: 50,
fill: 0x00FF00
});
upgrade6Text.anchor.set(0.5, 0.5);
upgrade6Text.x = 2048 / 2;
upgrade6Text.y = 1100;
upgrade6Text.visible = false;
game.addChild(upgrade6Text);
// Shop section navigation
var upgradesSection = new Text2('UPGRADES', {
size: 60,
fill: 0x00FF00
});
upgradesSection.anchor.set(0.5, 0.5);
upgradesSection.x = 2048 / 2 - 300;
upgradesSection.y = 500;
upgradesSection.visible = false;
game.addChild(upgradesSection);
var skinsSection = new Text2('SKINS', {
size: 60,
fill: 0xFFFFFF
});
skinsSection.anchor.set(0.5, 0.5);
skinsSection.x = 2048 / 2;
skinsSection.y = 500;
skinsSection.visible = false;
game.addChild(skinsSection);
var projectilesSection = new Text2('PROJECTILES', {
size: 60,
fill: 0xFFFFFF
});
projectilesSection.anchor.set(0.5, 0.5);
projectilesSection.x = 2048 / 2 + 300;
projectilesSection.y = 500;
projectilesSection.visible = false;
game.addChild(projectilesSection);
// Skin shop elements
var skin1Text = new Text2('Player Skin 2 - Price: 100 coins', {
size: 50,
fill: 0x00FF00
});
skin1Text.anchor.set(0.5, 0.5);
skin1Text.x = 2048 / 2;
skin1Text.y = 600;
skin1Text.visible = false;
game.addChild(skin1Text);
var skin1EquipText = new Text2('EQUIP', {
size: 40,
fill: 0xFFD700
});
skin1EquipText.anchor.set(0.5, 0.5);
skin1EquipText.x = 2048 / 2;
skin1EquipText.y = 650;
skin1EquipText.visible = false;
game.addChild(skin1EquipText);
var backButton = new Text2('BACK', {
size: 70,
fill: 0xFF4444
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 2048 / 2;
backButton.y = 1200;
backButton.visible = false;
game.addChild(backButton);
// Start title music
LK.playMusic('title_music');
// Game elements (initially hidden)
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 200;
player.visible = false;
var bullets = [];
var fallingObjects = [];
var lives = 3;
var maxLives = 3;
var objectTypes = ['knife', 'sword', 'bat', 'stick'];
var spawnTimer = 0;
var spawnRate = 60;
var difficultyTimer = 0;
var maxBullets = 3;
// Challenge variables
var objectsDestroyed = 0;
var challengeTarget = 5;
var challengesCompleted = 0;
var rockActive = false;
var rockBatTimer = 0;
var rockBatSpawnRate = 420; // 7 seconds at 60 FPS
var challengeTimer = 0;
var challengeTimeLimit = 900; // 15 seconds at 60 FPS
var currentChallenge = 0; // Track current challenge number
// Power-up variables
var batsDestroyed = 0;
var swordsDestroyed = 0;
var knivesDestroyed = 0;
var sticksDestroyed = 0;
var powerUps = [];
var doubleDamageActive = false;
var doubleDamageTimer = 0;
var doubleDamageTimeLimit = 600; // 10 seconds at 60 FPS
var unlimitedShootingActive = false;
var unlimitedShootingTimer = 0;
var unlimitedShootingTimeLimit = 600; // 10 seconds at 60 FPS
var damageUpgrade = storage.damageUpgrade || 0;
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 150;
scoreText.y = 50;
scoreText.visible = false;
LK.gui.topLeft.addChild(scoreText);
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF4444
});
livesText.anchor.set(1, 0);
livesText.visible = false;
LK.gui.topRight.addChild(livesText);
var timerText = new Text2('Target: 5', {
size: 50,
fill: 0xFFFF00
});
timerText.anchor.set(0.5, 0);
timerText.x = 0;
timerText.y = 50;
timerText.visible = false;
LK.gui.top.addChild(timerText);
var powerUpText = new Text2('', {
size: 45,
fill: 0x00FF00
});
powerUpText.anchor.set(0.5, 0);
powerUpText.x = 0;
powerUpText.y = 120;
powerUpText.visible = false;
LK.gui.top.addChild(powerUpText);
var dragActive = false;
var lastTouchX = 0;
var lastTouchY = 0;
function showShop() {
gameState = 'shop';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
shopButton.visible = false;
saveButton.visible = false;
loadButton.visible = false;
saveMessageText.visible = false;
loadMessageText.visible = false;
// Show shop elements
shopTitle.visible = true;
coinsText.visible = true;
upgradesSection.visible = true;
skinsSection.visible = true;
projectilesSection.visible = true;
backButton.visible = true;
// Show appropriate section elements
if (currentShopSection === 'upgrades') {
upgrade1Text.visible = true;
upgrade2Text.visible = true;
upgrade3Text.visible = true;
upgrade4Text.visible = true;
upgrade5Text.visible = true;
upgrade6Text.visible = true;
} else if (currentShopSection === 'skins') {
// Update skin text based on ownership
if (ownedSkins.indexOf('player2') >= 0) {
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
if (equippedSkin === 'player2') {
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
} else {
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
}
} else {
skin1Text.setText('Player Skin 2 - Price: 100 coins');
skin1EquipText.visible = false;
}
skin1Text.visible = true;
}
// Update section colors based on current section
if (currentShopSection === 'upgrades') {
upgradesSection.tint = 0x00FF00;
} else {
upgradesSection.tint = 0xFFFFFF;
}
if (currentShopSection === 'skins') {
skinsSection.tint = 0x00FF00;
} else {
skinsSection.tint = 0xFFFFFF;
}
projectilesSection.tint = 0xFFFFFF;
// Update coins display
coinsText.setText('Coins: ' + totalEarnings);
}
function hideShop() {
gameState = 'menu';
// Hide shop elements
shopTitle.visible = false;
coinsText.visible = false;
upgradesSection.visible = false;
skinsSection.visible = false;
projectilesSection.visible = false;
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
skin1Text.visible = false;
skin1EquipText.visible = false;
backButton.visible = false;
// Show menu elements
titleText.visible = true;
playButton.visible = true;
shopButton.visible = true;
saveButton.visible = true;
loadButton.visible = true;
}
function saveGame() {
// Save current upgrades and earnings using individual properties
storage.savedDoubleDamage = shopUpgrades.doubleDamagePrice;
storage.savedUnlimitedShooting = shopUpgrades.unlimitedShootingPrice;
storage.savedExtraLife = shopUpgrades.extraLifePrice;
storage.savedFastShooting = shopUpgrades.fastShootingPrice;
storage.savedShield = shopUpgrades.shieldPrice;
storage.savedDamageUpgradePrice = shopUpgrades.damageUpgradePrice;
storage.savedEarnings = totalEarnings;
storage.damageUpgrade = damageUpgrade;
storage.ownedSkins = ownedSkins;
storage.equippedSkin = equippedSkin;
storage.totalEarnings = totalEarnings;
}
function loadGame() {
// Load saved upgrades and earnings if they exist using individual properties
if (storage.savedDoubleDamage !== undefined) {
shopUpgrades.doubleDamagePrice = storage.savedDoubleDamage;
}
if (storage.savedUnlimitedShooting !== undefined) {
shopUpgrades.unlimitedShootingPrice = storage.savedUnlimitedShooting;
}
if (storage.savedExtraLife !== undefined) {
shopUpgrades.extraLifePrice = storage.savedExtraLife;
}
if (storage.savedFastShooting !== undefined) {
shopUpgrades.fastShootingPrice = storage.savedFastShooting;
}
if (storage.savedShield !== undefined) {
shopUpgrades.shieldPrice = storage.savedShield;
}
if (storage.savedDamageUpgradePrice !== undefined) {
shopUpgrades.damageUpgradePrice = storage.savedDamageUpgradePrice;
}
if (storage.savedEarnings !== undefined) {
totalEarnings = storage.savedEarnings;
}
if (storage.damageUpgrade !== undefined) {
damageUpgrade = storage.damageUpgrade;
}
if (storage.ownedSkins) {
ownedSkins = storage.ownedSkins;
}
if (storage.equippedSkin) {
equippedSkin = storage.equippedSkin;
}
// Update shop display texts
upgrade1Text.setText('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins');
upgrade2Text.setText('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins');
upgrade3Text.setText('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins');
upgrade4Text.setText('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins');
upgrade5Text.setText('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins');
upgrade6Text.setText('+1 Damage - Price: ' + shopUpgrades.damageUpgradePrice + ' coins');
// Update coins display in shop
coinsText.setText('Coins: ' + totalEarnings);
}
function showSaveMessage() {
// Show the save message
saveMessageText.visible = true;
saveMessageText.alpha = 1;
// Hide the message after 10 seconds using tween
tween(saveMessageText, {
alpha: 0
}, {
duration: 10000,
easing: tween.linear,
onFinish: function onFinish() {
saveMessageText.visible = false;
}
});
}
function showLoadMessage() {
// Show the load message
loadMessageText.visible = true;
loadMessageText.alpha = 1;
// Hide the message after 10 seconds using tween
tween(loadMessageText, {
alpha: 0
}, {
duration: 10000,
easing: tween.linear,
onFinish: function onFinish() {
loadMessageText.visible = false;
}
});
}
function startGame() {
gameState = 'playing';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
shopButton.visible = false;
saveButton.visible = false;
loadButton.visible = false;
saveMessageText.visible = false;
loadMessageText.visible = false;
// Show game elements
player.visible = true;
scoreText.visible = true;
livesText.visible = true;
timerText.visible = true;
powerUpText.visible = true;
// Stop title music and start survival piano music
LK.stopMusic();
LK.playMusic('survival_piano');
// Reset game variables
lives = maxLives;
objectsDestroyed = 0;
challengesCompleted = 0;
rockActive = false;
challengeTimer = 0;
// Reset power-up variables
batsDestroyed = 0;
swordsDestroyed = 0;
knivesDestroyed = 0;
sticksDestroyed = 0;
doubleDamageActive = false;
doubleDamageTimer = 0;
unlimitedShootingActive = false;
unlimitedShootingTimer = 0;
powerUps = [];
LK.setScore(0);
updateScore();
updateLives();
updateTimer();
}
function updateScore() {
scoreText.setText('Score: ' + LK.getScore());
}
function updateLives() {
livesText.setText('Lives: ' + lives);
}
function updateTimer() {
if (rockActive) {
timerText.setText('DESTROY THE ROCK!');
} else {
var remaining = Math.max(0, challengeTarget - objectsDestroyed);
var timeLeft = Math.ceil((challengeTimeLimit - challengeTimer) / 60);
timerText.setText('Target: ' + remaining + ' | Time: ' + timeLeft + 's');
}
}
function spawnFallingObject() {
var type = objectTypes[Math.floor(Math.random() * objectTypes.length)];
var obj = new FallingObject(type);
obj.x = Math.random() * (2048 - 100) + 50;
obj.y = -50;
fallingObjects.push(obj);
game.addChild(obj);
}
function spawnRock() {
var rock = new FallingObject('rock');
rock.x = 2048 / 2; // Center of screen
rock.y = 200; // Fixed Y position
rock.speed = 0; // No forward movement
rock.horizontalSpeed = 3; // Side to side movement speed
rock.direction = Math.random() < 0.5 ? -1 : 1; // Random initial direction
fallingObjects.push(rock);
game.addChild(rock);
rockActive = true;
updateTimer();
}
function resetChallenge() {
objectsDestroyed = 0;
challengeTimer = 0;
currentChallenge++;
updateTimer();
}
function spawnRockBats() {
for (var i = 0; i < 10; i++) {
var bat = new FallingObject('bat');
bat.x = 2048 / 11 * (i + 1); // Distribute evenly across screen
bat.y = -50;
fallingObjects.push(bat);
game.addChild(bat);
}
}
function spawnPowerUp(x, y, type) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
powerUp.powerUpType = type || 'doubleDamage';
powerUps.push(powerUp);
game.addChild(powerUp);
}
function updatePowerUpDisplay() {
if (doubleDamageActive && unlimitedShootingActive) {
var doubleDamageTimeLeft = Math.ceil((doubleDamageTimeLimit - doubleDamageTimer) / 60);
var unlimitedTimeLeft = Math.ceil((unlimitedShootingTimeLimit - unlimitedShootingTimer) / 60);
powerUpText.setText('DOUBLE DAMAGE: ' + doubleDamageTimeLeft + 's | UNLIMITED: ' + unlimitedTimeLeft + 's');
} else if (doubleDamageActive) {
var timeLeft = Math.ceil((doubleDamageTimeLimit - doubleDamageTimer) / 60);
powerUpText.setText('DOUBLE DAMAGE: ' + timeLeft + 's');
} else if (unlimitedShootingActive) {
var timeLeft = Math.ceil((unlimitedShootingTimeLimit - unlimitedShootingTimer) / 60);
powerUpText.setText('UNLIMITED SHOOTING: ' + timeLeft + 's');
} else {
powerUpText.setText('');
}
}
function shootBullet() {
var canShoot = unlimitedShootingActive || player.shootCooldown <= 0 && bullets.length < maxBullets;
if (canShoot) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 40;
bullets.push(bullet);
game.addChild(bullet);
if (!unlimitedShootingActive) {
player.shootCooldown = 15;
}
LK.getSound('shoot').play();
}
}
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was tapped
var playButtonBounds = {
left: playButton.x - 100,
right: playButton.x + 100,
top: playButton.y - 50,
bottom: playButton.y + 50
};
if (x >= playButtonBounds.left && x <= playButtonBounds.right && y >= playButtonBounds.top && y <= playButtonBounds.bottom) {
startGame();
}
// Check if shop button was tapped
var shopButtonBounds = {
left: shopButton.x - 100,
right: shopButton.x + 100,
top: shopButton.y - 50,
bottom: shopButton.y + 50
};
if (x >= shopButtonBounds.left && x <= shopButtonBounds.right && y >= shopButtonBounds.top && y <= shopButtonBounds.bottom) {
showShop();
}
// Check if save button was tapped
var saveButtonBounds = {
left: saveButton.x - 80,
right: saveButton.x + 80,
top: saveButton.y - 40,
bottom: saveButton.y + 40
};
if (x >= saveButtonBounds.left && x <= saveButtonBounds.right && y >= saveButtonBounds.top && y <= saveButtonBounds.bottom) {
saveGame();
showSaveMessage();
}
// Check if load button was tapped
var loadButtonBounds = {
left: loadButton.x - 80,
right: loadButton.x + 80,
top: loadButton.y - 40,
bottom: loadButton.y + 40
};
if (x >= loadButtonBounds.left && x <= loadButtonBounds.right && y >= loadButtonBounds.top && y <= loadButtonBounds.bottom) {
loadGame();
showLoadMessage();
}
} else if (gameState === 'shop') {
// Check upgrade buttons
var upgradeHeight = 50;
var upgradeWidth = 800;
// Back button
var backButtonBounds = {
left: backButton.x - 100,
right: backButton.x + 100,
top: backButton.y - 40,
bottom: backButton.y + 40
};
if (x >= backButtonBounds.left && x <= backButtonBounds.right && y >= backButtonBounds.top && y <= backButtonBounds.bottom) {
hideShop();
return;
}
// Check section navigation
var sectionHeight = 30;
var sectionWidth = 150;
// Upgrades section
if (x >= upgradesSection.x - sectionWidth && x <= upgradesSection.x + sectionWidth && y >= upgradesSection.y - sectionHeight && y <= upgradesSection.y + sectionHeight) {
currentShopSection = 'upgrades';
upgradesSection.tint = 0x00FF00;
skinsSection.tint = 0xFFFFFF;
projectilesSection.tint = 0xFFFFFF;
// Show upgrades, hide others
upgrade1Text.visible = true;
upgrade2Text.visible = true;
upgrade3Text.visible = true;
upgrade4Text.visible = true;
upgrade5Text.visible = true;
upgrade6Text.visible = true;
return;
}
// Skins section
if (x >= skinsSection.x - sectionWidth && x <= skinsSection.x + sectionWidth && y >= skinsSection.y - sectionHeight && y <= skinsSection.y + sectionHeight) {
currentShopSection = 'skins';
upgradesSection.tint = 0xFFFFFF;
skinsSection.tint = 0x00FF00;
projectilesSection.tint = 0xFFFFFF;
// Hide upgrades and show skins
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
// Show skin elements
if (ownedSkins.indexOf('player2') >= 0) {
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
if (equippedSkin === 'player2') {
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
} else {
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
}
} else {
skin1Text.setText('Player Skin 2 - Price: 100 coins');
skin1EquipText.visible = false;
}
skin1Text.visible = true;
return;
}
// Projectiles section
if (x >= projectilesSection.x - sectionWidth && x <= projectilesSection.x + sectionWidth && y >= projectilesSection.y - sectionHeight && y <= projectilesSection.y + sectionHeight) {
currentShopSection = 'projectiles';
upgradesSection.tint = 0xFFFFFF;
skinsSection.tint = 0xFFFFFF;
projectilesSection.tint = 0x00FF00;
// Hide upgrades for now (projectiles not implemented yet)
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
return;
}
// Check upgrade purchases when in upgrades section
if (currentShopSection === 'upgrades') {
// Upgrade 1 - Double Damage Start
if (x >= upgrade1Text.x - upgradeWidth / 2 && x <= upgrade1Text.x + upgradeWidth / 2 && y >= upgrade1Text.y - upgradeHeight / 2 && y <= upgrade1Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.doubleDamagePrice) {
totalEarnings -= shopUpgrades.doubleDamagePrice;
shopUpgrades.doubleDamagePrice += 50;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade1Text.setText('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 2 - Unlimited Shooting Start
if (x >= upgrade2Text.x - upgradeWidth / 2 && x <= upgrade2Text.x + upgradeWidth / 2 && y >= upgrade2Text.y - upgradeHeight / 2 && y <= upgrade2Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.unlimitedShootingPrice) {
totalEarnings -= shopUpgrades.unlimitedShootingPrice;
shopUpgrades.unlimitedShootingPrice += 75;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade2Text.setText('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 3 - Extra Life
if (x >= upgrade3Text.x - upgradeWidth / 2 && x <= upgrade3Text.x + upgradeWidth / 2 && y >= upgrade3Text.y - upgradeHeight / 2 && y <= upgrade3Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.extraLifePrice) {
totalEarnings -= shopUpgrades.extraLifePrice;
shopUpgrades.extraLifePrice += 100;
maxLives += 1; // Increase max lives by 1
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade3Text.setText('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 4 - More Projectile
if (x >= upgrade4Text.x - upgradeWidth / 2 && x <= upgrade4Text.x + upgradeWidth / 2 && y >= upgrade4Text.y - upgradeHeight / 2 && y <= upgrade4Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.fastShootingPrice) {
totalEarnings -= shopUpgrades.fastShootingPrice;
shopUpgrades.fastShootingPrice += 60;
maxBullets += 1; // Increase max bullets by 1
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade4Text.setText('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 5 - Shield Power
if (x >= upgrade5Text.x - upgradeWidth / 2 && x <= upgrade5Text.x + upgradeWidth / 2 && y >= upgrade5Text.y - upgradeHeight / 2 && y <= upgrade5Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.shieldPrice) {
totalEarnings -= shopUpgrades.shieldPrice;
shopUpgrades.shieldPrice += 90;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade5Text.setText('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 6 - +1 Damage
if (x >= upgrade6Text.x - upgradeWidth / 2 && x <= upgrade6Text.x + upgradeWidth / 2 && y >= upgrade6Text.y - upgradeHeight / 2 && y <= upgrade6Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.damageUpgradePrice) {
totalEarnings -= shopUpgrades.damageUpgradePrice;
shopUpgrades.damageUpgradePrice += 125;
damageUpgrade += 1;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
storage.damageUpgrade = damageUpgrade;
upgrade6Text.setText('+1 Damage - Price: ' + shopUpgrades.damageUpgradePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
}
// Handle skin section interactions
if (currentShopSection === 'skins') {
// Skin purchase/equip button
if (x >= skin1Text.x - upgradeWidth / 2 && x <= skin1Text.x + upgradeWidth / 2 && y >= skin1Text.y - upgradeHeight / 2 && y <= skin1Text.y + upgradeHeight / 2) {
if (ownedSkins.indexOf('player2') < 0 && totalEarnings >= skinPrices.player2) {
// Purchase skin
totalEarnings -= skinPrices.player2;
ownedSkins.push('player2');
storage.totalEarnings = totalEarnings;
storage.ownedSkins = ownedSkins;
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Equip/Unequip button
if (skin1EquipText.visible && x >= skin1EquipText.x - 100 && x <= skin1EquipText.x + 100 && y >= skin1EquipText.y - 20 && y <= skin1EquipText.y + 20) {
if (equippedSkin === 'player2') {
// Unequip (revert to default)
equippedSkin = 'player';
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
} else {
// Equip this skin
equippedSkin = 'player2';
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
}
storage.equippedSkin = equippedSkin;
// Update player graphics immediately using the updateSkin method
player.updateSkin(equippedSkin);
}
return;
}
} else if (gameState === 'playing') {
dragActive = true;
lastTouchX = x;
lastTouchY = y;
shootBullet();
}
};
game.move = function (x, y, obj) {
if (gameState === 'playing' && dragActive) {
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
player.x += deltaX;
player.y += deltaY;
// Keep player within screen bounds
if (player.x < 40) {
player.x = 40;
}
if (player.x > 2048 - 40) {
player.x = 2048 - 40;
}
if (player.y < 40) {
player.y = 40;
}
if (player.y > 2732 - 40) {
player.y = 2732 - 40;
}
lastTouchX = x;
lastTouchY = y;
}
};
game.up = function (x, y, obj) {
if (gameState === 'playing') {
dragActive = false;
}
};
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle challenge timer (only when not in rock mode)
if (!rockActive) {
challengeTimer++;
if (challengeTimer >= challengeTimeLimit) {
// Time limit reached - game over
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
updateTimer();
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer % 400 === 0 && spawnRate > 20) {
spawnRate -= 3;
}
// Check if there's a rock to determine if we should spawn normal objects
var hasRockForSpawning = false;
for (var rs = 0; rs < fallingObjects.length; rs++) {
if (fallingObjects[rs].type === 'rock') {
hasRockForSpawning = true;
break;
}
}
// Spawn falling objects with consistent timing only if no rock is present
if (!hasRockForSpawning) {
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnFallingObject();
spawnTimer = 0;
}
} else {
spawnTimer = 0; // Reset spawn timer when rock is present
}
// Handle double damage timer
if (doubleDamageActive) {
doubleDamageTimer++;
if (doubleDamageTimer >= doubleDamageTimeLimit) {
doubleDamageActive = false;
doubleDamageTimer = 0;
}
}
// Handle unlimited shooting timer
if (unlimitedShootingActive) {
unlimitedShootingTimer++;
if (unlimitedShootingTimer >= unlimitedShootingTimeLimit) {
unlimitedShootingActive = false;
unlimitedShootingTimer = 0;
}
}
updatePowerUpDisplay();
// Update power-ups
for (var p = powerUps.length - 1; p >= 0; p--) {
var powerUp = powerUps[p];
if (powerUp.lastY === undefined) {
powerUp.lastY = powerUp.y;
}
// Remove power-ups that fall off screen
if (powerUp.lastY <= 2732 + 50 && powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(p, 1);
continue;
}
// Check collision with player
if (powerUp.intersects(player)) {
// Check power-up type and activate accordingly
if (powerUp.powerUpType === 'doubleDamage') {
doubleDamageActive = true;
doubleDamageTimer = 0;
} else if (powerUp.powerUpType === 'unlimitedShooting') {
unlimitedShootingActive = true;
unlimitedShootingTimer = 0;
} else if (powerUp.powerUpType === 'health') {
if (lives < maxLives) {
lives++;
updateLives();
}
} else if (powerUp.powerUpType === 'clearScreen') {
// Destroy all objects except rocks and swords
for (var cs = fallingObjects.length - 1; cs >= 0; cs--) {
var objToClear = fallingObjects[cs];
// Check if object still exists before clearing
if (!objToClear || !objToClear.parent) {
fallingObjects.splice(cs, 1);
continue;
}
if (objToClear.type !== 'rock') {
// Create explosion effect for cleared objects
tween(objToClear, {
scaleX: 2,
scaleY: 2,
alpha: 0,
tint: 0xffaa00
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
objToClear.destroy();
}
});
fallingObjects.splice(cs, 1);
}
}
}
// Visual effect
tween(powerUp, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
powerUp.destroy();
}
});
powerUps.splice(p, 1);
continue;
}
powerUp.lastY = powerUp.y;
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet still exists and hasn't been destroyed
if (!bullet || !bullet.parent) {
bullets.splice(i, 1);
continue;
}
if (bullet.lastY === undefined) {
bullet.lastY = bullet.y;
}
// Remove bullets that go off screen
if (bullet.lastY >= -50 && bullet.y < -50) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet collision with falling objects
for (var j = fallingObjects.length - 1; j >= 0; j--) {
var obj = fallingObjects[j];
// Check if objects still exist before checking intersection
if (!obj || !obj.parent || !bullet || !bullet.parent) {
continue;
}
if (bullet.intersects(obj)) {
// Reduce hit points (double damage if power-up is active, plus upgrade damage)
var baseDamage = 1 + damageUpgrade;
var damage = doubleDamageActive ? baseDamage * 2 : baseDamage;
obj.hitPoints -= damage;
// Flash object to show it was hit
var hitTint = 0xff0000;
var originalTint = obj.tint || 0xffffff;
tween(obj, {
tint: hitTint
}, {
duration: 100,
onFinish: function onFinish() {
tween(obj, {
tint: originalTint
}, {
duration: 100
});
}
});
// Destroy bullet
bullet.destroy();
bullets.splice(i, 1);
// Check if object should be destroyed
if (obj.hitPoints <= 0) {
if (obj.type === 'rock') {
LK.setScore(LK.getScore() + 50);
lives = maxLives; // Restore full health
updateLives();
rockActive = false;
resetChallenge();
} else {
LK.setScore(LK.getScore() + 1);
objectsDestroyed++;
// Track bat destruction for power-up
if (obj.type === 'bat') {
batsDestroyed++;
// Spawn power-up every 10 bats destroyed
if (batsDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'doubleDamage');
}
}
// Track sword destruction for power-up
if (obj.type === 'sword') {
swordsDestroyed++;
// Spawn unlimited shooting power-up every 10 swords destroyed
if (swordsDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'unlimitedShooting');
}
}
// Track knife destruction for health power-up
if (obj.type === 'knife') {
knivesDestroyed++;
// Spawn health power-up every 10 knives destroyed
if (knivesDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'health');
}
}
// Track stick destruction for clear screen power-up
if (obj.type === 'stick') {
sticksDestroyed++;
// Spawn clear screen power-up every 10 sticks destroyed
if (sticksDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'clearScreen');
}
}
// Check if challenge is completed (only when no rock is active)
if (!rockActive && objectsDestroyed >= challengeTarget) {
challengesCompleted++;
if (challengesCompleted % 5 === 0) {
spawnRock();
} else {
resetChallenge();
}
}
// Add coins based on score when objects are destroyed
totalEarnings += 1;
storage.totalEarnings = totalEarnings;
}
updateScore();
LK.getSound('destroy').play();
// Create explosion effect
tween(obj, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
obj.destroy();
}
});
fallingObjects.splice(j, 1);
} else {
LK.getSound('hit').play();
}
break;
}
}
if (bullets[i]) {
bullet.lastY = bullet.y;
}
}
// Check if there's a rock and handle bat spawning timer
var hasRock = false;
for (var r = 0; r < fallingObjects.length; r++) {
if (fallingObjects[r].type === 'rock') {
hasRock = true;
break;
}
}
if (hasRock) {
rockBatTimer++;
if (rockBatTimer >= rockBatSpawnRate) {
spawnRockBats();
rockBatTimer = 0;
}
} else {
rockBatTimer = 0;
}
// Update falling objects
for (var k = fallingObjects.length - 1; k >= 0; k--) {
var fallingObj = fallingObjects[k];
// Check if object still exists and hasn't been destroyed
if (!fallingObj || !fallingObj.parent) {
fallingObjects.splice(k, 1);
continue;
}
if (fallingObj.lastY === undefined) {
fallingObj.lastY = fallingObj.y;
}
// Handle rock horizontal movement
if (fallingObj.type === 'rock') {
fallingObj.x += fallingObj.horizontalSpeed * fallingObj.direction;
// Bounce off screen edges
if (fallingObj.x <= 50 || fallingObj.x >= 2048 - 50) {
fallingObj.direction *= -1;
}
}
// Remove objects that fall off screen
if (fallingObj.lastY <= 2732 + 50 && fallingObj.y > 2732 + 50) {
fallingObj.destroy();
fallingObjects.splice(k, 1);
continue;
}
// Check collision with player
if (fallingObj.intersects(player)) {
// If player touches rock, instant game over
if (fallingObj.type === 'rock') {
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
lives--;
updateLives();
LK.getSound('hit').play();
// Flash player red
tween(player, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
tint: 0xffffff
}, {
duration: 200
});
}
});
fallingObj.destroy();
fallingObjects.splice(k, 1);
if (lives <= 0) {
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
continue;
}
fallingObj.lastY = fallingObj.y;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.update = function () {
self.y += self.speed;
};
return self;
});
var FallingObject = Container.expand(function (type) {
var self = Container.call(this);
var objectGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = (Math.random() * 3 + 2) * 2;
self.type = type;
// Set hit points based on object type
if (type === 'bat') {
self.hitPoints = 2;
} else if (type === 'stick') {
self.hitPoints = 1;
} else if (type === 'knife') {
self.hitPoints = 1;
} else if (type === 'sword') {
self.hitPoints = 4;
} else if (type === 'rock') {
self.hitPoints = 25;
}
self.maxHitPoints = self.hitPoints;
self.update = function () {
self.y += self.speed;
self.rotation += 0.05;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset(equippedSkin, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.shootCooldown = 0;
self.updateSkin = function (newSkin) {
self.removeChildren();
playerGraphics = self.attachAsset(newSkin, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
// Pulse effect
self.scaleX = 1 + Math.sin(LK.ticks * 0.2) * 0.2;
self.scaleY = 1 + Math.sin(LK.ticks * 0.2) * 0.2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing', or 'shop'
// Shop variables
var totalEarnings = storage.totalEarnings || 0;
var currentShopSection = 'upgrades'; // Track current shop section
var shopUpgrades = {
doubleDamagePrice: storage.savedDoubleDamage || 100,
unlimitedShootingPrice: storage.savedUnlimitedShooting || 150,
extraLifePrice: storage.savedExtraLife || 200,
fastShootingPrice: storage.savedFastShooting || 120,
shieldPrice: storage.savedShield || 180,
damageUpgradePrice: storage.savedDamageUpgradePrice || 150
};
// Skin system variables
var ownedSkins = storage.ownedSkins || ['player']; // Default skin is always owned
var equippedSkin = storage.equippedSkin || 'player';
var skinPrices = {
player2: 100
};
// Add blue background
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Menu elements
var titleText = new Text2('Dodge & Destroy', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 2 - 200;
game.addChild(titleText);
var playButton = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.x = 2048 / 2;
playButton.y = 2732 / 2 + 100;
game.addChild(playButton);
var shopButton = new Text2('SHOP', {
size: 80,
fill: 0xFFD700
});
shopButton.anchor.set(0.5, 0.5);
shopButton.x = 2048 / 2;
shopButton.y = 2732 / 2 + 200;
game.addChild(shopButton);
var saveButton = new Text2('SAVE', {
size: 60,
fill: 0x00FFFF
});
saveButton.anchor.set(0.5, 0.5);
saveButton.x = 2048 / 2 - 200;
saveButton.y = 2732 / 2 + 300;
game.addChild(saveButton);
var loadButton = new Text2('LOAD', {
size: 60,
fill: 0xFF00FF
});
loadButton.anchor.set(0.5, 0.5);
loadButton.x = 2048 / 2 + 200;
loadButton.y = 2732 / 2 + 300;
game.addChild(loadButton);
// Save confirmation message
var saveMessageText = new Text2('PROGRESS SAVED', {
size: 70,
fill: 0x00FF00
});
saveMessageText.anchor.set(0.5, 0.5);
saveMessageText.x = 2048 / 2;
saveMessageText.y = 2732 / 2 - 100;
saveMessageText.visible = false;
game.addChild(saveMessageText);
// Load confirmation message
var loadMessageText = new Text2('PROGRESS RESTORED', {
size: 70,
fill: 0x00FFFF
});
loadMessageText.anchor.set(0.5, 0.5);
loadMessageText.x = 2048 / 2;
loadMessageText.y = 2732 / 2 - 100;
loadMessageText.visible = false;
game.addChild(loadMessageText);
// Game version text
var versionText = new Text2('Game version: V1.00', {
size: 40,
fill: 0xFFFFFF
});
versionText.anchor.set(0, 1);
versionText.x = 120;
versionText.y = 2732 - 20;
game.addChild(versionText);
// Shop UI elements (initially hidden)
var shopTitle = new Text2('SHOP', {
size: 100,
fill: 0xFFD700
});
shopTitle.anchor.set(0.5, 0.5);
shopTitle.x = 2048 / 2;
shopTitle.y = 300;
shopTitle.visible = false;
game.addChild(shopTitle);
var coinsText = new Text2('Coins: ' + totalEarnings, {
size: 60,
fill: 0xFFFFFF
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 2048 / 2;
coinsText.y = 400;
coinsText.visible = false;
game.addChild(coinsText);
// Shop upgrades
var upgrade1Text = new Text2('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade1Text.anchor.set(0.5, 0.5);
upgrade1Text.x = 2048 / 2;
upgrade1Text.y = 600;
upgrade1Text.visible = false;
game.addChild(upgrade1Text);
var upgrade2Text = new Text2('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade2Text.anchor.set(0.5, 0.5);
upgrade2Text.x = 2048 / 2;
upgrade2Text.y = 700;
upgrade2Text.visible = false;
game.addChild(upgrade2Text);
var upgrade3Text = new Text2('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade3Text.anchor.set(0.5, 0.5);
upgrade3Text.x = 2048 / 2;
upgrade3Text.y = 800;
upgrade3Text.visible = false;
game.addChild(upgrade3Text);
var upgrade4Text = new Text2('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade4Text.anchor.set(0.5, 0.5);
upgrade4Text.x = 2048 / 2;
upgrade4Text.y = 900;
upgrade4Text.visible = false;
game.addChild(upgrade4Text);
var upgrade5Text = new Text2('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins', {
size: 50,
fill: 0x00FF00
});
upgrade5Text.anchor.set(0.5, 0.5);
upgrade5Text.x = 2048 / 2;
upgrade5Text.y = 1000;
upgrade5Text.visible = false;
game.addChild(upgrade5Text);
var upgrade6Text = new Text2('+1 Damage - Price: 150 coins', {
size: 50,
fill: 0x00FF00
});
upgrade6Text.anchor.set(0.5, 0.5);
upgrade6Text.x = 2048 / 2;
upgrade6Text.y = 1100;
upgrade6Text.visible = false;
game.addChild(upgrade6Text);
// Shop section navigation
var upgradesSection = new Text2('UPGRADES', {
size: 60,
fill: 0x00FF00
});
upgradesSection.anchor.set(0.5, 0.5);
upgradesSection.x = 2048 / 2 - 300;
upgradesSection.y = 500;
upgradesSection.visible = false;
game.addChild(upgradesSection);
var skinsSection = new Text2('SKINS', {
size: 60,
fill: 0xFFFFFF
});
skinsSection.anchor.set(0.5, 0.5);
skinsSection.x = 2048 / 2;
skinsSection.y = 500;
skinsSection.visible = false;
game.addChild(skinsSection);
var projectilesSection = new Text2('PROJECTILES', {
size: 60,
fill: 0xFFFFFF
});
projectilesSection.anchor.set(0.5, 0.5);
projectilesSection.x = 2048 / 2 + 300;
projectilesSection.y = 500;
projectilesSection.visible = false;
game.addChild(projectilesSection);
// Skin shop elements
var skin1Text = new Text2('Player Skin 2 - Price: 100 coins', {
size: 50,
fill: 0x00FF00
});
skin1Text.anchor.set(0.5, 0.5);
skin1Text.x = 2048 / 2;
skin1Text.y = 600;
skin1Text.visible = false;
game.addChild(skin1Text);
var skin1EquipText = new Text2('EQUIP', {
size: 40,
fill: 0xFFD700
});
skin1EquipText.anchor.set(0.5, 0.5);
skin1EquipText.x = 2048 / 2;
skin1EquipText.y = 650;
skin1EquipText.visible = false;
game.addChild(skin1EquipText);
var backButton = new Text2('BACK', {
size: 70,
fill: 0xFF4444
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 2048 / 2;
backButton.y = 1200;
backButton.visible = false;
game.addChild(backButton);
// Start title music
LK.playMusic('title_music');
// Game elements (initially hidden)
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 200;
player.visible = false;
var bullets = [];
var fallingObjects = [];
var lives = 3;
var maxLives = 3;
var objectTypes = ['knife', 'sword', 'bat', 'stick'];
var spawnTimer = 0;
var spawnRate = 60;
var difficultyTimer = 0;
var maxBullets = 3;
// Challenge variables
var objectsDestroyed = 0;
var challengeTarget = 5;
var challengesCompleted = 0;
var rockActive = false;
var rockBatTimer = 0;
var rockBatSpawnRate = 420; // 7 seconds at 60 FPS
var challengeTimer = 0;
var challengeTimeLimit = 900; // 15 seconds at 60 FPS
var currentChallenge = 0; // Track current challenge number
// Power-up variables
var batsDestroyed = 0;
var swordsDestroyed = 0;
var knivesDestroyed = 0;
var sticksDestroyed = 0;
var powerUps = [];
var doubleDamageActive = false;
var doubleDamageTimer = 0;
var doubleDamageTimeLimit = 600; // 10 seconds at 60 FPS
var unlimitedShootingActive = false;
var unlimitedShootingTimer = 0;
var unlimitedShootingTimeLimit = 600; // 10 seconds at 60 FPS
var damageUpgrade = storage.damageUpgrade || 0;
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 150;
scoreText.y = 50;
scoreText.visible = false;
LK.gui.topLeft.addChild(scoreText);
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF4444
});
livesText.anchor.set(1, 0);
livesText.visible = false;
LK.gui.topRight.addChild(livesText);
var timerText = new Text2('Target: 5', {
size: 50,
fill: 0xFFFF00
});
timerText.anchor.set(0.5, 0);
timerText.x = 0;
timerText.y = 50;
timerText.visible = false;
LK.gui.top.addChild(timerText);
var powerUpText = new Text2('', {
size: 45,
fill: 0x00FF00
});
powerUpText.anchor.set(0.5, 0);
powerUpText.x = 0;
powerUpText.y = 120;
powerUpText.visible = false;
LK.gui.top.addChild(powerUpText);
var dragActive = false;
var lastTouchX = 0;
var lastTouchY = 0;
function showShop() {
gameState = 'shop';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
shopButton.visible = false;
saveButton.visible = false;
loadButton.visible = false;
saveMessageText.visible = false;
loadMessageText.visible = false;
// Show shop elements
shopTitle.visible = true;
coinsText.visible = true;
upgradesSection.visible = true;
skinsSection.visible = true;
projectilesSection.visible = true;
backButton.visible = true;
// Show appropriate section elements
if (currentShopSection === 'upgrades') {
upgrade1Text.visible = true;
upgrade2Text.visible = true;
upgrade3Text.visible = true;
upgrade4Text.visible = true;
upgrade5Text.visible = true;
upgrade6Text.visible = true;
} else if (currentShopSection === 'skins') {
// Update skin text based on ownership
if (ownedSkins.indexOf('player2') >= 0) {
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
if (equippedSkin === 'player2') {
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
} else {
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
}
} else {
skin1Text.setText('Player Skin 2 - Price: 100 coins');
skin1EquipText.visible = false;
}
skin1Text.visible = true;
}
// Update section colors based on current section
if (currentShopSection === 'upgrades') {
upgradesSection.tint = 0x00FF00;
} else {
upgradesSection.tint = 0xFFFFFF;
}
if (currentShopSection === 'skins') {
skinsSection.tint = 0x00FF00;
} else {
skinsSection.tint = 0xFFFFFF;
}
projectilesSection.tint = 0xFFFFFF;
// Update coins display
coinsText.setText('Coins: ' + totalEarnings);
}
function hideShop() {
gameState = 'menu';
// Hide shop elements
shopTitle.visible = false;
coinsText.visible = false;
upgradesSection.visible = false;
skinsSection.visible = false;
projectilesSection.visible = false;
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
skin1Text.visible = false;
skin1EquipText.visible = false;
backButton.visible = false;
// Show menu elements
titleText.visible = true;
playButton.visible = true;
shopButton.visible = true;
saveButton.visible = true;
loadButton.visible = true;
}
function saveGame() {
// Save current upgrades and earnings using individual properties
storage.savedDoubleDamage = shopUpgrades.doubleDamagePrice;
storage.savedUnlimitedShooting = shopUpgrades.unlimitedShootingPrice;
storage.savedExtraLife = shopUpgrades.extraLifePrice;
storage.savedFastShooting = shopUpgrades.fastShootingPrice;
storage.savedShield = shopUpgrades.shieldPrice;
storage.savedDamageUpgradePrice = shopUpgrades.damageUpgradePrice;
storage.savedEarnings = totalEarnings;
storage.damageUpgrade = damageUpgrade;
storage.ownedSkins = ownedSkins;
storage.equippedSkin = equippedSkin;
storage.totalEarnings = totalEarnings;
}
function loadGame() {
// Load saved upgrades and earnings if they exist using individual properties
if (storage.savedDoubleDamage !== undefined) {
shopUpgrades.doubleDamagePrice = storage.savedDoubleDamage;
}
if (storage.savedUnlimitedShooting !== undefined) {
shopUpgrades.unlimitedShootingPrice = storage.savedUnlimitedShooting;
}
if (storage.savedExtraLife !== undefined) {
shopUpgrades.extraLifePrice = storage.savedExtraLife;
}
if (storage.savedFastShooting !== undefined) {
shopUpgrades.fastShootingPrice = storage.savedFastShooting;
}
if (storage.savedShield !== undefined) {
shopUpgrades.shieldPrice = storage.savedShield;
}
if (storage.savedDamageUpgradePrice !== undefined) {
shopUpgrades.damageUpgradePrice = storage.savedDamageUpgradePrice;
}
if (storage.savedEarnings !== undefined) {
totalEarnings = storage.savedEarnings;
}
if (storage.damageUpgrade !== undefined) {
damageUpgrade = storage.damageUpgrade;
}
if (storage.ownedSkins) {
ownedSkins = storage.ownedSkins;
}
if (storage.equippedSkin) {
equippedSkin = storage.equippedSkin;
}
// Update shop display texts
upgrade1Text.setText('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins');
upgrade2Text.setText('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins');
upgrade3Text.setText('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins');
upgrade4Text.setText('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins');
upgrade5Text.setText('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins');
upgrade6Text.setText('+1 Damage - Price: ' + shopUpgrades.damageUpgradePrice + ' coins');
// Update coins display in shop
coinsText.setText('Coins: ' + totalEarnings);
}
function showSaveMessage() {
// Show the save message
saveMessageText.visible = true;
saveMessageText.alpha = 1;
// Hide the message after 10 seconds using tween
tween(saveMessageText, {
alpha: 0
}, {
duration: 10000,
easing: tween.linear,
onFinish: function onFinish() {
saveMessageText.visible = false;
}
});
}
function showLoadMessage() {
// Show the load message
loadMessageText.visible = true;
loadMessageText.alpha = 1;
// Hide the message after 10 seconds using tween
tween(loadMessageText, {
alpha: 0
}, {
duration: 10000,
easing: tween.linear,
onFinish: function onFinish() {
loadMessageText.visible = false;
}
});
}
function startGame() {
gameState = 'playing';
// Hide menu elements
titleText.visible = false;
playButton.visible = false;
shopButton.visible = false;
saveButton.visible = false;
loadButton.visible = false;
saveMessageText.visible = false;
loadMessageText.visible = false;
// Show game elements
player.visible = true;
scoreText.visible = true;
livesText.visible = true;
timerText.visible = true;
powerUpText.visible = true;
// Stop title music and start survival piano music
LK.stopMusic();
LK.playMusic('survival_piano');
// Reset game variables
lives = maxLives;
objectsDestroyed = 0;
challengesCompleted = 0;
rockActive = false;
challengeTimer = 0;
// Reset power-up variables
batsDestroyed = 0;
swordsDestroyed = 0;
knivesDestroyed = 0;
sticksDestroyed = 0;
doubleDamageActive = false;
doubleDamageTimer = 0;
unlimitedShootingActive = false;
unlimitedShootingTimer = 0;
powerUps = [];
LK.setScore(0);
updateScore();
updateLives();
updateTimer();
}
function updateScore() {
scoreText.setText('Score: ' + LK.getScore());
}
function updateLives() {
livesText.setText('Lives: ' + lives);
}
function updateTimer() {
if (rockActive) {
timerText.setText('DESTROY THE ROCK!');
} else {
var remaining = Math.max(0, challengeTarget - objectsDestroyed);
var timeLeft = Math.ceil((challengeTimeLimit - challengeTimer) / 60);
timerText.setText('Target: ' + remaining + ' | Time: ' + timeLeft + 's');
}
}
function spawnFallingObject() {
var type = objectTypes[Math.floor(Math.random() * objectTypes.length)];
var obj = new FallingObject(type);
obj.x = Math.random() * (2048 - 100) + 50;
obj.y = -50;
fallingObjects.push(obj);
game.addChild(obj);
}
function spawnRock() {
var rock = new FallingObject('rock');
rock.x = 2048 / 2; // Center of screen
rock.y = 200; // Fixed Y position
rock.speed = 0; // No forward movement
rock.horizontalSpeed = 3; // Side to side movement speed
rock.direction = Math.random() < 0.5 ? -1 : 1; // Random initial direction
fallingObjects.push(rock);
game.addChild(rock);
rockActive = true;
updateTimer();
}
function resetChallenge() {
objectsDestroyed = 0;
challengeTimer = 0;
currentChallenge++;
updateTimer();
}
function spawnRockBats() {
for (var i = 0; i < 10; i++) {
var bat = new FallingObject('bat');
bat.x = 2048 / 11 * (i + 1); // Distribute evenly across screen
bat.y = -50;
fallingObjects.push(bat);
game.addChild(bat);
}
}
function spawnPowerUp(x, y, type) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
powerUp.powerUpType = type || 'doubleDamage';
powerUps.push(powerUp);
game.addChild(powerUp);
}
function updatePowerUpDisplay() {
if (doubleDamageActive && unlimitedShootingActive) {
var doubleDamageTimeLeft = Math.ceil((doubleDamageTimeLimit - doubleDamageTimer) / 60);
var unlimitedTimeLeft = Math.ceil((unlimitedShootingTimeLimit - unlimitedShootingTimer) / 60);
powerUpText.setText('DOUBLE DAMAGE: ' + doubleDamageTimeLeft + 's | UNLIMITED: ' + unlimitedTimeLeft + 's');
} else if (doubleDamageActive) {
var timeLeft = Math.ceil((doubleDamageTimeLimit - doubleDamageTimer) / 60);
powerUpText.setText('DOUBLE DAMAGE: ' + timeLeft + 's');
} else if (unlimitedShootingActive) {
var timeLeft = Math.ceil((unlimitedShootingTimeLimit - unlimitedShootingTimer) / 60);
powerUpText.setText('UNLIMITED SHOOTING: ' + timeLeft + 's');
} else {
powerUpText.setText('');
}
}
function shootBullet() {
var canShoot = unlimitedShootingActive || player.shootCooldown <= 0 && bullets.length < maxBullets;
if (canShoot) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 40;
bullets.push(bullet);
game.addChild(bullet);
if (!unlimitedShootingActive) {
player.shootCooldown = 15;
}
LK.getSound('shoot').play();
}
}
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was tapped
var playButtonBounds = {
left: playButton.x - 100,
right: playButton.x + 100,
top: playButton.y - 50,
bottom: playButton.y + 50
};
if (x >= playButtonBounds.left && x <= playButtonBounds.right && y >= playButtonBounds.top && y <= playButtonBounds.bottom) {
startGame();
}
// Check if shop button was tapped
var shopButtonBounds = {
left: shopButton.x - 100,
right: shopButton.x + 100,
top: shopButton.y - 50,
bottom: shopButton.y + 50
};
if (x >= shopButtonBounds.left && x <= shopButtonBounds.right && y >= shopButtonBounds.top && y <= shopButtonBounds.bottom) {
showShop();
}
// Check if save button was tapped
var saveButtonBounds = {
left: saveButton.x - 80,
right: saveButton.x + 80,
top: saveButton.y - 40,
bottom: saveButton.y + 40
};
if (x >= saveButtonBounds.left && x <= saveButtonBounds.right && y >= saveButtonBounds.top && y <= saveButtonBounds.bottom) {
saveGame();
showSaveMessage();
}
// Check if load button was tapped
var loadButtonBounds = {
left: loadButton.x - 80,
right: loadButton.x + 80,
top: loadButton.y - 40,
bottom: loadButton.y + 40
};
if (x >= loadButtonBounds.left && x <= loadButtonBounds.right && y >= loadButtonBounds.top && y <= loadButtonBounds.bottom) {
loadGame();
showLoadMessage();
}
} else if (gameState === 'shop') {
// Check upgrade buttons
var upgradeHeight = 50;
var upgradeWidth = 800;
// Back button
var backButtonBounds = {
left: backButton.x - 100,
right: backButton.x + 100,
top: backButton.y - 40,
bottom: backButton.y + 40
};
if (x >= backButtonBounds.left && x <= backButtonBounds.right && y >= backButtonBounds.top && y <= backButtonBounds.bottom) {
hideShop();
return;
}
// Check section navigation
var sectionHeight = 30;
var sectionWidth = 150;
// Upgrades section
if (x >= upgradesSection.x - sectionWidth && x <= upgradesSection.x + sectionWidth && y >= upgradesSection.y - sectionHeight && y <= upgradesSection.y + sectionHeight) {
currentShopSection = 'upgrades';
upgradesSection.tint = 0x00FF00;
skinsSection.tint = 0xFFFFFF;
projectilesSection.tint = 0xFFFFFF;
// Show upgrades, hide others
upgrade1Text.visible = true;
upgrade2Text.visible = true;
upgrade3Text.visible = true;
upgrade4Text.visible = true;
upgrade5Text.visible = true;
upgrade6Text.visible = true;
return;
}
// Skins section
if (x >= skinsSection.x - sectionWidth && x <= skinsSection.x + sectionWidth && y >= skinsSection.y - sectionHeight && y <= skinsSection.y + sectionHeight) {
currentShopSection = 'skins';
upgradesSection.tint = 0xFFFFFF;
skinsSection.tint = 0x00FF00;
projectilesSection.tint = 0xFFFFFF;
// Hide upgrades and show skins
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
// Show skin elements
if (ownedSkins.indexOf('player2') >= 0) {
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
if (equippedSkin === 'player2') {
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
} else {
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
}
} else {
skin1Text.setText('Player Skin 2 - Price: 100 coins');
skin1EquipText.visible = false;
}
skin1Text.visible = true;
return;
}
// Projectiles section
if (x >= projectilesSection.x - sectionWidth && x <= projectilesSection.x + sectionWidth && y >= projectilesSection.y - sectionHeight && y <= projectilesSection.y + sectionHeight) {
currentShopSection = 'projectiles';
upgradesSection.tint = 0xFFFFFF;
skinsSection.tint = 0xFFFFFF;
projectilesSection.tint = 0x00FF00;
// Hide upgrades for now (projectiles not implemented yet)
upgrade1Text.visible = false;
upgrade2Text.visible = false;
upgrade3Text.visible = false;
upgrade4Text.visible = false;
upgrade5Text.visible = false;
upgrade6Text.visible = false;
return;
}
// Check upgrade purchases when in upgrades section
if (currentShopSection === 'upgrades') {
// Upgrade 1 - Double Damage Start
if (x >= upgrade1Text.x - upgradeWidth / 2 && x <= upgrade1Text.x + upgradeWidth / 2 && y >= upgrade1Text.y - upgradeHeight / 2 && y <= upgrade1Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.doubleDamagePrice) {
totalEarnings -= shopUpgrades.doubleDamagePrice;
shopUpgrades.doubleDamagePrice += 50;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade1Text.setText('Double Damage Start - Price: ' + shopUpgrades.doubleDamagePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 2 - Unlimited Shooting Start
if (x >= upgrade2Text.x - upgradeWidth / 2 && x <= upgrade2Text.x + upgradeWidth / 2 && y >= upgrade2Text.y - upgradeHeight / 2 && y <= upgrade2Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.unlimitedShootingPrice) {
totalEarnings -= shopUpgrades.unlimitedShootingPrice;
shopUpgrades.unlimitedShootingPrice += 75;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade2Text.setText('Unlimited Shooting Start - Price: ' + shopUpgrades.unlimitedShootingPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 3 - Extra Life
if (x >= upgrade3Text.x - upgradeWidth / 2 && x <= upgrade3Text.x + upgradeWidth / 2 && y >= upgrade3Text.y - upgradeHeight / 2 && y <= upgrade3Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.extraLifePrice) {
totalEarnings -= shopUpgrades.extraLifePrice;
shopUpgrades.extraLifePrice += 100;
maxLives += 1; // Increase max lives by 1
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade3Text.setText('Extra Life - Price: ' + shopUpgrades.extraLifePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 4 - More Projectile
if (x >= upgrade4Text.x - upgradeWidth / 2 && x <= upgrade4Text.x + upgradeWidth / 2 && y >= upgrade4Text.y - upgradeHeight / 2 && y <= upgrade4Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.fastShootingPrice) {
totalEarnings -= shopUpgrades.fastShootingPrice;
shopUpgrades.fastShootingPrice += 60;
maxBullets += 1; // Increase max bullets by 1
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade4Text.setText('More Projectile - Price: ' + shopUpgrades.fastShootingPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 5 - Shield Power
if (x >= upgrade5Text.x - upgradeWidth / 2 && x <= upgrade5Text.x + upgradeWidth / 2 && y >= upgrade5Text.y - upgradeHeight / 2 && y <= upgrade5Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.shieldPrice) {
totalEarnings -= shopUpgrades.shieldPrice;
shopUpgrades.shieldPrice += 90;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
upgrade5Text.setText('Shield (2 hits = 1 life) - Price: ' + shopUpgrades.shieldPrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Upgrade 6 - +1 Damage
if (x >= upgrade6Text.x - upgradeWidth / 2 && x <= upgrade6Text.x + upgradeWidth / 2 && y >= upgrade6Text.y - upgradeHeight / 2 && y <= upgrade6Text.y + upgradeHeight / 2) {
if (totalEarnings >= shopUpgrades.damageUpgradePrice) {
totalEarnings -= shopUpgrades.damageUpgradePrice;
shopUpgrades.damageUpgradePrice += 125;
damageUpgrade += 1;
storage.totalEarnings = totalEarnings;
// Removed invalid nested object assignment - use individual properties instead
storage.damageUpgrade = damageUpgrade;
upgrade6Text.setText('+1 Damage - Price: ' + shopUpgrades.damageUpgradePrice + ' coins');
coinsText.setText('Coins: ' + totalEarnings);
}
}
}
// Handle skin section interactions
if (currentShopSection === 'skins') {
// Skin purchase/equip button
if (x >= skin1Text.x - upgradeWidth / 2 && x <= skin1Text.x + upgradeWidth / 2 && y >= skin1Text.y - upgradeHeight / 2 && y <= skin1Text.y + upgradeHeight / 2) {
if (ownedSkins.indexOf('player2') < 0 && totalEarnings >= skinPrices.player2) {
// Purchase skin
totalEarnings -= skinPrices.player2;
ownedSkins.push('player2');
storage.totalEarnings = totalEarnings;
storage.ownedSkins = ownedSkins;
skin1Text.setText('Player Skin 2 - OWNED');
skin1EquipText.visible = true;
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
coinsText.setText('Coins: ' + totalEarnings);
}
}
// Equip/Unequip button
if (skin1EquipText.visible && x >= skin1EquipText.x - 100 && x <= skin1EquipText.x + 100 && y >= skin1EquipText.y - 20 && y <= skin1EquipText.y + 20) {
if (equippedSkin === 'player2') {
// Unequip (revert to default)
equippedSkin = 'player';
skin1EquipText.setText('EQUIP');
skin1EquipText.tint = 0xFFD700;
} else {
// Equip this skin
equippedSkin = 'player2';
skin1EquipText.setText('UNEQUIP');
skin1EquipText.tint = 0xFF4444;
}
storage.equippedSkin = equippedSkin;
// Update player graphics immediately using the updateSkin method
player.updateSkin(equippedSkin);
}
return;
}
} else if (gameState === 'playing') {
dragActive = true;
lastTouchX = x;
lastTouchY = y;
shootBullet();
}
};
game.move = function (x, y, obj) {
if (gameState === 'playing' && dragActive) {
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
player.x += deltaX;
player.y += deltaY;
// Keep player within screen bounds
if (player.x < 40) {
player.x = 40;
}
if (player.x > 2048 - 40) {
player.x = 2048 - 40;
}
if (player.y < 40) {
player.y = 40;
}
if (player.y > 2732 - 40) {
player.y = 2732 - 40;
}
lastTouchX = x;
lastTouchY = y;
}
};
game.up = function (x, y, obj) {
if (gameState === 'playing') {
dragActive = false;
}
};
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle challenge timer (only when not in rock mode)
if (!rockActive) {
challengeTimer++;
if (challengeTimer >= challengeTimeLimit) {
// Time limit reached - game over
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
updateTimer();
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer % 400 === 0 && spawnRate > 20) {
spawnRate -= 3;
}
// Check if there's a rock to determine if we should spawn normal objects
var hasRockForSpawning = false;
for (var rs = 0; rs < fallingObjects.length; rs++) {
if (fallingObjects[rs].type === 'rock') {
hasRockForSpawning = true;
break;
}
}
// Spawn falling objects with consistent timing only if no rock is present
if (!hasRockForSpawning) {
spawnTimer++;
if (spawnTimer >= spawnRate) {
spawnFallingObject();
spawnTimer = 0;
}
} else {
spawnTimer = 0; // Reset spawn timer when rock is present
}
// Handle double damage timer
if (doubleDamageActive) {
doubleDamageTimer++;
if (doubleDamageTimer >= doubleDamageTimeLimit) {
doubleDamageActive = false;
doubleDamageTimer = 0;
}
}
// Handle unlimited shooting timer
if (unlimitedShootingActive) {
unlimitedShootingTimer++;
if (unlimitedShootingTimer >= unlimitedShootingTimeLimit) {
unlimitedShootingActive = false;
unlimitedShootingTimer = 0;
}
}
updatePowerUpDisplay();
// Update power-ups
for (var p = powerUps.length - 1; p >= 0; p--) {
var powerUp = powerUps[p];
if (powerUp.lastY === undefined) {
powerUp.lastY = powerUp.y;
}
// Remove power-ups that fall off screen
if (powerUp.lastY <= 2732 + 50 && powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(p, 1);
continue;
}
// Check collision with player
if (powerUp.intersects(player)) {
// Check power-up type and activate accordingly
if (powerUp.powerUpType === 'doubleDamage') {
doubleDamageActive = true;
doubleDamageTimer = 0;
} else if (powerUp.powerUpType === 'unlimitedShooting') {
unlimitedShootingActive = true;
unlimitedShootingTimer = 0;
} else if (powerUp.powerUpType === 'health') {
if (lives < maxLives) {
lives++;
updateLives();
}
} else if (powerUp.powerUpType === 'clearScreen') {
// Destroy all objects except rocks and swords
for (var cs = fallingObjects.length - 1; cs >= 0; cs--) {
var objToClear = fallingObjects[cs];
// Check if object still exists before clearing
if (!objToClear || !objToClear.parent) {
fallingObjects.splice(cs, 1);
continue;
}
if (objToClear.type !== 'rock') {
// Create explosion effect for cleared objects
tween(objToClear, {
scaleX: 2,
scaleY: 2,
alpha: 0,
tint: 0xffaa00
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
objToClear.destroy();
}
});
fallingObjects.splice(cs, 1);
}
}
}
// Visual effect
tween(powerUp, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
powerUp.destroy();
}
});
powerUps.splice(p, 1);
continue;
}
powerUp.lastY = powerUp.y;
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet still exists and hasn't been destroyed
if (!bullet || !bullet.parent) {
bullets.splice(i, 1);
continue;
}
if (bullet.lastY === undefined) {
bullet.lastY = bullet.y;
}
// Remove bullets that go off screen
if (bullet.lastY >= -50 && bullet.y < -50) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet collision with falling objects
for (var j = fallingObjects.length - 1; j >= 0; j--) {
var obj = fallingObjects[j];
// Check if objects still exist before checking intersection
if (!obj || !obj.parent || !bullet || !bullet.parent) {
continue;
}
if (bullet.intersects(obj)) {
// Reduce hit points (double damage if power-up is active, plus upgrade damage)
var baseDamage = 1 + damageUpgrade;
var damage = doubleDamageActive ? baseDamage * 2 : baseDamage;
obj.hitPoints -= damage;
// Flash object to show it was hit
var hitTint = 0xff0000;
var originalTint = obj.tint || 0xffffff;
tween(obj, {
tint: hitTint
}, {
duration: 100,
onFinish: function onFinish() {
tween(obj, {
tint: originalTint
}, {
duration: 100
});
}
});
// Destroy bullet
bullet.destroy();
bullets.splice(i, 1);
// Check if object should be destroyed
if (obj.hitPoints <= 0) {
if (obj.type === 'rock') {
LK.setScore(LK.getScore() + 50);
lives = maxLives; // Restore full health
updateLives();
rockActive = false;
resetChallenge();
} else {
LK.setScore(LK.getScore() + 1);
objectsDestroyed++;
// Track bat destruction for power-up
if (obj.type === 'bat') {
batsDestroyed++;
// Spawn power-up every 10 bats destroyed
if (batsDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'doubleDamage');
}
}
// Track sword destruction for power-up
if (obj.type === 'sword') {
swordsDestroyed++;
// Spawn unlimited shooting power-up every 10 swords destroyed
if (swordsDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'unlimitedShooting');
}
}
// Track knife destruction for health power-up
if (obj.type === 'knife') {
knivesDestroyed++;
// Spawn health power-up every 10 knives destroyed
if (knivesDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'health');
}
}
// Track stick destruction for clear screen power-up
if (obj.type === 'stick') {
sticksDestroyed++;
// Spawn clear screen power-up every 10 sticks destroyed
if (sticksDestroyed % 10 === 0) {
spawnPowerUp(obj.x, obj.y, 'clearScreen');
}
}
// Check if challenge is completed (only when no rock is active)
if (!rockActive && objectsDestroyed >= challengeTarget) {
challengesCompleted++;
if (challengesCompleted % 5 === 0) {
spawnRock();
} else {
resetChallenge();
}
}
// Add coins based on score when objects are destroyed
totalEarnings += 1;
storage.totalEarnings = totalEarnings;
}
updateScore();
LK.getSound('destroy').play();
// Create explosion effect
tween(obj, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
obj.destroy();
}
});
fallingObjects.splice(j, 1);
} else {
LK.getSound('hit').play();
}
break;
}
}
if (bullets[i]) {
bullet.lastY = bullet.y;
}
}
// Check if there's a rock and handle bat spawning timer
var hasRock = false;
for (var r = 0; r < fallingObjects.length; r++) {
if (fallingObjects[r].type === 'rock') {
hasRock = true;
break;
}
}
if (hasRock) {
rockBatTimer++;
if (rockBatTimer >= rockBatSpawnRate) {
spawnRockBats();
rockBatTimer = 0;
}
} else {
rockBatTimer = 0;
}
// Update falling objects
for (var k = fallingObjects.length - 1; k >= 0; k--) {
var fallingObj = fallingObjects[k];
// Check if object still exists and hasn't been destroyed
if (!fallingObj || !fallingObj.parent) {
fallingObjects.splice(k, 1);
continue;
}
if (fallingObj.lastY === undefined) {
fallingObj.lastY = fallingObj.y;
}
// Handle rock horizontal movement
if (fallingObj.type === 'rock') {
fallingObj.x += fallingObj.horizontalSpeed * fallingObj.direction;
// Bounce off screen edges
if (fallingObj.x <= 50 || fallingObj.x >= 2048 - 50) {
fallingObj.direction *= -1;
}
}
// Remove objects that fall off screen
if (fallingObj.lastY <= 2732 + 50 && fallingObj.y > 2732 + 50) {
fallingObj.destroy();
fallingObjects.splice(k, 1);
continue;
}
// Check collision with player
if (fallingObj.intersects(player)) {
// If player touches rock, instant game over
if (fallingObj.type === 'rock') {
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
lives--;
updateLives();
LK.getSound('hit').play();
// Flash player red
tween(player, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
tint: 0xffffff
}, {
duration: 200
});
}
});
fallingObj.destroy();
fallingObjects.splice(k, 1);
if (lives <= 0) {
LK.stopMusic();
LK.playMusic('game_over_music');
LK.showGameOver();
return;
}
continue;
}
fallingObj.lastY = fallingObj.y;
}
};
Quiero qie sea como un bate de béisbol de color cafe, en estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero un cuchillo de color metal en estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero una roca de color gris, circular, en estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero un palo o rama de color cafe, en estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero una espada de metal, estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero una manzana roja, en estilo 32 bits. In-Game asset. 2d. High contrast. No shadows
Quiero un arbusto visto desde abajo, en 32 bits. In-Game asset. 2d. High contrast. No shadows
Una luz fuerte de color amarillo, en 32 bits. In-Game asset. 2d. High contrast. No shadows
Un coco, visto desde arriba, en 32 bits. In-Game asset. 2d. High contrast. No shadows