var config = { type: Phaser.AUTO, parent: 'phaser-example', width: 800, height: 600, scene: { init: init, preload: preload, create: create, extend: { startGame: startGame, moveBlocks: moveBlocks, getGridX: getGridX, nextRow: nextRow, hasBlockBelow: hasBlockBelow, drop: drop, totalBlocks: totalBlocks, gameOver: gameOver, gameWon: gameWon } } }; var grid; var gridWidth = 7; var gridHeight = 15; var gridSize = 32; var block1; var block2; var block3; var speed = 250; var direction = 0; var currentY = gridHeight; var timer; var game = new Phaser.Game(config); function init () { var element = document.createElement('style'); document.head.appendChild(element); element.sheet.insertRule('@font-face { font-family: "bebas"; src: url("assets/fonts/ttf/bebas.ttf") format("truetype"); }', 0); } function preload () { this.load.setBaseURL('https://cdn.phaserfiles.com/v355'); this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js'); } function create () { WebFont.load({ custom: { families: [ 'bebas' ] }, active: this.startGame.bind(this) }); } function startGame () { this.add.text(400, 32, 'Stacker', { fontFamily: 'bebas', fontSize: 80, color: '#ffffff' }).setShadow(2, 2, "#333333", 2, false, true); this.add.grid(0, 0, gridWidth * gridSize, gridHeight * gridSize, gridSize, gridSize, 0x999999, 1, 0x666666).setOrigin(0); var space = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); block1 = this.add.rectangle(gridSize * 2, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); block2 = this.add.rectangle(gridSize * 3, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); block3 = this.add.rectangle(gridSize * 4, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); grid = []; for (var y = 0; y < gridHeight; y++) { grid.push([ 0, 0, 0, 0, 0, 0, 0 ]); } timer = this.time.addEvent({ delay: speed, callback: this.moveBlocks, callbackScope: this, loop: true }); this.input.keyboard.on('keydown_SPACE', this.drop, this); this.input.on('pointerdown', this.drop, this); } function gameOver () { } function gameWon () { } function getGridX (block) { return Math.ceil(block.x / gridSize); } function hasBlockBelow (block) { return (block && grid[currentY][this.getGridX(block)]); } function moveBlocks () { if (direction === 0) { // Moving right if (block1) { block1.x += gridSize; if (this.getGridX(block1) === gridWidth - 1) { direction = 1; } } if (block2) { block2.x += gridSize; if (this.getGridX(block2) === gridWidth - 1) { direction = 1; } } if (block3) { block3.x += gridSize; if (this.getGridX(block3) === gridWidth - 1) { direction = 1; } } } else { // Moving left if (block1) { block1.x -= gridSize; if (block1 && this.getGridX(block1) === 0) { direction = 0; } } if (block2) { block2.x -= gridSize; if (block2 && this.getGridX(block2) === 0) { direction = 0; } } if (block3) { block3.x -= gridSize; if (block3 && this.getGridX(block3) === 0) { direction = 0; } } } } function totalBlocks () { var total = 0; if (block1) { total++; } if (block2) { total++; } if (block3) { total++; } return total; } function nextRow () { currentY--; if (currentY === 10 || currentY === 5) { console.log('GETTING HARDER!', currentY); speed -= (currentY === 10) ? 90 : 50; // We also need to remove a block if they've still got the full amount if (currentY === 10 && this.totalBlocks() === 3) { // 3 down to 2 block1 = null; } else if (currentY === 5 && this.totalBlocks() === 2) { // 2 down to 1 if (block1 && block2 || block1 && block3) { block1 = null; } else { block2 = null; } } } // Pick either left or right to appear from var side = 0; var shift = gridSize; if (Math.random() >= 0.5) { direction = 1; side = (gridWidth - 1) * gridSize; shift = -gridSize; } else { direction = 0; } if (block1) { block1 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); side += shift; } if (block2) { block2 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); side += shift; } if (block3) { block3 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); } timer = this.time.addEvent({ delay: speed, callback: this.moveBlocks, callbackScope: this, loop: true }); } function drop () { timer.remove(false); var pos1 = (block1) ? this.getGridX(block1) : -1; var pos2 = (block2) ? this.getGridX(block2) : -1; var pos3 = (block3) ? this.getGridX(block3) : -1; // console.log('drop y', currentY, 'pos', pos1, pos2, pos3); var mapY = currentY - 1; if (currentY === gridHeight) { // Is this the first row? If so we just drop and carry on. grid[mapY][pos1] = 1; grid[mapY][pos2] = 1; grid[mapY][pos3] = 1; this.nextRow(); } else { // Can we drop? First check all 3 blocks. If none of them have anything // below then it's game over. if (!this.hasBlockBelow(block1) && !this.hasBlockBelow(block2) && !this.hasBlockBelow(block3)) { this.gameOver(); } else { // Drop them one by one if (block1) { if (this.hasBlockBelow(block1)) { // There's something below this block, so we're good to carry on grid[mapY][pos1] = 1; } else { // There's nothing below this block, so they loose it block1.visible = false; block1 = null; } } if (block2) { if (this.hasBlockBelow(block2)) { // There's something below this block, so we're good to carry on grid[mapY][pos2] = 1; } else { // There's nothing below this block, so they loose it block2.visible = false; block2 = null; } } if (block3) { if (this.hasBlockBelow(block3)) { // There's something below this block, so we're good to carry on grid[mapY][pos3] = 1; } else { // There's nothing below this block, so they loose it block3.visible = false; block3 = null; } } // console.table(grid); if (block1 || block2 || block3) { if (currentY === 1) { this.gameWon(); } else { this.nextRow(); } } else { this.gameOver(); } } } }
Scan to open on your mobile device
var config = { type: Phaser.AUTO, parent: 'phaser-example', width: 800, height: 600, scene: { init: init, preload: preload, create: create, extend: { startGame: startGame, moveBlocks: moveBlocks, getGridX: getGridX, nextRow: nextRow, hasBlockBelow: hasBlockBelow, drop: drop, totalBlocks: totalBlocks, gameOver: gameOver, gameWon: gameWon } } }; var grid; var gridWidth = 7; var gridHeight = 15; var gridSize = 32; var block1; var block2; var block3; var speed = 250; var direction = 0; var currentY = gridHeight; var timer; var game = new Phaser.Game(config); function init () { var element = document.createElement('style'); document.head.appendChild(element); element.sheet.insertRule('@font-face { font-family: "bebas"; src: url("assets/fonts/ttf/bebas.ttf") format("truetype"); }', 0); } function preload () { this.load.setBaseURL('https://cdn.phaserfiles.com/v355'); this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js'); } function create () { WebFont.load({ custom: { families: [ 'bebas' ] }, active: this.startGame.bind(this) }); } function startGame () { this.add.text(400, 32, 'Stacker', { fontFamily: 'bebas', fontSize: 80, color: '#ffffff' }).setShadow(2, 2, "#333333", 2, false, true); this.add.grid(0, 0, gridWidth * gridSize, gridHeight * gridSize, gridSize, gridSize, 0x999999, 1, 0x666666).setOrigin(0); var space = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); block1 = this.add.rectangle(gridSize * 2, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); block2 = this.add.rectangle(gridSize * 3, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); block3 = this.add.rectangle(gridSize * 4, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); grid = []; for (var y = 0; y < gridHeight; y++) { grid.push([ 0, 0, 0, 0, 0, 0, 0 ]); } timer = this.time.addEvent({ delay: speed, callback: this.moveBlocks, callbackScope: this, loop: true }); this.input.keyboard.on('keydown_SPACE', this.drop, this); this.input.on('pointerdown', this.drop, this); } function gameOver () { } function gameWon () { } function getGridX (block) { return Math.ceil(block.x / gridSize); } function hasBlockBelow (block) { return (block && grid[currentY][this.getGridX(block)]); } function moveBlocks () { if (direction === 0) { // Moving right if (block1) { block1.x += gridSize; if (this.getGridX(block1) === gridWidth - 1) { direction = 1; } } if (block2) { block2.x += gridSize; if (this.getGridX(block2) === gridWidth - 1) { direction = 1; } } if (block3) { block3.x += gridSize; if (this.getGridX(block3) === gridWidth - 1) { direction = 1; } } } else { // Moving left if (block1) { block1.x -= gridSize; if (block1 && this.getGridX(block1) === 0) { direction = 0; } } if (block2) { block2.x -= gridSize; if (block2 && this.getGridX(block2) === 0) { direction = 0; } } if (block3) { block3.x -= gridSize; if (block3 && this.getGridX(block3) === 0) { direction = 0; } } } } function totalBlocks () { var total = 0; if (block1) { total++; } if (block2) { total++; } if (block3) { total++; } return total; } function nextRow () { currentY--; if (currentY === 10 || currentY === 5) { console.log('GETTING HARDER!', currentY); speed -= (currentY === 10) ? 90 : 50; // We also need to remove a block if they've still got the full amount if (currentY === 10 && this.totalBlocks() === 3) { // 3 down to 2 block1 = null; } else if (currentY === 5 && this.totalBlocks() === 2) { // 2 down to 1 if (block1 && block2 || block1 && block3) { block1 = null; } else { block2 = null; } } } // Pick either left or right to appear from var side = 0; var shift = gridSize; if (Math.random() >= 0.5) { direction = 1; side = (gridWidth - 1) * gridSize; shift = -gridSize; } else { direction = 0; } if (block1) { block1 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); side += shift; } if (block2) { block2 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); side += shift; } if (block3) { block3 = this.add.rectangle(side, (currentY - 1) * gridSize, gridSize - 1, gridSize - 1, 0x6666ff).setOrigin(0); } timer = this.time.addEvent({ delay: speed, callback: this.moveBlocks, callbackScope: this, loop: true }); } function drop () { timer.remove(false); var pos1 = (block1) ? this.getGridX(block1) : -1; var pos2 = (block2) ? this.getGridX(block2) : -1; var pos3 = (block3) ? this.getGridX(block3) : -1; // console.log('drop y', currentY, 'pos', pos1, pos2, pos3); var mapY = currentY - 1; if (currentY === gridHeight) { // Is this the first row? If so we just drop and carry on. grid[mapY][pos1] = 1; grid[mapY][pos2] = 1; grid[mapY][pos3] = 1; this.nextRow(); } else { // Can we drop? First check all 3 blocks. If none of them have anything // below then it's game over. if (!this.hasBlockBelow(block1) && !this.hasBlockBelow(block2) && !this.hasBlockBelow(block3)) { this.gameOver(); } else { // Drop them one by one if (block1) { if (this.hasBlockBelow(block1)) { // There's something below this block, so we're good to carry on grid[mapY][pos1] = 1; } else { // There's nothing below this block, so they loose it block1.visible = false; block1 = null; } } if (block2) { if (this.hasBlockBelow(block2)) { // There's something below this block, so we're good to carry on grid[mapY][pos2] = 1; } else { // There's nothing below this block, so they loose it block2.visible = false; block2 = null; } } if (block3) { if (this.hasBlockBelow(block3)) { // There's something below this block, so we're good to carry on grid[mapY][pos3] = 1; } else { // There's nothing below this block, so they loose it block3.visible = false; block3 = null; } } // console.table(grid); if (block1 || block2 || block3) { if (currentY === 1) { this.gameWon(); } else { this.nextRow(); } } else { this.gameOver(); } } } }