I create a game similar to Tetris, where instead of deleting one line, when you have a full line, I delete all the related parts. This led me to a standstill after clearing the pieces.
See this example for a quick and dirty version of what I'm trying to do.
function Board (width, height) { this.width = width; this.height = height; this.board = []; this.pieces = []; for (var y = 0; y < this.height; y++) { for (var x = 0; x < this.width; x++) { if (!this.board[y]) { this.board[y] = []; } this.board[y][x] = null; } } this.canPlace = function(piece, at) { for (var y = 0; y < piece.getHeight(); y++) { for (var x = 0; x < piece.getWidth(); x++) { if ((y+at.y >= this.height) || this.board[y+at.y][x+at.x]) { return false; } } } return true; } this.hasFullLine = function(line) { for (var x = 0; x < this.width; x++) { if (!this.board[line][x]) { return false; } } return true; } this.place = function(piece) { var position = piece.getPosition(); var shape = piece.getShape(); for (var y = 0; y < piece.getHeight(); y++) { for (var x = 0; x < piece.getWidth(); x++) { if (shape[y][x]) { this.board[y+position.y][x+position.x] = piece; } } } if (this.pieces.indexOf(piece) === -1) { this.pieces.push(piece); } piece.render(); } this.hardDropPieces = function() { var pieces = this.pieces.slice(); pieces = pieces.sort(function(a,b) { var aBottom = a.getPosition().y+a.getHeight(); var bBottom = b.getPosition().y+b.getHeight(); return bBottom-aBottom; }); for (var i = 0; i < pieces.length; i++) { this.hardDrop(pieces[i]); } } this.hardDrop = function(piece) { var position = piece.getPosition(); this.clearArea(piece); while(this.canPlace(piece, {x: piece.getPosition().x, y: piece.getPosition().y+1})) { piece.setPosition(piece.getPosition().x, piece.getPosition().y+1); } this.place(piece); } this.clearArea = function(piece) { var position = piece.getPosition(); var shape = piece.getShape(); for (var y = 0; y < piece.getHeight(); y++) { for (var x = 0; x < piece.getWidth(); x++) { if (shape[y][x]) { this.board[y+position.y][x+position.x] = null; } } } } this.remove = function(piece) { this.clearArea(piece); this.pieces.splice(this.pieces.indexOf(piece),1); } this.clearPiecesOnLine = function(line) { var piecesToClear = []; for (var x = 0; x < this.width; x++) { var piece = this.board[line][x]; if (piecesToClear.indexOf(piece) === -1) { piecesToClear.push(piece); } } for (var i = 0; i < piecesToClear.length; i++) { this.remove(piecesToClear[i]); } return piecesToClear; } this.toString = function() { var str = ""; for (var y = 0; y < this.height; y++) { for (var x = 0; x < this.width; x++) { str += this.board[y][x] ? "1" : "0"; } str += "\n"; } return str; } } function Piece (shape, fill, stroke, paper, cellWidth) { this.shape = shape; this.fill = fill; this.stroke = stroke; this.cellWidth = cellWidth; this.svgGroup = paper.g().append(); this.position = {x:0, y:0}; this.width = this.shape[0].length; this.height = this.shape.length; this.removed = false; for (var y = 0; y < this.height; y++) { for (var x = 0; x < this.width; x++) { if (this.shape[y][x]) { var rect = paper.rect(x*cellWidth, y*cellWidth, cellWidth, cellWidth); rect.attr({ fill: this.fill, stroke: this.stroke }); rect.appendTo(this.svgGroup); } } } this.setPosition = function(x, y) { this.position.x = x; this.position.y = y; } this.getPosition = function() { return this.position; } this.render = function() { var matrix = new Snap.Matrix(); matrix.translate(this.position.x*cellWidth, this.position.y*cellWidth); this.svgGroup.attr({ transform: matrix }); } this.getWidth = function() { return this.width; } this.getHeight = function() { return this.height; } this.getShape = function() { return this.shape; } this.delete = function() { this.svgGroup.remove(); } this.isRemoved = function() { return this.removed; } } var shapes = [ [ [0,1,0], [1,1,1] ], [ [1,1,1,1] ], [ [1,1,1], [0,1,0], [1,1,1] ], [ [1,1], [1,1] ], [ [1,1,1], [0,1,1], [0,1,1], [1,1,1] ], [ [1,1,1,1], [1,1,1,1], [1,1,1,1], [1,1,1,1] ], [ [1,0,1], [1,1,1] ] ]; var width = 10; var height = 20; var cellWidth = 20; var paper = Snap("#svg"); var board = new Board(width, height); var tick = 500; paper.attr({ width: cellWidth*width, height: cellWidth*height }); for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { var rect = paper.rect(x*cellWidth, y*cellWidth, cellWidth, cellWidth); rect.attr({ fill: "#ccc", stroke: "#ddd" }); } } var piece = new Piece(shapes[0], "red", "white", paper, cellWidth); piece.setPosition(0, 18); board.place(piece); piece = new Piece(shapes[1], "orange", "white", paper, cellWidth); piece.setPosition(3, 19); board.place(piece); piece = new Piece(shapes[2], "yellow", "white", paper, cellWidth); piece.setPosition(2, 8); board.place(piece); piece = new Piece(shapes[3], "green", "white", paper, cellWidth); piece.setPosition(0, 17); board.place(piece); piece = new Piece(shapes[4], "blue", "white", paper, cellWidth); piece.setPosition(2, 15); board.place(piece); piece = new Piece(shapes[5], "indigo", "white", paper, cellWidth); piece.setPosition(1, 11); board.place(piece); piece = new Piece(shapes[6], "violet", "white", paper, cellWidth); piece.setPosition(7, 17); piece.render(); function update() { if (piece.isRemoved()) { return; } var position = piece.getPosition(); if (board.canPlace(piece, {x:position.x,y:position.y+1})) { piece.setPosition(position.x,position.y+1); board.place(piece); for (var y = 0; y < piece.getHeight(); y++) { if (board.hasFullLine(piece.getPosition().y+y)) { var removed = board.clearPiecesOnLine(piece.getPosition().y+y); setTimeout(function() { for (var i = 0; i < removed.length; i++) { removed[i].delete(); } board.hardDropPieces(); },tick); } } } } setTimeout(update, tick);
This is largely the essence of rule-logic. The placed pieces are stored by reference in the array, after cleaning, I sort the pieces that are not deleted by their lowest point, and then throw each of them as far as they can go.
This works when no fragments are connected to each other, but I just canβt figure out how to do this when they are, as in this example .
Obviously, the blue piece is the lowest point, but it cannot move down, since the green piece is inside it. I thought about combining and lowering them, but this leads to other problems. Like what happens in this case ?
I'm sure I'm just fat and there is a relatively easy way to fix this ...? Any help would be greatly appreciated!
All parts are automatically generated, and there are too many, and much more can be added at any time, so as not to create a common solution.