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(); ===================================================================
--- original.js
+++ change.js
@@ -231,16 +231,20 @@
});
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);
}