var draw = use('draw2d') var input = use('input') var config = use('config') var color = use('color') var random = use('random') prosperon.camera.transform.pos = [0,0] // Board constants var COLS = 10, ROWS = 20 var TILE = 6 // each cell is 6x6 // Board storage (2D), each cell is either 0 or a [r,g,b,a] color var board = [] // Gravity timing var baseGravity = 0.8 // seconds between drops at level 0 var gravityTimer = 0 // Current piece & position var piece = null var pieceX = 0 var pieceY = 0 // Next piece var nextPiece = null // Score/lines/level var score = 0 var linesCleared = 0 var level = 0 // Rotation lock to prevent spinning with W var rotateHeld = false var gameOver = false // Horizontal movement gating var hMoveTimer = 0 var hDelay = 0.2 // delay before repeated moves begin var hRepeat = 0.05 // time between repeated moves var prevLeft = false var prevRight = false // Tetrimino definitions var SHAPES = { I: { color:[0,1,1,1], blocks:[[0,0],[1,0],[2,0],[3,0]] }, O: { color:[1,1,0,1], blocks:[[0,0],[1,0],[0,1],[1,1]] }, T: { color:[1,0,1,1], blocks:[[0,0],[1,0],[2,0],[1,1]] }, S: { color:[0,1,0,1], blocks:[[1,0],[2,0],[0,1],[1,1]] }, Z: { color:[1,0,0,1], blocks:[[0,0],[1,0],[1,1],[2,1]] }, J: { color:[0,0,1,1], blocks:[[0,0],[0,1],[1,1],[2,1]] }, L: { color:[1,0.5,0,1], blocks:[[2,0],[0,1],[1,1],[2,1]] } } var shapeKeys = array(SHAPES) // Initialize board with empty (0) function initBoard() { board = [] var r = 0; var row = null; var c = 0; for (r=0; r [b[0], b[1]]) } } function spawnPiece() { piece = nextPiece || randomShape() nextPiece = randomShape() pieceX = 3 pieceY = 0 // Collision on spawn => game over if (collides(pieceX, pieceY, piece.blocks)) gameOver = true } function collides(px, py, blocks) { var i = 0; var x = 0; var y = 0; for (i=0; i=COLS || y<0 || y>=ROWS) return true if (y>=0 && board[y][x]) return true } return false } // Lock piece into board function lockPiece() { var i = 0; var x = 0; var y = 0; for (i=0; i=0) board[y][x] = piece.color } } // Rotate 90° clockwise function rotate(blocks) { // (x,y) => (y,-x) var i = 0; var x = 0; var y = 0; for (i=0; i=0;) { if (every(board[r], cell => cell)) { lines++ // remove row board = array(array(board, 0, r), array(board, r+1)) // add empty row on top newRow = [] for (c=0; c 0 && !collides(pieceX+1, pieceY, piece.blocks)) pieceX++ // If neither A nor D is pressed, reset the timer so next press is immediate if (!leftPressed && !rightPressed) { hMoveTimer = 0 } // Decrement horizontal timer hMoveTimer -= dt prevLeft = leftPressed prevRight = rightPressed // ======= End Horizontal Movement Gate ======= // Rotate with W (once per press, no spinning) var test = null; if (input.keyboard.down('w')) { if (!rotateHeld) { rotateHeld = true test = array(piece.blocks, b => [b[0], b[1]]) rotate(test) if (!collides(pieceX, pieceY, test)) piece.blocks = test } } else { rotateHeld = false } // Soft drop if S is held (accelerates gravity) var fallSpeed = input.keyboard.down('s') ? 10 : 1 // Gravity gravityTimer += dt * fallSpeed var dropInterval = max(0.1, baseGravity - level*0.05) if (gravityTimer >= dropInterval) { gravityTimer = 0 if (!collides(pieceX, pieceY+1, piece.blocks)) { pieceY++ } else { placePiece() } } // Hard drop if space is held if (input.keyboard.down('space')) { // hardDrop() } } var hud = function() { // Clear screen draw.rectangle({x:0, y:0, width:config.width, height:config.height}, [0,0,0,1]) // Draw board var r = 0; var c = 0; var cell = null; var i = 0; var x = 0; var y = 0; var nx = 0; var ny = 0; var dx = 0; var dy = 0; for (r=0; r