User prompt
ses ekle
User prompt
her blok konulduğunda ses ekle
User prompt
arka plan ekle
User prompt
özel yetenekler ekle
User prompt
arka plan oluştur
User prompt
blockler daha uzun ve biraz daha ince olsun
Code edit (1 edits merged)
Please save this source code
User prompt
Ice Stack Tower
Initial prompt
bana ıce tower benzeri bi oyun yap
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { best: 0 }); /**** * Classes ****/ // IceBlock class: represents a single moving or stacked ice block var IceBlock = Container.expand(function () { var self = Container.call(this); // Default block size (will be set on creation) self.blockWidth = 900; self.blockHeight = 70; self.color = 0xB3E6FF; // Light blue ice color // Create and attach the block asset var blockAsset = self.attachAsset('iceBlock', { width: self.blockWidth, height: self.blockHeight, color: self.color, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Update block asset size if changed self.setSize = function (w, h) { self.blockWidth = w; self.blockHeight = h; blockAsset.width = w; blockAsset.height = h; }; // Set color (for possible effects) self.setColor = function (color) { self.color = color; blockAsset.color = color; }; // Animate block to a new position (used for drop) self.animateTo = function (targetY, duration, onFinish) { tween(self, { y: targetY }, { duration: duration, easing: tween.cubicOut, onFinish: onFinish }); }; // Animate block shrink (used for misaligned drops) self.animateShrink = function (newWidth, duration, _onFinish) { tween(self, { blockWidth: newWidth }, { duration: duration, easing: tween.cubicInOut, onFinish: function onFinish() { self.setSize(newWidth, self.blockHeight); if (_onFinish) _onFinish(); } }); }; // For collision and alignment calculations self.getLeft = function () { return self.x - self.blockWidth / 2; }; self.getRight = function () { return self.x + self.blockWidth / 2; }; // For updating asset size if tweened self.update = function () { // If tweening blockWidth, update asset if (blockAsset.width !== self.blockWidth) { blockAsset.width = self.blockWidth; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Tween plugin for block drop and shrink animations // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; // Add background image to the game scene var bg = LK.getAsset('iceBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: GAME_WIDTH, height: GAME_HEIGHT }); game.addChild(bg); var START_BLOCK_WIDTH = 900; var BLOCK_HEIGHT = 70; var BLOCK_COLOR = 0xB3E6FF; var BLOCK_SPEED = 16; // px per frame var MIN_BLOCK_WIDTH = 80; // Minimum width before game over var DROP_ANIMATION_TIME = 180; // ms var SHRINK_ANIMATION_TIME = 120; // ms var START_Y = GAME_HEIGHT - 400; // Y position of the first block // Game state var stack = []; // Array of stacked blocks (bottom to top) var movingBlock = null; // The current moving block var movingDirection = 1; // 1 = right, -1 = left var isDropping = false; // Prevents double drop var scoreTxt = null; var bestTxt = null; var currentScore = 0; var bestScore = 0; // Special ability state var specialReady = true; var specialCooldown = 0; // ms remaining var SPECIAL_COOLDOWN_TIME = 5000; // 5 seconds cooldown var specialBtn = null; // Storage for best score if (typeof storage.best === 'number') { bestScore = storage.best; } // Score display scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); bestTxt = new Text2('Best: ' + bestScore, { size: 60, fill: 0xAEEFFF }); bestTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bestTxt); bestTxt.y = 120; // Special ability button specialBtn = new Text2('ICE POWER', { size: 70, fill: specialReady ? 0x00eaff : 0x888888 }); specialBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(specialBtn); specialBtn.y = -120; // Raise above bottom edge specialBtn.x = 0; // Centered // Cooldown text var cooldownTxt = new Text2('', { size: 40, fill: 0xAEEFFF }); cooldownTxt.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(cooldownTxt); cooldownTxt.y = -40; cooldownTxt.x = 0; // Helper: update score display function updateScoreDisplay() { scoreTxt.setText(currentScore); if (currentScore > bestScore) { bestScore = currentScore; storage.best = bestScore; bestTxt.setText('Best: ' + bestScore); } } // Helper: center X for a block function getCenterX() { return GAME_WIDTH / 2; } // Helper: spawn a new moving block function spawnMovingBlock(width) { var block = new IceBlock(); block.setSize(width, BLOCK_HEIGHT); block.setColor(BLOCK_COLOR); // Start above the last block, or at START_Y if first var y = START_Y - stack.length * BLOCK_HEIGHT; block.y = y; block.blockHeight = BLOCK_HEIGHT; // Start at left or right edge, alternate each time if (stack.length % 2 === 0) { block.x = 0 + width / 2; movingDirection = 1; } else { block.x = GAME_WIDTH - width / 2; movingDirection = -1; } game.addChild(block); return block; } // Helper: get top block (last in stack) function getTopBlock() { if (stack.length === 0) return null; return stack[stack.length - 1]; } // Helper: drop the moving block function dropBlock() { if (!movingBlock || isDropping) return; isDropping = true; // Find where the block should land (on top of stack or at START_Y) var targetY = START_Y - stack.length * BLOCK_HEIGHT; // Animate drop movingBlock.animateTo(targetY, DROP_ANIMATION_TIME, function () { // After drop, check alignment var prevBlock = getTopBlock(); var overlapLeft, overlapRight, overlapWidth; if (prevBlock) { // Calculate overlap var left = Math.max(movingBlock.getLeft(), prevBlock.getLeft()); var right = Math.min(movingBlock.getRight(), prevBlock.getRight()); overlapWidth = right - left; if (overlapWidth <= 0 || overlapWidth < MIN_BLOCK_WIDTH) { // No overlap or too small: game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } // Shrink block to overlap var newWidth = overlapWidth; var newX = left + overlapWidth / 2; // Animate shrink and move to center of overlap tween(movingBlock, { x: newX }, { duration: SHRINK_ANIMATION_TIME, easing: tween.cubicInOut }); movingBlock.animateShrink(newWidth, SHRINK_ANIMATION_TIME, function () { // Add to stack stack.push(movingBlock); // Play block placed sound LK.getSound('a').play(); currentScore++; updateScoreDisplay(); // Next block nextTurn(newWidth); }); } else { // First block, always succeeds stack.push(movingBlock); // Play block placed sound LK.getSound('a').play(); currentScore = 1; updateScoreDisplay(); nextTurn(movingBlock.blockWidth); } }); } // Helper: start next turn function nextTurn(width) { // Check win condition (optional: e.g. 50 blocks) if (currentScore >= 50) { LK.showYouWin(); return; } // Spawn next moving block movingBlock = spawnMovingBlock(width); isDropping = false; } // Game move handler: tap/click anywhere to drop game.down = function (x, y, obj) { // Check if special button pressed if (specialBtn && obj && obj.target === specialBtn && specialReady && movingBlock && !isDropping) { // Activate special ability: perfect align the block specialReady = false; specialCooldown = SPECIAL_COOLDOWN_TIME; specialBtn.setText('COOLDOWN'); specialBtn.setStyle({ fill: 0x888888 }); // Instantly align moving block to top of stack (or center if first) var prevBlock = getTopBlock(); if (prevBlock) { movingBlock.x = prevBlock.x; movingBlock.blockWidth = prevBlock.blockWidth; movingBlock.setSize(prevBlock.blockWidth, BLOCK_HEIGHT); } else { movingBlock.x = getCenterX(); } // Drop the block as if perfectly aligned dropBlock(); return; } // Normal drop if (!isDropping) { dropBlock(); } }; // Main game update loop game.update = function () { // Move the moving block horizontally if (movingBlock && !isDropping) { movingBlock.x += movingDirection * BLOCK_SPEED; // Bounce at edges var halfW = movingBlock.blockWidth / 2; if (movingBlock.x + halfW > GAME_WIDTH) { movingBlock.x = GAME_WIDTH - halfW; movingDirection = -1; } if (movingBlock.x - halfW < 0) { movingBlock.x = halfW; movingDirection = 1; } } // Update all blocks (for tweened width) for (var i = 0; i < stack.length; i++) { if (stack[i].update) stack[i].update(); } if (movingBlock && movingBlock.update) movingBlock.update(); // Special ability cooldown logic if (!specialReady && specialCooldown > 0) { specialCooldown -= 1000 / 60; // Approx ms per frame at 60fps if (specialCooldown <= 0) { specialReady = true; specialBtn.setText('ICE POWER'); specialBtn.setStyle({ fill: 0x00eaff }); cooldownTxt.setText(''); } else { // Show seconds left var secs = Math.ceil(specialCooldown / 1000); cooldownTxt.setText('Ready in ' + secs + 's'); } } else if (specialReady) { cooldownTxt.setText(''); } }; // Game reset: clear stack and start new game function resetGame() { // Remove all blocks for (var i = 0; i < stack.length; i++) { stack[i].destroy(); } stack = []; if (movingBlock) { movingBlock.destroy(); movingBlock = null; } currentScore = 0; updateScoreDisplay(); // Start first block movingBlock = spawnMovingBlock(START_BLOCK_WIDTH); isDropping = false; // Reset special ability specialReady = true; specialCooldown = 0; if (specialBtn) { specialBtn.setText('ICE POWER'); specialBtn.setStyle({ fill: 0x00eaff }); } if (typeof cooldownTxt !== 'undefined') { cooldownTxt.setText(''); } } // Listen for game over to reset LK.on('gameover', function () { // Delay reset to allow game over screen LK.setTimeout(function () { resetGame(); }, 800); }); // Listen for you win to reset LK.on('youwin', function () { LK.setTimeout(function () { resetGame(); }, 1200); }); // Start the game resetGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
best: 0
});
/****
* Classes
****/
// IceBlock class: represents a single moving or stacked ice block
var IceBlock = Container.expand(function () {
var self = Container.call(this);
// Default block size (will be set on creation)
self.blockWidth = 900;
self.blockHeight = 70;
self.color = 0xB3E6FF; // Light blue ice color
// Create and attach the block asset
var blockAsset = self.attachAsset('iceBlock', {
width: self.blockWidth,
height: self.blockHeight,
color: self.color,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Update block asset size if changed
self.setSize = function (w, h) {
self.blockWidth = w;
self.blockHeight = h;
blockAsset.width = w;
blockAsset.height = h;
};
// Set color (for possible effects)
self.setColor = function (color) {
self.color = color;
blockAsset.color = color;
};
// Animate block to a new position (used for drop)
self.animateTo = function (targetY, duration, onFinish) {
tween(self, {
y: targetY
}, {
duration: duration,
easing: tween.cubicOut,
onFinish: onFinish
});
};
// Animate block shrink (used for misaligned drops)
self.animateShrink = function (newWidth, duration, _onFinish) {
tween(self, {
blockWidth: newWidth
}, {
duration: duration,
easing: tween.cubicInOut,
onFinish: function onFinish() {
self.setSize(newWidth, self.blockHeight);
if (_onFinish) _onFinish();
}
});
};
// For collision and alignment calculations
self.getLeft = function () {
return self.x - self.blockWidth / 2;
};
self.getRight = function () {
return self.x + self.blockWidth / 2;
};
// For updating asset size if tweened
self.update = function () {
// If tweening blockWidth, update asset
if (blockAsset.width !== self.blockWidth) {
blockAsset.width = self.blockWidth;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Tween plugin for block drop and shrink animations
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Add background image to the game scene
var bg = LK.getAsset('iceBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: GAME_WIDTH,
height: GAME_HEIGHT
});
game.addChild(bg);
var START_BLOCK_WIDTH = 900;
var BLOCK_HEIGHT = 70;
var BLOCK_COLOR = 0xB3E6FF;
var BLOCK_SPEED = 16; // px per frame
var MIN_BLOCK_WIDTH = 80; // Minimum width before game over
var DROP_ANIMATION_TIME = 180; // ms
var SHRINK_ANIMATION_TIME = 120; // ms
var START_Y = GAME_HEIGHT - 400; // Y position of the first block
// Game state
var stack = []; // Array of stacked blocks (bottom to top)
var movingBlock = null; // The current moving block
var movingDirection = 1; // 1 = right, -1 = left
var isDropping = false; // Prevents double drop
var scoreTxt = null;
var bestTxt = null;
var currentScore = 0;
var bestScore = 0;
// Special ability state
var specialReady = true;
var specialCooldown = 0; // ms remaining
var SPECIAL_COOLDOWN_TIME = 5000; // 5 seconds cooldown
var specialBtn = null;
// Storage for best score
if (typeof storage.best === 'number') {
bestScore = storage.best;
}
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
bestTxt = new Text2('Best: ' + bestScore, {
size: 60,
fill: 0xAEEFFF
});
bestTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(bestTxt);
bestTxt.y = 120;
// Special ability button
specialBtn = new Text2('ICE POWER', {
size: 70,
fill: specialReady ? 0x00eaff : 0x888888
});
specialBtn.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(specialBtn);
specialBtn.y = -120; // Raise above bottom edge
specialBtn.x = 0; // Centered
// Cooldown text
var cooldownTxt = new Text2('', {
size: 40,
fill: 0xAEEFFF
});
cooldownTxt.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(cooldownTxt);
cooldownTxt.y = -40;
cooldownTxt.x = 0;
// Helper: update score display
function updateScoreDisplay() {
scoreTxt.setText(currentScore);
if (currentScore > bestScore) {
bestScore = currentScore;
storage.best = bestScore;
bestTxt.setText('Best: ' + bestScore);
}
}
// Helper: center X for a block
function getCenterX() {
return GAME_WIDTH / 2;
}
// Helper: spawn a new moving block
function spawnMovingBlock(width) {
var block = new IceBlock();
block.setSize(width, BLOCK_HEIGHT);
block.setColor(BLOCK_COLOR);
// Start above the last block, or at START_Y if first
var y = START_Y - stack.length * BLOCK_HEIGHT;
block.y = y;
block.blockHeight = BLOCK_HEIGHT;
// Start at left or right edge, alternate each time
if (stack.length % 2 === 0) {
block.x = 0 + width / 2;
movingDirection = 1;
} else {
block.x = GAME_WIDTH - width / 2;
movingDirection = -1;
}
game.addChild(block);
return block;
}
// Helper: get top block (last in stack)
function getTopBlock() {
if (stack.length === 0) return null;
return stack[stack.length - 1];
}
// Helper: drop the moving block
function dropBlock() {
if (!movingBlock || isDropping) return;
isDropping = true;
// Find where the block should land (on top of stack or at START_Y)
var targetY = START_Y - stack.length * BLOCK_HEIGHT;
// Animate drop
movingBlock.animateTo(targetY, DROP_ANIMATION_TIME, function () {
// After drop, check alignment
var prevBlock = getTopBlock();
var overlapLeft, overlapRight, overlapWidth;
if (prevBlock) {
// Calculate overlap
var left = Math.max(movingBlock.getLeft(), prevBlock.getLeft());
var right = Math.min(movingBlock.getRight(), prevBlock.getRight());
overlapWidth = right - left;
if (overlapWidth <= 0 || overlapWidth < MIN_BLOCK_WIDTH) {
// No overlap or too small: game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
// Shrink block to overlap
var newWidth = overlapWidth;
var newX = left + overlapWidth / 2;
// Animate shrink and move to center of overlap
tween(movingBlock, {
x: newX
}, {
duration: SHRINK_ANIMATION_TIME,
easing: tween.cubicInOut
});
movingBlock.animateShrink(newWidth, SHRINK_ANIMATION_TIME, function () {
// Add to stack
stack.push(movingBlock);
// Play block placed sound
LK.getSound('a').play();
currentScore++;
updateScoreDisplay();
// Next block
nextTurn(newWidth);
});
} else {
// First block, always succeeds
stack.push(movingBlock);
// Play block placed sound
LK.getSound('a').play();
currentScore = 1;
updateScoreDisplay();
nextTurn(movingBlock.blockWidth);
}
});
}
// Helper: start next turn
function nextTurn(width) {
// Check win condition (optional: e.g. 50 blocks)
if (currentScore >= 50) {
LK.showYouWin();
return;
}
// Spawn next moving block
movingBlock = spawnMovingBlock(width);
isDropping = false;
}
// Game move handler: tap/click anywhere to drop
game.down = function (x, y, obj) {
// Check if special button pressed
if (specialBtn && obj && obj.target === specialBtn && specialReady && movingBlock && !isDropping) {
// Activate special ability: perfect align the block
specialReady = false;
specialCooldown = SPECIAL_COOLDOWN_TIME;
specialBtn.setText('COOLDOWN');
specialBtn.setStyle({
fill: 0x888888
});
// Instantly align moving block to top of stack (or center if first)
var prevBlock = getTopBlock();
if (prevBlock) {
movingBlock.x = prevBlock.x;
movingBlock.blockWidth = prevBlock.blockWidth;
movingBlock.setSize(prevBlock.blockWidth, BLOCK_HEIGHT);
} else {
movingBlock.x = getCenterX();
}
// Drop the block as if perfectly aligned
dropBlock();
return;
}
// Normal drop
if (!isDropping) {
dropBlock();
}
};
// Main game update loop
game.update = function () {
// Move the moving block horizontally
if (movingBlock && !isDropping) {
movingBlock.x += movingDirection * BLOCK_SPEED;
// Bounce at edges
var halfW = movingBlock.blockWidth / 2;
if (movingBlock.x + halfW > GAME_WIDTH) {
movingBlock.x = GAME_WIDTH - halfW;
movingDirection = -1;
}
if (movingBlock.x - halfW < 0) {
movingBlock.x = halfW;
movingDirection = 1;
}
}
// Update all blocks (for tweened width)
for (var i = 0; i < stack.length; i++) {
if (stack[i].update) stack[i].update();
}
if (movingBlock && movingBlock.update) movingBlock.update();
// Special ability cooldown logic
if (!specialReady && specialCooldown > 0) {
specialCooldown -= 1000 / 60; // Approx ms per frame at 60fps
if (specialCooldown <= 0) {
specialReady = true;
specialBtn.setText('ICE POWER');
specialBtn.setStyle({
fill: 0x00eaff
});
cooldownTxt.setText('');
} else {
// Show seconds left
var secs = Math.ceil(specialCooldown / 1000);
cooldownTxt.setText('Ready in ' + secs + 's');
}
} else if (specialReady) {
cooldownTxt.setText('');
}
};
// Game reset: clear stack and start new game
function resetGame() {
// Remove all blocks
for (var i = 0; i < stack.length; i++) {
stack[i].destroy();
}
stack = [];
if (movingBlock) {
movingBlock.destroy();
movingBlock = null;
}
currentScore = 0;
updateScoreDisplay();
// Start first block
movingBlock = spawnMovingBlock(START_BLOCK_WIDTH);
isDropping = false;
// Reset special ability
specialReady = true;
specialCooldown = 0;
if (specialBtn) {
specialBtn.setText('ICE POWER');
specialBtn.setStyle({
fill: 0x00eaff
});
}
if (typeof cooldownTxt !== 'undefined') {
cooldownTxt.setText('');
}
}
// Listen for game over to reset
LK.on('gameover', function () {
// Delay reset to allow game over screen
LK.setTimeout(function () {
resetGame();
}, 800);
});
// Listen for you win to reset
LK.on('youwin', function () {
LK.setTimeout(function () {
resetGame();
}, 1200);
});
// Start the game
resetGame();