jacobinathanialpeterson's picture
Upload 1035 files
1e40c2a
raw
history blame
7.29 kB
function Game(inputMapping, autoRepeat, threshold) {
var thisObject = this,
i;
this.firstLoop = true;
this.blocks = [];
this.controlGroup = null;
// make the preview blocks
this.previewBlocks = [];
for (i = 0; i < 4; i += 1) {
this.previewBlocks.push(new Block({blockX: -10, blockY: -10, preview: true}));
}
this.scoreOutput = new TtyBlock("scoreDiv", 3);
this.linesOutput = new TtyBlock("linesDiv", 3);
this.levelOutput = new TtyBlock("levelDiv", 3);
this.tickerOutput = new TtyBlock("tickerDiv", 5);
this.scoreTracker = new ScoreTracker(this.scoreOutput, this.linesOutput, this.levelOutput, this.tickerOutput);
this.dropPeriod = this.scoreTracker.getLevelPeriod();
this.timeToNextDrop = this.dropPeriod;
// TODO: find the official values for these constants
this.keyChargeTime = threshold;
this.keyRepeatTime = autoRepeat;
this.bottomTimer = null;
this.bottomLockTime = 500;
this.lastBottomedState = false;
this.lastTime = null;
this.gameLost = false;
// evenly distributed random piece generator
this.previewLength = 5;
this.randBag = new RandomBag(this.previewLength);
// make the preview blocks
this.previewGroups = [];
for (i = 0; i < this.previewLength; i += 1) {
this.previewGroups.push(new PreviewGroup(330, 70 * i + 35));
}
this.swapGroup = null;
this.swapAllowed = true;
// the currently occupied positions, number of blocks at a position
// indexed by the position as a string
this.occupiedPositions = {};
this.input = {
shiftLeft: {
autoRepeat: true,
handler: function () {
if (thisObject.controlGroup.shift(true)) {
thisObject.resetLockCounter(true);
}
}
},
shiftRight: {
autoRepeat: true,
handler: function() {
if (thisObject.controlGroup.shift(false)) {
thisObject.resetLockCounter(true);
}
}
},
softDrop: {
autoRepeat: true,
preCharged: true,
handler: function() {
thisObject.dropBlock();
thisObject.scoreTracker.softDrop();
}
},
hardDrop: { handler: function() {
var dist = thisObject.controlGroup.fall();
thisObject.scoreTracker.hardDrop(dist);
thisObject.lockBlocks();
}},
rotateLeft: { handler: function() {
if (thisObject.controlGroup.turn(false)) {
thisObject.resetLockCounter(true);
}
}},
rotateRight: { handler: function() {
if (thisObject.controlGroup.turn(true)) {
thisObject.resetLockCounter(true);
}
}},
swap: { handler: function() {
thisObject.swap();
}}
};
this.inputMapping = inputMapping;
}
/**
* drops a new block into the game
*/
Game.prototype.newBlock = function (calledBySwap) {
var thisObject = this,
shape = this.randBag.popQueue(),
newBlocks = [],
curBlock,
i;
this.dropPeriod = this.scoreTracker.getLevelPeriod();
// create some new blocks
for (i = 0; i < 4; i += 1) {
curBlock = new Block({blockX: -10, blockY: -10, shape: shape, occupiedPositions: this.occupiedPositions});
newBlocks.push(curBlock);
this.blocks.push(curBlock);
}
this.controlGroup = new ControlGroup(newBlocks, shape, function(x, y){
return thisObject.isLegalPosition(x, y);
});
if (this.controlGroup.isIllegalStart) {
this.gameLost = true;
}
if (!calledBySwap) {
// the user is allowed to swap blocks again
this.swapAllowed = true;
}
this.updatePreviews(this.randBag.getQueue());
};
/**
* processes the input keys
* @param {Number} dTime - the time in milliseconds since the last frame
*/
Game.prototype.processInput = function(dTime) {
var curInput,
keyName,
curKeys,
pressed,
curInput,
i;
for (actionType in this.inputMapping) {
curKeys = this.inputMapping[actionType];
curInput = this.input[actionType];
pressed = false;
for (i = 0; i < curKeys.length; i += 1) {
if (jaws.pressed(curKeys[i])) {
pressed = true;
}
}
// if the key is down
if (pressed) {
// if it is a 'press' frame
if (!curInput.lastState) {
curInput.handler();
curInput.lastState = true;
curInput.charged = (curInput.preCharged ? true : false);
curInput.holdTime = 0;
}
// if it supports auto-repeat
if (curInput.autoRepeat) {
curInput.holdTime += dTime;
// if not charged and past the charge time
if ((!curInput.charged) && (curInput.holdTime > this.keyChargeTime)) {
// call the handler, and reset the hold time
curInput.holdTime -= this.keyChargeTime;
curInput.handler();
curInput.charged = true;
}
// if charged and past the repeat time
if (curInput.charged && (curInput.holdTime > this.keyRepeatTime)) {
curInput.holdTime -= this.keyRepeatTime;
curInput.handler();
}
}
} else {
// it was released
curInput.lastState = false;
}
}
};
Game.prototype.update = function(time) {
var curTime,
dTime,
i;
// if the first block needs to be made
if (this.firstLoop) {
this.firstLoop = false;
this.newBlock();
this.lastTime = time;
}
curTime = time;
dTime = curTime - this.lastTime;
this.lastTime = curTime;
this.processInput(dTime);
if (!this.controlGroup.isBottomed()) {
this.lastBottomedState = false;
this.applyGravity(dTime);
} else {
// if it has just touched hte bottom
if (!this.lastBottomedState) {
this.resetLockCounter(false);
} else {
this.bottomTimer -= dTime;
if (this.bottomTimer <= 0 || this.slideCount >= 15) {
this.lockBlocks();
}
}
this.lastBottomedState = true;
}
// update the position of the preview blocks
if (this.controlGroup) {
// ask the control group to move the preview blocks
this.controlGroup.configurePreviewBlocks(this.previewBlocks);
} else {
// if there is no contorl group, just move them off the screen
for (i = 0; i < 4; i += 1) {
this.previewBlocks[i].setPosition(-10, -10);
}
}
};
/**
* Renders the entire game scene
*/
Game.prototype.draw = function(dTime) {
var i;
this.scoreOutput.draw(dTime);
this.linesOutput.draw(dTime);
this.levelOutput.draw(dTime);
this.tickerOutput.draw(dTime);
// draw the preview blocks
for (i = 0; i < 4; i += 1) {
this.previewBlocks[i].drawIfInvalid();
}
// draw the swap block
if (this.swapGroup) {
this.swapGroup.draw();
}
// draw the queue
for (i = 0; i < this.previewGroups.length; i += 1) {
this.previewGroups[i].draw();
}
for (i = 0; i < this.blocks.length; i += 1) {
this.blocks[i].drawIfInvalid();
}
};
/**
* Returns true iff the given position can be moved into
* @param {Number} x - the x position
* @param {Number} y - the y position
* @returns {Boolean} true iff the new position is legal
*/
Game.prototype.isLegalPosition = function (x, y) {
// if there is a block in the way
if (this.occupiedPositions[x+','+y]) {
return false;
}
// if it's on the field
if (x >= 10 || x < 0 || y >= 20) {
return false;
}
return true;
};
/**
* drops the controlled blocks by one
*/
Game.prototype.dropBlock = function (causedByGravity) {
if (!causedByGravity) {
this.timeToNextDrop = this.dropPeriod;
}
this.controlGroup.drop();
};