forked from sent/waves
210 lines
4.7 KiB
JavaScript
210 lines
4.7 KiB
JavaScript
|
|
/**
|
|
* @returns {[Number]} the line numbers of all the completed rows
|
|
*/
|
|
Game.prototype.getRows = function () {
|
|
var i,
|
|
rows = [],
|
|
res = [],
|
|
curRow;
|
|
|
|
// initialize the rows to 0
|
|
for (i = 0; i < 20; i += 1) {
|
|
rows[i] = 0;
|
|
}
|
|
// for each block
|
|
for (i = 0; i < this.blocks.length; i += 1) {
|
|
// increment the appropriate row
|
|
curRow = this.blocks[i].getY();
|
|
rows[curRow] += 1;
|
|
// if the row is full
|
|
if (rows[curRow] === 10) {
|
|
res.push(curRow);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
/**
|
|
* Removes the rows from the field
|
|
*/
|
|
Game.prototype.removeRows = function (rows) {
|
|
var dropDist = {},
|
|
i, j,
|
|
remove = {},
|
|
curBlock,
|
|
curY;
|
|
|
|
// initialize drops to 0
|
|
for (i = -4; i < 20; i += 1) {
|
|
dropDist[i] = 0;
|
|
}
|
|
|
|
// for each removed row
|
|
for (i = 0; i < rows.length; i += 1) {
|
|
remove[rows[i]] = true;
|
|
|
|
// every row above this should be dropped another spot
|
|
for (j = -4; j < rows[i]; j += 1) {
|
|
dropDist[j] += 1;
|
|
}
|
|
}
|
|
|
|
// for each block
|
|
for (i = 0; i < this.blocks.length; i += 1) {
|
|
curBlock = this.blocks[i];
|
|
curY = curBlock.getY();
|
|
|
|
// if it is being removed
|
|
if (remove[curY]) {
|
|
// remove the block
|
|
this.removeBlock(i);
|
|
i -= 1;
|
|
} else {
|
|
// it is being dropped
|
|
curBlock.setPosition(curBlock.getX(), curBlock.getY() + dropDist[curY]);
|
|
}
|
|
}
|
|
};
|
|
|
|
Game.prototype.removeBlock = function(index) {
|
|
this.blocks[index].kill();
|
|
return this.blocks.splice(index, 1);
|
|
};
|
|
|
|
Game.prototype.applyGravity = function (dTime) {
|
|
this.timeToNextDrop -= dTime;
|
|
|
|
// drop until there is a positive time until the next drop time is positive, or the control group s bottomed out
|
|
while (this.timeToNextDrop < 0 && (!this.controlGroup.isBottomed())) {
|
|
this.dropBlock(true);
|
|
this.timeToNextDrop += this.dropPeriod;
|
|
}
|
|
|
|
// if it exited through bottoming, reset the drop period
|
|
if (this.controlGroup.isBottomed()) {
|
|
this.timeToNextDrop = this.dropPeriod;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Changes the shapes of the preview along the side
|
|
* @param {[Char]} queue - the queue of pieces
|
|
*/
|
|
Game.prototype.updatePreviews = function(queue) {
|
|
var i;
|
|
for (i = 0; i < queue.length; i += 1) {
|
|
this.previewGroups[i].setShape(queue[i]);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* called when the user attempts to swap a block
|
|
*/
|
|
Game.prototype.swap = function() {
|
|
var i, j,
|
|
newShape,
|
|
oldShape = this.controlGroup.getShape(),
|
|
oldBlocks = this.controlGroup.getBlocks(),
|
|
newBlocks = [],
|
|
thisObject = this;
|
|
|
|
// can only be called once per drop
|
|
if (!this.swapAllowed) {
|
|
return;
|
|
}
|
|
this.swapAllowed = false;
|
|
|
|
// Reset the locking
|
|
this.resetLockCounter(false);
|
|
|
|
// remove the blocks
|
|
// for each block on the field
|
|
for (i = 0; i < this.blocks.length; i += 1) {
|
|
// if the block is part of the control group, remove it
|
|
for (j = 0; j < 4; j += 1) {
|
|
if (oldBlocks[j] === this.blocks[i]) {
|
|
this.removeBlock(i);
|
|
i -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if there is a block waiting
|
|
if (this.swapGroup) {
|
|
newShape = this.swapGroup.getShape();
|
|
for (i = 0; i < 4; i += 1) {
|
|
newBlocks.push(new Block({blockX:-10, blockY:-10, shape: newShape, occupiedPositions: this.occupiedPositions}));
|
|
this.blocks.push(newBlocks[i]);
|
|
}
|
|
|
|
this.controlGroup = new ControlGroup(newBlocks, newShape, function(x, y){
|
|
return thisObject.isLegalPosition(x, y);
|
|
});
|
|
|
|
this.swapGroup.setShape(oldShape);
|
|
|
|
return;
|
|
}
|
|
|
|
// if there is no block waiting
|
|
this.swapGroup = new PreviewGroup(-100, 60);
|
|
this.swapGroup.setShape(oldShape);
|
|
this.newBlock(true);
|
|
|
|
};
|
|
|
|
/**
|
|
* locks the currnt piece in, registers lines and makes a new block
|
|
*/
|
|
Game.prototype.lockBlocks = function() {
|
|
// figure out if it a t-spin/t-spin mini
|
|
var tSpinType = this.controlGroup.getTSpin(),
|
|
scoreObject = {},
|
|
rows;
|
|
|
|
if (tSpinType === 'mini') {
|
|
scoreObject.miniT = true;
|
|
} else if (tSpinType === 'normal') {
|
|
scoreObject.normalT = true;
|
|
}
|
|
|
|
// look for rows
|
|
rows = this.getRows();
|
|
scoreObject.lines = rows.length;
|
|
if (rows.length > 0) {
|
|
this.removeRows(rows);
|
|
}
|
|
|
|
// apply the score
|
|
this.scoreTracker.updateScore(scoreObject);
|
|
|
|
this.newBlock();
|
|
this.resetLockCounter(false);
|
|
};
|
|
|
|
/**
|
|
* Resets the lock counter, and the slide counter if not soft
|
|
* @param {Boolean} soft = true if a soft reset, and the slide counter should not be reset
|
|
*/
|
|
Game.prototype.resetLockCounter = function (soft) {
|
|
if (soft) {
|
|
this.slideCount += 1;
|
|
} else {
|
|
this.slideCount = 0;
|
|
}
|
|
this.bottomTimer = this.bottomLockTime;
|
|
};
|
|
|
|
/**
|
|
* Determines if the game is over and returns a score object
|
|
* if it is. Otherwise, returns null
|
|
*/
|
|
Game.prototype.getResults = function() {
|
|
if (this.gameLost || this.scoreTracker.gameWon()) {
|
|
return this.scoreTracker.getResults();
|
|
}
|
|
return null;
|
|
};
|