/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var MenuButton = Container.expand(function (label, yPos) { var self = Container.call(this); // Button background var buttonBg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); // Button highlight (initially invisible) var highlight = self.attachAsset('buttonHighlight', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Button text var text = new Text2(label, { size: 70, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(text); // Set position self.y = yPos; // Event handlers self.down = function (x, y, obj) { // Scale down effect tween(buttonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); // Play sound LK.getSound('buttonClick').play(); }; self.up = function (x, y, obj) { // Scale back to normal tween(buttonBg, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); // Handle button action if (label === "Shop") { showShopView(); } else if (label === "Play") { showPlayView(); } else if (label === "Settings") { showSettingsView(); } }; // Hover effect methods self.showHighlight = function () { tween(highlight, { alpha: 0.3 }, { duration: 200, easing: tween.easeOut }); }; self.hideHighlight = function () { tween(highlight, { alpha: 0 }, { duration: 200, easing: tween.easeOut }); }; // Function to set the button text self.setLabel = function (newLabel) { text.setText(newLabel); }; return self; }); var MenuView = Container.expand(function () { var self = Container.call(this); // Background panel var background = self.attachAsset('menuBackground', { anchorX: 0.5, anchorY: 0.5 }); // Title text var titleText = new Text2("Game Menu", { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -600; self.addChild(titleText); // Buttons var playButton = new MenuButton("Play", -250); var shopButton = new MenuButton("Shop", 0); var settingsButton = new MenuButton("Settings", 250); self.addChild(shopButton); self.addChild(playButton); self.addChild(settingsButton); // Hover tracking var hoveredButton = null; // Track mouse movement for hover effects self.move = function (x, y, obj) { var localPos = { x: x, y: y }; // Clear previous hover state if (hoveredButton) { hoveredButton.hideHighlight(); hoveredButton = null; } // Check if hovering over any button if (playButton.getBounds().contains(localPos.x, localPos.y)) { playButton.showHighlight(); hoveredButton = playButton; } else if (shopButton.getBounds().contains(localPos.x, localPos.y)) { shopButton.showHighlight(); hoveredButton = shopButton; } else if (settingsButton.getBounds().contains(localPos.x, localPos.y)) { settingsButton.showHighlight(); hoveredButton = settingsButton; } }; // Animation for showing the menu self.animateIn = function () { // Initial state background.alpha = 0; titleText.alpha = 0; shopButton.alpha = 0; playButton.alpha = 0; settingsButton.alpha = 0; // Background fade in tween(background, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); // Title slide down titleText.y = -800; tween(titleText, { alpha: 1, y: -600 }, { duration: 700, easing: tween.easeOut }); // Buttons fade in sequence LK.setTimeout(function () { tween(playButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 200); LK.setTimeout(function () { tween(shopButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 350); LK.setTimeout(function () { tween(settingsButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 500); }; return self; }); var ShooterGame = Container.expand(function () { var self = Container.call(this); // Game elements var player = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100, tint: 0xff0000 }); // Position player at bottom center player.x = 0; player.y = 500; // Score display var scoreText = new Text2("Score: 0", { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 0; scoreText.y = -650; self.addChild(scoreText); // Game variables // Initialize score but keep coins from storage var score = 0; var bullets = []; var enemies = []; var enemyBullets = []; // Array to track enemy bullets // Player control - optimized for mobile touch self.move = function (x, y, obj) { // Convert global position to local position // Clamp player position within screen bounds to prevent going off-screen player.x = Math.max(-900, Math.min(900, x)); // Limit horizontal movement }; // Shoot function - optimized for mobile function shoot() { // Don't create too many bullets on mobile if (bullets.length > 80) { // Remove oldest bullets if we have too many (mobile optimization) var bulletsToRemove = bullets.length - 80; for (var i = 0; i < bulletsToRemove; i++) { if (bullets[i]) { bullets[i].destroy(); } } bullets.splice(0, bulletsToRemove); } var bullet = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 30, // Slightly larger for better visibility on mobile height: 50, tint: 0xffff00 }); bullet.x = player.x; bullet.y = player.y - 50; bullet.speed = -20; // Fast upward speed self.addChild(bullet); bullets.push(bullet); LK.getSound('buttonClick').play(); } // Player shooting - optimized for mobile touch self.down = function (x, y, obj) { // On mobile, we want to ensure the player can still shoot even if they tap slightly away from ship var touchDistance = Math.sqrt(Math.pow(x - player.x, 2) + Math.pow(y - player.y, 2)); if (touchDistance < 150) { // Larger touch area for mobile shoot(); } else { // If they tap elsewhere, move the player there and shoot player.x = x; shoot(); } }; // Main game loop - optimized for mobile self.update = function () { // Auto shooting (adjust fire rate for mobile - slightly slower to prevent lag) if (LK.ticks % 15 === 0) { // Fire every 15 ticks instead of 10 for better mobile performance shoot(); } // Update bullets - with limit for mobile performance // Only process a maximum of 50 bullets at once to prevent performance issues var bulletProcessLimit = Math.min(bullets.length, 50); for (var i = bulletProcessLimit - 1; i >= 0; i--) { var bullet = bullets[i]; bullet.y += bullet.speed; // Remove bullets that go off screen if (bullet.y < -700) { bullet.destroy(); bullets.splice(i, 1); } } // Create enemies randomly - reduced rate for mobile if (Math.random() < 0.008) { // Reduced spawn rate further // Reduced spawn rate for mobile performance var enemy = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80, tint: 0x00ff00 }); enemy.x = Math.random() * 1000 - 500; // Random position enemy.y = -700; // Start from top enemy.speed = 3; // Move downward enemy.lastShot = LK.ticks; // Track last shot time self.addChild(enemy); enemies.push(enemy); } // Update enemies - with limit for mobile performance // Only process a maximum of 30 enemies at once to prevent performance issues var enemyProcessLimit = Math.min(enemies.length, 30); for (var j = enemyProcessLimit - 1; j >= 0; j--) { var enemy = enemies[j]; enemy.y += enemy.speed; // Enemy shooting logic if (LK.ticks - enemy.lastShot > 90) { // Shoot every ~1.5 seconds // Create enemy bullet var enemyBullet = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 20, height: 40, tint: 0xff0088 }); enemyBullet.x = enemy.x; enemyBullet.y = enemy.y + 50; enemyBullet.speed = 8; // Downward speed self.addChild(enemyBullet); enemyBullets.push(enemyBullet); enemy.lastShot = LK.ticks; } // Check collision with bullets - optimized for mobile var hitDetected = false; for (var k = 0; k < bullets.length && !hitDetected; k++) { if (enemy.intersects(bullets[k])) { // Increase score score += 10; // Update coins in storage storage.coins = (storage.coins || 0) + 10; scoreText.setText("Score: " + score); // Remove bullet and enemy bullets[k].destroy(); bullets.splice(k, 1); enemy.destroy(); enemies.splice(j, 1); hitDetected = true; break; } } // Skip rest of processing if enemy was destroyed if (hitDetected) { continue; } // Remove enemies that go off screen if (enemy.y > 700) { enemy.destroy(); enemies.splice(j, 1); } } // Update enemy bullets for (var m = enemyBullets.length - 1; m >= 0; m--) { var enemyBullet = enemyBullets[m]; enemyBullet.y += enemyBullet.speed; // Check collision with player if (enemyBullet.intersects(player)) { // Player hit - ensure coins are saved before game over storage.coins = storage.coins || 0; // Player hit - game over LK.showGameOver(); enemyBullet.destroy(); enemyBullets.splice(m, 1); continue; } // Remove bullets that go off screen if (enemyBullet.y > 700) { enemyBullet.destroy(); enemyBullets.splice(m, 1); } } }; return self; }); var ShopView = Container.expand(function () { var self = Container.call(this); // Background panel var background = self.attachAsset('menuBackground', { anchorX: 0.5, anchorY: 0.5 }); // Title text var titleText = new Text2("Shop", { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -600; self.addChild(titleText); // Buttons var skinsButton = new MenuButton("Skins", -250); var upgradesButton = new MenuButton("Upgrades", 0); var backButton = new MenuButton("Back to Menu", 250); self.addChild(skinsButton); self.addChild(upgradesButton); self.addChild(backButton); // Button actions skinsButton.up = function (x, y, obj) { // Open skins view showSkinsView(); }; backButton.up = function (x, y, obj) { // Return to main menu showMainMenu(); }; // Animation for showing the shop self.animateIn = function () { // Initial state background.alpha = 0; titleText.alpha = 0; skinsButton.alpha = 0; upgradesButton.alpha = 0; backButton.alpha = 0; // Background fade in tween(background, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); // Title slide down titleText.y = -800; tween(titleText, { alpha: 1, y: -600 }, { duration: 700, easing: tween.easeOut }); // Buttons fade in sequence LK.setTimeout(function () { tween(skinsButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 200); LK.setTimeout(function () { tween(upgradesButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 350); LK.setTimeout(function () { tween(backButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 500); }; return self; }); var SkinsView = Container.expand(function () { var self = Container.call(this); // Background panel var background = self.attachAsset('menuBackground', { anchorX: 0.5, anchorY: 0.5 }); // Title text var titleText = new Text2("Skins", { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -600; self.addChild(titleText); // Skins display (example skins) var skin1 = new MenuButton("Blue - $10", -250); var skin2 = new MenuButton("Red - $14", 0); var greenButton = new MenuButton("Green - $12", 250); self.addChild(skin1); self.addChild(skin2); self.addChild(greenButton); var backButton = new MenuButton("Back to Shop", 250); self.addChild(backButton); // Button actions backButton.up = function (x, y, obj) { // Return to shop view showShopView(); }; // Animation for showing the skins self.animateIn = function () { // Initial state background.alpha = 0; titleText.alpha = 0; skin1.alpha = 0; skin2.alpha = 0; backButton.alpha = 0; // Background fade in tween(background, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); // Title slide down titleText.y = -800; tween(titleText, { alpha: 1, y: -600 }, { duration: 700, easing: tween.easeOut }); // Skins fade in sequence LK.setTimeout(function () { tween(skin1, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 200); LK.setTimeout(function () { tween(skin2, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 350); LK.setTimeout(function () { tween(backButton, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); }, 500); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ function showSkinsView() { if (currentView === "skins") { return; } // Destroy current view and create skins view if (currentView === "shop") { shopView.destroy(); } skinsView = new SkinsView(); skinsView.x = 2048 / 2; skinsView.y = 2732 / 2; game.addChild(skinsView); skinsView.animateIn(); currentView = "skins"; } function showMainMenu() { if (currentView === "main") { return; } // Destroy current view and create main menu if (currentView === "shop") { shopView.destroy(); } createMainMenu(); currentView = "main"; } // Main elements var mainMenu; var currentView = "main"; // Track which view is currently shown // Create the main menu function createMainMenu() { // Initialize storage.coins if it doesn't exist yet storage.coins = storage.coins || 0; mainMenu = new MenuView(); mainMenu.x = 2048 / 2; mainMenu.y = 2732 / 2; game.addChild(mainMenu); mainMenu.animateIn(); } // Show functions for different views function showShopView() { if (currentView === "shop") { return; } // Destroy current view and create shop view if (currentView === "main") { mainMenu.destroy(); } shopView = new ShopView(); shopView.x = 2048 / 2; shopView.y = 2732 / 2; game.addChild(shopView); shopView.animateIn(); // Add coins display to shop view from persistent storage var scoreDisplay = new Text2("Your Coins: " + (storage.coins || 0), { size: 60, fill: 0xFFFFFF }); scoreDisplay.anchor.set(0.5, 0.5); scoreDisplay.x = 0; scoreDisplay.y = -400; shopView.addChild(scoreDisplay); currentView = "shop"; } function showPlayView() { if (currentView === "play") { return; } // Destroy current view if (currentView === "main") { mainMenu.destroy(); } else if (currentView === "shop") { shopView.destroy(); } else if (currentView === "skins") { skinsView.destroy(); } // Create and start the shooter game function startShooterGame() { // Initialize the shooter game - with mobile optimizations var shooterGame = new ShooterGame(); shooterGame.x = 2048 / 2; shooterGame.y = 2732 / 2; game.addChild(shooterGame); // Add mobile-specific instructions var instructionText = new Text2("Tap to shoot\nDrag to move", { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 0; instructionText.y = 300; shooterGame.addChild(instructionText); // Fade out instructions after 3 seconds LK.setTimeout(function () { tween(instructionText, { alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { instructionText.destroy(); } }); }, 3000); console.log("Shooter game started!"); } // Start the shooter game startShooterGame(); currentView = "play"; } function showSettingsView() { if (currentView === "settings") { return; } // Simple feedback for now - in a real game, this would show settings menu var notification = new Text2("Opening Settings...", { size: 70, fill: 0xFFFFFF }); notification.anchor.set(0.5, 0.5); notification.x = 2048 / 2; notification.y = 2732 - 300; notification.alpha = 0; game.addChild(notification); tween(notification, { alpha: 1 }, { duration: 300, easing: tween.linear, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 300, easing: tween.linear, onFinish: function onFinish() { notification.destroy(); } }); }, 1500); } }); currentView = "settings"; } // Game events game.down = function (x, y, obj) { // Global down event if needed }; game.up = function (x, y, obj) { // Global up event if needed }; game.move = function (x, y, obj) { // Pass touch/mouse movement to active view based on current state // For mobile: Add check to ensure we have valid obj if (!obj || !obj.event) { return; } // Normalize touch events for mobile if (currentView === "play" && game.getChildAt(0) instanceof ShooterGame) { // Calculate position relative to game center for consistent mobile experience var gameX = x - 2048 / 2; var gameY = y - 2732 / 2; // Pass the normalized coordinates game.getChildAt(0).move(gameX, gameY, obj); } }; // Initialize game createMainMenu(); // Play background music LK.playMusic('menuMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Main game loop game.update = function () { // Any continuous updates can go here // For a menu, we don't need much in the update loop };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MenuButton = Container.expand(function (label, yPos) {
var self = Container.call(this);
// Button background
var buttonBg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
// Button highlight (initially invisible)
var highlight = self.attachAsset('buttonHighlight', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Button text
var text = new Text2(label, {
size: 70,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
// Set position
self.y = yPos;
// Event handlers
self.down = function (x, y, obj) {
// Scale down effect
tween(buttonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
// Play sound
LK.getSound('buttonClick').play();
};
self.up = function (x, y, obj) {
// Scale back to normal
tween(buttonBg, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
// Handle button action
if (label === "Shop") {
showShopView();
} else if (label === "Play") {
showPlayView();
} else if (label === "Settings") {
showSettingsView();
}
};
// Hover effect methods
self.showHighlight = function () {
tween(highlight, {
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
};
self.hideHighlight = function () {
tween(highlight, {
alpha: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
// Function to set the button text
self.setLabel = function (newLabel) {
text.setText(newLabel);
};
return self;
});
var MenuView = Container.expand(function () {
var self = Container.call(this);
// Background panel
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
// Title text
var titleText = new Text2("Game Menu", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -600;
self.addChild(titleText);
// Buttons
var playButton = new MenuButton("Play", -250);
var shopButton = new MenuButton("Shop", 0);
var settingsButton = new MenuButton("Settings", 250);
self.addChild(shopButton);
self.addChild(playButton);
self.addChild(settingsButton);
// Hover tracking
var hoveredButton = null;
// Track mouse movement for hover effects
self.move = function (x, y, obj) {
var localPos = {
x: x,
y: y
};
// Clear previous hover state
if (hoveredButton) {
hoveredButton.hideHighlight();
hoveredButton = null;
}
// Check if hovering over any button
if (playButton.getBounds().contains(localPos.x, localPos.y)) {
playButton.showHighlight();
hoveredButton = playButton;
} else if (shopButton.getBounds().contains(localPos.x, localPos.y)) {
shopButton.showHighlight();
hoveredButton = shopButton;
} else if (settingsButton.getBounds().contains(localPos.x, localPos.y)) {
settingsButton.showHighlight();
hoveredButton = settingsButton;
}
};
// Animation for showing the menu
self.animateIn = function () {
// Initial state
background.alpha = 0;
titleText.alpha = 0;
shopButton.alpha = 0;
playButton.alpha = 0;
settingsButton.alpha = 0;
// Background fade in
tween(background, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Title slide down
titleText.y = -800;
tween(titleText, {
alpha: 1,
y: -600
}, {
duration: 700,
easing: tween.easeOut
});
// Buttons fade in sequence
LK.setTimeout(function () {
tween(playButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 200);
LK.setTimeout(function () {
tween(shopButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 350);
LK.setTimeout(function () {
tween(settingsButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 500);
};
return self;
});
var ShooterGame = Container.expand(function () {
var self = Container.call(this);
// Game elements
var player = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100,
tint: 0xff0000
});
// Position player at bottom center
player.x = 0;
player.y = 500;
// Score display
var scoreText = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 0;
scoreText.y = -650;
self.addChild(scoreText);
// Game variables
// Initialize score but keep coins from storage
var score = 0;
var bullets = [];
var enemies = [];
var enemyBullets = []; // Array to track enemy bullets
// Player control - optimized for mobile touch
self.move = function (x, y, obj) {
// Convert global position to local position
// Clamp player position within screen bounds to prevent going off-screen
player.x = Math.max(-900, Math.min(900, x)); // Limit horizontal movement
};
// Shoot function - optimized for mobile
function shoot() {
// Don't create too many bullets on mobile
if (bullets.length > 80) {
// Remove oldest bullets if we have too many (mobile optimization)
var bulletsToRemove = bullets.length - 80;
for (var i = 0; i < bulletsToRemove; i++) {
if (bullets[i]) {
bullets[i].destroy();
}
}
bullets.splice(0, bulletsToRemove);
}
var bullet = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 30,
// Slightly larger for better visibility on mobile
height: 50,
tint: 0xffff00
});
bullet.x = player.x;
bullet.y = player.y - 50;
bullet.speed = -20; // Fast upward speed
self.addChild(bullet);
bullets.push(bullet);
LK.getSound('buttonClick').play();
}
// Player shooting - optimized for mobile touch
self.down = function (x, y, obj) {
// On mobile, we want to ensure the player can still shoot even if they tap slightly away from ship
var touchDistance = Math.sqrt(Math.pow(x - player.x, 2) + Math.pow(y - player.y, 2));
if (touchDistance < 150) {
// Larger touch area for mobile
shoot();
} else {
// If they tap elsewhere, move the player there and shoot
player.x = x;
shoot();
}
};
// Main game loop - optimized for mobile
self.update = function () {
// Auto shooting (adjust fire rate for mobile - slightly slower to prevent lag)
if (LK.ticks % 15 === 0) {
// Fire every 15 ticks instead of 10 for better mobile performance
shoot();
}
// Update bullets - with limit for mobile performance
// Only process a maximum of 50 bullets at once to prevent performance issues
var bulletProcessLimit = Math.min(bullets.length, 50);
for (var i = bulletProcessLimit - 1; i >= 0; i--) {
var bullet = bullets[i];
bullet.y += bullet.speed;
// Remove bullets that go off screen
if (bullet.y < -700) {
bullet.destroy();
bullets.splice(i, 1);
}
}
// Create enemies randomly - reduced rate for mobile
if (Math.random() < 0.008) {
// Reduced spawn rate further
// Reduced spawn rate for mobile performance
var enemy = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80,
tint: 0x00ff00
});
enemy.x = Math.random() * 1000 - 500; // Random position
enemy.y = -700; // Start from top
enemy.speed = 3; // Move downward
enemy.lastShot = LK.ticks; // Track last shot time
self.addChild(enemy);
enemies.push(enemy);
}
// Update enemies - with limit for mobile performance
// Only process a maximum of 30 enemies at once to prevent performance issues
var enemyProcessLimit = Math.min(enemies.length, 30);
for (var j = enemyProcessLimit - 1; j >= 0; j--) {
var enemy = enemies[j];
enemy.y += enemy.speed;
// Enemy shooting logic
if (LK.ticks - enemy.lastShot > 90) {
// Shoot every ~1.5 seconds
// Create enemy bullet
var enemyBullet = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 20,
height: 40,
tint: 0xff0088
});
enemyBullet.x = enemy.x;
enemyBullet.y = enemy.y + 50;
enemyBullet.speed = 8; // Downward speed
self.addChild(enemyBullet);
enemyBullets.push(enemyBullet);
enemy.lastShot = LK.ticks;
}
// Check collision with bullets - optimized for mobile
var hitDetected = false;
for (var k = 0; k < bullets.length && !hitDetected; k++) {
if (enemy.intersects(bullets[k])) {
// Increase score
score += 10;
// Update coins in storage
storage.coins = (storage.coins || 0) + 10;
scoreText.setText("Score: " + score);
// Remove bullet and enemy
bullets[k].destroy();
bullets.splice(k, 1);
enemy.destroy();
enemies.splice(j, 1);
hitDetected = true;
break;
}
}
// Skip rest of processing if enemy was destroyed
if (hitDetected) {
continue;
}
// Remove enemies that go off screen
if (enemy.y > 700) {
enemy.destroy();
enemies.splice(j, 1);
}
}
// Update enemy bullets
for (var m = enemyBullets.length - 1; m >= 0; m--) {
var enemyBullet = enemyBullets[m];
enemyBullet.y += enemyBullet.speed;
// Check collision with player
if (enemyBullet.intersects(player)) {
// Player hit - ensure coins are saved before game over
storage.coins = storage.coins || 0;
// Player hit - game over
LK.showGameOver();
enemyBullet.destroy();
enemyBullets.splice(m, 1);
continue;
}
// Remove bullets that go off screen
if (enemyBullet.y > 700) {
enemyBullet.destroy();
enemyBullets.splice(m, 1);
}
}
};
return self;
});
var ShopView = Container.expand(function () {
var self = Container.call(this);
// Background panel
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
// Title text
var titleText = new Text2("Shop", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -600;
self.addChild(titleText);
// Buttons
var skinsButton = new MenuButton("Skins", -250);
var upgradesButton = new MenuButton("Upgrades", 0);
var backButton = new MenuButton("Back to Menu", 250);
self.addChild(skinsButton);
self.addChild(upgradesButton);
self.addChild(backButton);
// Button actions
skinsButton.up = function (x, y, obj) {
// Open skins view
showSkinsView();
};
backButton.up = function (x, y, obj) {
// Return to main menu
showMainMenu();
};
// Animation for showing the shop
self.animateIn = function () {
// Initial state
background.alpha = 0;
titleText.alpha = 0;
skinsButton.alpha = 0;
upgradesButton.alpha = 0;
backButton.alpha = 0;
// Background fade in
tween(background, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Title slide down
titleText.y = -800;
tween(titleText, {
alpha: 1,
y: -600
}, {
duration: 700,
easing: tween.easeOut
});
// Buttons fade in sequence
LK.setTimeout(function () {
tween(skinsButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 200);
LK.setTimeout(function () {
tween(upgradesButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 350);
LK.setTimeout(function () {
tween(backButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 500);
};
return self;
});
var SkinsView = Container.expand(function () {
var self = Container.call(this);
// Background panel
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5
});
// Title text
var titleText = new Text2("Skins", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -600;
self.addChild(titleText);
// Skins display (example skins)
var skin1 = new MenuButton("Blue - $10", -250);
var skin2 = new MenuButton("Red - $14", 0);
var greenButton = new MenuButton("Green - $12", 250);
self.addChild(skin1);
self.addChild(skin2);
self.addChild(greenButton);
var backButton = new MenuButton("Back to Shop", 250);
self.addChild(backButton);
// Button actions
backButton.up = function (x, y, obj) {
// Return to shop view
showShopView();
};
// Animation for showing the skins
self.animateIn = function () {
// Initial state
background.alpha = 0;
titleText.alpha = 0;
skin1.alpha = 0;
skin2.alpha = 0;
backButton.alpha = 0;
// Background fade in
tween(background, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Title slide down
titleText.y = -800;
tween(titleText, {
alpha: 1,
y: -600
}, {
duration: 700,
easing: tween.easeOut
});
// Skins fade in sequence
LK.setTimeout(function () {
tween(skin1, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 200);
LK.setTimeout(function () {
tween(skin2, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 350);
LK.setTimeout(function () {
tween(backButton, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}, 500);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
function showSkinsView() {
if (currentView === "skins") {
return;
}
// Destroy current view and create skins view
if (currentView === "shop") {
shopView.destroy();
}
skinsView = new SkinsView();
skinsView.x = 2048 / 2;
skinsView.y = 2732 / 2;
game.addChild(skinsView);
skinsView.animateIn();
currentView = "skins";
}
function showMainMenu() {
if (currentView === "main") {
return;
}
// Destroy current view and create main menu
if (currentView === "shop") {
shopView.destroy();
}
createMainMenu();
currentView = "main";
}
// Main elements
var mainMenu;
var currentView = "main"; // Track which view is currently shown
// Create the main menu
function createMainMenu() {
// Initialize storage.coins if it doesn't exist yet
storage.coins = storage.coins || 0;
mainMenu = new MenuView();
mainMenu.x = 2048 / 2;
mainMenu.y = 2732 / 2;
game.addChild(mainMenu);
mainMenu.animateIn();
}
// Show functions for different views
function showShopView() {
if (currentView === "shop") {
return;
}
// Destroy current view and create shop view
if (currentView === "main") {
mainMenu.destroy();
}
shopView = new ShopView();
shopView.x = 2048 / 2;
shopView.y = 2732 / 2;
game.addChild(shopView);
shopView.animateIn();
// Add coins display to shop view from persistent storage
var scoreDisplay = new Text2("Your Coins: " + (storage.coins || 0), {
size: 60,
fill: 0xFFFFFF
});
scoreDisplay.anchor.set(0.5, 0.5);
scoreDisplay.x = 0;
scoreDisplay.y = -400;
shopView.addChild(scoreDisplay);
currentView = "shop";
}
function showPlayView() {
if (currentView === "play") {
return;
}
// Destroy current view
if (currentView === "main") {
mainMenu.destroy();
} else if (currentView === "shop") {
shopView.destroy();
} else if (currentView === "skins") {
skinsView.destroy();
}
// Create and start the shooter game
function startShooterGame() {
// Initialize the shooter game - with mobile optimizations
var shooterGame = new ShooterGame();
shooterGame.x = 2048 / 2;
shooterGame.y = 2732 / 2;
game.addChild(shooterGame);
// Add mobile-specific instructions
var instructionText = new Text2("Tap to shoot\nDrag to move", {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 0;
instructionText.y = 300;
shooterGame.addChild(instructionText);
// Fade out instructions after 3 seconds
LK.setTimeout(function () {
tween(instructionText, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
instructionText.destroy();
}
});
}, 3000);
console.log("Shooter game started!");
}
// Start the shooter game
startShooterGame();
currentView = "play";
}
function showSettingsView() {
if (currentView === "settings") {
return;
}
// Simple feedback for now - in a real game, this would show settings menu
var notification = new Text2("Opening Settings...", {
size: 70,
fill: 0xFFFFFF
});
notification.anchor.set(0.5, 0.5);
notification.x = 2048 / 2;
notification.y = 2732 - 300;
notification.alpha = 0;
game.addChild(notification);
tween(notification, {
alpha: 1
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 1500);
}
});
currentView = "settings";
}
// Game events
game.down = function (x, y, obj) {
// Global down event if needed
};
game.up = function (x, y, obj) {
// Global up event if needed
};
game.move = function (x, y, obj) {
// Pass touch/mouse movement to active view based on current state
// For mobile: Add check to ensure we have valid obj
if (!obj || !obj.event) {
return;
}
// Normalize touch events for mobile
if (currentView === "play" && game.getChildAt(0) instanceof ShooterGame) {
// Calculate position relative to game center for consistent mobile experience
var gameX = x - 2048 / 2;
var gameY = y - 2732 / 2;
// Pass the normalized coordinates
game.getChildAt(0).move(gameX, gameY, obj);
}
};
// Initialize game
createMainMenu();
// Play background music
LK.playMusic('menuMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Main game loop
game.update = function () {
// Any continuous updates can go here
// For a menu, we don't need much in the update loop
};