/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 9 + Math.random() * 4.5; // Increase base speed and range self.health = 1; self.lastWasIntersecting = false; self.update = function () { // Move towards the player's current position self.x += self.vx; self.y += self.vy; // Check collision with player var isIntersecting = self.intersects(player); // Only deal damage if enemy collides with the white part of the player (not the headDot) // Since headDot is not a child, calculate its global position based on player's position and rotation var headDotOffset = 90; // Distance from player center to nose (approximate, based on player asset height/2 - headDot radius) var headDotLocalX = 0; var headDotLocalY = -headDotOffset; var sin = Math.sin(player.rotation); var cos = Math.cos(player.rotation); var headDotGlobal = { x: player.x + (headDotLocalX * cos - headDotLocalY * sin), y: player.y + (headDotLocalX * sin + headDotLocalY * cos) }; var enemyGlobal = self.toGlobal({ x: 0, y: 0 }); var dx = headDotGlobal.x - enemyGlobal.x; var dy = headDotGlobal.y - enemyGlobal.y; var distToHead = Math.sqrt(dx * dx + dy * dy); // The headDot has a radius of 12, so if the enemy is within 24px of the headDot center, it's hitting the head var isHittingHead = distToHead < 24; if (!self.lastWasIntersecting && isIntersecting && !isHittingHead) { player.takeDamage(10); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } self.lastWasIntersecting = isIntersecting; // Check if the enemy has exited the screen without colliding with the player if (!isIntersecting && (self.x < -self.width || self.x > 2048 + self.width || self.y < -self.height || self.y > 2732 + self.height)) { LK.setScore(LK.getScore() + 10); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { LK.getSound('explosion').play(); LK.effects.flashObject(self, 0xFFFFFF, 100); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } LK.setScore(LK.getScore() + 10); } }; return self; }); // Set background color var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // The headDot is not added to the player, so the red ellipse is not visible self.health = 100; self.rotation = 0; self.shootCooldown = 0; // Store targetX and targetY for movement and aiming self.targetX = 2048 / 2; self.targetY = 2732 / 2; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } // Move player towards target position var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 1) { self.x += dx / dist * 8; // Slightly increased speed for faster movement self.y += dy / dist * 8; // Slightly increased speed for faster movement } // Rotate player so the head (red dot) points away from the target self.rotation = Math.atan2(self.targetY - self.y, self.targetX - self.x) + Math.PI / 2; }; self.shoot = function () { // Shooting functionality removed }; self.takeDamage = function (amount) { self.health -= 20; LK.getSound('damage').play(); LK.effects.flashObject(self, 0xFF0000, 300); healthBarForeground.width = self.health / 100 * 400; // Update health bar width to match new size // Update health text healthText.setText(self.health); // Calculate the gray overlay intensity based on remaining health var grayIntensity = 1 - self.health / 100; LK.effects.flashScreen(0x808080, 300, { alpha: grayIntensity }); if (self.health <= 0) { LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Main menu overlay var mainMenuOverlay = new Container(); mainMenuOverlay.interactive = true; // Add background image to menu var menuBg = LK.getAsset('backround', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); mainMenuOverlay.addChild(menuBg); // Add title text var titleText = new Text2('AIR RAID', { size: 180, fill: 0xffffff, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 900; mainMenuOverlay.addChild(titleText); // Add start button var startButton = LK.getAsset('healthBarForeground', { anchorX: 0.5, anchorY: 0.5, width: 600, height: 160, x: 2048 / 2, y: 1400 }); mainMenuOverlay.addChild(startButton); var startText = new Text2('START', { size: 100, fill: 0x000000, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); startText.anchor.set(0.5, 0.5); startText.x = 2048 / 2; startText.y = 1400; mainMenuOverlay.addChild(startText); // Add overlay to game game.addChild(mainMenuOverlay); // Play music in menu LK.playMusic('ss'); // Hide game elements until game starts var gameStarted = false; // Define player and enemies in the global scope so they are accessible everywhere var player; var enemies = []; // Ensure enemies is always defined as an array var spawnTimer; var spawnInterval; var spawnDistance; var aimDirection; var score; // Initialize isTouching to false to avoid undefined errors if (typeof player === 'undefined' || player === null) { player = {}; } player.isTouching = false; // Define level variable in global scope so it is accessible everywhere var level = 1; // Start game handler function startGame() { if (gameStarted) return; gameStarted = true; mainMenuOverlay.visible = false; // Set the background image as the game background var backgroundImage = LK.getAsset('backround', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChildAt(backgroundImage, 0); // Add as the bottom-most layer // Always play the background music asset 'ss' LK.playMusic('ss'); // Game variables player = new Player(); player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); enemies = []; spawnTimer = 0; level = 1; spawnInterval = 60; spawnDistance = 800; aimDirection = 0; score = 0; // Spawn an initial enemy at the start of the game spawnEnemy(); } // Touch/click handler for start button mainMenuOverlay.down = function (x, y, obj) { // Only start if touch/click is inside the start button var local = startButton.toLocal({ x: x, y: y }, game); if (local.x >= -startButton.width / 2 && local.x <= startButton.width / 2 && local.y >= -startButton.height / 2 && local.y <= startButton.height / 2) { startGame(); } }; // Create graphical health bar var healthBarContainer = new Container(); var healthBarBackground = LK.getAsset('healthBarBackground', { anchorX: 0, anchorY: 0 }); var healthBarForeground = LK.getAsset('healthBarForeground', { anchorX: 0, anchorY: 0 }); healthBarContainer.addChild(healthBarBackground); healthBarContainer.addChild(healthBarForeground); // Add text to display remaining health var healthText = new Text2('100', { size: 40, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game }); healthText.anchor.set(0.5, 0.5); healthBarContainer.addChild(healthText); healthText.x = healthBarBackground.width / 2; healthText.y = healthBarBackground.height / 2; healthBarForeground.anchorX = 0; healthBarForeground.anchorY = 0; LK.gui.topLeft.addChild(healthBarContainer); healthBarContainer.x = 10; // Position health bar away from the left edge healthBarContainer.y = 10; // Position health bar away from the top edge // Create score text var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Create level text var levelText = new Text2('Level: ' + level, { size: 60, fill: 0xFFFFFF, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game }); levelText.anchor.set(1, 0); LK.gui.topRight.addChild(levelText); levelText.x = -10; // Position level text away from the right edge // Handle touch/click input for aiming and shooting game.down = function (x, y, obj) { // Set target position for player to move towards and rotate head to this position player.targetX = x; player.targetY = y; // Mark that the player is being controlled player.isTouching = true; }; game.move = function (x, y, obj) { // If the player is being touched/dragged, update the target position continuously if (player.isTouching) { player.targetX = x; player.targetY = y; } }; game.up = function (x, y, obj) { // Stop continuous control when touch/click is released player.isTouching = false; }; // Spawn enemy at random position around the player function spawnEnemy() { var enemy; enemy = new Enemy(); // Randomly choose an edge of the screen to spawn the enemy var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top edge enemy.x = Math.random() * 2048; enemy.y = -enemy.height; break; case 1: // Right edge enemy.x = 2048 + enemy.width; enemy.y = Math.random() * 2732; break; case 2: // Bottom edge enemy.x = Math.random() * 2048; enemy.y = 2732 + enemy.height; break; case 3: // Left edge enemy.x = -enemy.width; enemy.y = Math.random() * 2732; break; } // Calculate direction towards player var dx = player.x - enemy.x; var dy = player.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); enemy.vx = dx / dist * (enemy.speed + level * 0.5); enemy.vy = dy / dist * (enemy.speed + level * 0.5); // Rotate enemy to face the player with its sharp edge enemy.rotation = Math.atan2(dy, dx); game.addChild(enemy); enemies.push(enemy); // Increase difficulty if (spawnInterval > 30) { spawnInterval -= 0.5; } } // Game update loop game.update = function () { // Update player if (typeof player !== 'undefined' && player !== null && typeof player.update === 'function') { player.update(); } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].update(); // Add animation to enemy if (typeof enemies[i] !== 'undefined' && typeof enemies[i].rotation !== 'undefined') { tween(enemies[i], { rotation: enemies[i].rotation + Math.PI * 2 }, { duration: 2000, easing: tween.easeInOut }); } } // Spawn enemies spawnTimer++; if (spawnTimer >= spawnInterval) { spawnEnemy(); spawnTimer = 0; } // Update score and level display scoreText.setText('Score: ' + LK.getScore()); levelText.setText('Level: ' + level); // Increase level every 30 points if (LK.getScore() >= level * 30) { level++; levelText.setText('Level: ' + level); // Play level up sound LK.getSound('levelUp').play(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9 + Math.random() * 4.5; // Increase base speed and range
self.health = 1;
self.lastWasIntersecting = false;
self.update = function () {
// Move towards the player's current position
self.x += self.vx;
self.y += self.vy;
// Check collision with player
var isIntersecting = self.intersects(player);
// Only deal damage if enemy collides with the white part of the player (not the headDot)
// Since headDot is not a child, calculate its global position based on player's position and rotation
var headDotOffset = 90; // Distance from player center to nose (approximate, based on player asset height/2 - headDot radius)
var headDotLocalX = 0;
var headDotLocalY = -headDotOffset;
var sin = Math.sin(player.rotation);
var cos = Math.cos(player.rotation);
var headDotGlobal = {
x: player.x + (headDotLocalX * cos - headDotLocalY * sin),
y: player.y + (headDotLocalX * sin + headDotLocalY * cos)
};
var enemyGlobal = self.toGlobal({
x: 0,
y: 0
});
var dx = headDotGlobal.x - enemyGlobal.x;
var dy = headDotGlobal.y - enemyGlobal.y;
var distToHead = Math.sqrt(dx * dx + dy * dy);
// The headDot has a radius of 12, so if the enemy is within 24px of the headDot center, it's hitting the head
var isHittingHead = distToHead < 24;
if (!self.lastWasIntersecting && isIntersecting && !isHittingHead) {
player.takeDamage(10);
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
}
self.lastWasIntersecting = isIntersecting;
// Check if the enemy has exited the screen without colliding with the player
if (!isIntersecting && (self.x < -self.width || self.x > 2048 + self.width || self.y < -self.height || self.y > 2732 + self.height)) {
LK.setScore(LK.getScore() + 10);
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
LK.getSound('explosion').play();
LK.effects.flashObject(self, 0xFFFFFF, 100);
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
LK.setScore(LK.getScore() + 10);
}
};
return self;
});
// Set background color
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// The headDot is not added to the player, so the red ellipse is not visible
self.health = 100;
self.rotation = 0;
self.shootCooldown = 0;
// Store targetX and targetY for movement and aiming
self.targetX = 2048 / 2;
self.targetY = 2732 / 2;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Move player towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 1) {
self.x += dx / dist * 8; // Slightly increased speed for faster movement
self.y += dy / dist * 8; // Slightly increased speed for faster movement
}
// Rotate player so the head (red dot) points away from the target
self.rotation = Math.atan2(self.targetY - self.y, self.targetX - self.x) + Math.PI / 2;
};
self.shoot = function () {
// Shooting functionality removed
};
self.takeDamage = function (amount) {
self.health -= 20;
LK.getSound('damage').play();
LK.effects.flashObject(self, 0xFF0000, 300);
healthBarForeground.width = self.health / 100 * 400; // Update health bar width to match new size
// Update health text
healthText.setText(self.health);
// Calculate the gray overlay intensity based on remaining health
var grayIntensity = 1 - self.health / 100;
LK.effects.flashScreen(0x808080, 300, {
alpha: grayIntensity
});
if (self.health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Main menu overlay
var mainMenuOverlay = new Container();
mainMenuOverlay.interactive = true;
// Add background image to menu
var menuBg = LK.getAsset('backround', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
mainMenuOverlay.addChild(menuBg);
// Add title text
var titleText = new Text2('AIR RAID', {
size: 180,
fill: 0xffffff,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 900;
mainMenuOverlay.addChild(titleText);
// Add start button
var startButton = LK.getAsset('healthBarForeground', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 160,
x: 2048 / 2,
y: 1400
});
mainMenuOverlay.addChild(startButton);
var startText = new Text2('START', {
size: 100,
fill: 0x000000,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 1400;
mainMenuOverlay.addChild(startText);
// Add overlay to game
game.addChild(mainMenuOverlay);
// Play music in menu
LK.playMusic('ss');
// Hide game elements until game starts
var gameStarted = false;
// Define player and enemies in the global scope so they are accessible everywhere
var player;
var enemies = []; // Ensure enemies is always defined as an array
var spawnTimer;
var spawnInterval;
var spawnDistance;
var aimDirection;
var score;
// Initialize isTouching to false to avoid undefined errors
if (typeof player === 'undefined' || player === null) {
player = {};
}
player.isTouching = false;
// Define level variable in global scope so it is accessible everywhere
var level = 1;
// Start game handler
function startGame() {
if (gameStarted) return;
gameStarted = true;
mainMenuOverlay.visible = false;
// Set the background image as the game background
var backgroundImage = LK.getAsset('backround', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChildAt(backgroundImage, 0); // Add as the bottom-most layer
// Always play the background music asset 'ss'
LK.playMusic('ss');
// Game variables
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
enemies = [];
spawnTimer = 0;
level = 1;
spawnInterval = 60;
spawnDistance = 800;
aimDirection = 0;
score = 0;
// Spawn an initial enemy at the start of the game
spawnEnemy();
}
// Touch/click handler for start button
mainMenuOverlay.down = function (x, y, obj) {
// Only start if touch/click is inside the start button
var local = startButton.toLocal({
x: x,
y: y
}, game);
if (local.x >= -startButton.width / 2 && local.x <= startButton.width / 2 && local.y >= -startButton.height / 2 && local.y <= startButton.height / 2) {
startGame();
}
};
// Create graphical health bar
var healthBarContainer = new Container();
var healthBarBackground = LK.getAsset('healthBarBackground', {
anchorX: 0,
anchorY: 0
});
var healthBarForeground = LK.getAsset('healthBarForeground', {
anchorX: 0,
anchorY: 0
});
healthBarContainer.addChild(healthBarBackground);
healthBarContainer.addChild(healthBarForeground);
// Add text to display remaining health
var healthText = new Text2('100', {
size: 40,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game
});
healthText.anchor.set(0.5, 0.5);
healthBarContainer.addChild(healthText);
healthText.x = healthBarBackground.width / 2;
healthText.y = healthBarBackground.height / 2;
healthBarForeground.anchorX = 0;
healthBarForeground.anchorY = 0;
LK.gui.topLeft.addChild(healthBarContainer);
healthBarContainer.x = 10; // Position health bar away from the left edge
healthBarContainer.y = 10; // Position health bar away from the top edge
// Create score text
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create level text
var levelText = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" // Suitable font for the game
});
levelText.anchor.set(1, 0);
LK.gui.topRight.addChild(levelText);
levelText.x = -10; // Position level text away from the right edge
// Handle touch/click input for aiming and shooting
game.down = function (x, y, obj) {
// Set target position for player to move towards and rotate head to this position
player.targetX = x;
player.targetY = y;
// Mark that the player is being controlled
player.isTouching = true;
};
game.move = function (x, y, obj) {
// If the player is being touched/dragged, update the target position continuously
if (player.isTouching) {
player.targetX = x;
player.targetY = y;
}
};
game.up = function (x, y, obj) {
// Stop continuous control when touch/click is released
player.isTouching = false;
};
// Spawn enemy at random position around the player
function spawnEnemy() {
var enemy;
enemy = new Enemy();
// Randomly choose an edge of the screen to spawn the enemy
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top edge
enemy.x = Math.random() * 2048;
enemy.y = -enemy.height;
break;
case 1:
// Right edge
enemy.x = 2048 + enemy.width;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom edge
enemy.x = Math.random() * 2048;
enemy.y = 2732 + enemy.height;
break;
case 3:
// Left edge
enemy.x = -enemy.width;
enemy.y = Math.random() * 2732;
break;
}
// Calculate direction towards player
var dx = player.x - enemy.x;
var dy = player.y - enemy.y;
var dist = Math.sqrt(dx * dx + dy * dy);
enemy.vx = dx / dist * (enemy.speed + level * 0.5);
enemy.vy = dy / dist * (enemy.speed + level * 0.5);
// Rotate enemy to face the player with its sharp edge
enemy.rotation = Math.atan2(dy, dx);
game.addChild(enemy);
enemies.push(enemy);
// Increase difficulty
if (spawnInterval > 30) {
spawnInterval -= 0.5;
}
}
// Game update loop
game.update = function () {
// Update player
if (typeof player !== 'undefined' && player !== null && typeof player.update === 'function') {
player.update();
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].update();
// Add animation to enemy
if (typeof enemies[i] !== 'undefined' && typeof enemies[i].rotation !== 'undefined') {
tween(enemies[i], {
rotation: enemies[i].rotation + Math.PI * 2
}, {
duration: 2000,
easing: tween.easeInOut
});
}
}
// Spawn enemies
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnEnemy();
spawnTimer = 0;
}
// Update score and level display
scoreText.setText('Score: ' + LK.getScore());
levelText.setText('Level: ' + level);
// Increase level every 30 points
if (LK.getScore() >= level * 30) {
level++;
levelText.setText('Level: ' + level);
// Play level up sound
LK.getSound('levelUp').play();
}
};