diff --git a/index.html b/index.html
index 8f632ee..5cca42e 100755
--- a/index.html
+++ b/index.html
@@ -51,7 +51,7 @@
Hold
Piece 块 |
- 00:00.00 |
+ |
@@ -66,7 +66,7 @@ Hold
diff --git a/piece.js b/piece.js
index 4e127d2..b0d93fd 100644
--- a/piece.js
+++ b/piece.js
@@ -7,6 +7,10 @@ function Piece() {
this.gravity = gravityUnit;
this.lockDelay = 0;
this.lockDelayLimit = 30;
+ this.are = 0;
+ this.areLimit = 0;
+ this.irsDir = 0;
+ this.ihs = false;
this.shiftDelay = 0;
this.shiftDir;
this.shiftReleased;
@@ -21,9 +25,14 @@ function Piece() {
*/
Piece.prototype.new = function(index) {
// TODO if no arguments, get next grabbag piece
+ console.log("new irs"+this.irsDir+", ihs"+this.ihs);
this.pos = RotSys[settings.RotSys].initinfo[index][2];
+ this.x = ~~((stack.width - 4) / 2) + RotSys[settings.RotSys].initinfo[index][0];
+ this.y = stack.hiddenHeight - 2 + RotSys[settings.RotSys].initinfo[index][1];
+ this.index = index;
this.tetro = [];
this.held = false;
+ this.ihs = false;
this.finesse = 0;
this.dirty = true;
this.dead = false;
@@ -32,11 +41,28 @@ Piece.prototype.new = function(index) {
// TODO Do this better. Make clone object func maybe.
//for property in pieces, this.prop = piece.prop
- this.tetro = pieces[index].tetro[this.pos];
- this.x = ~~((stack.width - 4) / 2) + RotSys[settings.RotSys].initinfo[index][0];
- this.y = stack.hiddenHeight - 2 + RotSys[settings.RotSys].initinfo[index][1];
- this.index = index;
-
+ if (this.irsDir !== 0) {
+ var curPos = this.pos;
+ var newPos = (this.pos+this.irsDir).mod(4);
+ var offsetX =
+ RotSys[settings.RotSys].offset[this.index][newPos][0] -
+ RotSys[settings.RotSys].offset[this.index][curPos][0];
+ var offsetY =
+ RotSys[settings.RotSys].offset[this.index][newPos][1] -
+ RotSys[settings.RotSys].offset[this.index][curPos][1];
+ this.tetro = pieces[index].tetro[newPos];
+ if (!this.moveValid(offsetX, offsetY, this.tetro)) {
+ this.tetro = pieces[index].tetro[curPos];
+ } else {
+ this.x += offsetX;
+ this.y += offsetY;
+ this.pos = newPos;
+ }
+ this.irsDir = 0;
+ } else {
+ this.tetro = pieces[index].tetro[this.pos];
+ }
+
// TODO ---------------- snip
//TODO Do this better. (make grabbag object)
@@ -46,8 +72,10 @@ Piece.prototype.new = function(index) {
this.lockDelayLimit = setting['Lock Delay'][settings['Lock Delay']];
if (settings.Gravity !== 0) {
+ this.areLimit = 0;
this.gravity = gravityArr[settings.Gravity - 1];
} else if (gametype === 1) { //Marathon
+ this.areLimit = 0;
if (level < 20) {
this.gravity = [
1/60, 1/30, 1/25, 1/20, 1/15, 1/12, 1/10, 1/8, 1/6, 1/6,
@@ -58,13 +86,29 @@ Piece.prototype.new = function(index) {
this.gravity = 20;
this.lockDelayLimit = ~~(30 * Math.pow(0.93, (Math.pow(level-20, 0.8)))); // magic!
}
+ } else if (gametype === 6) { //Death
+ this.gravity = 20;
+ if (level < 20) {
+ this.lockDelayLimit = [
+ 30, 25, 22, 20, 20, 18, 17, 17, 15, 15,
+ 13, 13, 13, 13, 13, 12, 12, 12, 11, 11
+ ][level];
+ this.areLimit = [
+ 18, 18, 18, 15, 15, 12, 12, 12, 12, 12,
+ 12, 12, 10, 10, 10, 8, 8, 8, 8, 8
+ ][level];
+ } else {
+ this.lockDelayLimit = 11;
+ this.areLimit = 6;
+ }
} else {
+ this.areLimit = 0;
this.gravity = gravityUnit;
}
// Check for blockout.
if (!this.moveValid(0, 0, this.tetro)) {
- this.dead = true;
+ //this.dead = true; //show it?
gameState = 9;
msg.innerHTML = 'BLOCK OUT!';
menu(3);
@@ -332,7 +376,14 @@ Piece.prototype.update = function() {
stack.addPiece(this.tetro);
sound.playse("lock");
this.dead = true;
- this.new(preview.next()); // consider move to main update
+ this.dirty = true;
+ this.held = false;
+ if (this.areLimit === 0) {
+ this.new(preview.next()); // consider move to main update
+ } else {
+ gameState = 4;
+ this.are = 0;
+ }
/* farter */
} else {
this.lockDelay++;
@@ -340,7 +391,9 @@ Piece.prototype.update = function() {
}
}
Piece.prototype.draw = function() {
+ clear(activeCtx);
if (!this.dead) {
+ this.drawGhost();
if (settings.Ghost !== 3) {
var a = void 0;
if (landed) {
@@ -352,17 +405,15 @@ Piece.prototype.draw = function() {
}
}
Piece.prototype.drawGhost = function() {
- if (!this.dead) {
- activeCtx.globalAlpha = 0.4;
- if (settings.Ghost === 0 && !landed) {
- draw(this.tetro, this.x,
- Math.floor(this.y + this.getDrop(2147483647)) - stack.hiddenHeight, activeCtx, 0);
- } else if (settings.Ghost === 1 && !landed) {
- draw(this.tetro, this.x,
- Math.floor(this.y + this.getDrop(2147483647)) - stack.hiddenHeight, activeCtx);
- }
- activeCtx.globalAlpha = 1;
+ activeCtx.globalAlpha = 0.4;
+ if (settings.Ghost === 0 && !landed) {
+ draw(this.tetro, this.x,
+ Math.floor(this.y + this.getDrop(2147483647)) - stack.hiddenHeight, activeCtx, 0);
+ } else if (settings.Ghost === 1 && !landed) {
+ draw(this.tetro, this.x,
+ Math.floor(this.y + this.getDrop(2147483647)) - stack.hiddenHeight, activeCtx);
}
+ activeCtx.globalAlpha = 1;
}
var piece = new Piece();
diff --git a/stack.js b/stack.js
index 4f09a84..09ffc60 100644
--- a/stack.js
+++ b/stack.js
@@ -131,7 +131,7 @@ Stack.prototype.addPiece = function(tetro) {
combo = 0;
}
lines += lineClear;
- if (gametype === 1)
+ if (gametype === 1 || gametype === 6)
level = ~~(lines / 10);
score = score.add(scoreAdd.mul(bigInt(16).pow(allclear)));
diff --git a/style.css b/style.css
index 7552358..5b9b403 100755
--- a/style.css
+++ b/style.css
@@ -148,6 +148,7 @@ nav li {
#stats {
display: block;
position: absolute;
+ padding: 0;
}
#stats tbody {
display: block;
@@ -155,7 +156,6 @@ nav li {
#stats tr {
display: block;
width: 100%;
- padding: 0 0.5rem;
}
#stats th {
text-transform: uppercase;
@@ -173,10 +173,12 @@ nav li {
}
#time {
text-align: center;
- font-weight: 900;
- font-size: 1.125em;
display: block;
}
+#time > canvas {
+ width: 100%;
+ height: 1.125em;
+}
#score {
text-align: center;
font-weight: 900;
diff --git a/tetris.js b/tetris.js
index 89bd2a3..2a8ab02 100644
--- a/tetris.js
+++ b/tetris.js
@@ -47,6 +47,8 @@ var activeCanvas = document.getElementById('active');
var previewCanvas = document.getElementById('preview');
var spriteCanvas = document.getElementById('sprite');
+var timeCanvas = document.getElementById('time').childNodes[0];
+
var holdCtx = holdCanvas.getContext('2d');
var bgStackCtx = bgStackCanvas.getContext('2d');
var stackCtx = stackCanvas.getContext('2d');
@@ -54,6 +56,7 @@ var activeCtx = activeCanvas.getContext('2d');
var previewCtx = previewCanvas.getContext('2d');
var spriteCtx = spriteCanvas.getContext('2d');
+var timeCtx = timeCanvas.getContext('2d');
var touchLeft = document.getElementById('touchLeft');
var touchRight = document.getElementById('touchRight');
@@ -79,7 +82,7 @@ touchRotRight.bindsMemberName = "rotRight";
touchRotLeft.bindsMemberName = "rotLeft";
touchRot180.bindsMemberName = "rot180";
-var nLayouts = 7, currLayout = -1 /* auto */;
+var nLayouts = 8, currLayout = -1 /* auto */;
/**
* Piece data
@@ -505,6 +508,8 @@ var arrStages = [
];
var frame;
var frameLastRise;
+var frameLastHarddropDown;
+var frameSkipped;
/**
*Pausing variables
@@ -547,6 +552,7 @@ var statsFinesse;
var piecesSet;
var startTime;
var scoreTime;
+var scoreStartTime;
var digLines = [];
// Keys
@@ -640,11 +646,19 @@ function resize() {
stats.style.fontSize = ~~(stackCanvas.width / 11) + 'px';
document.documentElement.style.fontSize = ~~(stackCanvas.width / 16) + 'px';
- stats.style.width = a.style.width;
for (var i = 0, len = h3.length; i < len; i++) {
h3[i].style.lineHeight = (cellSize * 2) + 'px';
h3[i].style.fontSize = stats.style.fontSize;
}
+ stats.style.width = h3[0].clientWidth + 'px';
+
+ timeCanvas.width = h3[0].clientWidth;
+ timeCanvas.height = timeCanvas.clientHeight || timeCanvas.offsetHeight || timeCanvas.getBoundingClientRect().height;
+ timeCtx.fillStyle = "#fff";
+ timeCtx.font = 'bold 1.125em "Trebuchet MS"';
+ timeCtx.textAlign = "center";
+ timeCtx.textBaseline = "middle";
+
// position of touch buttons
{
@@ -652,7 +666,7 @@ function resize() {
var dpiY = 96;
var winW = window.innerWidth / dpiX;
var winH = window.innerHeight / dpiY;
- var buttonH = 0.7, buttonW = 1, fontSize=0.55, unit="in";
+ var buttonH = 0.7, buttonW = 1, fontSize=0.55, margin=0.1, unit="in";
var setPos = function(elem, posX, posY, sizeW, sizeH,
alignX, alignY, offsetX, offsetY, clientW, clientH)
@@ -660,8 +674,8 @@ function resize() {
elem.style.width = "" + sizeW + unit;
elem.style.height = "" + sizeH + unit;
// border ignored, for now
- elem.style.left = "" + (offsetX + alignX * 0.5 * (clientW - sizeW) + posX * sizeW - ( (alignX-1) * 0.05)) + unit;
- elem.style.top = "" + (offsetY + alignY * 0.5 * (clientH - sizeH) + posY * sizeH - ( (alignY-1) * 0.05)) + unit;
+ elem.style.left = "" + (offsetX + alignX * 0.5 * (clientW - sizeW) + posX * sizeW - ( (alignX-1) * margin/2 )) + unit;
+ elem.style.top = "" + (offsetY + alignY * 0.5 * (clientH - sizeH) + posY * sizeH - ( (alignY-1) * margin/2 )) + unit;
elem.style.display = "block";
elem.style.fontSize = "" + fontSize + unit;
}
@@ -696,14 +710,25 @@ function resize() {
},
"JOY":
function() {
- setPos(touchRotLeft, -0.5, 1, buttonW, buttonH, 2, 1, 0, 0, winW, winH);
- setPos(touchRot180, -0.5, -1, buttonW, buttonH, 2, 1, 0, 0, winW, winH);
- setPos(touchRotRight, 0, 0, buttonW, buttonH, 2, 1, 0, 0, winW, winH);
- setPos(touchHold, -1, 0, buttonW, buttonH, 2, 1, 0, 0, winW, winH);
- setPos(touchRight, 1, 0, buttonW, buttonH, 0, 1, 0, 0, winW, winH);
- setPos(touchLeft, 0, 0, buttonW, buttonH, 0, 1, 0, 0, winW, winH);
- setPos(touchDown, 0.5, 1, buttonW, buttonH, 0, 1, 0, 0, winW, winH);
- setPos(touchDrop, 0.5, -1, buttonW, buttonH, 0, 1, 0, 0, winW, winH);
+ var oy/*offset Y by block*/,ay/*align Y*/;
+ if (winH-winW>buttonH*1.5) {
+ oy=-1; ay=2;
+ } else {
+ oy=0; ay=1;
+ }
+ /* single finger */
+ buttonW = 0.8;
+ if ((winW-0.1)/4fsbl)?fsbl:skipR;
+ skipL = skipL/fsbl*timeCanvas.width;
+ skipR = skipR/fsbl*timeCanvas.width;
+
+ timeCtx.clearRect(0, 0, timeCanvas.width, timeCanvas.height);
+ timeCtx.fillText(displayTime, timeCanvas.width/2, timeCanvas.height/2);
+ timeCtx.fillRect(skipL,timeCanvas.height-0.2,skipR,timeCanvas.height);
}
/**
@@ -1386,19 +1427,6 @@ function touch(e)
preventDefault: function(){}
});
for (var i = 0, l = e.touches.length; i < l; i++) {
- /*
- //fails when dragged
- if (e.touches[i].target) {
- if (e.touches[i].target.hasOwnProperty("bindsMemberName")) {
- keyUpDown({
- type: "keydown",
- keyCode: binds[e.touches[i].target.bindsMemberName],
- preventDefault: function(){}
- });
- e.preventDefault();
- }
- }
- */
var tX = e.touches[i].pageX, tY = e.touches[i].pageY;
for (var j in touchButtons) {
var oRef = touchButtons[j];
@@ -1469,6 +1497,7 @@ function update() {
//piece.finesse++;
}
if (!(lastKeys & flags.hardDrop) && flags.hardDrop & keysDown) {
+ frameLastHarddropDown = frame;
piece.hardDrop();
}
@@ -1476,40 +1505,41 @@ function update() {
if(gametype === 3) { //Dig
var fromLastRise = frame-frameLastRise;
+ var fromLastHD = (flags.hardDrop & keysDown)?(frame-frameLastHarddropDown):0;
+
var arrRow = [8,8,8,8,8,8,8,8,8,8];
- {
- var curStage = 0, objCurStage;
- while(curStage= objCurStage.delay || (fromLastHD >= 20 && fromLastRise >= 15)) {
+ //IJLOSTZ
+ var arrRainbow=[
+ 2,-1,1,5,4,3,7,6,-1,8,
+ 8,8,8,6,6,2,1,5,8,-1,
+ 7,7,-1,8,8];
+ var idxRainbow,flagAll,colorUsed;
+ idxRainbow = ~~(objCurStage.begin/100);
+ flagAll = (~~(objCurStage.begin/50))%2;
+ if(idxRainbow >= arrRainbow.length) {
+ idxRainbow = arrRainbow.length - 1;
}
- curStage--;
- objCurStage = arrStages[curStage];
- if(fromLastRise >= objCurStage.delay) {
- //IJLOSTZ
- var arrRainbow=[
- 2,-1,1,5,4,3,7,6,-1,8,
- 8,8,8,6,6,2,1,5,8,-1,
- 7,7,-1,8,8];
- var idxRainbow,flagAll,colorUsed;
- idxRainbow = ~~(objCurStage.begin/100);
- flagAll = (~~(objCurStage.begin/50))%2;
- if(idxRainbow >= arrRainbow.length) {
- idxRainbow = arrRainbow.length - 1;
- }
- colorUsed = arrRainbow[idxRainbow];
- for(var x=0; x=300) { // exp
+ gameState = 1;
+ msg.innerHTML = 'GREAT!';
+ piece.dead = true;
+ menu(3);
+ sound.playse("endingstart");
+ }
}
/* farter */
+ scoreTime = Date.now() - scoreStartTime - pauseTime;
statistics();
if (lastKeys !== keysDown) {
@@ -1617,90 +1656,129 @@ function gameLoop() {
if (!paused && gameState !== 3) {
requestAnimFrame(gameLoop);
- //setTimeout(gameLoop, 33);
-
- //TODO check to see how pause works in replays.
- frame++;
-
- if (gameState === 0) {
- // Playing
-
- update();
+ var repeat = ~~((Date.now() - startTime - pauseTime)/1000*60) - frame;
+ if (repeat>1) {
+ frameSkipped += repeat-1;
+ }
- // TODO improve this with 'dirty' flags.
- /* farter */ // as you draw for lock delay brightness gradient... give this up..
+ for (var repf=0;repf= stack.hiddenHeight) {
- /**
- * Fade to grey animation played when player loses.
- */
- if (toGreyRow === stack.height - 1)
- clear(activeCtx);
- if (frame % 2) {
- for (var x = 0; x < stack.width; x++) {
- /* farter */ //WTF gamestate-1
- if (stack.grid[x][toGreyRow])
- stack.grid[x][toGreyRow] =
- (gameState === 9 ? 8 : 0);
+ if (piece.x !== lastX ||
+ Math.floor(piece.y) !== lastY ||
+ piece.pos !== lastPos ||
+ piece.lockDelay !== lastLockDelay ||
+ piece.dirty) {
+ piece.draw();
+ }
+ lastX = piece.x;
+ lastY = Math.floor(piece.y);
+ lastPos = piece.pos;
+ lastLockDelay = piece.lockDelay;
+ piece.dirty = false;
+
+ } else if (gameState === 2 || gameState === 4) {
+
+ if (lastKeys !== keysDown && !watchingReplay) {
+ replay.keys[frame] = keysDown;
+ } else if (frame in replay.keys) {
+ keysDown = replay.keys[frame];
+ }
+ // DAS Preload
+ if (keysDown & flags.moveLeft) {
+ piece.shiftDelay = settings.DAS;
+ piece.shiftReleased = false;
+ piece.shiftDir = -1;
+ } else if (keysDown & flags.moveRight) {
+ piece.shiftDelay = settings.DAS;
+ piece.shiftReleased = false;
+ piece.shiftDir = 1;
+ } else {
+ piece.shiftDelay = 0;
+ piece.shiftReleased = true;
+ piece.shiftDir = 0;
+ }
+ if (flags.rotLeft & keysDown && !(lastKeys & flags.rotLeft)) {
+ piece.irsDir = -1;
+ piece.finesse++;
+ console.log("IRS");
+ } else if (flags.rotRight & keysDown && !(lastKeys & flags.rotRight)) {
+ piece.irsDir = 1;
+ piece.finesse++;
+ console.log("IRS");
+ } else if (flags.rot180 & keysDown && !(lastKeys & flags.rot180)) {
+ piece.irsDir = 2;
+ piece.finesse++;
+ console.log("IRS");
+ }
+ if (!(lastKeys & flags.holdPiece) && flags.holdPiece & keysDown) {
+ piece.ihs = true;
+ console.log("IHS");
+ }
+ if (lastKeys !== keysDown) {
+ lastKeys = keysDown;
+ }
+ if (gameState === 2) {
+ // Count Down
+ if (frame < 50) {
+ if (msg.innerHTML !== 'READY') msg.innerHTML = 'READY';
+ } else if (frame < 100) {
+ if (msg.innerHTML !== 'GO!') msg.innerHTML = 'GO!';
+ } else {
+ msg.innerHTML = '';
+ scoreStartTime = Date.now();
+ scoreTime = 0;
}
- stack.draw();
- toGreyRow--;
+ } else {
+ piece.are++;
+ scoreTime = Date.now() - scoreStartTime - pauseTime;
+ }
+ if (
+ (gameState === 2 && frame >= 100) ||
+ (gameState === 4 && piece.are >= piece.areLimit)
+ ) {
+ gameState = 0;
+ if (piece.ihs) {
+ piece.index = preview.next();
+ piece.hold();
+ } else {
+ piece.new(preview.next());
+ }
+ piece.draw();
+ }
+
+ statistics();
+
+ } else if (gameState === 9 || gameState === 1) {
+ if (toGreyRow >= stack.hiddenHeight) {
+ /**
+ * Fade to grey animation played when player loses.
+ */
+ if (frame % 2) {
+ for (var x = 0; x < stack.width; x++) {
+ /* farter */ //WTF gamestate-1
+ if (stack.grid[x][toGreyRow])
+ stack.grid[x][toGreyRow] =
+ (gameState === 9 ? 8 : 0);
+ }
+ stack.draw();
+ toGreyRow--;
+ }
+ } else {
+ //clear(activeCtx);
+ //piece.dead = true;
+ trysubmitscore();
+ gameState = 3;
}
- } else {
- trysubmitscore();
- gameState = 3;
}
}
}