User prompt
add view leaderboard a leaderboard and name creation ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
different warriors with different stats and different ship types neither of those have a change for what anything looks like there is a warrior selection battle and ship type selection menu ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
gun type selection menu back button
User prompt
tutorial gun types not seen but effects speed and damage and finally enemies can have varied health numbers and guns ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var clickPos = self.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 182
User prompt
levels, home screen , and story mode ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Space Defender
Initial prompt
shooting game
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
unlockedLevels: 1,
gameMode: "story",
storyProgress: 0
});
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1;
self.hp = 10;
self.shootTimer = 0;
self.shootInterval = 30;
self.moveDirection = 1;
self.update = function () {
self.y += self.speed;
self.x += self.moveDirection * 2;
if (self.x <= 100 || self.x >= 1948) {
self.moveDirection *= -1;
}
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 60;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
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.hp = 1;
self.shootTimer = 0;
self.shootInterval = 120;
self.update = function () {
self.y += self.speed;
self.shootTimer++;
if (self.shootTimer >= self.shootInterval && Math.random() < 0.01) {
self.shootTimer = 0;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 30;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var LevelSelectScreen = Container.expand(function () {
var self = Container.call(this);
var titleText = new Text2('SELECT LEVEL', {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
self.addChild(titleText);
var levelButtons = [];
for (var i = 1; i <= 10; i++) {
var button = new Text2(i.toString(), {
size: 60,
fill: i <= storage.unlockedLevels ? 0xFFFFFF : 0x666666
});
button.anchor.set(0.5, 0.5);
button.x = 400 + (i - 1) % 5 * 300;
button.y = 600 + Math.floor((i - 1) / 5) * 200;
button.levelNumber = i;
self.addChild(button);
levelButtons.push(button);
}
var backButton = new Text2('BACK', {
size: 80,
fill: 0xFF0000
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 1024;
backButton.y = 1400;
self.addChild(backButton);
self.down = function (x, y, obj) {
var clickPos = obj.parent ? self.toLocal(obj.parent.toGlobal(obj.position)) : {
x: x,
y: y
};
if (clickPos.y > 1350 && clickPos.y < 1450) {
// Back button clicked
showMenu();
return;
}
// Check level buttons
for (var i = 0; i < levelButtons.length; i++) {
var btn = levelButtons[i];
if (Math.abs(clickPos.x - btn.x) < 100 && Math.abs(clickPos.y - btn.y) < 50) {
if (btn.levelNumber <= storage.unlockedLevels) {
storage.gameMode = 'level';
storage.currentLevel = btn.levelNumber;
startGame();
}
break;
}
}
};
return self;
});
var MenuScreen = Container.expand(function () {
var self = Container.call(this);
var titleText = new Text2('SPACE DEFENDER', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
var storyButton = new Text2('STORY MODE', {
size: 80,
fill: 0x00FF00
});
storyButton.anchor.set(0.5, 0.5);
storyButton.x = 1024;
storyButton.y = 800;
self.addChild(storyButton);
var levelsButton = new Text2('LEVEL SELECT', {
size: 80,
fill: 0x0080FF
});
levelsButton.anchor.set(0.5, 0.5);
levelsButton.x = 1024;
levelsButton.y = 1000;
self.addChild(levelsButton);
var endlessButton = new Text2('ENDLESS MODE', {
size: 80,
fill: 0xFF8000
});
endlessButton.anchor.set(0.5, 0.5);
endlessButton.x = 1024;
endlessButton.y = 1200;
self.addChild(endlessButton);
self.down = function (x, y, obj) {
var clickPos = obj.parent ? self.toLocal(obj.parent.toGlobal(obj.position)) : {
x: x,
y: y
};
if (clickPos.y > 750 && clickPos.y < 850) {
// Story mode clicked
storage.gameMode = 'story';
storage.currentLevel = storage.storyProgress + 1;
startGame();
} else if (clickPos.y > 950 && clickPos.y < 1050) {
// Level select clicked
showLevelSelect();
} else if (clickPos.y > 1150 && clickPos.y < 1250) {
// Endless mode clicked
storage.gameMode = 'endless';
storage.currentLevel = 1;
startGame();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 3;
self.shootTimer = 0;
self.shootInterval = 15;
self.powerUpTimer = 0;
self.rapidFire = false;
self.update = function () {
self.shootTimer++;
var currentShootInterval = self.rapidFire ? 5 : self.shootInterval;
if (self.shootTimer >= currentShootInterval) {
self.shootTimer = 0;
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
if (self.rapidFire) {
self.powerUpTimer--;
if (self.powerUpTimer <= 0) {
self.rapidFire = false;
}
}
};
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 = 4;
self.type = 'rapidFire'; // rapidFire, shield
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
var StoryPanel = Container.expand(function (levelNumber) {
var self = Container.call(this);
var stories = ["The alien invasion has begun!\nDefend Earth's last outpost.", "Enemy forces are multiplying.\nPrepare for heavier resistance.", "Advanced alien fighters detected.\nUpgrade your weapons!", "The mothership approaches.\nThis is our final stand!", "Victory! Earth is safe.\nBut stay vigilant, commander."];
var storyText = new Text2(stories[Math.min(levelNumber - 1, stories.length - 1)] || "Mission briefing loading...", {
size: 70,
fill: 0xFFFFFF
});
storyText.anchor.set(0.5, 0.5);
storyText.x = 1024;
storyText.y = 800;
self.addChild(storyText);
var continueText = new Text2('TAP TO CONTINUE', {
size: 60,
fill: 0x00FF00
});
continueText.anchor.set(0.5, 0.5);
continueText.x = 1024;
continueText.y = 1200;
self.addChild(continueText);
self.down = function (x, y, obj) {
self.destroy();
initializeGameplay();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Game state variables
var gameState = 'menu'; // menu, levelSelect, story, playing
var menuScreen = null;
var levelSelectScreen = null;
var storyPanel = null;
// Game variables
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var powerUps = [];
var bosses = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 60;
var powerUpSpawnTimer = 0;
var bossSpawnScore = 500;
var nextBossScore = bossSpawnScore;
var dragNode = null;
var waveLevel = 1;
var levelTargetScore = 0;
var levelCompleted = false;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
var hpTxt = new Text2('HP: 3', {
size: 60,
fill: 0xFF0000
});
hpTxt.anchor.set(1, 0);
hpTxt.x = -50;
hpTxt.y = 50;
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0x00FF00
});
levelTxt.anchor.set(0.5, 0);
levelTxt.y = 50;
function showMenu() {
gameState = 'menu';
clearGame();
menuScreen = new MenuScreen();
game.addChild(menuScreen);
}
function showLevelSelect() {
gameState = 'levelSelect';
if (menuScreen) {
menuScreen.destroy();
menuScreen = null;
}
levelSelectScreen = new LevelSelectScreen();
game.addChild(levelSelectScreen);
}
function startGame() {
gameState = storage.gameMode === 'story' ? 'story' : 'playing';
if (levelSelectScreen) {
levelSelectScreen.destroy();
levelSelectScreen = null;
}
if (menuScreen) {
menuScreen.destroy();
menuScreen = null;
}
if (storage.gameMode === 'story' && storage.currentLevel <= 5) {
storyPanel = new StoryPanel(storage.currentLevel);
game.addChild(storyPanel);
} else {
initializeGameplay();
}
}
function initializeGameplay() {
gameState = 'playing';
// Clear any story panel
if (storyPanel) {
storyPanel.destroy();
storyPanel = null;
}
// Reset game variables
clearGame();
LK.setScore(0);
// Set level parameters
setupLevel(storage.currentLevel);
// Initialize player
player = new Player();
player.x = 1024;
player.y = 2400;
game.addChild(player);
// Add UI elements
LK.gui.topLeft.addChild(scoreTxt);
LK.gui.topRight.addChild(hpTxt);
LK.gui.top.addChild(levelTxt);
levelTxt.setText('Level: ' + storage.currentLevel);
}
function setupLevel(level) {
// Set level-specific parameters
if (storage.gameMode === 'endless') {
levelTargetScore = 0; // No target for endless mode
enemySpawnInterval = 60;
} else {
levelTargetScore = level * 200; // Score needed to complete level
enemySpawnInterval = Math.max(20, 80 - level * 5);
bossSpawnScore = levelTargetScore * 0.8;
nextBossScore = bossSpawnScore;
}
levelCompleted = false;
}
function clearGame() {
// Clear all game objects
for (var i = 0; i < enemies.length; i++) {
enemies[i].destroy();
}
for (var i = 0; i < enemyBullets.length; i++) {
enemyBullets[i].destroy();
}
for (var i = 0; i < playerBullets.length; i++) {
playerBullets[i].destroy();
}
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].destroy();
}
for (var i = 0; i < bosses.length; i++) {
bosses[i].destroy();
}
if (player) {
player.destroy();
player = null;
}
// Clear arrays
enemies = [];
enemyBullets = [];
playerBullets = [];
powerUps = [];
bosses = [];
// Remove UI elements
if (scoreTxt.parent) scoreTxt.parent.removeChild(scoreTxt);
if (hpTxt.parent) hpTxt.parent.removeChild(hpTxt);
if (levelTxt.parent) levelTxt.parent.removeChild(levelTxt);
}
function checkLevelComplete() {
if (storage.gameMode !== 'endless' && !levelCompleted && LK.getScore() >= levelTargetScore) {
levelCompleted = true;
// Update progress
if (storage.gameMode === 'story') {
storage.storyProgress = Math.max(storage.storyProgress, storage.currentLevel);
}
storage.unlockedLevels = Math.max(storage.unlockedLevels, storage.currentLevel + 1);
// Show level complete message
var completeText = new Text2('LEVEL COMPLETE!', {
size: 100,
fill: 0x00FF00
});
completeText.anchor.set(0.5, 0.5);
completeText.x = 1024;
completeText.y = 1366;
game.addChild(completeText);
// Auto-advance after 2 seconds
LK.setTimeout(function () {
if (storage.gameMode === 'story' && storage.currentLevel < 5) {
storage.currentLevel++;
startGame();
} else {
showMenu();
}
}, 2000);
}
}
// Initialize menu on start
showMenu();
// Event handlers
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = Math.max(40, Math.min(2008, x));
dragNode.y = Math.max(100, Math.min(2632, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
if (gameState !== 'playing') return;
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
hpTxt.setText('HP: ' + player.hp);
// Check level completion
checkLevelComplete();
// Spawn enemies
enemySpawnTimer++;
var currentSpawnInterval = Math.max(20, enemySpawnInterval - Math.floor(LK.getScore() / 100) * 5);
if (enemySpawnTimer >= currentSpawnInterval) {
enemySpawnTimer = 0;
var enemy = new Enemy();
enemy.x = Math.random() * 1800 + 124;
enemy.y = -50;
enemy.speed = 2 + Math.floor(LK.getScore() / 200) + (storage.currentLevel - 1);
enemies.push(enemy);
game.addChild(enemy);
}
// Spawn power-ups occasionally
powerUpSpawnTimer++;
if (powerUpSpawnTimer >= 900 && Math.random() < 0.02) {
powerUpSpawnTimer = 0;
var powerUp = new PowerUp();
powerUp.x = Math.random() * 1800 + 124;
powerUp.y = -50;
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Spawn boss at score milestones
if (LK.getScore() >= nextBossScore && bosses.length === 0) {
var boss = new Boss();
boss.x = 1024;
boss.y = -100;
bosses.push(boss);
game.addChild(boss);
nextBossScore += bossSpawnScore;
}
// Handle 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 >= -50 && bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j])) {
enemies[j].hp--;
if (enemies[j].hp <= 0) {
LK.setScore(LK.getScore() + 10);
LK.getSound('enemyHit').play();
enemies[j].destroy();
enemies.splice(j, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (hitEnemy) continue;
// Check collision with bosses
for (var k = bosses.length - 1; k >= 0; k--) {
if (bullet.intersects(bosses[k])) {
bosses[k].hp--;
if (bosses[k].hp <= 0) {
LK.setScore(LK.getScore() + 100);
LK.getSound('enemyHit').play();
bosses[k].destroy();
bosses.splice(k, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
bullet.lastY = bullet.y;
}
// Handle enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2782 && bullet.y > 2782) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
player.hp--;
LK.getSound('playerHit').play();
LK.effects.flashObject(player, 0xff0000, 500);
if (player.hp <= 0) {
LK.setTimeout(function () {
showMenu();
}, 2000);
LK.showGameOver();
return;
}
bullet.destroy();
enemyBullets.splice(i, 1);
}
bullet.lastY = bullet.y;
}
// Handle enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that go off screen
if (enemy.lastY <= 2782 && enemy.y > 2782) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
player.hp--;
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 1000);
if (player.hp <= 0) {
LK.setTimeout(function () {
showMenu();
}, 2000);
LK.showGameOver();
return;
}
enemy.destroy();
enemies.splice(i, 1);
}
enemy.lastY = enemy.y;
}
// Handle bosses
for (var i = bosses.length - 1; i >= 0; i--) {
var boss = bosses[i];
if (boss.lastY === undefined) boss.lastY = boss.y;
// Remove bosses that go off screen
if (boss.lastY <= 2782 && boss.y > 2782) {
boss.destroy();
bosses.splice(i, 1);
continue;
}
// Check collision with player
if (boss.intersects(player)) {
player.hp--;
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 1000);
if (player.hp <= 0) {
LK.setTimeout(function () {
showMenu();
}, 2000);
LK.showGameOver();
return;
}
}
boss.lastY = boss.y;
}
// Handle power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (powerUp.lastY === undefined) powerUp.lastY = powerUp.y;
// Remove power-ups that go off screen
if (powerUp.lastY <= 2782 && powerUp.y > 2782) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with player
if (powerUp.intersects(player)) {
LK.getSound('powerUpSound').play();
if (powerUp.type === 'rapidFire') {
player.rapidFire = true;
player.powerUpTimer = 600; // 10 seconds at 60fps
}
powerUp.destroy();
powerUps.splice(i, 1);
}
powerUp.lastY = powerUp.y;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -108,9 +108,12 @@
backButton.x = 1024;
backButton.y = 1400;
self.addChild(backButton);
self.down = function (x, y, obj) {
- var clickPos = self.toLocal(obj.parent.toGlobal(obj.position));
+ var clickPos = obj.parent ? self.toLocal(obj.parent.toGlobal(obj.position)) : {
+ x: x,
+ y: y
+ };
if (clickPos.y > 1350 && clickPos.y < 1450) {
// Back button clicked
showMenu();
return;
@@ -164,9 +167,12 @@
endlessButton.x = 1024;
endlessButton.y = 1200;
self.addChild(endlessButton);
self.down = function (x, y, obj) {
- var clickPos = self.toLocal(obj.parent.toGlobal(obj.position));
+ var clickPos = obj.parent ? self.toLocal(obj.parent.toGlobal(obj.position)) : {
+ x: x,
+ y: y
+ };
if (clickPos.y > 750 && clickPos.y < 850) {
// Story mode clicked
storage.gameMode = 'story';
storage.currentLevel = storage.storyProgress + 1;