/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; return self; }); var Rock = Container.expand(function (rockType) { var self = Container.call(this); var assetName = rockType || 'rock_medium'; var rockGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); // Set falling speed based on rock type if (assetName === 'rock_small') { self.fallSpeed = 3; } else if (assetName === 'rock_medium') { self.fallSpeed = 4; } else { self.fallSpeed = 2; } // Add chance for fast-falling rocks (20% chance) if (Math.random() < 0.2) { self.fallSpeed *= 2.5; // Make some rocks fall much faster } // Store rock type for breaking logic self.rockType = assetName; self.update = function () { // Check collision with other rocks before moving var proposedY = self.y + self.fallSpeed; var canMove = true; var collidingRock = null; // Check against all other rocks for (var i = 0; i < rocks.length; i++) { var otherRock = rocks[i]; if (otherRock === self) continue; // Skip self // Check if we would collide with another rock var tempY = self.y; self.y = proposedY; if (self.intersects(otherRock)) { canMove = false; collidingRock = otherRock; } self.y = tempY; // Restore original position if (!canMove) break; } // If collision detected, break both rocks if (!canMove && collidingRock) { self.shouldBreak = true; collidingRock.shouldBreak = true; } // Only move if no collision would occur if (canMove) { self.y = proposedY; } }; return self; }); var RockPiece = Container.expand(function (size) { var self = Container.call(this); var pieceGraphics = self.attachAsset('rock_small', { anchorX: 0.5, anchorY: 0.5 }); // Scale down based on size parameter var scale = size || 0.3; pieceGraphics.scaleX = scale; pieceGraphics.scaleY = scale; // Random velocity for flying pieces self.velocityX = (Math.random() - 0.5) * 8; self.velocityY = -Math.random() * 5 - 2; self.gravity = 0.3; self.lifeTime = 0; self.maxLifeTime = 120; // 2 seconds at 60fps self.update = function () { // Apply physics self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; // Fade out over time self.lifeTime++; var alpha = 1 - self.lifeTime / self.maxLifeTime; pieceGraphics.alpha = Math.max(0, alpha); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb }); /**** * Game Code ****/ // Game variables var player; var rocks = []; var rockPieces = []; var rockSpawnTimer = 0; var rockSpawnDelay = 90; // Initial spawn delay (60fps = 1.5 seconds) var gameSpeed = 1; var speedIncreaseTimer = 0; var dragNode = null; // UI Elements var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var timeTxt = new Text2('Time: 0s', { size: 60, fill: 0xFFFFFF }); timeTxt.anchor.set(0, 0); timeTxt.x = 50; timeTxt.y = 150; LK.gui.topLeft.addChild(timeTxt); // Initialize player player = game.addChild(new Player()); player.x = 2048 / 2; player.y = 2732 - 150; // Game state tracking var gameTime = 0; var lastIntersecting = false; // Rock types for variety var rockTypes = ['rock_small', 'rock_medium', 'rock_large']; // Event handlers function handleMove(x, y, obj) { if (dragNode) { // Convert to game coordinates and constrain to screen bounds var newX = x; var playerWidth = 40; // Half width for boundary checking if (newX < playerWidth) { newX = playerWidth; } else if (newX > 2048 - playerWidth) { newX = 2048 - playerWidth; } dragNode.x = newX; } } game.move = handleMove; game.down = function (x, y, obj) { dragNode = player; handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; }; // Function to create rock pieces when rocks break function createRockPieces(rock) { var numPieces = 4 + Math.floor(Math.random() * 4); // 4-7 pieces for (var p = 0; p < numPieces; p++) { var piece = new RockPiece(0.2 + Math.random() * 0.3); piece.x = rock.x + (Math.random() - 0.5) * 40; piece.y = rock.y + (Math.random() - 0.5) * 40; rockPieces.push(piece); game.addChild(piece); } } // Spawn rock function function spawnRock() { var rockType = rockTypes[Math.floor(Math.random() * rockTypes.length)]; var newRock = new Rock(rockType); // Try to find a safe horizontal position to prevent immediate overlap var attempts = 0; var safePosition = false; var proposedX; while (!safePosition && attempts < 10) { proposedX = Math.random() * (2048 - 200) + 100; safePosition = true; // Check against existing rocks in the spawn area for (var i = 0; i < rocks.length; i++) { var existingRock = rocks[i]; if (existingRock.y < 200) { // Only check rocks near spawn area var distance = Math.abs(existingRock.x - proposedX); if (distance < 150) { // Minimum spacing safePosition = false; break; } } } attempts++; } newRock.x = proposedX; newRock.y = -100 - Math.random() * 50; // Vary spawn height slightly // Apply game speed multiplier newRock.fallSpeed *= gameSpeed; // Initialize tracking variables newRock.lastY = newRock.y; newRock.lastIntersecting = false; rocks.push(newRock); game.addChild(newRock); } // Main game update loop game.update = function () { gameTime++; // Update score and time display var seconds = Math.floor(gameTime / 60); LK.setScore(seconds); scoreTxt.setText(LK.getScore()); timeTxt.setText('Time: ' + seconds + 's'); // Increase difficulty over time speedIncreaseTimer++; if (speedIncreaseTimer >= 300) { // Every 5 seconds speedIncreaseTimer = 0; gameSpeed += 0.1; if (rockSpawnDelay > 10) { rockSpawnDelay -= 5; // Reduce spawn delay even more aggressively } // Ensure minimum spawn delay if (rockSpawnDelay < 8) { rockSpawnDelay = 8; } } // Spawn rocks rockSpawnTimer++; if (rockSpawnTimer >= rockSpawnDelay) { rockSpawnTimer = 0; // Spawn multiple rocks based on game progression var rocksToSpawn = 1; if (seconds > 15) rocksToSpawn = 2; if (seconds > 30) rocksToSpawn = 3; if (seconds > 45) rocksToSpawn = 4; if (seconds > 60) rocksToSpawn = 5; if (seconds > 90) rocksToSpawn = 6; if (seconds > 120) rocksToSpawn = 7; for (var spawnCount = 0; spawnCount < rocksToSpawn; spawnCount++) { spawnRock(); } } // Additional frequent spawning for more rocks if (rockSpawnTimer % Math.max(15, rockSpawnDelay / 3) === 0 && seconds > 10) { spawnRock(); } // Update and check rocks for (var i = rocks.length - 1; i >= 0; i--) { var rock = rocks[i]; // Check if rock should break if (rock.shouldBreak) { createRockPieces(rock); rock.destroy(); rocks.splice(i, 1); continue; } // Track off-screen removal if (rock.lastY <= 2732 + 100 && rock.y > 2732 + 100) { rock.destroy(); rocks.splice(i, 1); continue; } // Check collision with player var currentIntersecting = rock.intersects(player); if (!rock.lastIntersecting && currentIntersecting) { // Collision detected - game over LK.getSound('hit').play(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } // Update tracking variables rock.lastY = rock.y; rock.lastIntersecting = currentIntersecting; } // Update rock pieces for (var j = rockPieces.length - 1; j >= 0; j--) { var piece = rockPieces[j]; // Remove pieces that have expired if (piece.lifeTime >= piece.maxLifeTime) { piece.destroy(); rockPieces.splice(j, 1); continue; } // Remove pieces that fall off screen if (piece.y > 2732 + 100) { piece.destroy(); rockPieces.splice(j, 1); continue; } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
return self;
});
var Rock = Container.expand(function (rockType) {
var self = Container.call(this);
var assetName = rockType || 'rock_medium';
var rockGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
// Set falling speed based on rock type
if (assetName === 'rock_small') {
self.fallSpeed = 3;
} else if (assetName === 'rock_medium') {
self.fallSpeed = 4;
} else {
self.fallSpeed = 2;
}
// Add chance for fast-falling rocks (20% chance)
if (Math.random() < 0.2) {
self.fallSpeed *= 2.5; // Make some rocks fall much faster
}
// Store rock type for breaking logic
self.rockType = assetName;
self.update = function () {
// Check collision with other rocks before moving
var proposedY = self.y + self.fallSpeed;
var canMove = true;
var collidingRock = null;
// Check against all other rocks
for (var i = 0; i < rocks.length; i++) {
var otherRock = rocks[i];
if (otherRock === self) continue; // Skip self
// Check if we would collide with another rock
var tempY = self.y;
self.y = proposedY;
if (self.intersects(otherRock)) {
canMove = false;
collidingRock = otherRock;
}
self.y = tempY; // Restore original position
if (!canMove) break;
}
// If collision detected, break both rocks
if (!canMove && collidingRock) {
self.shouldBreak = true;
collidingRock.shouldBreak = true;
}
// Only move if no collision would occur
if (canMove) {
self.y = proposedY;
}
};
return self;
});
var RockPiece = Container.expand(function (size) {
var self = Container.call(this);
var pieceGraphics = self.attachAsset('rock_small', {
anchorX: 0.5,
anchorY: 0.5
});
// Scale down based on size parameter
var scale = size || 0.3;
pieceGraphics.scaleX = scale;
pieceGraphics.scaleY = scale;
// Random velocity for flying pieces
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = -Math.random() * 5 - 2;
self.gravity = 0.3;
self.lifeTime = 0;
self.maxLifeTime = 120; // 2 seconds at 60fps
self.update = function () {
// Apply physics
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Fade out over time
self.lifeTime++;
var alpha = 1 - self.lifeTime / self.maxLifeTime;
pieceGraphics.alpha = Math.max(0, alpha);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Game variables
var player;
var rocks = [];
var rockPieces = [];
var rockSpawnTimer = 0;
var rockSpawnDelay = 90; // Initial spawn delay (60fps = 1.5 seconds)
var gameSpeed = 1;
var speedIncreaseTimer = 0;
var dragNode = null;
// UI Elements
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0, 0);
timeTxt.x = 50;
timeTxt.y = 150;
LK.gui.topLeft.addChild(timeTxt);
// Initialize player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150;
// Game state tracking
var gameTime = 0;
var lastIntersecting = false;
// Rock types for variety
var rockTypes = ['rock_small', 'rock_medium', 'rock_large'];
// Event handlers
function handleMove(x, y, obj) {
if (dragNode) {
// Convert to game coordinates and constrain to screen bounds
var newX = x;
var playerWidth = 40; // Half width for boundary checking
if (newX < playerWidth) {
newX = playerWidth;
} else if (newX > 2048 - playerWidth) {
newX = 2048 - playerWidth;
}
dragNode.x = newX;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Function to create rock pieces when rocks break
function createRockPieces(rock) {
var numPieces = 4 + Math.floor(Math.random() * 4); // 4-7 pieces
for (var p = 0; p < numPieces; p++) {
var piece = new RockPiece(0.2 + Math.random() * 0.3);
piece.x = rock.x + (Math.random() - 0.5) * 40;
piece.y = rock.y + (Math.random() - 0.5) * 40;
rockPieces.push(piece);
game.addChild(piece);
}
}
// Spawn rock function
function spawnRock() {
var rockType = rockTypes[Math.floor(Math.random() * rockTypes.length)];
var newRock = new Rock(rockType);
// Try to find a safe horizontal position to prevent immediate overlap
var attempts = 0;
var safePosition = false;
var proposedX;
while (!safePosition && attempts < 10) {
proposedX = Math.random() * (2048 - 200) + 100;
safePosition = true;
// Check against existing rocks in the spawn area
for (var i = 0; i < rocks.length; i++) {
var existingRock = rocks[i];
if (existingRock.y < 200) {
// Only check rocks near spawn area
var distance = Math.abs(existingRock.x - proposedX);
if (distance < 150) {
// Minimum spacing
safePosition = false;
break;
}
}
}
attempts++;
}
newRock.x = proposedX;
newRock.y = -100 - Math.random() * 50; // Vary spawn height slightly
// Apply game speed multiplier
newRock.fallSpeed *= gameSpeed;
// Initialize tracking variables
newRock.lastY = newRock.y;
newRock.lastIntersecting = false;
rocks.push(newRock);
game.addChild(newRock);
}
// Main game update loop
game.update = function () {
gameTime++;
// Update score and time display
var seconds = Math.floor(gameTime / 60);
LK.setScore(seconds);
scoreTxt.setText(LK.getScore());
timeTxt.setText('Time: ' + seconds + 's');
// Increase difficulty over time
speedIncreaseTimer++;
if (speedIncreaseTimer >= 300) {
// Every 5 seconds
speedIncreaseTimer = 0;
gameSpeed += 0.1;
if (rockSpawnDelay > 10) {
rockSpawnDelay -= 5; // Reduce spawn delay even more aggressively
}
// Ensure minimum spawn delay
if (rockSpawnDelay < 8) {
rockSpawnDelay = 8;
}
}
// Spawn rocks
rockSpawnTimer++;
if (rockSpawnTimer >= rockSpawnDelay) {
rockSpawnTimer = 0;
// Spawn multiple rocks based on game progression
var rocksToSpawn = 1;
if (seconds > 15) rocksToSpawn = 2;
if (seconds > 30) rocksToSpawn = 3;
if (seconds > 45) rocksToSpawn = 4;
if (seconds > 60) rocksToSpawn = 5;
if (seconds > 90) rocksToSpawn = 6;
if (seconds > 120) rocksToSpawn = 7;
for (var spawnCount = 0; spawnCount < rocksToSpawn; spawnCount++) {
spawnRock();
}
}
// Additional frequent spawning for more rocks
if (rockSpawnTimer % Math.max(15, rockSpawnDelay / 3) === 0 && seconds > 10) {
spawnRock();
}
// Update and check rocks
for (var i = rocks.length - 1; i >= 0; i--) {
var rock = rocks[i];
// Check if rock should break
if (rock.shouldBreak) {
createRockPieces(rock);
rock.destroy();
rocks.splice(i, 1);
continue;
}
// Track off-screen removal
if (rock.lastY <= 2732 + 100 && rock.y > 2732 + 100) {
rock.destroy();
rocks.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = rock.intersects(player);
if (!rock.lastIntersecting && currentIntersecting) {
// Collision detected - game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Update tracking variables
rock.lastY = rock.y;
rock.lastIntersecting = currentIntersecting;
}
// Update rock pieces
for (var j = rockPieces.length - 1; j >= 0; j--) {
var piece = rockPieces[j];
// Remove pieces that have expired
if (piece.lifeTime >= piece.maxLifeTime) {
piece.destroy();
rockPieces.splice(j, 1);
continue;
}
// Remove pieces that fall off screen
if (piece.y > 2732 + 100) {
piece.destroy();
rockPieces.splice(j, 1);
continue;
}
}
};