User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(projectile);' Line Number: 289
User prompt
add more cubes like gold diamond etc
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 219
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 219
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 217
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 217
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 217
User prompt
There is a bug in the boss fight, it says error addchild etc. fix that bug
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 216
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 217
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'game.addChild(self.healthBarContainer);' Line Number: 217
User prompt
change the bosses face and fix the health bar and have different phases of the boss, have 3 different phases and make the boss's health bar at the top so that it is visible when the boss comes
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'y')' in or related to this line: 'var angle = Math.atan2(player.y - self.y, player.x - self.x);' Line Number: 142
User prompt
Make the boss a little better, let his type be different and let us have a health bar and the boss's health bar is crooked, fix that too and in the boss fight, all the green and red hearts will be scared and run away and then watch us ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'x')' in or related to this line: 'var dx = target.x - self.x;' Line Number: 521
User prompt
When you reach the final 2500 points, there will be a boss fight and when you win, all the cups will be saved and there will be enemies and then suddenly an alien will appear on the screen and it will say to be continued
User prompt
Let the game be finalized when you reach 5500 points instead of 50 levels.
User prompt
Let's develop the game more and level up etc., let's earn weapons etc. as we level up for every 100 points and let's have different cups to collect, for example 20 point or 30 point cups and let's see these as we level up
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'timerText.style.fill = 0x2ecc71;' Line Number: 392
User prompt
Edit the game assests, make the main character's face visible and how many points we have at the moment, make the obstacles have faces and make the graphics better, make the background colorful ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Cube Collector
Initial prompt
Here’s the idea in English: Game Concept: "Collect the Cubes" Gameplay: The player controls a square (character) on the screen and the goal is to collect randomly placed small cubes. The cubes will appear at different locations each time, and the player gains points by collecting them. Mechanics: The player moves the square up, down, left, or right using arrow keys or touch controls. The cubes will randomly appear on the screen, and the player needs to collect them. Over time, the speed of the cubes increases, or more obstacles might appear on the screen, challenging the player to stay alert. Each collected cube earns the player a point. The game can either last for a set amount of time or end once the player reaches a specific score. Extra Features: Obstacles: Moving obstacles on the screen could limit the player's movement area or cause the game to end if hit. Time Limit: The player earns more points for collecting cubes within a certain time frame. Scoreboard: A high score table could be added to track the best scores. It’s a simple game, but with increasing difficulty, it can keep players engaged and challenged.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
self.bossType = Math.random() > 0.5 ? 'alien' : 'robot';
self.phase = 1; // Track boss phase (1-3)
// Initialize healthBarContainer before accessing it
self.healthBarContainer = new Container();
// Create boss body
var bossGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3,
tint: self.bossType === 'alien' ? 0x800080 : 0x444444 // Purple for alien, dark gray for robot
});
// Create face features based on boss type
if (self.bossType === 'alien') {
// Alien face features - large oval eyes, small mouth
var leftEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25,
scaleY: 0.35,
tint: 0x00FFFF,
// Cyan glowing eyes
x: -70,
y: -40
});
var rightEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.25,
scaleY: 0.35,
tint: 0x00FFFF,
// Cyan glowing eyes
x: 70,
y: -40
});
var mouth = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.1,
tint: 0x000000,
// Small mouth
x: 0,
y: 40
});
// Add antenna
var antenna1 = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.08,
scaleY: 0.6,
tint: 0x00FF00,
// Green antenna
x: -50,
y: -120
});
var antenna2 = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.08,
scaleY: 0.6,
tint: 0x00FF00,
// Green antenna
x: 50,
y: -120
});
// Add some unique alien features
var thirdEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.15,
tint: 0xFF00FF,
x: 0,
y: -70
});
self.addChild(thirdEye);
} else {
// Robot face features - square eyes, rectangular mouth, mechanical look
var leftEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xFF0000,
// Red eyes
x: -70,
y: -30
});
var rightEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xFF0000,
// Red eyes
x: 70,
y: -30
});
var mouth = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.1,
tint: 0x666666,
// Metallic mouth
x: 0,
y: 50
});
// Add mechanical parts instead of antenna
var antenna1 = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.4,
tint: 0x999999,
// Metal parts
x: -90,
y: -80
});
var antenna2 = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.4,
tint: 0x999999,
// Metal parts
x: 90,
y: -80
});
// Add some robot-specific features
var centerPlate = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.15,
tint: 0x333333,
x: 0,
y: 0
});
self.addChild(centerPlate);
}
// Add face features to boss
self.addChild(leftEye);
self.addChild(rightEye);
self.addChild(mouth);
self.addChild(antenna1);
self.addChild(antenna2);
// Configure the health bar container which was initialized earlier
self.healthBarContainer.x = 2048 / 2; // Center horizontally
self.healthBarContainer.y = 150; // Fixed position at top
// Boss health indicator background
var healthBarBg = LK.getAsset('timerBarBackground', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.5,
tint: 0x333333
});
self.healthBarContainer.addChild(healthBarBg);
// Boss health indicator
var healthBar = LK.getAsset('timerBar', {
anchorX: 0,
anchorY: 0.5,
scaleX: 1,
scaleY: 0.5,
tint: 0xFF0000,
// Red health bar
x: -healthBarBg.width / 2,
y: 0,
rotation: 0 // Ensure the bar is straight
});
self.healthBarContainer.addChild(healthBar);
// Add boss name/type label
var bossLabel = new Text2(self.bossType.toUpperCase() + " BOSS", {
size: 40,
fill: 0xFFFFFF
});
bossLabel.anchor.set(0.5, 0.5);
bossLabel.y = -healthBarBg.height;
self.healthBarContainer.addChild(bossLabel);
// Store references to health bar elements
self.healthBar = healthBar;
self.healthBarBg = healthBarBg;
self.maxHealth = 100;
self.health = self.maxHealth;
self.speedX = 5;
self.speedY = 3;
self.attackCooldown = 0;
self.shootInterval = 60; // Frames between attacks
self.update = function (player, weaponEffects, game) {
// Update health bar position with game
if (self.healthBarContainer.parent !== game) {
game.addChild(self.healthBarContainer);
}
// Movement pattern based on phase
self.x += self.speedX;
self.y += self.speedY;
// Bounce off screen edges
if (self.x < bossGraphics.width / 2 || self.x > 2048 - bossGraphics.width / 2) {
self.speedX *= -1;
}
if (self.y < bossGraphics.height / 2 || self.y > 2732 - bossGraphics.height / 2) {
self.speedY *= -1;
}
// Update health bar
self.healthBar.scale.x = self.health / self.maxHealth;
// Check for phase transitions
var healthPercentage = self.health / self.maxHealth;
if (healthPercentage <= 0.66 && self.phase === 1) {
self.phase = 2;
self.transitionToPhase2();
} else if (healthPercentage <= 0.33 && self.phase === 2) {
self.phase = 3;
self.transitionToPhase3();
}
// Different attack patterns based on phase
if (self.attackCooldown <= 0) {
// Create enemy projectile(s)
if (self.phase === 1) {
// Phase 1: Single projectile
fireProjectile(0);
} else if (self.phase === 2) {
// Phase 2: Two projectiles at slight angles
fireProjectile(-0.2);
fireProjectile(0.2);
} else {
// Phase 3: Three projectiles in spread pattern
fireProjectile(-0.4);
fireProjectile(0);
fireProjectile(0.4);
}
// Reset cooldown - faster in later phases
self.attackCooldown = self.shootInterval;
// Expression change when attacking
mouth.scaleY = 0.3;
// Reset mouth after attack
tween(mouth, {
scaleY: self.bossType === 'alien' ? 0.1 : 0.2
}, {
duration: 300,
easing: tween.easeOut
});
} else {
self.attackCooldown--;
}
// Make boss more aggressive as health decreases
self.shootInterval = Math.max(20, Math.floor(60 * (self.health / self.maxHealth)));
// Helper function to fire a projectile
function fireProjectile(angleOffset) {
var projectile = new WeaponEffect();
projectile.setEffectType('boss', 1 + self.phase); // More damage in later phases
// Position at boss and aim at player
projectile.x = self.x;
projectile.y = self.y;
// Check if player exists before trying to calculate angle
if (player) {
var angle = Math.atan2(player.y - self.y, player.x - self.x);
projectile.rotation = angle + angleOffset;
} else {
// Default direction if player is null
projectile.rotation = Math.PI / 2 + angleOffset; // Down
}
game.addChild(projectile);
weaponEffects.push(projectile);
}
};
self.transitionToPhase2 = function () {
// Visual effect for phase transition
LK.effects.flashScreen(0xFF8800, 500);
// Increase boss speed
self.speedX *= 1.3;
self.speedY *= 1.3;
// Visual changes based on boss type
if (self.bossType === 'alien') {
// Alien gets more aggressive
tween(bossGraphics, {
tint: 0xAA00AA // Deeper purple
}, {
duration: 500,
easing: tween.easeOut
});
// Eyes glow more intensely
tween(leftEye, {
tint: 0x00FFAA,
scaleX: 0.3,
scaleY: 0.4
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightEye, {
tint: 0x00FFAA,
scaleX: 0.3,
scaleY: 0.4
}, {
duration: 500,
easing: tween.easeOut
});
} else {
// Robot gets more mechanical
tween(bossGraphics, {
tint: 0x666666 // Darker metal
}, {
duration: 500,
easing: tween.easeOut
});
// Eyes glow more intensely
tween(leftEye, {
tint: 0xFF6600,
scaleX: 0.25,
scaleY: 0.25
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightEye, {
tint: 0xFF6600,
scaleX: 0.25,
scaleY: 0.25
}, {
duration: 500,
easing: tween.easeOut
});
}
};
self.transitionToPhase3 = function () {
// Visual effect for phase transition
LK.effects.flashScreen(0xFF0000, 500);
// Major speed increase for final phase
self.speedX *= 1.5;
self.speedY *= 1.5;
// Visual changes based on boss type
if (self.bossType === 'alien') {
// Alien becomes enraged
tween(bossGraphics, {
tint: 0xFF00FF // Bright magenta
}, {
duration: 500,
easing: tween.easeOut
});
// Eyes glow intensely
tween(leftEye, {
tint: 0xFFFF00,
scaleX: 0.35,
scaleY: 0.45
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightEye, {
tint: 0xFFFF00,
scaleX: 0.35,
scaleY: 0.45
}, {
duration: 500,
easing: tween.easeOut
});
// Mouth becomes more aggressive
tween(mouth, {
scaleX: 0.6,
scaleY: 0.2
}, {
duration: 500,
easing: tween.easeOut
});
} else {
// Robot enters combat mode
tween(bossGraphics, {
tint: 0x990000 // Dark red
}, {
duration: 500,
easing: tween.easeOut
});
// Eyes glow intensely
tween(leftEye, {
tint: 0xFFFF00,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 500,
easing: tween.easeOut
});
tween(rightEye, {
tint: 0xFFFF00,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 500,
easing: tween.easeOut
});
// Mouth becomes more aggressive
tween(mouth, {
scaleX: 0.8,
scaleY: 0.15
}, {
duration: 500,
easing: tween.easeOut
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
// Update health bar immediately
self.healthBar.scale.x = self.health / self.maxHealth;
// Shake boss when taking damage
var originalX = self.x;
var originalY = self.y;
tween(self, {
x: originalX + (Math.random() * 30 - 15),
y: originalY + (Math.random() * 30 - 15)
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
x: originalX,
y: originalY
}, {
duration: 50,
easing: tween.easeIn
});
}
});
// Flash red when taking damage
var currentTint = bossGraphics.tint;
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(bossGraphics, {
tint: currentTint
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Return true if boss is defeated
return self.health <= 0;
};
return self;
});
var CollectableCube = Container.expand(function () {
var self = Container.call(this);
var cubeGraphics = self.attachAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x00ffff // Cyan color for the cube
});
// Create face features
var leftEye = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0x000000,
// Black eyes
x: -15,
y: -10
});
var rightEye = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0x000000,
// Black eyes
x: 15,
y: -10
});
var mouth = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.15,
tint: 0x000000,
// Black mouth
x: 0,
y: 15
});
// Add the face features to the cube
self.addChild(leftEye);
self.addChild(rightEye);
self.addChild(mouth);
// Add point value text
var pointsTxt = new Text2('+10', {
size: 30,
fill: 0xFFFFFF
});
pointsTxt.anchor.set(0.5, 0.5);
pointsTxt.y = -40;
self.addChild(pointsTxt);
self.value = 10;
self.cubeType = 'normal';
self.spawnTime = 0;
self.pulseAnimation = function () {
tween(cubeGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cubeGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
};
self.randomPosition = function (minX, maxX, minY, maxY) {
self.x = minX + Math.random() * (maxX - minX);
self.y = minY + Math.random() * (maxY - minY);
self.spawnTime = Date.now();
self.pulseAnimation();
};
self.setCubeType = function (type) {
self.cubeType = type;
switch (type) {
case 'silver':
self.value = 20;
pointsTxt.setText('+20');
cubeGraphics.tint = 0xC0C0C0; // Silver
break;
case 'gold':
self.value = 30;
pointsTxt.setText('+30');
cubeGraphics.tint = 0xFFD700; // Gold
break;
case 'normal':
default:
self.value = 10;
pointsTxt.setText('+10');
cubeGraphics.tint = 0x00FFFF; // Cyan
break;
}
// Update the facial expression based on cube type
if (type === 'gold') {
// Happy expression for gold cubes
mouth.scaleY = 0.2;
mouth.y = 10;
} else if (type === 'silver') {
// Neutral expression for silver cubes
mouth.scaleY = 0.15;
mouth.y = 15;
} else {
// Normal expression
mouth.scaleY = 0.15;
mouth.y = 15;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff5555 // Bright red for obstacles
});
// Create angry face for obstacle
var leftEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.25,
tint: 0xFFFFFF,
// White eyes
x: -40,
y: -5
});
var rightEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.25,
tint: 0xFFFFFF,
// White eyes
x: 40,
y: -5
});
var leftPupil = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.06,
scaleY: 0.12,
tint: 0x000000,
// Black pupils
x: -40,
y: -2
});
var rightPupil = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.06,
scaleY: 0.12,
tint: 0x000000,
// Black pupils
x: 40,
y: -2
});
var mouth = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.12,
tint: 0x000000,
// Black mouth
x: 0,
y: 10
});
// Add face features to obstacle
self.addChild(leftEye);
self.addChild(rightEye);
self.addChild(leftPupil);
self.addChild(rightPupil);
self.addChild(mouth);
self.speedX = 0;
self.speedY = 0;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Bounce off screen edges
if (self.x < obstacleGraphics.width / 2 || self.x > 2048 - obstacleGraphics.width / 2) {
self.speedX *= -1;
}
if (self.y < obstacleGraphics.height / 2 || self.y > 2732 - obstacleGraphics.height / 2) {
self.speedY *= -1;
}
// Rotate obstacle slightly based on direction for visual effect
var targetRotation = Math.atan2(self.speedY, self.speedX) * 0.2;
self.rotation += (targetRotation - self.rotation) * 0.1;
};
self.setRandomSpeed = function (maxSpeed) {
// Ensure obstacle always moves by setting minimum speed
var minSpeed = maxSpeed * 0.3;
// Generate random speeds between min and max
self.speedX = (Math.random() > 0.5 ? 1 : -1) * (minSpeed + Math.random() * (maxSpeed - minSpeed));
self.speedY = (Math.random() > 0.5 ? 1 : -1) * (minSpeed + Math.random() * (maxSpeed - minSpeed));
// Give each obstacle a unique color variation
obstacleGraphics.tint = 0xff0000 + Math.floor(Math.random() * 0x5555);
};
self.randomPosition = function (minX, maxX, minY, maxY) {
self.x = minX + Math.random() * (maxX - minX);
self.y = minY + Math.random() * (maxY - minY);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x3498db // Bright blue for player
});
// Create face for player
var leftEye = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xFFFFFF,
// White eyes
x: -20,
y: -15
});
var rightEye = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xFFFFFF,
// White eyes
x: 20,
y: -15
});
var leftPupil = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000,
// Black pupils
x: -20,
y: -15
});
var rightPupil = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000,
// Black pupils
x: 20,
y: -15
});
var mouth = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.2,
tint: 0x000000,
// Black mouth
x: 0,
y: 15
});
// Add score display on player
var scoreBubble = LK.getAsset('playerCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.5,
tint: 0xFFFFFF,
// White bubble
x: 0,
y: -60
});
// Add face features to player
self.addChild(leftEye);
self.addChild(rightEye);
self.addChild(leftPupil);
self.addChild(rightPupil);
self.addChild(mouth);
self.addChild(scoreBubble);
// Create player score display
var playerScoreTxt = new Text2('0', {
size: 32,
fill: 0x000000
});
playerScoreTxt.anchor.set(0.5, 0.5);
playerScoreTxt.y = -60;
self.addChild(playerScoreTxt);
// Add weapon display
var weaponHolder = new Container();
self.addChild(weaponHolder);
weaponHolder.y = 50;
// Current weapon
self.weapon = new Weapon();
self.weapon.setWeaponType('basic', 1);
weaponHolder.addChild(self.weapon);
// Level indicators
var levelIndicator = new Text2('Lv.1', {
size: 24,
fill: 0xFFFFFF
});
levelIndicator.anchor.set(0.5, 0.5);
levelIndicator.y = 25;
weaponHolder.addChild(levelIndicator);
self.updateScore = function (newScore) {
playerScoreTxt.setText(newScore);
};
self.updateWeapon = function (type, level) {
self.weapon.setWeaponType(type, level);
levelIndicator.setText('Lv.' + level);
// Flash weapon effect
tween(weaponHolder, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(weaponHolder, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
};
self.fireWeapon = function (targets, game, weaponEffects) {
if (self.weapon.canFire()) {
// Get weapon stats
var damage = self.weapon.fire();
var type = self.weapon.type;
// Create weapon effect
var effect = new WeaponEffect();
effect.setEffectType(type, damage);
// Position at player
effect.x = self.x;
effect.y = self.y;
// If we have targets, aim at the nearest one
var nearestTarget = null;
var minDistance = Number.MAX_VALUE;
for (var i = 0; i < targets.length; i++) {
var target = targets[i];
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < minDistance) {
minDistance = distance;
nearestTarget = target;
}
}
}
if (nearestTarget) {
var angle = Math.atan2(nearestTarget.y - self.y, nearestTarget.x - self.x);
effect.rotation = angle;
} else {
// If no targets, fire forward
effect.rotation = 0;
}
game.addChild(effect);
weaponEffects.push(effect);
// Flash the weapon
self.weapon.alpha = 0.7;
tween(self.weapon, {
alpha: 1
}, {
duration: 200,
easing: tween.easeOut
});
return true;
}
return false;
};
self.speed = 10;
self.targetX = 0;
self.targetY = 0;
self.moving = false;
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
self.moving = true;
// Animate eyes to look in move direction
var eyeAngle = Math.atan2(y - self.y, x - self.x);
var eyeOffsetX = Math.cos(eyeAngle) * 3;
var eyeOffsetY = Math.sin(eyeAngle) * 3;
tween(leftPupil, {
x: -20 + eyeOffsetX,
y: -15 + eyeOffsetY
}, {
duration: 200,
easing: tween.easeOut
});
tween(rightPupil, {
x: 20 + eyeOffsetX,
y: -15 + eyeOffsetY
}, {
duration: 200,
easing: tween.easeOut
});
};
self.update = function () {
if (self.moving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.moving = false;
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
}
}
// Update weapon cooldown
self.weapon.update();
};
return self;
});
var TimerBar = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('timerBarBackground', {
anchorX: 0,
anchorY: 0.5,
alpha: 0.7 // Semi-transparent background
});
var bar = self.attachAsset('timerBar', {
anchorX: 0,
anchorY: 0.5
});
// Add clock icon
var clockIcon = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
tint: 0xFFFFFF,
x: -50,
y: 0
});
self.addChild(clockIcon);
// Add timer text
var timerText = new Text2('30s', {
size: 40,
fill: 0xFFFFFF
});
timerText.anchor.set(0, 0.5);
timerText.x = background.width + 20;
timerText.y = 0;
self.addChild(timerText);
self.maxTime = 30000; // 30 seconds in milliseconds
self.timeRemaining = self.maxTime;
self.update = function (delta) {
self.timeRemaining -= delta;
if (self.timeRemaining < 0) {
self.timeRemaining = 0;
}
var percentage = self.timeRemaining / self.maxTime;
bar.scale.x = percentage;
// Update timer text
var secondsLeft = Math.ceil(self.timeRemaining / 1000);
timerText.setText(secondsLeft + 's');
// Change color as time runs out
if (percentage < 0.2) {
bar.tint = 0xe74c3c; // Red
clockIcon.tint = 0xe74c3c;
timerText.setText(secondsLeft + 's', {
fill: 0xe74c3c
});
// Pulse animation when low on time
if (Math.floor(self.timeRemaining / 200) % 2 === 0) {
clockIcon.scale.x = 0.9;
clockIcon.scale.y = 0.9;
} else {
clockIcon.scale.x = 0.8;
clockIcon.scale.y = 0.8;
}
} else if (percentage < 0.5) {
bar.tint = 0xf39c12; // Orange
clockIcon.tint = 0xf39c12;
timerText.setText(secondsLeft + 's', {
fill: 0xf39c12
});
} else {
bar.tint = 0x2ecc71; // Green
clockIcon.tint = 0x2ecc71;
timerText.setText(secondsLeft + 's', {
fill: 0x2ecc71
});
}
};
self.reset = function () {
self.timeRemaining = self.maxTime;
bar.scale.x = 1;
bar.tint = 0x2ecc71;
clockIcon.tint = 0x2ecc71;
timerText.setText(Math.ceil(self.timeRemaining / 1000) + 's', {
fill: 0x2ecc71
});
};
return self;
});
var Weapon = Container.expand(function () {
var self = Container.call(this);
var weaponGraphics = self.attachAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.15,
tint: 0xFFFFFF
});
self.type = 'basic';
self.level = 1;
self.attackSpeed = 1;
self.damage = 1;
self.cooldown = 0;
self.setWeaponType = function (type, level) {
self.type = type;
self.level = level || 1;
switch (type) {
case 'laser':
weaponGraphics.tint = 0xFF0000; // Red laser
self.attackSpeed = 1.5;
self.damage = 1;
break;
case 'plasma':
weaponGraphics.tint = 0x00FF00; // Green plasma
self.attackSpeed = 1;
self.damage = 2;
break;
case 'wave':
weaponGraphics.tint = 0x0000FF; // Blue wave
self.attackSpeed = 0.7;
self.damage = 3;
break;
case 'basic':
default:
weaponGraphics.tint = 0xFFFFFF; // White basic
self.attackSpeed = 1;
self.damage = 1;
break;
}
// Apply level multipliers
self.attackSpeed *= 1 + (self.level - 1) * 0.1;
self.damage *= self.level;
};
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
}
};
self.canFire = function () {
return self.cooldown <= 0;
};
self.fire = function () {
// Set cooldown based on attack speed (higher attack speed = lower cooldown)
self.cooldown = Math.round(60 / self.attackSpeed);
return self.damage;
};
return self;
});
var WeaponEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.type = 'basic';
self.damage = 1;
self.speed = 15;
self.lifetime = 60; // frames
self.setEffectType = function (type, damage) {
self.type = type;
self.damage = damage || 1;
switch (type) {
case 'laser':
effectGraphics.tint = 0xFF0000; // Red laser
effectGraphics.scaleX = 0.2;
effectGraphics.scaleY = 0.5;
self.speed = 20;
break;
case 'plasma':
effectGraphics.tint = 0x00FF00; // Green plasma
effectGraphics.scaleX = 0.4;
effectGraphics.scaleY = 0.4;
self.speed = 15;
break;
case 'wave':
effectGraphics.tint = 0x0000FF; // Blue wave
effectGraphics.scaleX = 0.6;
effectGraphics.scaleY = 0.3;
self.speed = 10;
break;
case 'boss':
// Boss projectiles have different appearances based on damage level (boss phase)
var phase = damage;
if (phase === 1) {
effectGraphics.tint = 0xFF00FF; // Purple boss projectile (phase 1)
effectGraphics.scaleX = 0.4;
effectGraphics.scaleY = 0.4;
self.speed = 8;
} else if (phase === 2) {
effectGraphics.tint = 0xFF6600; // Orange boss projectile (phase 2)
effectGraphics.scaleX = 0.5;
effectGraphics.scaleY = 0.5;
self.speed = 10;
} else {
effectGraphics.tint = 0xFF0000; // Red boss projectile (phase 3)
effectGraphics.scaleX = 0.6;
effectGraphics.scaleY = 0.6;
self.speed = 12;
}
break;
case 'basic':
default:
effectGraphics.tint = 0xFFFFFF; // White basic
effectGraphics.scaleX = 0.3;
effectGraphics.scaleY = 0.3;
self.speed = 15;
break;
}
// Pulse animation
tween(effectGraphics, {
alpha: 0.7
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(effectGraphics, {
alpha: 1
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
};
self.update = function () {
// Move in direction of rotation
self.x += Math.cos(self.rotation) * self.speed;
self.y += Math.sin(self.rotation) * self.speed;
// Update lifetime
self.lifetime--;
// Add trailing effect
if (self.lifetime % 3 === 0) {
var trail = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: effectGraphics.scaleX * 0.7,
scaleY: effectGraphics.scaleY * 0.7,
alpha: 0.5,
tint: effectGraphics.tint,
x: 0,
y: 0
});
trail.x = self.x;
trail.y = self.y;
trail.parent = self.parent;
self.parent.addChild(trail);
tween(trail, {
alpha: 0,
scaleX: trail.scaleX * 0.5,
scaleY: trail.scaleY * 0.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (trail.parent) {
trail.parent.removeChild(trail);
}
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8e44ad // Vibrant purple background
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_SPEED_BASE = 10;
var OBSTACLE_SPEED_BASE = 3;
var CUBE_SPAWN_INTERVAL_BASE = 1500; // ms
var OBSTACLE_SPAWN_INTERVAL = 5000; // ms
var LEVEL_UP_SCORE = 100;
var TIME_BONUS_MAX = 50;
var TIME_BONUS_THRESHOLD = 1000; // ms
var WEAPON_UPGRADE_SCORE = 100; // Score needed for weapon upgrades
// Cube type probabilities
var CUBE_TYPES = {
normal: {
chance: 70,
value: 10
},
silver: {
chance: 20,
value: 20
},
gold: {
chance: 10,
value: 30
}
};
// Weapon types by level
var WEAPON_UPGRADES = [{
level: 1,
type: 'basic',
name: 'Basic Blaster'
}, {
level: 2,
type: 'laser',
name: 'Laser Beam'
}, {
level: 3,
type: 'plasma',
name: 'Plasma Cannon'
}, {
level: 4,
type: 'wave',
name: 'Wave Disruptor'
}];
// Game variables
var player;
var collectableCubes = [];
var obstacles = [];
var weaponEffects = [];
var timerBar;
var score = 0;
var level = 1;
var weaponLevel = 1;
var lastCubeSpawnTime = 0;
var lastObstacleSpawnTime = 0;
var lastWeaponFireTime = 0;
var cubeSpawnInterval = CUBE_SPAWN_INTERVAL_BASE;
var playerSpeed = PLAYER_SPEED_BASE;
var obstacleSpeed = OBSTACLE_SPEED_BASE;
var lastTime = Date.now();
var gameActive = true;
var highScore = storage.highScore || 0;
var nextWeaponUpgrade = WEAPON_UPGRADE_SCORE;
var boss = null;
var inBossFight = false;
var bossDefeated = false;
var savedCubes = [];
var endingSequenceStarted = false;
var endingSequenceStep = 0;
var endingSequenceTimer = 0;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -scoreTxt.width - 20;
scoreTxt.y = 20;
var levelTxt = new Text2('Level: 1', {
size: 70,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -levelTxt.width - 20;
levelTxt.y = scoreTxt.y + scoreTxt.height + 10;
var highScoreTxt = new Text2('High Score: ' + highScore, {
size: 70,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -highScoreTxt.width - 20;
highScoreTxt.y = levelTxt.y + levelTxt.height + 10;
// Initialize game elements
function initGame() {
// Create colorful background patterns
createBackgroundPatterns();
// Create and position player
player = new Player();
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT / 2;
player.speed = playerSpeed;
game.addChild(player);
// Add a welcome animation
tween(player, {
scaleX: 0,
scaleY: 0
}, {
duration: 0
});
tween(player, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(player, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
});
// Create timer bar
timerBar = new TimerBar();
timerBar.x = (GAME_WIDTH - 1800) / 2;
timerBar.y = 100;
game.addChild(timerBar);
// Start with a few cubes and obstacles
spawnCollectableCube();
spawnObstacle();
// Play background music
LK.playMusic('gameMusic');
}
function createBackgroundPatterns() {
// Create some decorative background elements
for (var i = 0; i < 20; i++) {
var decoration = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3 + Math.random() * 0.3,
scaleY: 0.3 + Math.random() * 0.3,
alpha: 0.15,
tint: Math.random() * 0xFFFFFF,
x: Math.random() * GAME_WIDTH,
y: Math.random() * GAME_HEIGHT
});
// Place decorations behind game elements
game.addChildAt(decoration, 0);
// Add subtle animation to background elements
var animDuration = 3000 + Math.random() * 5000;
tween(decoration, {
rotation: Math.random() * Math.PI * 2
}, {
duration: animDuration,
easing: tween.easeInOut
});
}
}
function updateGame() {
if (!gameActive) {
return;
}
var currentTime = Date.now();
var delta = currentTime - lastTime;
lastTime = currentTime;
// Check if we're in ending sequence
if (endingSequenceStarted) {
updateEndingSequence();
return;
}
// Check if we're in boss fight
if (inBossFight) {
updateBossFight();
// Only check timer if boss isn't defeated
if (!bossDefeated) {
// Update timer
timerBar.update(delta);
if (timerBar.timeRemaining <= 0) {
gameOver();
return;
}
}
// Continue with collision checks and updates
} else {
// Update timer
timerBar.update(delta);
if (timerBar.timeRemaining <= 0) {
gameOver();
return;
}
// Spawn new cubes
if (currentTime - lastCubeSpawnTime > cubeSpawnInterval) {
spawnCollectableCube();
lastCubeSpawnTime = currentTime;
}
// Spawn new obstacles
if (currentTime - lastObstacleSpawnTime > OBSTACLE_SPAWN_INTERVAL) {
spawnObstacle();
lastObstacleSpawnTime = currentTime;
}
}
// Fire weapon automatically
if (currentTime - lastWeaponFireTime > 1000) {
var targets = inBossFight ? [boss] : obstacles;
if (player.fireWeapon(targets, game, weaponEffects)) {
lastWeaponFireTime = currentTime;
}
}
// Update weapon effects
for (var i = weaponEffects.length - 1; i >= 0; i--) {
var effect = weaponEffects[i];
// Update effect
effect.update();
// Check if effect is expired
if (effect.lifetime <= 0) {
game.removeChild(effect);
weaponEffects.splice(i, 1);
continue;
}
// Skip boss projectile collisions with obstacles
if (effect.type === 'boss') {
continue;
}
// Check for collisions with obstacles
for (var j = 0; j < obstacles.length; j++) {
var obstacle = obstacles[j];
if (effect.intersects(obstacle)) {
// Hit effect
var hitEffect = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: effect.tint,
alpha: 0.8,
x: effect.x,
y: effect.y
});
game.addChild(hitEffect);
// Animate hit effect
tween(hitEffect, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(hitEffect);
}
});
// Remove effect
game.removeChild(effect);
weaponEffects.splice(i, 1);
// Destroy obstacle
game.removeChild(obstacle);
obstacles.splice(j, 1);
// Add score for destroying obstacle
addScore(5 * weaponLevel);
break;
}
}
}
// Check for collisions
if (!endingSequenceStarted) {
checkCollisions();
}
}
function spawnCollectableCube() {
var cube = new CollectableCube();
// Determine cube type based on probabilities and level
var rand = Math.random() * 100;
var cubeType = 'normal';
// Adjust probabilities based on level (higher levels get better cubes)
var silverChance = CUBE_TYPES.silver.chance + level * 1.5;
var goldChance = CUBE_TYPES.gold.chance + level * 1;
if (rand < goldChance) {
cubeType = 'gold';
} else if (rand < goldChance + silverChance) {
cubeType = 'silver';
}
// Set the cube type
cube.setCubeType(cubeType);
cube.randomPosition(100, GAME_WIDTH - 100, 200, GAME_HEIGHT - 200);
// Make sure cube doesn't spawn on obstacles
var validPosition = false;
var maxAttempts = 10;
var attempts = 0;
while (!validPosition && attempts < maxAttempts) {
validPosition = true;
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
var dx = cube.x - obstacle.x;
var dy = cube.y - obstacle.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
validPosition = false;
cube.randomPosition(100, GAME_WIDTH - 100, 200, GAME_HEIGHT - 200);
break;
}
}
attempts++;
}
collectableCubes.push(cube);
game.addChild(cube);
// Animate cube entrance
cube.scale.x = 0;
cube.scale.y = 0;
tween(cube, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
}
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.randomPosition(100, GAME_WIDTH - 100, 200, GAME_HEIGHT - 200);
obstacle.setRandomSpeed(obstacleSpeed);
// Make sure obstacle doesn't spawn on player
var dx = obstacle.x - player.x;
var dy = obstacle.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
obstacle.x = GAME_WIDTH - obstacle.x;
obstacle.y = GAME_HEIGHT - obstacle.y;
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
function checkCollisions() {
// Check collisions with collectables
for (var i = collectableCubes.length - 1; i >= 0; i--) {
var cube = collectableCubes[i];
if (player.intersects(cube)) {
// Calculate time bonus
var collectionTime = Date.now() - cube.spawnTime;
var timeBonus = 0;
if (collectionTime < TIME_BONUS_THRESHOLD) {
timeBonus = Math.round(TIME_BONUS_MAX * (1 - collectionTime / TIME_BONUS_THRESHOLD));
}
// Add score and remove cube
addScore(cube.value + timeBonus);
game.removeChild(cube);
collectableCubes.splice(i, 1);
// Play collect sound
LK.getSound('collect').play();
// Check for level up
checkLevelUp();
}
}
// Check collisions with obstacles
for (var j = 0; j < obstacles.length; j++) {
var obstacle = obstacles[j];
if (player.intersects(obstacle)) {
// Player hit an obstacle
LK.getSound('collision').play();
LK.effects.flashScreen(0xe74c3c, 300);
// Reduce timer as penalty
timerBar.timeRemaining -= 3000; // 3 second penalty
// Push player away from obstacle
var dx = player.x - obstacle.x;
var dy = player.y - obstacle.y;
var angle = Math.atan2(dy, dx);
player.x += Math.cos(angle) * 100;
player.y += Math.sin(angle) * 100;
// Keep player within bounds
player.x = Math.max(40, Math.min(GAME_WIDTH - 40, player.x));
player.y = Math.max(40, Math.min(GAME_HEIGHT - 40, player.y));
}
}
}
function addScore(points) {
score += points;
scoreTxt.setText('Score: ' + score);
// Update player's score display
if (player && player.updateScore) {
player.updateScore(score);
}
// Create floating points animation
var floatingPoints = new Text2("+" + points, {
size: 60,
fill: 0x00ff00
});
floatingPoints.anchor.set(0.5, 0.5);
floatingPoints.x = player.x;
floatingPoints.y = player.y - 100;
game.addChild(floatingPoints);
// Animate the floating points
tween(floatingPoints, {
y: floatingPoints.y - 150,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(floatingPoints);
}
});
// Flash score text
tween(scoreTxt, {
scale: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scale: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
function checkLevelUp() {
// Check if player reached 2500 points to start boss fight
if (score >= 2500 && !inBossFight && !bossDefeated) {
startBossFight();
return;
}
// Check for weapon upgrades first
if (score >= nextWeaponUpgrade) {
// Find next weapon upgrade
var upgrade = null;
for (var i = 0; i < WEAPON_UPGRADES.length; i++) {
if (WEAPON_UPGRADES[i].level > weaponLevel) {
upgrade = WEAPON_UPGRADES[i];
break;
}
}
if (upgrade) {
weaponLevel = upgrade.level;
nextWeaponUpgrade += WEAPON_UPGRADE_SCORE * weaponLevel;
// Update player's weapon
player.updateWeapon(upgrade.type, weaponLevel);
// Show weapon upgrade notification
var upgradeText = new Text2("New Weapon: " + upgrade.name + "!", {
size: 80,
fill: 0xFFD700
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = GAME_WIDTH / 2;
upgradeText.y = GAME_HEIGHT / 2 - 200;
game.addChild(upgradeText);
// Animate the notification
tween(upgradeText, {
y: upgradeText.y - 100,
alpha: 0
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(upgradeText);
}
});
// Visual effect for weapon upgrade
LK.effects.flashScreen(0x00FFFF, 500);
}
}
// Regular level up check
if (score >= level * LEVEL_UP_SCORE) {
level++;
levelTxt.setText('Level: ' + level);
// Increase difficulty
cubeSpawnInterval = Math.max(500, CUBE_SPAWN_INTERVAL_BASE - (level - 1) * 150);
playerSpeed = PLAYER_SPEED_BASE + (level - 1) * 1;
obstacleSpeed = OBSTACLE_SPEED_BASE + (level - 1) * 0.5;
// Update player speed
player.speed = playerSpeed;
// Update obstacle speeds
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].setRandomSpeed(obstacleSpeed);
}
// Visual feedback for level up
LK.effects.flashScreen(0x2ecc71, 500);
// Add time bonus for leveling up
timerBar.timeRemaining += 5000; // 5 second bonus
if (timerBar.timeRemaining > timerBar.maxTime) {
timerBar.timeRemaining = timerBar.maxTime;
}
// Flash level text
tween(levelTxt, {
scale: 1.3
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(levelTxt, {
scale: 1
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
}
function gameOver() {
gameActive = false;
// Update high score
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
highScoreTxt.setText('High Score: ' + highScore);
}
// Show game over
LK.showGameOver();
}
function startBossFight() {
inBossFight = true;
// Show boss intro message
var bossText = new Text2("BOSS FIGHT!", {
size: 120,
fill: 0xFF0000
});
bossText.anchor.set(0.5, 0.5);
bossText.x = GAME_WIDTH / 2;
bossText.y = GAME_HEIGHT / 2;
game.addChild(bossText);
// Create phase indicator
var phaseText = new Text2("PHASE 1", {
size: 60,
fill: 0xFFFFFF
});
phaseText.anchor.set(0.5, 0.5);
phaseText.x = GAME_WIDTH / 2;
phaseText.y = GAME_HEIGHT / 2 + 120;
phaseText.alpha = 0;
game.addChild(phaseText);
// Fade in phase text
tween(phaseText, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(phaseText, {
alpha: 0
}, {
duration: 1000,
delay: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(phaseText);
}
});
}
});
// Stop time from decreasing during boss fight
var originalTimeRemaining = timerBar.timeRemaining;
timerBar.timeRemaining = timerBar.maxTime;
// Add dramatic flash effect
LK.effects.flashScreen(0xFF0000, 1000);
// Clear all obstacles
while (obstacles.length > 0) {
var obstacle = obstacles.pop();
game.removeChild(obstacle);
}
// Make collectableCubes scared and run away
for (var i = 0; i < collectableCubes.length; i++) {
var cube = collectableCubes[i];
// Add scared face to cube
if (cube.children[2]) {
// mouth
cube.children[2].scaleY = 0.3; // wide open mouth for fear
cube.children[2].y = 20; // adjust mouth position
}
// Make eyes wide with fear
if (cube.children[0] && cube.children[1]) {
tween(cube.children[0], {
scaleY: 0.3,
y: -15
}, {
duration: 300,
easing: tween.easeOut
});
tween(cube.children[1], {
scaleY: 0.3,
y: -15
}, {
duration: 300,
easing: tween.easeOut
});
}
// Add scared movement
cube.isScared = true;
cube.scaredSpeed = 3 + Math.random() * 2;
cube.originalUpdate = cube.update || function () {};
cube.update = function () {
this.originalUpdate();
if (this.isScared) {
// Run away from center of screen
var dx = this.x - GAME_WIDTH / 2;
var dy = this.y - GAME_HEIGHT / 2;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
this.x += dx / dist * this.scaredSpeed;
this.y += dy / dist * this.scaredSpeed;
}
// Keep inside screen
this.x = Math.max(50, Math.min(GAME_WIDTH - 50, this.x));
this.y = Math.max(50, Math.min(GAME_HEIGHT - 50, this.y));
// Shake with fear
this.rotation = (Math.random() - 0.5) * 0.2;
}
};
}
// Animate boss text then create boss
tween(bossText, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(bossText);
// Create boss - randomly select boss type
boss = new Boss();
boss.x = GAME_WIDTH / 2;
boss.y = 400;
boss.scale.x = 0;
boss.scale.y = 0;
game.addChild(boss);
// Animate boss entrance
tween(boss, {
scaleX: 1,
scaleY: 1
}, {
duration: 1000,
easing: tween.elasticOut
});
// Announce boss type
var bossTypeText = new Text2(boss.bossType.toUpperCase() + " BOSS APPEARS!", {
size: 80,
fill: boss.bossType === 'alien' ? 0x00FFFF : 0xFF6600
});
bossTypeText.anchor.set(0.5, 0.5);
bossTypeText.x = GAME_WIDTH / 2;
bossTypeText.y = GAME_HEIGHT / 2 - 200;
game.addChild(bossTypeText);
// Animate the announcement
tween(bossTypeText, {
y: bossTypeText.y - 100,
alpha: 0
}, {
duration: 2000,
delay: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(bossTypeText);
}
});
}
});
}
function updateBossFight() {
if (!boss) {
return;
}
// Update boss
boss.update(player, weaponEffects, game);
// Check if phase has changed
var lastPhase = boss.lastPhase || 1;
if (boss.phase !== lastPhase) {
// Phase transition
var phaseText = new Text2("PHASE " + boss.phase, {
size: 80,
fill: boss.phase === 2 ? 0xFF8800 : 0xFF0000
});
phaseText.anchor.set(0.5, 0.5);
phaseText.x = GAME_WIDTH / 2;
phaseText.y = GAME_HEIGHT / 2;
game.addChild(phaseText);
// Animate phase announcement
tween(phaseText, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(phaseText);
}
});
boss.lastPhase = boss.phase;
}
// Check for weapon effects hitting the boss
for (var i = weaponEffects.length - 1; i >= 0; i--) {
var effect = weaponEffects[i];
// Skip boss projectiles
if (effect.type === 'boss') {
continue;
}
// Check if weapon hit boss
if (effect.intersects(boss)) {
// Create hit effect
var hitEffect = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: effect.tint,
alpha: 0.8,
x: effect.x,
y: effect.y
});
game.addChild(hitEffect);
// Animate hit effect
tween(hitEffect, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (hitEffect.parent) {
game.removeChild(hitEffect);
}
}
});
// Remove weapon effect
game.removeChild(effect);
weaponEffects.splice(i, 1);
// Damage boss
var bossDefeated = boss.takeDamage(effect.damage);
// Add score based on current phase (more points in later phases)
addScore(5 * boss.phase);
// Check if boss is defeated
if (bossDefeated) {
defeatBoss();
break;
}
}
}
// Check for boss projectiles hitting player
for (var i = weaponEffects.length - 1; i >= 0; i--) {
var effect = weaponEffects[i];
// Only check boss projectiles
if (effect.type !== 'boss') {
continue;
}
// Check if projectile hit player
if (effect.intersects(player)) {
// Create hit effect
var hitEffect = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: effect.tint,
alpha: 0.8,
x: effect.x,
y: effect.y
});
game.addChild(hitEffect);
// Animate hit effect
tween(hitEffect, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (hitEffect.parent) {
game.removeChild(hitEffect);
}
}
});
// Remove projectile
game.removeChild(effect);
weaponEffects.splice(i, 1);
// Flash screen
LK.effects.flashScreen(0xFF0000, 300);
// Reduce timer as penalty, more in later phases
timerBar.timeRemaining -= 1000 * boss.phase; // More penalty in higher phases
break;
}
}
// Update cubes that are watching the battle
for (var i = 0; i < savedCubes.length; i++) {
if (savedCubes[i].watching && savedCubes[i].update) {
savedCubes[i].update();
}
}
}
function defeatBoss() {
bossDefeated = true;
// Create explosion effect
for (var i = 0; i < 20; i++) {
var explosionPart = LK.getAsset('collectableCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFF0000,
alpha: 0.8,
x: boss.x,
y: boss.y
});
game.addChild(explosionPart);
// Random direction
var angle = Math.random() * Math.PI * 2;
var distance = 100 + Math.random() * 200;
// Animate explosion parts
tween(explosionPart, {
x: explosionPart.x + Math.cos(angle) * distance,
y: explosionPart.y + Math.sin(angle) * distance,
alpha: 0,
rotation: Math.random() * Math.PI * 4
}, {
duration: 1000 + Math.random() * 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(explosionPart);
}
});
}
// Flash screen
LK.effects.flashScreen(0xFFFFFF, 1000);
// Remove boss
game.removeChild(boss);
boss = null;
// Show victory message
var victoryText = new Text2("BOSS DEFEATED!", {
size: 100,
fill: 0xFFD700
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = GAME_WIDTH / 2;
victoryText.y = GAME_HEIGHT / 2;
game.addChild(victoryText);
// Add score bonus
addScore(500);
// Animate victory text
tween(victoryText, {
y: victoryText.y - 100,
alpha: 0
}, {
duration: 3000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(victoryText);
startEndingSequence();
}
});
// Add extra time to the timer
timerBar.timeRemaining += 30000; // 30 seconds bonus
if (timerBar.timeRemaining > timerBar.maxTime) {
timerBar.timeRemaining = timerBar.maxTime;
}
}
function startEndingSequence() {
endingSequenceStarted = true;
endingSequenceStep = 0;
endingSequenceTimer = 0;
// Create a group that will watch the player
var watchingGroup = new Container();
watchingGroup.x = GAME_WIDTH / 2;
watchingGroup.y = GAME_HEIGHT / 2 - 500;
game.addChild(watchingGroup);
// Clear all existing cubes and obstacles
while (collectableCubes.length > 0) {
var cube = collectableCubes.pop();
game.removeChild(cube);
}
while (obstacles.length > 0) {
var obstacle = obstacles.pop();
game.removeChild(obstacle);
}
// Spawn cubes of all types, some watching
for (var i = 0; i < 20; i++) {
var cube = spawnSavedCube(i % 3);
// Position the first 5 cubes in a watching group
if (i < 5) {
cube.watching = true;
cube.originalX = cube.x;
cube.originalY = cube.y;
// Position in semicircle
var angle = i / 5 * Math.PI;
var radius = 200;
cube.x = watchingGroup.x + Math.cos(angle) * radius - GAME_WIDTH / 2;
cube.y = watchingGroup.y + Math.sin(angle) * radius - 100;
// Make cube happy
if (cube.children[2]) {
// mouth
tween(cube.children[2], {
scaleY: 0.25,
y: 10
}, {
duration: 300,
easing: tween.easeOut
});
}
// Add special watching behavior
cube.originalUpdate = cube.update || function () {};
cube.update = function () {
this.originalUpdate();
// Always look at player
if (player) {
var dx = player.x - this.x;
var dy = player.y - this.y;
var angle = Math.atan2(dy, dx);
// Move eyes to look at player
if (this.children[0] && this.children[1]) {
var eyeOffsetX = Math.cos(angle) * 5;
var eyeOffsetY = Math.sin(angle) * 5;
this.children[0].x = -15 + eyeOffsetX;
this.children[0].y = -10 + eyeOffsetY;
this.children[1].x = 15 + eyeOffsetX;
this.children[1].y = -10 + eyeOffsetY;
}
}
};
}
}
// Update player
player.updateWeapon('wave', 5);
}
function spawnSavedCube(typeIndex) {
var cube = new CollectableCube();
var types = ['normal', 'silver', 'gold'];
var type = types[typeIndex % types.length];
cube.setCubeType(type);
cube.randomPosition(100, GAME_WIDTH - 100, 200, GAME_HEIGHT - 200);
// Make cubes move around
cube.speedX = (Math.random() - 0.5) * 5;
cube.speedY = (Math.random() - 0.5) * 5;
cube.update = function () {
this.x += this.speedX;
this.y += this.speedY;
// Bounce off screen edges
if (this.x < 50 || this.x > GAME_WIDTH - 50) {
this.speedX *= -1;
}
if (this.y < 50 || this.y > GAME_HEIGHT - 50) {
this.speedY *= -1;
}
};
savedCubes.push(cube);
game.addChild(cube);
// Animate cube entrance
cube.scale.x = 0;
cube.scale.y = 0;
tween(cube, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
return cube;
}
function updateEndingSequence() {
endingSequenceTimer++;
// Update saved cubes
for (var i = 0; i < savedCubes.length; i++) {
if (savedCubes[i].update) {
savedCubes[i].update();
}
}
// Progress through ending sequence steps
if (endingSequenceTimer === 120) {
// 2 seconds
endingSequenceStep = 1;
// Spawn enemies
for (var i = 0; i < 5; i++) {
spawnObstacle();
}
// Show message
var messageText = new Text2("The cubes have been saved!", {
size: 80,
fill: 0x00FFFF
});
messageText.anchor.set(0.5, 0.5);
messageText.x = GAME_WIDTH / 2;
messageText.y = GAME_HEIGHT / 2 - 400;
game.addChild(messageText);
// Animate message
tween(messageText, {
alpha: 0
}, {
duration: 3000,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(messageText);
}
});
}
if (endingSequenceTimer === 360) {
// 6 seconds
endingSequenceStep = 2;
// Create alien
var alien = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
tint: 0x00FF00
});
alien.x = GAME_WIDTH / 2;
alien.y = -200;
game.addChild(alien);
// Add alien face
var leftEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000,
x: -50,
y: -50
});
var rightEye = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000,
x: 50,
y: -50
});
var mouth = LK.getAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.1,
tint: 0x000000,
x: 0,
y: 30
});
alien.addChild(leftEye);
alien.addChild(rightEye);
alien.addChild(mouth);
// Animate alien entrance
tween(alien, {
y: 400
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show final message
var finalText = new Text2("To be continued...", {
size: 120,
fill: 0xFFFFFF
});
finalText.anchor.set(0.5, 0.5);
finalText.x = GAME_WIDTH / 2;
finalText.y = GAME_HEIGHT / 2 + 300;
finalText.alpha = 0;
game.addChild(finalText);
// Animate final message
tween(finalText, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Wait 3 seconds then show game win
LK.setTimeout(function () {
LK.showYouWin();
}, 3000);
}
});
}
});
}
}
function resetGame() {
// Reset game variables
score = 0;
level = 1;
weaponLevel = 1;
nextWeaponUpgrade = WEAPON_UPGRADE_SCORE;
cubeSpawnInterval = CUBE_SPAWN_INTERVAL_BASE;
playerSpeed = PLAYER_SPEED_BASE;
obstacleSpeed = OBSTACLE_SPEED_BASE;
lastTime = Date.now();
lastCubeSpawnTime = 0;
lastObstacleSpawnTime = 0;
lastWeaponFireTime = 0;
gameActive = true;
inBossFight = false;
bossDefeated = false;
endingSequenceStarted = false;
endingSequenceStep = 0;
endingSequenceTimer = 0;
// Clear all game elements
while (collectableCubes.length > 0) {
var cube = collectableCubes.pop();
game.removeChild(cube);
}
while (obstacles.length > 0) {
var obstacle = obstacles.pop();
game.removeChild(obstacle);
}
while (weaponEffects.length > 0) {
var effect = weaponEffects.pop();
game.removeChild(effect);
}
while (savedCubes.length > 0) {
var savedCube = savedCubes.pop();
game.removeChild(savedCube);
}
if (boss) {
game.removeChild(boss);
boss = null;
}
if (player) {
game.removeChild(player);
}
if (timerBar) {
game.removeChild(timerBar);
}
// Reset UI
scoreTxt.setText('Score: 0');
levelTxt.setText('Level: 1');
highScoreTxt.setText('High Score: ' + highScore);
// Initialize game again
initGame();
}
// Event handlers
game.down = function (x, y, obj) {
if (gameActive) {
player.setTarget(x, y);
}
};
game.move = function (x, y, obj) {
if (gameActive && obj.down) {
player.setTarget(x, y);
}
};
game.update = function () {
updateGame();
// Update player
if (player) {
player.update();
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// Update weapon effects
for (var i = 0; i < weaponEffects.length; i++) {
if (weaponEffects[i].update) {
weaponEffects[i].update();
}
}
// Update saved cubes
for (var i = 0; i < savedCubes.length; i++) {
if (savedCubes[i].update) {
savedCubes[i].update();
}
}
};
// Initialize the game
initGame(); ===================================================================
--- original.js
+++ change.js
@@ -156,10 +156,9 @@
self.addChild(rightEye);
self.addChild(mouth);
self.addChild(antenna1);
self.addChild(antenna2);
- // Create a container for the health bar to position it at the top of the screen
- self.healthBarContainer = new Container();
+ // Configure the health bar container which was initialized earlier
self.healthBarContainer.x = 2048 / 2; // Center horizontally
self.healthBarContainer.y = 150; // Fixed position at top
// Boss health indicator background
var healthBarBg = LK.getAsset('timerBarBackground', {