/****
* 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;
}
}
};