User prompt
Add green platforms that make you go faster if you touch them for 20 seconds ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add turrets that shoot that shoot you with homing missiles and if the missile touches the floor or a platform it explodes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add drones that shoot red cubes to attack you in the sky ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add Saws
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 529
User prompt
Make the blue cube has facial expressions on the eyes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add particles when the blue cube moves ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add moveable boxes
User prompt
Add sprinting
User prompt
Add spinning obstacles ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add lasers
User prompt
Add the obstacle wall
User prompt
Remove the big red cube
User prompt
Make a new enemies that is a big red cube that jumps toward you to attack
User prompt
Make the blue cube be able to dash ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make it so that the blue cube can double jump
User prompt
Make the platforms collidable
Code edit (1 edits merged)
Please save this source code
User prompt
Junkyard Journey
Initial prompt
Make a platformer game about a blue cube with eyes exploring the junkyard with enemies trying to kill the blue cube, the blue cube must get to the blue circle at the other side of the junkyard
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Drone = Container.expand(function () {
var self = Container.call(this);
var droneBody = self.attachAsset('drone', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5;
self.direction = 1;
self.startX = 0;
self.patrolDistance = 250;
self.shootCooldown = 2000; // 2 seconds
self.lastShotTime = 0;
self.detectionRange = 400;
self.hoverHeight = 100; // Height above ground to hover
self.update = function () {
// Patrol movement
self.x += self.speed * self.direction;
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
// Hover at fixed height
var targetY = groundLevel - self.hoverHeight;
if (self.y > targetY) {
self.y -= 2;
} else if (self.y < targetY) {
self.y += 2;
}
// Check if player is in range and shoot
var distanceToPlayer = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
var currentTime = Date.now();
if (distanceToPlayer < self.detectionRange && currentTime - self.lastShotTime >= self.shootCooldown) {
self.shoot();
self.lastShotTime = currentTime;
}
// Add floating animation with tween
if (!self.isFloating) {
self.isFloating = true;
self.startFloat();
}
};
self.shoot = function () {
// Calculate direction to player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Normalize direction
var dirX = deltaX / distance;
var dirY = deltaY / distance;
// Create bullet
var bullet = game.addChild(new DroneBullet());
bullet.x = self.x;
bullet.y = self.y;
bullet.velocityX = dirX * bullet.speed;
bullet.velocityY = dirY * bullet.speed;
droneBullets.push(bullet);
// Play shoot sound
LK.getSound('droneShoot').play();
// Visual feedback - flash red briefly
tween(self, {
tint: 0xff0000
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeIn
});
}
});
};
self.startFloat = function () {
tween(self, {
y: self.y - 10
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 10
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isFloating = false;
}
});
}
});
};
return self;
});
var DroneBullet = Container.expand(function () {
var self = Container.call(this);
var bulletBody = self.attachAsset('droneBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 8;
self.lifeTime = 3000; // 3 seconds
self.age = 0;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.age += 16; // Assuming 60fps
// Remove bullet if it's too old or off screen
if (self.age >= self.lifeTime || self.x < -100 || self.x > levelWidth + 100 || self.y < -100 || self.y > groundLevel + 500) {
self.destroy();
for (var i = droneBullets.length - 1; i >= 0; i--) {
if (droneBullets[i] === self) {
droneBullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyBody = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = 2;
self.direction = 1;
self.startX = 0;
self.patrolDistance = 300;
self.update = function () {
self.x += self.speed * self.direction;
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
// Ground collision for enemies
if (self.y >= groundLevel) {
self.y = groundLevel;
}
// Platform collision for enemies
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if enemy is on top of platform
if (self.intersects(platform)) {
var platformLeft = platform.x - 100; // platform width/2
var platformRight = platform.x + 100; // platform width/2
var platformTop = platform.y - 20; // platform height/2
var enemyLeft = self.x - 30; // enemy width/2
var enemyRight = self.x + 30; // enemy width/2
var enemyBottom = self.y;
// Landing on platform
if (enemyBottom > platformTop && enemyBottom < platformTop + 50 && enemyRight > platformLeft && enemyLeft < platformRight) {
self.y = platformTop;
}
}
}
};
return self;
});
var HomingMissile = Container.expand(function () {
var self = Container.call(this);
var missileBody = self.attachAsset('homingMissile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 6;
self.homingStrength = 0.15;
self.lifeTime = 5000; // 5 seconds
self.age = 0;
self.hasExploded = false;
self.update = function () {
// Calculate direction to player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
// Normalize direction
var dirX = deltaX / distance;
var dirY = deltaY / distance;
// Apply homing
self.velocityX += dirX * self.homingStrength;
self.velocityY += dirY * self.homingStrength;
// Limit speed
var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (currentSpeed > self.speed) {
self.velocityX = self.velocityX / currentSpeed * self.speed;
self.velocityY = self.velocityY / currentSpeed * self.speed;
}
}
self.x += self.velocityX;
self.y += self.velocityY;
self.age += 16; // Assuming 60fps
// Check ground/platform collision for explosion
if (self.y >= groundLevel && !self.hasExploded) {
self.explode();
}
// Check platform collision
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (self.intersects(platform) && !self.hasExploded) {
self.explode();
break;
}
}
// Remove missile if it's too old or off screen
if (self.age >= self.lifeTime || self.x < -200 || self.x > levelWidth + 200 || self.y > groundLevel + 500) {
self.destroy();
for (var j = homingMissiles.length - 1; j >= 0; j--) {
if (homingMissiles[j] === self) {
homingMissiles.splice(j, 1);
break;
}
}
}
};
self.explode = function () {
if (self.hasExploded) return;
self.hasExploded = true;
// Create explosion visual
var explosion = game.addChild(LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8
}));
// Explosion animation with tween
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Damage player if close enough
var distanceToPlayer = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
if (distanceToPlayer < 100) {
LK.getSound('hit').play();
LK.effects.flashScreen(0xFF0000, 500);
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
}
// Remove missile from game
self.destroy();
for (var j = homingMissiles.length - 1; j >= 0; j--) {
if (homingMissiles[j] === self) {
homingMissiles.splice(j, 1);
break;
}
}
};
return self;
});
var JunkPile = Container.expand(function () {
var self = Container.call(this);
var junkBody = self.attachAsset('junkPile', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformBody = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerBody = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
var leftEye = self.attachAsset('playerEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -20,
y: -50
});
var rightEye = self.attachAsset('playerEye', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: -50
});
var leftPupil = self.attachAsset('playerPupil', {
anchorX: 0.5,
anchorY: 0.5,
x: -20,
y: -50
});
var rightPupil = self.attachAsset('playerPupil', {
anchorX: 0.5,
anchorY: 0.5,
x: 20,
y: -50
});
self.velocityX = 0;
self.velocityY = 0;
self.onGround = false;
self.jumpCount = 0;
self.maxJumps = 2;
self.jumpPower = -15;
self.gravity = 0.8;
self.maxSpeed = 8;
self.friction = 0.85;
self.dashPower = 20;
self.dashDuration = 200;
self.dashCooldown = 1000;
self.isDashing = false;
self.dashTimeRemaining = 0;
self.lastDashTime = 0;
self.isSprinting = false;
self.sprintMultiplier = 1.8;
self.normalMaxSpeed = 8;
self.sprintMaxSpeed = 14;
self.update = function () {
// Handle dash mechanics
if (self.isDashing && self.dashTimeRemaining > 0) {
self.dashTimeRemaining -= 16; // Assuming 60fps, ~16ms per frame
if (self.dashTimeRemaining <= 0) {
self.isDashing = false;
}
}
// Apply gravity (reduced during dash)
if (!self.isDashing) {
self.velocityY += self.gravity;
} else {
self.velocityY += self.gravity * 0.3; // Reduced gravity during dash
}
// Apply friction
self.velocityX *= self.friction;
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Ground collision
if (self.y >= groundLevel) {
self.y = groundLevel;
self.velocityY = 0;
self.onGround = true;
self.jumpCount = 0;
} else {
self.onGround = false;
}
// Platform collision
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Check if player is intersecting with platform
if (self.intersects(platform)) {
// Calculate platform boundaries
var platformLeft = platform.x - 100; // platform width/2
var platformRight = platform.x + 100; // platform width/2
var platformTop = platform.y - 20; // platform height/2
var platformBottom = platform.y + 20; // platform height/2
var playerLeft = self.x - 40; // player width/2
var playerRight = self.x + 40; // player width/2
var playerTop = self.y - 80; // player height
var playerBottom = self.y;
// Landing on top of platform
if (self.velocityY > 0 && playerBottom > platformTop && playerTop < platformTop && playerRight > platformLeft && playerLeft < platformRight) {
self.y = platformTop;
self.velocityY = 0;
self.onGround = true;
self.jumpCount = 0;
}
// Hitting platform from below
else if (self.velocityY < 0 && playerTop < platformBottom && playerBottom > platformBottom && playerRight > platformLeft && playerLeft < platformRight) {
self.y = platformBottom + 80;
self.velocityY = 0;
}
// Hitting platform from left
else if (self.velocityX > 0 && playerRight > platformLeft && playerLeft < platformLeft && playerBottom > platformTop && playerTop < platformBottom) {
self.x = platformLeft - 40;
self.velocityX = 0;
}
// Hitting platform from right
else if (self.velocityX < 0 && playerLeft < platformRight && playerRight > platformRight && playerBottom > platformTop && playerTop < platformBottom) {
self.x = platformRight + 40;
self.velocityX = 0;
}
}
}
// Boundary checking
if (self.x < 40) {
self.x = 40;
}
if (self.x > levelWidth - 40) {
self.x = levelWidth - 40;
}
};
self.jump = function () {
if (self.jumpCount < self.maxJumps) {
self.velocityY = self.jumpPower;
self.jumpCount++;
self.onGround = false;
LK.getSound('jump').play();
}
};
self.moveLeft = function () {
var currentMaxSpeed = self.isSprinting ? self.sprintMaxSpeed : self.normalMaxSpeed;
var acceleration = self.isSprinting ? 2.2 : 1.5;
self.velocityX = Math.max(self.velocityX - acceleration, -currentMaxSpeed);
};
self.moveRight = function () {
var currentMaxSpeed = self.isSprinting ? self.sprintMaxSpeed : self.normalMaxSpeed;
var acceleration = self.isSprinting ? 2.2 : 1.5;
self.velocityX = Math.min(self.velocityX + acceleration, currentMaxSpeed);
};
self.dash = function (direction) {
var currentTime = Date.now();
if (currentTime - self.lastDashTime >= self.dashCooldown && !self.isDashing) {
self.isDashing = true;
self.dashTimeRemaining = self.dashDuration;
self.lastDashTime = currentTime;
// Apply dash velocity
self.velocityX = self.dashPower * direction;
// Visual dash effect with tween
tween(self, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Flash effect during dash
tween(self, {
alpha: 0.7
}, {
duration: self.dashDuration / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
alpha: 1
}, {
duration: self.dashDuration / 2,
easing: tween.easeInOut
});
}
});
}
};
self.startSprint = function () {
self.isSprinting = true;
// Visual sprint effect with tween
tween(self, {
tint: 0x87CEEB
}, {
duration: 200,
easing: tween.easeOut
});
};
self.stopSprint = function () {
self.isSprinting = false;
// Remove sprint visual effect
tween(self, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
};
return self;
});
var Turret = Container.expand(function () {
var self = Container.call(this);
var turretBody = self.attachAsset('turret', {
anchorX: 0.5,
anchorY: 1.0
});
self.shootCooldown = 3000; // 3 seconds
self.lastShotTime = 0;
self.detectionRange = 500;
self.update = function () {
// Check if player is in range and shoot
var distanceToPlayer = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
var currentTime = Date.now();
if (distanceToPlayer < self.detectionRange && currentTime - self.lastShotTime >= self.shootCooldown) {
self.shoot();
self.lastShotTime = currentTime;
}
};
self.shoot = function () {
// Create homing missile
var missile = game.addChild(new HomingMissile());
missile.x = self.x;
missile.y = self.y - 40;
// Initial velocity toward player
var deltaX = player.x - missile.x;
var deltaY = player.y - missile.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var dirX = deltaX / distance;
var dirY = deltaY / distance;
missile.velocityX = dirX * 3;
missile.velocityY = dirY * 3;
homingMissiles.push(missile);
// Visual feedback - flash red briefly
tween(self, {
tint: 0xff0000
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xFFFFFF
}, {
duration: 150,
easing: tween.easeIn
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var player;
var enemies = [];
var platforms = [];
var junkPiles = [];
var drones = [];
var droneBullets = [];
var turrets = [];
var homingMissiles = [];
var goal;
var camera;
var groundLevel = 2600;
var levelWidth = 4000;
var gameWon = false;
// Create camera object for following player
camera = {
x: 0,
y: 0,
targetX: 0,
targetY: 0,
smoothing: 0.1
};
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = groundLevel;
// Create platforms
var platformPositions = [{
x: 500,
y: 2400
}, {
x: 800,
y: 2200
}, {
x: 1200,
y: 2300
}, {
x: 1600,
y: 2100
}, {
x: 2000,
y: 2000
}, {
x: 2400,
y: 2200
}, {
x: 2800,
y: 2400
}, {
x: 3200,
y: 2300
}, {
x: 3600,
y: 2500
}];
for (var i = 0; i < platformPositions.length; i++) {
var platform = game.addChild(new Platform());
platform.x = platformPositions[i].x;
platform.y = platformPositions[i].y;
platforms.push(platform);
}
// Create enemies
var enemyPositions = [{
x: 600,
y: groundLevel
}, {
x: 1000,
y: 2200
}, {
x: 1400,
y: groundLevel
}, {
x: 1800,
y: 2000
}, {
x: 2200,
y: groundLevel
}, {
x: 2600,
y: 2200
}, {
x: 3000,
y: groundLevel
}, {
x: 3400,
y: 2300
}];
for (var i = 0; i < enemyPositions.length; i++) {
var enemy = game.addChild(new Enemy());
enemy.x = enemyPositions[i].x;
enemy.y = enemyPositions[i].y;
enemy.startX = enemy.x;
enemies.push(enemy);
}
// Create junk piles for decoration
var junkPositions = [{
x: 300,
y: groundLevel
}, {
x: 700,
y: groundLevel
}, {
x: 1100,
y: groundLevel
}, {
x: 1500,
y: groundLevel
}, {
x: 1900,
y: groundLevel
}, {
x: 2300,
y: groundLevel
}, {
x: 2700,
y: groundLevel
}, {
x: 3100,
y: groundLevel
}, {
x: 3500,
y: groundLevel
}];
for (var i = 0; i < junkPositions.length; i++) {
var junk = game.addChild(new JunkPile());
junk.x = junkPositions[i].x;
junk.y = junkPositions[i].y;
junkPiles.push(junk);
}
// Create drones
var dronePositions = [{
x: 800,
y: groundLevel - 150
}, {
x: 1400,
y: groundLevel - 200
}, {
x: 2200,
y: groundLevel - 180
}, {
x: 2900,
y: groundLevel - 160
}, {
x: 3500,
y: groundLevel - 170
}];
for (var i = 0; i < dronePositions.length; i++) {
var drone = game.addChild(new Drone());
drone.x = dronePositions[i].x;
drone.y = dronePositions[i].y;
drone.startX = drone.x;
drones.push(drone);
}
// Create turrets
var turretPositions = [{
x: 1000,
y: groundLevel
}, {
x: 1800,
y: 2000
}, {
x: 2600,
y: groundLevel
}, {
x: 3200,
y: 2300
}];
for (var i = 0; i < turretPositions.length; i++) {
var turret = game.addChild(new Turret());
turret.x = turretPositions[i].x;
turret.y = turretPositions[i].y;
turrets.push(turret);
}
// Create goal
goal = game.addChild(LK.getAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
}));
goal.x = levelWidth - 200;
goal.y = groundLevel - 50;
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var isDragging = false;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
isDragging = true;
// Jump on tap
player.jump();
};
game.move = function (x, y, obj) {
if (isDragging) {
var deltaX = x - touchStartX;
var deltaY = Math.abs(y - touchStartY);
// Check for dash gesture (fast horizontal swipe)
if (Math.abs(deltaX) > 100 && deltaY < 50) {
var dashDirection = deltaX > 0 ? 1 : -1;
player.dash(dashDirection);
isDragging = false; // End drag to prevent continuous movement
}
// Check for sprint gesture (long horizontal drag)
else if (Math.abs(deltaX) > 50) {
if (!player.isSprinting) {
player.startSprint();
}
if (deltaX < -20) {
player.moveLeft();
} else if (deltaX > 20) {
player.moveRight();
}
}
// Regular movement for smaller gestures
else if (deltaX < -20) {
player.moveLeft();
} else if (deltaX > 20) {
player.moveRight();
}
}
};
game.up = function (x, y, obj) {
isDragging = false;
if (player.isSprinting) {
player.stopSprint();
}
};
// Game update loop
game.update = function () {
if (gameWon) return;
// Update camera to follow player
camera.targetX = player.x - 1024;
camera.targetY = player.y - 1366;
camera.x += (camera.targetX - camera.x) * camera.smoothing;
camera.y += (camera.targetY - camera.y) * camera.smoothing;
// Keep camera within level bounds
if (camera.x < 0) camera.x = 0;
if (camera.x > levelWidth - 2048) camera.x = levelWidth - 2048;
if (camera.y < -500) camera.y = -500;
if (camera.y > 0) camera.y = 0;
// Apply camera offset to game
game.x = -camera.x;
game.y = -camera.y;
// Check collision with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
LK.getSound('hit').play();
LK.effects.flashScreen(0xFF0000, 500);
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
return;
}
}
// Check collision with drone bullets
for (var i = droneBullets.length - 1; i >= 0; i--) {
var bullet = droneBullets[i];
if (player.intersects(bullet)) {
LK.getSound('hit').play();
LK.effects.flashScreen(0xFF0000, 500);
bullet.destroy();
droneBullets.splice(i, 1);
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
return;
}
}
// Check collision with homing missiles
for (var i = homingMissiles.length - 1; i >= 0; i--) {
var missile = homingMissiles[i];
if (player.intersects(missile) && !missile.hasExploded) {
missile.explode();
return;
}
}
// Check if player reached goal
if (player.intersects(goal)) {
gameWon = true;
LK.effects.flashScreen(0x00FF00, 1000);
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
return;
}
// Check if player fell off the level
if (player.y > groundLevel + 500) {
LK.effects.flashScreen(0xFF0000, 500);
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
return;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -166,8 +166,109 @@
}
};
return self;
});
+var HomingMissile = Container.expand(function () {
+ var self = Container.call(this);
+ var missileBody = self.attachAsset('homingMissile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.velocityX = 0;
+ self.velocityY = 0;
+ self.speed = 6;
+ self.homingStrength = 0.15;
+ self.lifeTime = 5000; // 5 seconds
+ self.age = 0;
+ self.hasExploded = false;
+ self.update = function () {
+ // Calculate direction to player
+ var deltaX = player.x - self.x;
+ var deltaY = player.y - self.y;
+ var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ if (distance > 0) {
+ // Normalize direction
+ var dirX = deltaX / distance;
+ var dirY = deltaY / distance;
+ // Apply homing
+ self.velocityX += dirX * self.homingStrength;
+ self.velocityY += dirY * self.homingStrength;
+ // Limit speed
+ var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
+ if (currentSpeed > self.speed) {
+ self.velocityX = self.velocityX / currentSpeed * self.speed;
+ self.velocityY = self.velocityY / currentSpeed * self.speed;
+ }
+ }
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.age += 16; // Assuming 60fps
+ // Check ground/platform collision for explosion
+ if (self.y >= groundLevel && !self.hasExploded) {
+ self.explode();
+ }
+ // Check platform collision
+ for (var i = 0; i < platforms.length; i++) {
+ var platform = platforms[i];
+ if (self.intersects(platform) && !self.hasExploded) {
+ self.explode();
+ break;
+ }
+ }
+ // Remove missile if it's too old or off screen
+ if (self.age >= self.lifeTime || self.x < -200 || self.x > levelWidth + 200 || self.y > groundLevel + 500) {
+ self.destroy();
+ for (var j = homingMissiles.length - 1; j >= 0; j--) {
+ if (homingMissiles[j] === self) {
+ homingMissiles.splice(j, 1);
+ break;
+ }
+ }
+ }
+ };
+ self.explode = function () {
+ if (self.hasExploded) return;
+ self.hasExploded = true;
+ // Create explosion visual
+ var explosion = game.addChild(LK.getAsset('explosion', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: self.x,
+ y: self.y,
+ alpha: 0.8
+ }));
+ // Explosion animation with tween
+ tween(explosion, {
+ scaleX: 2,
+ scaleY: 2,
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ explosion.destroy();
+ }
+ });
+ // Damage player if close enough
+ var distanceToPlayer = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
+ if (distanceToPlayer < 100) {
+ LK.getSound('hit').play();
+ LK.effects.flashScreen(0xFF0000, 500);
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 500);
+ }
+ // Remove missile from game
+ self.destroy();
+ for (var j = homingMissiles.length - 1; j >= 0; j--) {
+ if (homingMissiles[j] === self) {
+ homingMissiles.splice(j, 1);
+ break;
+ }
+ }
+ };
+ return self;
+});
var JunkPile = Container.expand(function () {
var self = Container.call(this);
var junkBody = self.attachAsset('junkPile', {
anchorX: 0.5,
@@ -387,8 +488,58 @@
});
};
return self;
});
+var Turret = Container.expand(function () {
+ var self = Container.call(this);
+ var turretBody = self.attachAsset('turret', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ self.shootCooldown = 3000; // 3 seconds
+ self.lastShotTime = 0;
+ self.detectionRange = 500;
+ self.update = function () {
+ // Check if player is in range and shoot
+ var distanceToPlayer = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2));
+ var currentTime = Date.now();
+ if (distanceToPlayer < self.detectionRange && currentTime - self.lastShotTime >= self.shootCooldown) {
+ self.shoot();
+ self.lastShotTime = currentTime;
+ }
+ };
+ self.shoot = function () {
+ // Create homing missile
+ var missile = game.addChild(new HomingMissile());
+ missile.x = self.x;
+ missile.y = self.y - 40;
+ // Initial velocity toward player
+ var deltaX = player.x - missile.x;
+ var deltaY = player.y - missile.y;
+ var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+ var dirX = deltaX / distance;
+ var dirY = deltaY / distance;
+ missile.velocityX = dirX * 3;
+ missile.velocityY = dirY * 3;
+ homingMissiles.push(missile);
+ // Visual feedback - flash red briefly
+ tween(self, {
+ tint: 0xff0000
+ }, {
+ duration: 150,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ tint: 0xFFFFFF
+ }, {
+ duration: 150,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -404,8 +555,10 @@
var platforms = [];
var junkPiles = [];
var drones = [];
var droneBullets = [];
+var turrets = [];
+var homingMissiles = [];
var goal;
var camera;
var groundLevel = 2600;
var levelWidth = 4000;
@@ -548,8 +701,28 @@
drone.y = dronePositions[i].y;
drone.startX = drone.x;
drones.push(drone);
}
+// Create turrets
+var turretPositions = [{
+ x: 1000,
+ y: groundLevel
+}, {
+ x: 1800,
+ y: 2000
+}, {
+ x: 2600,
+ y: groundLevel
+}, {
+ x: 3200,
+ y: 2300
+}];
+for (var i = 0; i < turretPositions.length; i++) {
+ var turret = game.addChild(new Turret());
+ turret.x = turretPositions[i].x;
+ turret.y = turretPositions[i].y;
+ turrets.push(turret);
+}
// Create goal
goal = game.addChild(LK.getAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
@@ -643,8 +816,16 @@
}, 500);
return;
}
}
+ // Check collision with homing missiles
+ for (var i = homingMissiles.length - 1; i >= 0; i--) {
+ var missile = homingMissiles[i];
+ if (player.intersects(missile) && !missile.hasExploded) {
+ missile.explode();
+ return;
+ }
+ }
// Check if player reached goal
if (player.intersects(goal)) {
gameWon = true;
LK.effects.flashScreen(0x00FF00, 1000);