/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.health = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var MenuButton = Container.expand(function (text, color) {
var self = Container.call(this);
// Create button background
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Create button text
var buttonText = new Text2(text, {
size: 80,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Button press handling
self.down = function (x, y, obj) {
buttonBg.tint = 0xcccccc; // Darken on press
if (self.onPress) {
self.onPress();
}
};
self.up = function (x, y, obj) {
buttonBg.tint = 0xffffff; // Return to normal
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.fireRate = 10;
self.lastFireTick = 0;
self.rapidFireTimer = 0;
self.shieldTimer = 0;
self.update = function () {
// Auto-fire logic
var currentFireRate = self.rapidFireTimer > 0 ? 5 : self.fireRate;
if (LK.ticks - self.lastFireTick >= currentFireRate) {
self.fire();
self.lastFireTick = LK.ticks;
}
// Update power-up timers
if (self.rapidFireTimer > 0) {
self.rapidFireTimer--;
graphics.tint = 0xffaa00; // Orange tint for rapid fire
} else {
graphics.tint = 0xffffff; // Normal color
}
if (self.shieldTimer > 0) {
self.shieldTimer--;
graphics.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.3); // Pulsing shield effect
} else {
graphics.alpha = 1.0;
}
};
self.fire = function () {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.activatePowerUp = function (type) {
if (type === 'rapidfire') {
self.rapidFireTimer = 300; // 5 seconds at 60fps
} else if (type === 'shield') {
self.shieldTimer = 600; // 10 seconds at 60fps
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.type = 'rapidfire'; // rapidfire, shield
self.update = function () {
self.y += self.speed;
// Gentle floating animation
graphics.rotation += 0.02;
};
return self;
});
var TutorialPanel = Container.expand(function () {
var self = Container.call(this);
// Semi-transparent background
var bg = self.attachAsset('tutorialBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Tutorial text
var tutorialText = new Text2('HOW TO PLAY\n\n• Drag your ship to move\n• Avoid red enemies\n• Collect green power-ups\n• Survive as long as possible\n\nPOWER-UPS:\n• Orange: Rapid Fire (5s)\n• Pulsing: Shield (10s)', {
size: 60,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.y = -100;
self.addChild(tutorialText);
// Close button
var closeButton = new MenuButton('CLOSE', 0x666666);
closeButton.y = 400;
closeButton.onPress = function () {
currentMenuState = 'main';
setupMainMenu();
};
self.addChild(closeButton);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Menu state variables
var currentMenuState = 'main'; // 'main', 'tutorial', 'playing'
var menuContainer;
var tutorialContainer;
// Game variables
var player;
var enemies = [];
var playerBullets = [];
var powerUps = [];
var dragNode = null;
var gameSpeed = 1;
var enemySpawnRate = 60;
var powerUpSpawnRate = 900;
var difficultyTimer = 0;
// Menu setup functions
function setupMainMenu() {
// Clear existing menu
if (menuContainer) {
menuContainer.destroy();
}
if (tutorialContainer) {
tutorialContainer.destroy();
}
// Create main menu
menuContainer = game.addChild(new Container());
// Title
var titleText = new Text2('STELLAR DRAGSHOT', {
size: 120,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
menuContainer.addChild(titleText);
// Play button
var playButton = new MenuButton('PLAY', 0x00ff00);
playButton.x = 1024;
playButton.y = 1200;
playButton.onPress = function () {
startGame();
};
menuContainer.addChild(playButton);
// Tutorial button
var tutorialButton = new MenuButton('TUTORIAL', 0x0088ff);
tutorialButton.x = 1024;
tutorialButton.y = 1400;
tutorialButton.onPress = function () {
currentMenuState = 'tutorial';
setupTutorial();
};
menuContainer.addChild(tutorialButton);
}
function setupTutorial() {
// Clear existing menu
if (menuContainer) {
menuContainer.destroy();
}
// Create tutorial panel
tutorialContainer = game.addChild(new TutorialPanel());
tutorialContainer.x = 1024;
tutorialContainer.y = 1366;
}
function startGame() {
currentMenuState = 'playing';
// Clear menu
if (menuContainer) {
menuContainer.destroy();
}
if (tutorialContainer) {
tutorialContainer.destroy();
}
// Reset game variables
gameSpeed = 1;
enemySpawnRate = 60;
powerUpSpawnRate = 900;
difficultyTimer = 0;
LK.setScore(0);
// Clear arrays
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
for (var i = playerBullets.length - 1; i >= 0; i--) {
playerBullets[i].destroy();
}
for (var i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].destroy();
}
enemies = [];
playerBullets = [];
powerUps = [];
// Initialize player
if (player) {
player.destroy();
}
player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
// Start background music
LK.playMusic('background');
}
// Create UI (initially hidden)
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var survivalTimeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
survivalTimeTxt.anchor.set(1, 0);
survivalTimeTxt.x = -20;
survivalTimeTxt.y = 20;
survivalTimeTxt.visible = false;
LK.gui.topRight.addChild(survivalTimeTxt);
// Start with main menu
setupMainMenu();
// Movement handling
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(50, Math.min(1998, x));
dragNode.y = Math.max(100, Math.min(2600, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Spawn functions
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = Math.random() * 1900 + 74;
enemy.y = -30;
enemy.speed = 2 + Math.random() * 3 + gameSpeed;
enemies.push(enemy);
game.addChild(enemy);
}
function spawnPowerUp() {
var powerup = new PowerUp();
powerup.x = Math.random() * 1900 + 74;
powerup.y = -30;
powerup.type = Math.random() < 0.5 ? 'rapidfire' : 'shield';
powerUps.push(powerup);
game.addChild(powerup);
}
// Main game update
game.update = function () {
// Only run game logic when playing
if (currentMenuState !== 'playing') {
return;
}
// Show UI during gameplay
scoreTxt.visible = true;
survivalTimeTxt.visible = true;
// Update survival time
var survivalTime = Math.floor(LK.ticks / 60);
survivalTimeTxt.setText('Time: ' + survivalTime + 's');
// Difficulty progression
difficultyTimer++;
if (difficultyTimer % 600 === 0) {
// Every 10 seconds
gameSpeed += 0.5;
enemySpawnRate = Math.max(20, enemySpawnRate - 3);
}
// Spawn enemies
if (LK.ticks % enemySpawnRate === 0) {
spawnEnemy();
}
// Spawn power-ups
if (LK.ticks % powerUpSpawnRate === 0) {
spawnPowerUp();
}
// Update and manage player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -25 && bullet.y < -25) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
LK.getSound('hit').play();
// Remove bullet and enemy
bullet.destroy();
playerBullets.splice(i, 1);
enemy.destroy();
enemies.splice(j, 1);
break;
}
}
bullet.lastY = bullet.y;
}
// Update and manage enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
// Remove enemies that go off screen
if (enemy.lastY <= 2762 && enemy.y > 2762) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check player-enemy collision
var currentIntersecting = enemy.intersects(player);
if (!enemy.lastIntersecting && currentIntersecting) {
// Check if player has shield
if (player.shieldTimer > 0) {
// Shield absorbs hit
player.shieldTimer = 0;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
enemy.destroy();
enemies.splice(i, 1);
continue;
} else {
// Game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
enemy.lastY = enemy.y;
enemy.lastIntersecting = currentIntersecting;
}
// Update and manage power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerup = powerUps[i];
if (powerup.lastY === undefined) powerup.lastY = powerup.y;
if (powerup.lastIntersecting === undefined) powerup.lastIntersecting = false;
// Remove power-ups that go off screen
if (powerup.lastY <= 2762 && powerup.y > 2762) {
powerup.destroy();
powerUps.splice(i, 1);
continue;
}
// Check player-powerup collision
var currentIntersecting = powerup.intersects(player);
if (!powerup.lastIntersecting && currentIntersecting) {
// Collect power-up
player.activatePowerUp(powerup.type);
LK.getSound('powerup').play();
LK.setScore(LK.getScore() + 25);
scoreTxt.setText(LK.getScore());
powerup.destroy();
powerUps.splice(i, 1);
continue;
}
powerup.lastY = powerup.y;
powerup.lastIntersecting = currentIntersecting;
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.health = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var MenuButton = Container.expand(function (text, color) {
var self = Container.call(this);
// Create button background
var buttonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Create button text
var buttonText = new Text2(text, {
size: 80,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Button press handling
self.down = function (x, y, obj) {
buttonBg.tint = 0xcccccc; // Darken on press
if (self.onPress) {
self.onPress();
}
};
self.up = function (x, y, obj) {
buttonBg.tint = 0xffffff; // Return to normal
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.fireRate = 10;
self.lastFireTick = 0;
self.rapidFireTimer = 0;
self.shieldTimer = 0;
self.update = function () {
// Auto-fire logic
var currentFireRate = self.rapidFireTimer > 0 ? 5 : self.fireRate;
if (LK.ticks - self.lastFireTick >= currentFireRate) {
self.fire();
self.lastFireTick = LK.ticks;
}
// Update power-up timers
if (self.rapidFireTimer > 0) {
self.rapidFireTimer--;
graphics.tint = 0xffaa00; // Orange tint for rapid fire
} else {
graphics.tint = 0xffffff; // Normal color
}
if (self.shieldTimer > 0) {
self.shieldTimer--;
graphics.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.3); // Pulsing shield effect
} else {
graphics.alpha = 1.0;
}
};
self.fire = function () {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
};
self.activatePowerUp = function (type) {
if (type === 'rapidfire') {
self.rapidFireTimer = 300; // 5 seconds at 60fps
} else if (type === 'shield') {
self.shieldTimer = 600; // 10 seconds at 60fps
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.type = 'rapidfire'; // rapidfire, shield
self.update = function () {
self.y += self.speed;
// Gentle floating animation
graphics.rotation += 0.02;
};
return self;
});
var TutorialPanel = Container.expand(function () {
var self = Container.call(this);
// Semi-transparent background
var bg = self.attachAsset('tutorialBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Tutorial text
var tutorialText = new Text2('HOW TO PLAY\n\n• Drag your ship to move\n• Avoid red enemies\n• Collect green power-ups\n• Survive as long as possible\n\nPOWER-UPS:\n• Orange: Rapid Fire (5s)\n• Pulsing: Shield (10s)', {
size: 60,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.y = -100;
self.addChild(tutorialText);
// Close button
var closeButton = new MenuButton('CLOSE', 0x666666);
closeButton.y = 400;
closeButton.onPress = function () {
currentMenuState = 'main';
setupMainMenu();
};
self.addChild(closeButton);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Menu state variables
var currentMenuState = 'main'; // 'main', 'tutorial', 'playing'
var menuContainer;
var tutorialContainer;
// Game variables
var player;
var enemies = [];
var playerBullets = [];
var powerUps = [];
var dragNode = null;
var gameSpeed = 1;
var enemySpawnRate = 60;
var powerUpSpawnRate = 900;
var difficultyTimer = 0;
// Menu setup functions
function setupMainMenu() {
// Clear existing menu
if (menuContainer) {
menuContainer.destroy();
}
if (tutorialContainer) {
tutorialContainer.destroy();
}
// Create main menu
menuContainer = game.addChild(new Container());
// Title
var titleText = new Text2('STELLAR DRAGSHOT', {
size: 120,
fill: 0xFFFF00
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
menuContainer.addChild(titleText);
// Play button
var playButton = new MenuButton('PLAY', 0x00ff00);
playButton.x = 1024;
playButton.y = 1200;
playButton.onPress = function () {
startGame();
};
menuContainer.addChild(playButton);
// Tutorial button
var tutorialButton = new MenuButton('TUTORIAL', 0x0088ff);
tutorialButton.x = 1024;
tutorialButton.y = 1400;
tutorialButton.onPress = function () {
currentMenuState = 'tutorial';
setupTutorial();
};
menuContainer.addChild(tutorialButton);
}
function setupTutorial() {
// Clear existing menu
if (menuContainer) {
menuContainer.destroy();
}
// Create tutorial panel
tutorialContainer = game.addChild(new TutorialPanel());
tutorialContainer.x = 1024;
tutorialContainer.y = 1366;
}
function startGame() {
currentMenuState = 'playing';
// Clear menu
if (menuContainer) {
menuContainer.destroy();
}
if (tutorialContainer) {
tutorialContainer.destroy();
}
// Reset game variables
gameSpeed = 1;
enemySpawnRate = 60;
powerUpSpawnRate = 900;
difficultyTimer = 0;
LK.setScore(0);
// Clear arrays
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
for (var i = playerBullets.length - 1; i >= 0; i--) {
playerBullets[i].destroy();
}
for (var i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].destroy();
}
enemies = [];
playerBullets = [];
powerUps = [];
// Initialize player
if (player) {
player.destroy();
}
player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
// Start background music
LK.playMusic('background');
}
// Create UI (initially hidden)
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
var survivalTimeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
survivalTimeTxt.anchor.set(1, 0);
survivalTimeTxt.x = -20;
survivalTimeTxt.y = 20;
survivalTimeTxt.visible = false;
LK.gui.topRight.addChild(survivalTimeTxt);
// Start with main menu
setupMainMenu();
// Movement handling
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(50, Math.min(1998, x));
dragNode.y = Math.max(100, Math.min(2600, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Spawn functions
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = Math.random() * 1900 + 74;
enemy.y = -30;
enemy.speed = 2 + Math.random() * 3 + gameSpeed;
enemies.push(enemy);
game.addChild(enemy);
}
function spawnPowerUp() {
var powerup = new PowerUp();
powerup.x = Math.random() * 1900 + 74;
powerup.y = -30;
powerup.type = Math.random() < 0.5 ? 'rapidfire' : 'shield';
powerUps.push(powerup);
game.addChild(powerup);
}
// Main game update
game.update = function () {
// Only run game logic when playing
if (currentMenuState !== 'playing') {
return;
}
// Show UI during gameplay
scoreTxt.visible = true;
survivalTimeTxt.visible = true;
// Update survival time
var survivalTime = Math.floor(LK.ticks / 60);
survivalTimeTxt.setText('Time: ' + survivalTime + 's');
// Difficulty progression
difficultyTimer++;
if (difficultyTimer % 600 === 0) {
// Every 10 seconds
gameSpeed += 0.5;
enemySpawnRate = Math.max(20, enemySpawnRate - 3);
}
// Spawn enemies
if (LK.ticks % enemySpawnRate === 0) {
spawnEnemy();
}
// Spawn power-ups
if (LK.ticks % powerUpSpawnRate === 0) {
spawnPowerUp();
}
// Update and manage player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -25 && bullet.y < -25) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Hit enemy
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
LK.getSound('hit').play();
// Remove bullet and enemy
bullet.destroy();
playerBullets.splice(i, 1);
enemy.destroy();
enemies.splice(j, 1);
break;
}
}
bullet.lastY = bullet.y;
}
// Update and manage enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
if (enemy.lastIntersecting === undefined) enemy.lastIntersecting = false;
// Remove enemies that go off screen
if (enemy.lastY <= 2762 && enemy.y > 2762) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check player-enemy collision
var currentIntersecting = enemy.intersects(player);
if (!enemy.lastIntersecting && currentIntersecting) {
// Check if player has shield
if (player.shieldTimer > 0) {
// Shield absorbs hit
player.shieldTimer = 0;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
enemy.destroy();
enemies.splice(i, 1);
continue;
} else {
// Game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
enemy.lastY = enemy.y;
enemy.lastIntersecting = currentIntersecting;
}
// Update and manage power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerup = powerUps[i];
if (powerup.lastY === undefined) powerup.lastY = powerup.y;
if (powerup.lastIntersecting === undefined) powerup.lastIntersecting = false;
// Remove power-ups that go off screen
if (powerup.lastY <= 2762 && powerup.y > 2762) {
powerup.destroy();
powerUps.splice(i, 1);
continue;
}
// Check player-powerup collision
var currentIntersecting = powerup.intersects(player);
if (!powerup.lastIntersecting && currentIntersecting) {
// Collect power-up
player.activatePowerUp(powerup.type);
LK.getSound('powerup').play();
LK.setScore(LK.getScore() + 25);
scoreTxt.setText(LK.getScore());
powerup.destroy();
powerUps.splice(i, 1);
continue;
}
powerup.lastY = powerup.y;
powerup.lastIntersecting = currentIntersecting;
}
};