/****
* 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();
}
};