User prompt
range of platform not to far
User prompt
player and enemies can move left and right
User prompt
player movement light movement
User prompt
reduce more player speed
User prompt
reduce speed player
User prompt
make platform and platform not to closed
User prompt
go another level after win
User prompt
range of platform dont to far
User prompt
erase text final score
User prompt
add crystal every platform
User prompt
just 5 platforms
User prompt
limited platform just 7 platforms
User prompt
restart level when game over
User prompt
restart level when game over
User prompt
add asset background
User prompt
7x jump
User prompt
erase unlimited jump
User prompt
unlimited jump
User prompt
5x jump
User prompt
reduce speed player
User prompt
jump attack
Code edit (1 edits merged)
Please save this source code
User prompt
Dash Assault: Aerial Onslaught
User prompt
Please continue polishing my design document.
Initial prompt
make static random platform. dash attack game.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Crystal = Container.expand(function () { var self = Container.call(this); var crystalGraphics = self.attachAsset('crystal', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.update = function () { // Simple hover animation self.y += Math.sin(LK.ticks / 10) * 0.5; // Simple rotation crystalGraphics.rotation += 0.02; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = { x: 1, y: 0 }; self.patrolDistance = 100; self.startX = 0; self.direction = 1; self.update = function () { self.x += self.velocity.x * self.direction; if (self.x < 0) { self.x = 0; self.direction *= -1; } else if (self.x > GAME_WIDTH) { self.x = GAME_WIDTH; self.direction *= -1; } // Change direction when patrol limit reached if (Math.abs(self.x - self.startX) > self.patrolDistance) { self.direction *= -1; } }; self.initialize = function (x, y, patrolDistance) { self.x = x; self.y = y; self.startX = x; self.patrolDistance = patrolDistance || 100; }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.width = platformGraphics.width; self.height = platformGraphics.height; return self; }); var Player = Container.expand(function () { var self = Container.call(this); // Player visual var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Player properties self.velocity = { x: 0, y: 0 }; self.gravity = 0.1; self.jumpStrength = -15; self.isGrounded = false; self.canDash = true; self.dashCooldown = 30; // frames self.dashCooldownTimer = 0; self.dashSpeed = 10; self.dashDuration = 10; // frames self.dashTimer = 0; self.isDashing = false; self.dashDirection = { x: 0, y: 0 }; self.dashDistanceMultiplier = 1; // Dash effect var dashEffect = self.attachAsset('dashEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.update = function () { // Apply gravity if not dashing if (!self.isDashing) { self.velocity.y += self.gravity; } // Handle dash cooldown if (!self.canDash) { self.dashCooldownTimer--; if (self.dashCooldownTimer <= 0) { self.canDash = true; } } // Handle dash execution if (self.isDashing) { self.dashTimer--; // Apply dash movement self.x += self.dashDirection.x * self.dashSpeed * self.dashDistanceMultiplier; self.y += self.dashDirection.y * self.dashSpeed * self.dashDistanceMultiplier; // End dash if (self.dashTimer <= 0) { self.isDashing = false; tween(dashEffect, { alpha: 0 }, { duration: 200 }); self.velocity.x = self.dashDirection.x * 5; // Maintain some momentum self.velocity.y = self.dashDirection.y * 5; } } else { // Normal movement self.x += self.velocity.x; if (self.x < 0) { self.x = 0; self.velocity.x = 0; } else if (self.x > GAME_WIDTH) { self.x = GAME_WIDTH; self.velocity.x = 0; } self.y += self.velocity.y; // Dampen horizontal velocity self.velocity.x *= 0.95; } // Reset grounded status each frame self.isGrounded = false; }; self.dash = function (dirX, dirY) { if (!self.canDash) { return; } // Normalize direction var magnitude = Math.sqrt(dirX * dirX + dirY * dirY); if (magnitude === 0) { return; } // Prevent division by zero self.dashDirection.x = dirX / magnitude; self.dashDirection.y = dirY / magnitude; // Start dash self.isDashing = true; self.dashTimer = self.dashDuration; self.velocity.x = 0; self.velocity.y = 0; // Start cooldown self.canDash = false; self.dashCooldownTimer = self.dashCooldown; // Visual effect dashEffect.x = 0; dashEffect.y = 0; tween(dashEffect, { alpha: 0.7 }, { duration: 100 }); // Play sound LK.getSound('dash').play(); }; self.jump = function () { if (self.isGrounded) { self.velocity.y = self.jumpStrength; self.isGrounded = false; } else if (!self.isDashing && self.canDash) { self.dash(0, -1); // Perform a vertical dash if in the air and dash is available } }; self.upgradeDash = function () { // Increase dash distance self.dashDistanceMultiplier += 0.2; if (self.dashDistanceMultiplier > 2) { self.dashDistanceMultiplier = 2; } // Decrease cooldown self.dashCooldown -= 5; if (self.dashCooldown < 15) { self.dashCooldown = 15; } }; return self; }); var Portal = Container.expand(function () { var self = Container.call(this); var portalGraphics = self.attachAsset('portal', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Portal pulsing effect var scale = 1 + Math.sin(LK.ticks / 15) * 0.1; portalGraphics.scale.set(scale, scale); // Portal rotation portalGraphics.rotation += 0.01; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var PLATFORM_COUNT = 5; var ENEMY_COUNT = 5; var CRYSTAL_COUNT = 3; // Game state var currentLevel = storage.currentLevel || 1; var crystalsCollected = 0; var totalCrystals = 0; // Game entities var player; var platforms = []; var enemies = []; var crystals = []; var portal; // UI elements var levelText = new Text2("Level " + currentLevel, { size: 80, fill: 0xFFFFFF }); var crystalCountText = new Text2("Crystals: 0/" + CRYSTAL_COUNT, { size: 60, fill: 0xFFFFFF }); // Setup game elements function setupGame() { // Add background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH / 2, y: GAME_HEIGHT / 2 }); game.addChild(background); // Create player platforms = []; enemies = []; crystals = []; crystalsCollected = 0; totalCrystals = CRYSTAL_COUNT; // Create player player = new Player(); player.x = GAME_WIDTH / 2; player.y = GAME_HEIGHT - 200; game.addChild(player); // Create initial platform under player var startPlatform = new Platform(); startPlatform.x = GAME_WIDTH / 2; startPlatform.y = GAME_HEIGHT - 150; game.addChild(startPlatform); platforms.push(startPlatform); // Generate level generateLevel(); // Add portal at the highest platform var highestPlatform = platforms.reduce(function (prev, current) { return prev.y < current.y ? prev : current; }); portal = new Portal(); portal.x = highestPlatform.x; portal.y = highestPlatform.y - 100; game.addChild(portal); // Update UI levelText.setText("Level " + currentLevel); crystalCountText.setText("Crystals: " + crystalsCollected + "/" + totalCrystals); // Add UI to game LK.gui.top.addChild(levelText); levelText.anchor.set(0.5, 0); levelText.y = 50; LK.gui.topRight.addChild(crystalCountText); crystalCountText.anchor.set(1, 0); crystalCountText.x = -50; crystalCountText.y = 50; // Play background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.5, duration: 1000 } }); } function generateLevel() { // Generate platforms with increasing difficulty based on level var minGapX = 100 + currentLevel * 5; // Adjusted minimum horizontal gap var maxGapX = 200 + currentLevel * 10; // Adjusted maximum horizontal gap var minGapY = 100; // Adjusted minimum vertical gap var maxGapY = 150 + currentLevel * 5; // Adjusted maximum vertical gap var lastX = GAME_WIDTH / 2; var lastY = GAME_HEIGHT - 150; for (var i = 0; i < PLATFORM_COUNT; i++) { var platform = new Platform(); // Calculate new position with gaps var gapX = Math.random() * (maxGapX - minGapX) + minGapX; var gapY = Math.random() * (maxGapY - minGapY) + minGapY; // Alternate direction var directionX = Math.random() > 0.5 ? 1 : -1; var newX = lastX + gapX * directionX; var newY = lastY - gapY; // Keep platforms within bounds newX = Math.max(platform.width / 2, Math.min(GAME_WIDTH - platform.width / 2, newX)); platform.x = newX; platform.y = newY; game.addChild(platform); platforms.push(platform); lastX = newX; lastY = newY; // Add a crystal to each platform var crystal = new Crystal(); crystal.x = platform.x; crystal.y = platform.y - 50; // Position crystal above the platform game.addChild(crystal); crystals.push(crystal); // Add enemy on some platforms if (i > 0 && Math.random() < 0.3 && enemies.length < ENEMY_COUNT) { var enemy = new Enemy(); enemy.initialize(newX, newY - 50, platform.width * 0.8); game.addChild(enemy); enemies.push(enemy); } } // Add crystals in challenging positions for (var j = 0; j < CRYSTAL_COUNT; j++) { var crystal = new Crystal(); // Place crystals in challenging positions between platforms var platformIndex = Math.floor(Math.random() * (platforms.length - 1)) + 1; var platform1 = platforms[platformIndex - 1]; var platform2 = platforms[platformIndex]; crystal.x = platform1.x + (platform2.x - platform1.x) * 0.5; crystal.y = platform1.y + (platform2.y - platform1.y) * 0.5; game.addChild(crystal); crystals.push(crystal); } } function checkCollisions() { // Player-Platform collision platforms.forEach(function (platform) { if (player.y + 30 >= platform.y - platform.height / 2 && player.y - 30 <= platform.y + platform.height / 2 && player.x + 30 >= platform.x - platform.width / 2 && player.x - 30 <= platform.x + platform.width / 2 && player.velocity.y > 0) { player.y = platform.y - platform.height / 2 - 30; player.velocity.y = 0; player.isGrounded = true; } }); // Player-Enemy collision enemies.forEach(function (enemy, index) { if (player.isDashing && player.intersects(enemy)) { // Destroy enemy if player is dashing LK.effects.flashObject(enemy, 0xff0000, 300); LK.getSound('enemyDefeat').play(); LK.setTimeout(function () { enemy.destroy(); enemies.splice(index, 1); }, 300); } else if (!player.isDashing && player.intersects(enemy)) { // Player dies if not dashing LK.effects.flashScreen(0xff0000, 1000); resetGame(); } }); // Player-Crystal collision crystals.forEach(function (crystal, index) { if (!crystal.collected && player.intersects(crystal)) { crystal.collected = true; crystalsCollected++; // Visual effect tween(crystal, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { crystal.destroy(); crystals.splice(index, 1); } }); // Update UI crystalCountText.setText("Crystals: " + crystalsCollected + "/" + totalCrystals); // Play sound LK.getSound('crystal').play(); // Upgrade player player.upgradeDash(); } }); // Player-Portal collision if (player.intersects(portal)) { // Complete level LK.getSound('portalReached').play(); // Transition effect tween(portal, { scaleX: 3, scaleY: 3, alpha: 0.2 }, { duration: 1000, onFinish: function onFinish() { // Save progress and go to next level currentLevel++; storage.currentLevel = currentLevel; // Check if all levels are completed if (currentLevel > 10) { LK.showYouWin(); } else { // Transition to the next level setupGame(); } } }); } // Check if player fell off the bottom of the screen if (player.y > GAME_HEIGHT + 100) { LK.effects.flashScreen(0xff0000, 1000); resetGame(); } } function resetGame() { // Destroy existing entities if (player) { player.destroy(); } platforms.forEach(function (p) { return p.destroy(); }); enemies.forEach(function (e) { return e.destroy(); }); crystals.forEach(function (c) { return c.destroy(); }); if (portal) { portal.destroy(); } // Remove UI LK.gui.top.removeChild(levelText); LK.gui.topRight.removeChild(crystalCountText); // Final score text is not displayed, so no need to remove it // Setup new game setupGame(); } // Mouse/touch controls var startDragX = 0; var startDragY = 0; var isDragging = false; game.down = function (x, y) { startDragX = x; startDragY = y; isDragging = true; }; game.move = function (x, y) { // Used for drag-to-dash functionality }; game.up = function (x, y) { if (!isDragging || !player) { return; } // Calculate direction vector var dirX = x - startDragX; var dirY = y - startDragY; // Calculate magnitude var magnitude = Math.sqrt(dirX * dirX + dirY * dirY); // If the drag was long enough, dash in that direction if (magnitude > 30) { player.dash(dirX / magnitude, dirY / magnitude); } else { player.jump(); } isDragging = false; }; // Main game loop game.update = function () { // Skip if game hasn't been set up yet if (!player) { return; } // Update all game entities player.update(); platforms.forEach(function (platform) { return platform.update && platform.update(); }); enemies.forEach(function (enemy) { return enemy.update(); }); crystals.forEach(function (crystal) { return crystal.update(); }); if (portal) { portal.update(); } // Check for collisions checkCollisions(); }; // Initialize game setupGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Crystal = Container.expand(function () {
var self = Container.call(this);
var crystalGraphics = self.attachAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
// Simple hover animation
self.y += Math.sin(LK.ticks / 10) * 0.5;
// Simple rotation
crystalGraphics.rotation += 0.02;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 1,
y: 0
};
self.patrolDistance = 100;
self.startX = 0;
self.direction = 1;
self.update = function () {
self.x += self.velocity.x * self.direction;
if (self.x < 0) {
self.x = 0;
self.direction *= -1;
} else if (self.x > GAME_WIDTH) {
self.x = GAME_WIDTH;
self.direction *= -1;
}
// Change direction when patrol limit reached
if (Math.abs(self.x - self.startX) > self.patrolDistance) {
self.direction *= -1;
}
};
self.initialize = function (x, y, patrolDistance) {
self.x = x;
self.y = y;
self.startX = x;
self.patrolDistance = patrolDistance || 100;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = platformGraphics.width;
self.height = platformGraphics.height;
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Player visual
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Player properties
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.1;
self.jumpStrength = -15;
self.isGrounded = false;
self.canDash = true;
self.dashCooldown = 30; // frames
self.dashCooldownTimer = 0;
self.dashSpeed = 10;
self.dashDuration = 10; // frames
self.dashTimer = 0;
self.isDashing = false;
self.dashDirection = {
x: 0,
y: 0
};
self.dashDistanceMultiplier = 1;
// Dash effect
var dashEffect = self.attachAsset('dashEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.update = function () {
// Apply gravity if not dashing
if (!self.isDashing) {
self.velocity.y += self.gravity;
}
// Handle dash cooldown
if (!self.canDash) {
self.dashCooldownTimer--;
if (self.dashCooldownTimer <= 0) {
self.canDash = true;
}
}
// Handle dash execution
if (self.isDashing) {
self.dashTimer--;
// Apply dash movement
self.x += self.dashDirection.x * self.dashSpeed * self.dashDistanceMultiplier;
self.y += self.dashDirection.y * self.dashSpeed * self.dashDistanceMultiplier;
// End dash
if (self.dashTimer <= 0) {
self.isDashing = false;
tween(dashEffect, {
alpha: 0
}, {
duration: 200
});
self.velocity.x = self.dashDirection.x * 5; // Maintain some momentum
self.velocity.y = self.dashDirection.y * 5;
}
} else {
// Normal movement
self.x += self.velocity.x;
if (self.x < 0) {
self.x = 0;
self.velocity.x = 0;
} else if (self.x > GAME_WIDTH) {
self.x = GAME_WIDTH;
self.velocity.x = 0;
}
self.y += self.velocity.y;
// Dampen horizontal velocity
self.velocity.x *= 0.95;
}
// Reset grounded status each frame
self.isGrounded = false;
};
self.dash = function (dirX, dirY) {
if (!self.canDash) {
return;
}
// Normalize direction
var magnitude = Math.sqrt(dirX * dirX + dirY * dirY);
if (magnitude === 0) {
return;
} // Prevent division by zero
self.dashDirection.x = dirX / magnitude;
self.dashDirection.y = dirY / magnitude;
// Start dash
self.isDashing = true;
self.dashTimer = self.dashDuration;
self.velocity.x = 0;
self.velocity.y = 0;
// Start cooldown
self.canDash = false;
self.dashCooldownTimer = self.dashCooldown;
// Visual effect
dashEffect.x = 0;
dashEffect.y = 0;
tween(dashEffect, {
alpha: 0.7
}, {
duration: 100
});
// Play sound
LK.getSound('dash').play();
};
self.jump = function () {
if (self.isGrounded) {
self.velocity.y = self.jumpStrength;
self.isGrounded = false;
} else if (!self.isDashing && self.canDash) {
self.dash(0, -1); // Perform a vertical dash if in the air and dash is available
}
};
self.upgradeDash = function () {
// Increase dash distance
self.dashDistanceMultiplier += 0.2;
if (self.dashDistanceMultiplier > 2) {
self.dashDistanceMultiplier = 2;
}
// Decrease cooldown
self.dashCooldown -= 5;
if (self.dashCooldown < 15) {
self.dashCooldown = 15;
}
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var portalGraphics = self.attachAsset('portal', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Portal pulsing effect
var scale = 1 + Math.sin(LK.ticks / 15) * 0.1;
portalGraphics.scale.set(scale, scale);
// Portal rotation
portalGraphics.rotation += 0.01;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLATFORM_COUNT = 5;
var ENEMY_COUNT = 5;
var CRYSTAL_COUNT = 3;
// Game state
var currentLevel = storage.currentLevel || 1;
var crystalsCollected = 0;
var totalCrystals = 0;
// Game entities
var player;
var platforms = [];
var enemies = [];
var crystals = [];
var portal;
// UI elements
var levelText = new Text2("Level " + currentLevel, {
size: 80,
fill: 0xFFFFFF
});
var crystalCountText = new Text2("Crystals: 0/" + CRYSTAL_COUNT, {
size: 60,
fill: 0xFFFFFF
});
// Setup game elements
function setupGame() {
// Add background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2
});
game.addChild(background);
// Create player
platforms = [];
enemies = [];
crystals = [];
crystalsCollected = 0;
totalCrystals = CRYSTAL_COUNT;
// Create player
player = new Player();
player.x = GAME_WIDTH / 2;
player.y = GAME_HEIGHT - 200;
game.addChild(player);
// Create initial platform under player
var startPlatform = new Platform();
startPlatform.x = GAME_WIDTH / 2;
startPlatform.y = GAME_HEIGHT - 150;
game.addChild(startPlatform);
platforms.push(startPlatform);
// Generate level
generateLevel();
// Add portal at the highest platform
var highestPlatform = platforms.reduce(function (prev, current) {
return prev.y < current.y ? prev : current;
});
portal = new Portal();
portal.x = highestPlatform.x;
portal.y = highestPlatform.y - 100;
game.addChild(portal);
// Update UI
levelText.setText("Level " + currentLevel);
crystalCountText.setText("Crystals: " + crystalsCollected + "/" + totalCrystals);
// Add UI to game
LK.gui.top.addChild(levelText);
levelText.anchor.set(0.5, 0);
levelText.y = 50;
LK.gui.topRight.addChild(crystalCountText);
crystalCountText.anchor.set(1, 0);
crystalCountText.x = -50;
crystalCountText.y = 50;
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.5,
duration: 1000
}
});
}
function generateLevel() {
// Generate platforms with increasing difficulty based on level
var minGapX = 100 + currentLevel * 5; // Adjusted minimum horizontal gap
var maxGapX = 200 + currentLevel * 10; // Adjusted maximum horizontal gap
var minGapY = 100; // Adjusted minimum vertical gap
var maxGapY = 150 + currentLevel * 5; // Adjusted maximum vertical gap
var lastX = GAME_WIDTH / 2;
var lastY = GAME_HEIGHT - 150;
for (var i = 0; i < PLATFORM_COUNT; i++) {
var platform = new Platform();
// Calculate new position with gaps
var gapX = Math.random() * (maxGapX - minGapX) + minGapX;
var gapY = Math.random() * (maxGapY - minGapY) + minGapY;
// Alternate direction
var directionX = Math.random() > 0.5 ? 1 : -1;
var newX = lastX + gapX * directionX;
var newY = lastY - gapY;
// Keep platforms within bounds
newX = Math.max(platform.width / 2, Math.min(GAME_WIDTH - platform.width / 2, newX));
platform.x = newX;
platform.y = newY;
game.addChild(platform);
platforms.push(platform);
lastX = newX;
lastY = newY;
// Add a crystal to each platform
var crystal = new Crystal();
crystal.x = platform.x;
crystal.y = platform.y - 50; // Position crystal above the platform
game.addChild(crystal);
crystals.push(crystal);
// Add enemy on some platforms
if (i > 0 && Math.random() < 0.3 && enemies.length < ENEMY_COUNT) {
var enemy = new Enemy();
enemy.initialize(newX, newY - 50, platform.width * 0.8);
game.addChild(enemy);
enemies.push(enemy);
}
}
// Add crystals in challenging positions
for (var j = 0; j < CRYSTAL_COUNT; j++) {
var crystal = new Crystal();
// Place crystals in challenging positions between platforms
var platformIndex = Math.floor(Math.random() * (platforms.length - 1)) + 1;
var platform1 = platforms[platformIndex - 1];
var platform2 = platforms[platformIndex];
crystal.x = platform1.x + (platform2.x - platform1.x) * 0.5;
crystal.y = platform1.y + (platform2.y - platform1.y) * 0.5;
game.addChild(crystal);
crystals.push(crystal);
}
}
function checkCollisions() {
// Player-Platform collision
platforms.forEach(function (platform) {
if (player.y + 30 >= platform.y - platform.height / 2 && player.y - 30 <= platform.y + platform.height / 2 && player.x + 30 >= platform.x - platform.width / 2 && player.x - 30 <= platform.x + platform.width / 2 && player.velocity.y > 0) {
player.y = platform.y - platform.height / 2 - 30;
player.velocity.y = 0;
player.isGrounded = true;
}
});
// Player-Enemy collision
enemies.forEach(function (enemy, index) {
if (player.isDashing && player.intersects(enemy)) {
// Destroy enemy if player is dashing
LK.effects.flashObject(enemy, 0xff0000, 300);
LK.getSound('enemyDefeat').play();
LK.setTimeout(function () {
enemy.destroy();
enemies.splice(index, 1);
}, 300);
} else if (!player.isDashing && player.intersects(enemy)) {
// Player dies if not dashing
LK.effects.flashScreen(0xff0000, 1000);
resetGame();
}
});
// Player-Crystal collision
crystals.forEach(function (crystal, index) {
if (!crystal.collected && player.intersects(crystal)) {
crystal.collected = true;
crystalsCollected++;
// Visual effect
tween(crystal, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
crystal.destroy();
crystals.splice(index, 1);
}
});
// Update UI
crystalCountText.setText("Crystals: " + crystalsCollected + "/" + totalCrystals);
// Play sound
LK.getSound('crystal').play();
// Upgrade player
player.upgradeDash();
}
});
// Player-Portal collision
if (player.intersects(portal)) {
// Complete level
LK.getSound('portalReached').play();
// Transition effect
tween(portal, {
scaleX: 3,
scaleY: 3,
alpha: 0.2
}, {
duration: 1000,
onFinish: function onFinish() {
// Save progress and go to next level
currentLevel++;
storage.currentLevel = currentLevel;
// Check if all levels are completed
if (currentLevel > 10) {
LK.showYouWin();
} else {
// Transition to the next level
setupGame();
}
}
});
}
// Check if player fell off the bottom of the screen
if (player.y > GAME_HEIGHT + 100) {
LK.effects.flashScreen(0xff0000, 1000);
resetGame();
}
}
function resetGame() {
// Destroy existing entities
if (player) {
player.destroy();
}
platforms.forEach(function (p) {
return p.destroy();
});
enemies.forEach(function (e) {
return e.destroy();
});
crystals.forEach(function (c) {
return c.destroy();
});
if (portal) {
portal.destroy();
}
// Remove UI
LK.gui.top.removeChild(levelText);
LK.gui.topRight.removeChild(crystalCountText);
// Final score text is not displayed, so no need to remove it
// Setup new game
setupGame();
}
// Mouse/touch controls
var startDragX = 0;
var startDragY = 0;
var isDragging = false;
game.down = function (x, y) {
startDragX = x;
startDragY = y;
isDragging = true;
};
game.move = function (x, y) {
// Used for drag-to-dash functionality
};
game.up = function (x, y) {
if (!isDragging || !player) {
return;
}
// Calculate direction vector
var dirX = x - startDragX;
var dirY = y - startDragY;
// Calculate magnitude
var magnitude = Math.sqrt(dirX * dirX + dirY * dirY);
// If the drag was long enough, dash in that direction
if (magnitude > 30) {
player.dash(dirX / magnitude, dirY / magnitude);
} else {
player.jump();
}
isDragging = false;
};
// Main game loop
game.update = function () {
// Skip if game hasn't been set up yet
if (!player) {
return;
}
// Update all game entities
player.update();
platforms.forEach(function (platform) {
return platform.update && platform.update();
});
enemies.forEach(function (enemy) {
return enemy.update();
});
crystals.forEach(function (crystal) {
return crystal.update();
});
if (portal) {
portal.update();
}
// Check for collisions
checkCollisions();
};
// Initialize game
setupGame();
chibi 8 bit image green hopper insect anime protagonist. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
8 bit image anime green leaf. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
8 bit image 2d brown classic old door with beehive pattern. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows