User prompt
Its broken
User prompt
Design a Tetris-style block stacking game with a vibrant neon aesthetic. Use a dark black background to make the glowing neon blocks stand out — use colors like cyan, magenta, electric blue, and neon green. As each block moves, add a subtle neon trail effect. Include a synthwave-style background soundtrack with a futuristic vibe. Blocks should have unique animations when they land or when a line is cleared — like a quick pulse or shimmer effect. Occasionally spawn special power-up blocks: A 'Time Freeze' block that pauses the falling for 3 seconds A 'Line Blaster' that clears 2 lines at once A 'Slow Motion' block that slows game speed temporarily The game should speed up gradually over time. Display the score and level in the top corners using glowing neon fonts. The UI should be sleek and minimal, with futuristic UI buttons that pulse when touched. Make the game compatible with both desktop and mobile devices, and add satisfying sound effects when lines are cleared. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ben ı bloğu için assest ekledim ama kendi tekrar ediyor bir bütün olmalı
User prompt
cyberpunk teması olsun
User prompt
eline sağlık tam istediğim gibi olmuş ama biraz efekt ekleyelim
User prompt
bak şimdi hani blok düşüyor ya işte yana ekle görünsün bir sonraki gelicek blok
User prompt
yanda bir sonraki düşecek bloğu göster ve oyun ekranını biraz genişlet
User prompt
hayır geri getir nerde o
User prompt
şimdi hiç görünmüyor
User prompt
güzel şuanda ama yanda bir sonraki bloğu gösteriyor ya o biraz dışarıda kalmış
User prompt
müzik ekle
User prompt
bloklar indiğinde yok oluyor düzelt bu sorunu
User prompt
bozuk bu
Code edit (1 edits merged)
Please save this source code
User prompt
Tetris Evolution
Initial prompt
tetris yap ama gelişmiş
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Tetromino class
var Tetromino = Container.expand(function () {
var self = Container.call(this);
// Properties
self.type = null;
self.shape = null; // array of [x,y]
self.rotation = 0;
self.blocks = [];
self.x = 0; // board col
self.y = 0; // board row
self.isPowerup = false;
self.powerupType = null;
// Initialize tetromino
self.init = function (type, isPowerup) {
self.type = type;
self.isPowerup = !!isPowerup;
self.rotation = 0;
self.shape = [];
// Copy shape
var base = TETROMINO_SHAPES[type][0];
for (var i = 0; i < base.length; i++) {
self.shape.push([base[i][0], base[i][1]]);
}
self.blocks = [];
self.removeChildren();
for (var i = 0; i < self.shape.length; i++) {
var block;
if (self.isPowerup && i === 0) {
block = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
width: CELL_SIZE,
height: CELL_SIZE
});
self.powerupType = 'clearLine'; // Only one powerup for MVP
} else {
block = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5,
width: CELL_SIZE,
height: CELL_SIZE
});
}
self.blocks.push(block);
}
self.x = Math.floor(BOARD_COLS / 2) - 2;
self.y = 0;
self.updateBlockPositions();
};
// Update block positions
self.updateBlockPositions = function () {
for (var i = 0; i < self.shape.length; i++) {
var pos = self.shape[i];
self.blocks[i].x = (self.x + pos[0]) * CELL_SIZE + CELL_SIZE / 2;
self.blocks[i].y = (self.y + pos[1]) * CELL_SIZE + CELL_SIZE / 2;
}
};
// Try move
self.tryMove = function (dx, dy, board) {
if (self.canMove(dx, dy, self.shape, board)) {
self.x += dx;
self.y += dy;
self.updateBlockPositions();
return true;
}
return false;
};
// Try rotate
self.tryRotate = function (board) {
var rotated = rotateShape(self.shape);
if (self.canMove(0, 0, rotated, board)) {
self.shape = rotated;
self.updateBlockPositions();
return true;
}
return false;
};
// Can move/rotate
self.canMove = function (dx, dy, shape, board) {
for (var i = 0; i < shape.length; i++) {
var nx = self.x + shape[i][0] + dx;
var ny = self.y + shape[i][1] + dy;
if (nx < 0 || nx >= BOARD_COLS || ny < 0 || ny >= BOARD_ROWS) return false;
if (board[ny][nx]) return false;
}
return true;
};
// Lock tetromino into board
self.lockToBoard = function (board, blockRefs) {
for (var i = 0; i < self.shape.length; i++) {
var nx = self.x + self.shape[i][0];
var ny = self.y + self.shape[i][1];
board[ny][nx] = self.isPowerup && i === 0 ? 'powerup' : self.type;
blockRefs[ny][nx] = self.blocks[i];
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
// No title, no description
// Always backgroundColor is black
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Tetromino definitions (relative coordinates for each block in the tetromino)
// Power-up effect
// Power-up block
// New shapes
// Colors for each tetromino type
// Tetromino shapes (classic + new)
// Board state: 2D array [row][col], 0 = empty, else type string
var TETROMINO_SHAPES = {
I: [[[0, 1], [1, 1], [2, 1], [3, 1]]],
O: [[[1, 0], [2, 0], [1, 1], [2, 1]]],
T: [[[1, 0], [0, 1], [1, 1], [2, 1]]],
S: [[[1, 0], [2, 0], [0, 1], [1, 1]]],
Z: [[[0, 0], [1, 0], [1, 1], [2, 1]]],
J: [[[0, 0], [0, 1], [1, 1], [2, 1]]],
L: [[[2, 0], [0, 1], [1, 1], [2, 1]]],
U: [[[0, 0], [2, 0], [0, 1], [1, 1], [2, 1]]],
P: [[[0, 0], [1, 0], [0, 1], [1, 1], [0, 2]]],
Dot: [[[1, 1]]]
};
var TETROMINO_TYPES = ['I', 'O', 'T', 'S', 'Z', 'J', 'L', 'U', 'P'];
var POWERUP_CHANCE = 0.08; // 8% chance for a powerup block
// Board settings
var BOARD_COLS = 12; // Increased width for a wider play area
var BOARD_ROWS = 20;
var CELL_SIZE = 90; // px, fits well on 2048x2732
var BOARD_OFFSET_X = Math.floor((2048 - BOARD_COLS * CELL_SIZE) / 2) - 80; // Shift left to make space for preview
var BOARD_OFFSET_Y = 300;
// Helper: rotate a shape (array of [x,y]) 90deg clockwise
function rotateShape(shape) {
var maxX = 0,
maxY = 0;
for (var i = 0; i < shape.length; i++) {
if (shape[i][0] > maxX) maxX = shape[i][0];
if (shape[i][1] > maxY) maxY = shape[i][1];
}
var rotated = [];
for (var i = 0; i < shape.length; i++) {
var x = shape[i][0],
y = shape[i][1];
rotated.push([maxY - y, x]);
}
return rotated;
}
var board = [];
var blockRefs = []; // 2D array of block display objects
for (var r = 0; r < BOARD_ROWS; r++) {
board[r] = [];
blockRefs[r] = [];
for (var c = 0; c < BOARD_COLS; c++) {
board[r][c] = 0;
blockRefs[r][c] = null;
}
}
// Score and level
var score = 0;
var level = 1;
var linesCleared = 0;
var fallInterval = 1000; // ms, decreases with level
// GUI
var scoreTxt = new Text2('0', {
size: 100,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Lv.1', {
size: 60,
fill: "#fff"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 110;
// Next tetromino preview
var nextTetrominoType = null;
var nextTetrominoPreview = new Container();
game.addChild(nextTetrominoPreview);
// Current falling tetromino
var currentTetromino = null;
// Game state
var isGameOver = false;
var isDropping = false;
var dropTimer = null;
var moveTimer = null;
var moveDir = 0; // -1 left, 1 right, 0 none
// Helper: spawn new tetromino
function spawnTetromino() {
var type = nextTetrominoType;
if (!type) {
type = TETROMINO_TYPES[Math.floor(Math.random() * TETROMINO_TYPES.length)];
}
var isPowerup = Math.random() < POWERUP_CHANCE;
var tetro = new Tetromino();
tetro.init(type, isPowerup);
game.addChild(tetro);
currentTetromino = tetro;
// Next
nextTetrominoType = TETROMINO_TYPES[Math.floor(Math.random() * TETROMINO_TYPES.length)];
updateNextPreview();
// Flash effect on next preview
if (nextTetrominoPreview.children && nextTetrominoPreview.children.length > 0) {
for (var i = 0; i < nextTetrominoPreview.children.length; i++) {
LK.effects.flashObject(nextTetrominoPreview.children[i], 0xffffff, 180);
}
}
// If cannot place, game over
if (!tetro.canMove(0, 0, tetro.shape, board)) {
isGameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
// Helper: update next preview
function updateNextPreview() {
nextTetrominoPreview.removeChildren();
var type = nextTetrominoType;
if (!type) return;
var shape = TETROMINO_SHAPES[type][0];
// Find min/max for centering
var minX = 99,
maxX = -99,
minY = 99,
maxY = -99;
for (var i = 0; i < shape.length; i++) {
if (shape[i][0] < minX) minX = shape[i][0];
if (shape[i][0] > maxX) maxX = shape[i][0];
if (shape[i][1] < minY) minY = shape[i][1];
if (shape[i][1] > maxY) maxY = shape[i][1];
}
var previewWidth = (maxX - minX + 1) * CELL_SIZE;
var previewHeight = (maxY - minY + 1) * CELL_SIZE;
for (var i = 0; i < shape.length; i++) {
var block = LK.getAsset(type, {
anchorX: 0.5,
anchorY: 0.5,
width: CELL_SIZE,
height: CELL_SIZE
});
block.x = (shape[i][0] - minX) * CELL_SIZE + CELL_SIZE / 2;
block.y = (shape[i][1] - minY) * CELL_SIZE + CELL_SIZE / 2;
nextTetrominoPreview.addChild(block);
}
// Place preview to the right of the board, fully visible and inside the screen
nextTetrominoPreview.x = BOARD_OFFSET_X + BOARD_COLS * CELL_SIZE + 120;
nextTetrominoPreview.y = BOARD_OFFSET_Y + 200;
}
// Helper: clear full lines
function clearLines() {
var lines = [];
for (var r = 0; r < BOARD_ROWS; r++) {
var full = true;
for (var c = 0; c < BOARD_COLS; c++) {
if (!board[r][c]) {
full = false;
break;
}
}
if (full) lines.push(r);
}
if (lines.length === 0) return 0;
// Animate and remove lines
for (var i = 0; i < lines.length; i++) {
var row = lines[i];
for (var c = 0; c < BOARD_COLS; c++) {
if (blockRefs[row][c]) {
tween(blockRefs[row][c], {
alpha: 0
}, {
duration: 200,
onFinish: function (obj) {
if (obj.parent) obj.parent.removeChild(obj);
}.bind(null, blockRefs[row][c])
});
}
}
}
// Remove from board
for (var i = 0; i < lines.length; i++) {
var row = lines[i];
for (var c = 0; c < BOARD_COLS; c++) {
board[row][c] = 0;
blockRefs[row][c] = null;
}
}
// Drop above lines
for (var i = lines.length - 1; i >= 0; i--) {
var row = lines[i];
for (var r = row - 1; r >= 0; r--) {
for (var c = 0; c < BOARD_COLS; c++) {
board[r + 1][c] = board[r][c];
blockRefs[r + 1][c] = blockRefs[r][c];
if (blockRefs[r + 1][c]) {
tween(blockRefs[r + 1][c], {
y: blockRefs[r + 1][c].y + CELL_SIZE
}, {
duration: 100
});
}
}
}
// Clear top row
for (var c = 0; c < BOARD_COLS; c++) {
board[0][c] = 0;
blockRefs[0][c] = null;
}
}
return lines.length;
}
// Helper: activate powerup
function activatePowerup(row) {
// For MVP: clear the row where powerup landed
for (var c = 0; c < BOARD_COLS; c++) {
if (blockRefs[row][c]) {
tween(blockRefs[row][c], {
alpha: 0
}, {
duration: 200,
onFinish: function (obj) {
if (obj.parent) obj.parent.removeChild(obj);
}.bind(null, blockRefs[row][c])
});
board[row][c] = 0;
blockRefs[row][c] = null;
}
}
// Drop above lines
for (var r = row - 1; r >= 0; r--) {
for (var c = 0; c < BOARD_COLS; c++) {
board[r + 1][c] = board[r][c];
blockRefs[r + 1][c] = blockRefs[r][c];
if (blockRefs[r + 1][c]) {
tween(blockRefs[r + 1][c], {
y: blockRefs[r + 1][c].y + CELL_SIZE
}, {
duration: 100
});
}
}
}
// Clear top row
for (var c = 0; c < BOARD_COLS; c++) {
board[0][c] = 0;
blockRefs[0][c] = null;
}
}
// Helper: update score/level
function updateScore(lines) {
var points = [0, 100, 300, 500, 800];
score += points[lines] || 0;
linesCleared += lines;
scoreTxt.setText(score);
var newLevel = 1 + Math.floor(linesCleared / 10);
if (newLevel !== level) {
level = newLevel;
levelTxt.setText('Lv.' + level);
fallInterval = Math.max(150, 1000 - (level - 1) * 100);
}
}
// Helper: draw board grid (for visual reference)
var gridLines = new Container();
game.addChild(gridLines);
for (var r = 0; r <= BOARD_ROWS; r++) {
for (var c = 0; c <= BOARD_COLS; c++) {
if (r < BOARD_ROWS && c < BOARD_COLS) {
var cell = LK.getAsset('O', {
anchorX: 0.5,
anchorY: 0.5,
width: CELL_SIZE - 4,
height: CELL_SIZE - 4,
color: 0x222222
});
cell.x = c * CELL_SIZE + CELL_SIZE / 2;
cell.y = r * CELL_SIZE + CELL_SIZE / 2;
cell.alpha = 0.15;
gridLines.addChild(cell);
}
}
}
gridLines.x = BOARD_OFFSET_X;
gridLines.y = BOARD_OFFSET_Y;
// Move all blocks/containers to board offset
function updateBoardDisplayOffsets() {
gridLines.x = BOARD_OFFSET_X;
gridLines.y = BOARD_OFFSET_Y;
for (var r = 0; r < BOARD_ROWS; r++) {
for (var c = 0; c < BOARD_COLS; c++) {
if (blockRefs[r][c]) {
blockRefs[r][c].x = c * CELL_SIZE + CELL_SIZE / 2 + BOARD_OFFSET_X;
blockRefs[r][c].y = r * CELL_SIZE + CELL_SIZE / 2 + BOARD_OFFSET_Y;
}
}
}
if (currentTetromino) {
for (var i = 0; i < currentTetromino.blocks.length; i++) {
currentTetromino.blocks[i].x += BOARD_OFFSET_X;
currentTetromino.blocks[i].y += BOARD_OFFSET_Y;
}
}
}
// Remove board offset from tetromino before logic
function removeTetrominoOffset() {
if (currentTetromino) {
for (var i = 0; i < currentTetromino.blocks.length; i++) {
currentTetromino.blocks[i].x -= BOARD_OFFSET_X;
currentTetromino.blocks[i].y -= BOARD_OFFSET_Y;
}
}
}
// Touch controls
var dragStartX = null;
var dragStartY = null;
var dragTetrominoX = null;
var dragTetrominoY = null;
var lastTouchMove = 0;
var touchDown = false;
var hardDrop = false;
// Convert screen x,y to board col,row
function screenToBoard(x, y) {
var bx = Math.floor((x - BOARD_OFFSET_X) / CELL_SIZE);
var by = Math.floor((y - BOARD_OFFSET_Y) / CELL_SIZE);
return {
col: bx,
row: by
};
}
// Touch/mouse events
game.down = function (x, y, obj) {
if (isGameOver || !currentTetromino) return;
dragStartX = x;
dragStartY = y;
dragTetrominoX = currentTetromino.x;
dragTetrominoY = currentTetromino.y;
touchDown = true;
hardDrop = false;
lastTouchMove = Date.now();
};
game.move = function (x, y, obj) {
if (isGameOver || !currentTetromino || !touchDown) return;
var dx = x - dragStartX;
var dy = y - dragStartY;
var moved = false;
// Horizontal drag: move left/right
if (Math.abs(dx) > CELL_SIZE / 2) {
var dir = dx > 0 ? 1 : -1;
if (currentTetromino.tryMove(dir, 0, board)) {
dragStartX = x;
dragTetrominoX = currentTetromino.x;
moved = true;
}
}
// Vertical drag: hard drop
if (dy > CELL_SIZE * 2 && !hardDrop) {
// Hard drop
while (currentTetromino.tryMove(0, 1, board)) {}
hardDrop = true;
moved = true;
}
// Tap: rotate (handled in up)
if (moved) {
currentTetromino.updateBlockPositions();
updateBoardDisplayOffsets();
}
};
game.up = function (x, y, obj) {
if (isGameOver || !currentTetromino) return;
touchDown = false;
var dt = Date.now() - lastTouchMove;
var dx = x - dragStartX;
var dy = y - dragStartY;
// Tap: rotate
if (Math.abs(dx) < 30 && Math.abs(dy) < 30 && dt < 400) {
removeTetrominoOffset();
currentTetromino.tryRotate(board);
currentTetromino.updateBlockPositions();
updateBoardDisplayOffsets();
}
};
// Auto fall
function scheduleDrop() {
if (dropTimer) LK.clearTimeout(dropTimer);
if (isGameOver) return;
dropTimer = LK.setTimeout(function () {
if (isGameOver) return;
removeTetrominoOffset();
var moved = currentTetromino.tryMove(0, 1, board);
currentTetromino.updateBlockPositions();
updateBoardDisplayOffsets();
if (!moved) {
// Lock to board
currentTetromino.lockToBoard(board, blockRefs);
// Flash effect on lock
for (var i = 0; i < currentTetromino.blocks.length; i++) {
LK.effects.flashObject(currentTetromino.blocks[i], 0xffffff, 180);
}
// Powerup check
var landedPowerup = false;
for (var i = 0; i < currentTetromino.shape.length; i++) {
var nx = currentTetromino.x + currentTetromino.shape[i][0];
var ny = currentTetromino.y + currentTetromino.shape[i][1];
if (board[ny][nx] === 'powerup') {
activatePowerup(ny);
landedPowerup = true;
}
}
// Clear lines
var lines = clearLines();
updateScore(lines);
// Do not remove tetromino blocks here; they are now part of the board and will be removed when lines are cleared
currentTetromino = null;
// Spawn next
spawnTetromino();
updateBoardDisplayOffsets();
}
scheduleDrop();
}, fallInterval);
}
// Game update
game.update = function () {
// No per-frame logic needed for MVP
};
// Start game
function startGame() {
// Reset board
for (var r = 0; r < BOARD_ROWS; r++) {
for (var c = 0; c < BOARD_COLS; c++) {
board[r][c] = 0;
if (blockRefs[r][c]) {
if (blockRefs[r][c].parent) blockRefs[r][c].parent.removeChild(blockRefs[r][c]);
blockRefs[r][c] = null;
}
}
}
score = 0;
level = 1;
linesCleared = 0;
fallInterval = 1000;
scoreTxt.setText(score);
levelTxt.setText('Lv.1');
isGameOver = false;
nextTetrominoType = TETROMINO_TYPES[Math.floor(Math.random() * TETROMINO_TYPES.length)];
updateNextPreview();
if (currentTetromino) {
for (var i = 0; i < currentTetromino.blocks.length; i++) {
if (currentTetromino.blocks[i].parent) currentTetromino.blocks[i].parent.removeChild(currentTetromino.blocks[i]);
}
currentTetromino = null;
}
spawnTetromino();
updateBoardDisplayOffsets();
scheduleDrop();
}
// On game over, restart on new game
LK.on('gameStart', function () {
startGame();
});
// Initial start
LK.playMusic('tetris_bgm');
startGame(); ===================================================================
--- original.js
+++ change.js