policychanges/dist/tetrion.js

2854 lines
69 KiB
JavaScript
Raw Normal View History

2021-02-05 03:19:09 -06:00
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
var utils = require('./utils.js');
var consts = require('./consts.js');
2021-02-24 13:43:52 -06:00
// import * as utils from './utils.js';
// import * as consts from './const.js';
2021-02-05 03:19:09 -06:00
var lineColor = consts.GRID_LINE_COLOR;
var boxBorderColor = consts.BOX_BORDER_COLOR;
//Draw a single line in canvas context
var drawLine = function(ctx,p1,p2,color){
ctx.beginPath();
ctx.moveTo(p1.x,p1.y);
ctx.lineTo(p2.x,p2.y);
ctx.lineWidth=1;
ctx.strokeStyle= color;
ctx.stroke();
ctx.closePath();
};
//Draw game grids
var drawGrids = function(el,gridSize,colCount,rowCount,color1,color2){
var ctx = el.getContext('2d');
var width = el.width;
var height = el.height;
ctx.rect(0, 0, width, height);
var grd = ctx.createLinearGradient(0, 0, 0, height);
grd.addColorStop(0, color1);
grd.addColorStop(1, color2);
ctx.fillStyle = grd;
ctx.fill();
for (var i = 1; i < colCount; i++) {
var x = gridSize*i+0.5;
drawLine(ctx,{x:x,y:0},{x:x,y:height},lineColor);
};
for (var i = 1; i < rowCount; i++) {
var y = gridSize*i+0.5;
drawLine(ctx,{x:0,y:y},{x:width,y:y},lineColor);
};
};
//Draw box of shape (shape is the composition of boxes)
var drawBox = function(ctx,color,x,y,gridSize){
if (y<0){
return;
}
ctx.beginPath();
ctx.rect(x,y,gridSize,gridSize);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle= boxBorderColor;
ctx.lineWidth=1;
ctx.stroke();
ctx.closePath();
}
/*
Canvas main object, use to draw all games data.
*/
var tetrisCanvas = {
2021-02-09 21:19:20 -06:00
init:function(scene,preview,hold){
2021-02-05 03:19:09 -06:00
this.scene = scene;
this.preview = preview;
2021-02-09 21:19:20 -06:00
this.hold = hold;
2021-02-05 03:19:09 -06:00
this.sceneContext = scene.getContext('2d');
this.previewContext = preview.getContext('2d');
2021-02-09 21:19:20 -06:00
this.holdContext = hold.getContext('2d');
2021-02-05 03:19:09 -06:00
this.gridSize = scene.width / consts.COLUMN_COUNT;
2021-02-05 14:46:41 -06:00
this.previewGridSize = preview.width / 4;//consts.PREVIEW_COUNT;
2021-02-09 21:19:20 -06:00
this.holdGridSize = preview.width / 4;//consts.PREVIEW_COUNT;
2021-02-05 03:19:09 -06:00
this.drawScene();
},
//Clear game canvas
clearScene:function(){
this.sceneContext.clearRect(0, 0, this.scene.width, this.scene.height);
},
//Clear preview canvas
clearPreview:function(){
this.previewContext.clearRect(0,0,this.preview.width,this.preview.height);
2021-02-09 21:19:20 -06:00
}, //Clear preview canvas
clearHold:function(){
this.holdContext.clearRect(0,0,this.hold.width,this.hold.height);
2021-02-05 03:19:09 -06:00
},
//Draw game scene, grids
drawScene:function(){
this.clearScene();
drawGrids(this.scene,this.gridSize,
consts.COLUMN_COUNT,consts.ROW_COUNT,
consts.SCENE_BG_START,consts.SCENE_BG_END);
},
//Draw game data
drawMatrix:function(matrix){
for(var i = 0;i<matrix.length;i++){
var row = matrix[i];
for(var j = 0;j<row.length;j++){
if (row[j]!==0){
drawBox(this.sceneContext,row[j],j*this.gridSize,i*this.gridSize,this.gridSize);
}
}
}
},
//Draw preview data
drawPreview:function(){
drawGrids(this.preview,this.previewGridSize,
consts.PREVIEW_COUNT,consts.PREVIEW_COUNT,
consts.PREVIEW_BG,consts.PREVIEW_BG);
},
2021-02-09 21:19:20 -06:00
//Draw hold data
drawHold:function(){
drawGrids(this.hold,this.holdGridSize,
consts.PREVIEW_COUNT,consts.PREVIEW_COUNT,
consts.PREVIEW_BG,consts.PREVIEW_BG);
},
2021-02-05 03:19:09 -06:00
//Draw acitve shape in game
drawShape:function(shape){
if (!shape){
return;
}
var matrix = shape.matrix();
var gsize = this.gridSize;
for(var i = 0;i<matrix.length;i++){
for(var j = 0;j<matrix[i].length;j++){
var value = matrix[i][j];
if (value === 1){
var x = gsize *(shape.x + j);
var y = gsize *(shape.y + i);
drawBox(this.sceneContext,shape.color,x,y,gsize);
}
}
}
},
2021-02-05 14:46:41 -06:00
drawGhostShape:function(shape, bottomY){
2021-02-05 03:19:09 -06:00
if (!shape){
return;
}
var matrix = shape.matrix();
2021-02-05 14:46:41 -06:00
var gsize = this.gridSize;
2021-02-05 03:19:09 -06:00
for(var i = 0;i<matrix.length;i++){
for(var j = 0;j<matrix[i].length;j++){
var value = matrix[i][j];
if (value === 1){
2021-02-05 14:46:41 -06:00
var x = gsize *(shape.x + j);
var y = gsize *(bottomY + i); //(shape.y + i);
2021-02-12 22:44:49 -06:00
drawBox(this.sceneContext,"rgba(255, 255, 255, 0.2)",x,y,gsize);
}
}
}
},
hexToRgb: function(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
},
drawHintShape:function(shape){
if (!shape){
return;
}
var colorRGB = this.hexToRgb(shape.color);
var color = "rgba(" + colorRGB.r + "," + colorRGB.g + "," + colorRGB.b + "," + "0.2)";
2021-02-12 22:44:49 -06:00
var matrix = shape.matrix();
var gsize = this.gridSize;
for(var i = 0;i<matrix.length;i++){
for(var j = 0;j<matrix[i].length;j++){
var value = matrix[i][j];
if (value === 1){
var x = gsize *(shape.x + j);
var y = gsize *(shape.y + i);
drawBox(this.sceneContext, color, x, y, gsize);
2021-02-05 03:19:09 -06:00
}
}
}
2021-02-05 14:46:41 -06:00
},
//Draw preview shape in preview canvas
drawPreviewShape:function(shapeQueue){
if (!shapeQueue){
return;
}
this.clearPreview();
shapeQueue.forEach( (shape, index) => {
if(shape != undefined)
{
var matrix = shape.matrix();
var gsize = this.previewGridSize;
var startX = (this.preview.width - gsize*shape.getColumnCount()) / 2;
var startY = ((this.preview.height - gsize*shape.getRowCount()) / 2 / 4)*(index*2+1);
for(var i = 0;i<matrix.length;i++){
for(var j = 0;j<matrix[i].length;j++){
var value = matrix[i][j];
if (value === 1){
var x = startX + gsize * j;
var y = startY + gsize * i;
drawBox(this.previewContext,shape.color,x,y,gsize);
}
}
}
}
});
2021-02-09 21:19:20 -06:00
},
//Draw preview shape in preview canvas
drawHoldShape:function(holdQueue){
if (!holdQueue){
return;
}
this.clearHold();
q = holdQueue.reverse();
q.forEach( (shape, index) => {
if(shape != undefined)
{
var matrix = shape.matrix();
var gsize = this.holdGridSize;
var startX = (this.hold.width - gsize*shape.getColumnCount()) / 2;
var startY = ((this.hold.height - gsize*shape.getRowCount()) / 2 / 4)*(index*2+1);
for(var i = 0;i<matrix.length;i++){
for(var j = 0;j<matrix[i].length;j++){
var value = matrix[i][j];
if (value === 1){
var x = startX + gsize * j;
var y = startY + gsize * i;
drawBox(this.holdContext,shape.color,x,y,gsize);
}
}
}
}
});
holdQueue.reverse();
2021-02-05 03:19:09 -06:00
}
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
};
module.exports = tetrisCanvas;
2021-02-24 13:43:52 -06:00
// export tetrisCanvas;
2021-02-12 19:02:01 -06:00
},{"./consts.js":2,"./utils.js":8}],2:[function(require,module,exports){
2021-02-05 03:19:09 -06:00
2021-02-09 21:19:20 -06:00
//colors for shapes L, O, Z, T, J, S, I
var colors = ['#ef7a21','#f7d308','#ef2029','#ad4d9c','#5a658f','#42b642','#31c7ef'];
//['#ef7a21','#f7d308','#42b642','#ef2029','#ad4d9c','#5a658f','#31c7ef'];
//['#00af9d','#ffb652','#cd66cc','#66bc29','#0096db','#3a7dda','#ffe100'];
2021-02-05 03:19:09 -06:00
//sidebar width
var sideWidth = 120;
//scene column count
var columnCount = 10;
//scene row count;
var rowCount = 20;
//scene piece entry count;
var entryRowCount = 3;
//previewCount
var previewCount = 6;
//scene gradient start color
2021-02-09 21:19:20 -06:00
var sceneBgStart = "#000000"
//'#8e9ba6';
2021-02-05 03:19:09 -06:00
//scene gradient end color
2021-02-09 21:19:20 -06:00
var sceneBgEnd = '#000000'
//'#5c6975';
2021-02-05 03:19:09 -06:00
//preview background color
var previewBg = '#2f2f2f';
//grid line color
var gridLineColor = 'rgba(255,255,255,0.2)';
//box border color
var boxBorderColor = 'rgba(255,255,255,0.5)';
// Game speed
var defaultInterval = 600;
// Level update interval
var levelInterval = 120 * 1000;
var exports = module.exports = {};
exports.COLORS = colors;
exports.SIDE_WIDTH = sideWidth;
exports.ROW_COUNT = rowCount;
exports.COLUMN_COUNT = columnCount;
exports.SCENE_BG_START = sceneBgStart;
exports.SCENE_BG_END = sceneBgEnd;
exports.PREVIEW_BG = previewBg;
exports.PREVIEW_COUNT = previewCount;
exports.GRID_LINE_COLOR = gridLineColor;
exports.BOX_BORDER_COLOR = boxBorderColor;
exports.DEFAULT_INTERVAL = defaultInterval;
exports.LEVEL_INTERVAL = levelInterval;
},{}],3:[function(require,module,exports){
var gamepadAPI = {
controller: {},
turbo: false,
connect: function(evt) {
gamepadAPI.controller = evt.gamepad;
gamepadAPI.turbo = true;
console.log('Gamepad connected.');
},
disconnect: function(evt) {
gamepadAPI.turbo = false;
delete gamepadAPI.controller;
console.log('Gamepad disconnected.');
},
update: function() {
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
2021-02-09 21:19:20 -06:00
if(!isFirefox) {
for(var i = 0; i < 4; i++)
if((gp = window.navigator.getGamepads()[i]) != undefined) // dumb gamepad update. fix.
gamepadAPI.controller = gp;
}
2021-02-05 03:19:09 -06:00
gamepadAPI.buttonsCache = [];
for (var k = 0; k < gamepadAPI.buttonsStatus.length; k++) {
gamepadAPI.buttonsCache[k] = gamepadAPI.buttonsStatus[k];
}
gamepadAPI.buttonsStatus = [];
var c = gamepadAPI.controller || {};
var pressed = [];
if (c.buttons) {
for (var b = 0, t = c.buttons.length; b < t; b++) {
if (c.buttons[b].pressed) {
pressed.push(gamepadAPI.buttons[b]);
}
}
}
var axes = [];
if (c.axes) {
for (var a = 0, x = c.axes.length; a < x; a++) {
axes.push(c.axes[a].toFixed(2));
}
}
gamepadAPI.axesStatus = axes;
gamepadAPI.buttonsStatus = pressed;
return pressed;
},
buttonPressed: function(button, hold) {
var newPress = false;
for (var i = 0, s = gamepadAPI.buttonsStatus.length; i < s; i++) {
if (gamepadAPI.buttonsStatus[i] == button) {
newPress = true;
if (!hold) {
for (var j = 0, p = gamepadAPI.buttonsCache.length; j < p; j++) {
if (gamepadAPI.buttonsCache[j] == button) {
newPress = false;
}
}
}
}
}
return newPress;
},
buttons: [ // XBox360 layout
'A', 'B', 'X', 'Y',
'LB', 'RB', 'Axis-Left', 'DPad-Right',
'Back', 'Start', 'Power', 'Axis-Right','DPad-Up', 'DPad-Down' , 'DPad-Left','DPad-Right'
],
/*
'DPad-Up', 'DPad-Down', 'DPad-Left', 'DPad-Right',
'Start', 'Back', 'Axis-Left', 'Axis-Right',
'LB', 'RB', 'Power', 'A', 'B', 'X', 'Y',
],*/
buttonsCache: [],
buttonsStatus: [],
axesStatus: []
};
window.addEventListener("gamepadconnected", gamepadAPI.connect);
window.addEventListener("gamepaddisconnected", gamepadAPI.disconnect);
module.exports = gamepadAPI;
2021-02-24 13:43:52 -06:00
// export gamepadAPI;
2021-02-05 03:19:09 -06:00
},{}],4:[function(require,module,exports){
var gamepad = require('./gamepad.js');
2021-02-25 17:05:22 -06:00
var utils = require('./utils.js');
2021-02-24 13:43:52 -06:00
// import * as gamepad from './gamepad.js';
2021-02-05 03:19:09 -06:00
var UserInputs = {
2021-02-25 17:05:22 -06:00
init() {
this.settingsMap = new Map();
var options = "";
// var init = utils.getCookie("init");
// if(init == "")
for(var i in this.settingsList)
utils.setCookie(this.settingsList[i], this.settingsDefault[i], 30); // cookies expire in 30 days
// else
// for(var i in this.settingsList)
// this.settingsDefault[i] = utils.getCookie(this.settingsList[i]);
for(var i in this.settingsList)
this.settingsMap.set(this.settingsList[i], this.settingsDefault[i]);
//document.getElementById("setting").innerHTML = settings;
2021-02-05 09:11:17 -06:00
document.addEventListener('keydown', this.keyDown.bind(this));
document.addEventListener('keyup', this.keyUp.bind(this));
2021-02-05 03:19:09 -06:00
},
updateGamepad() {
this.gpButtons = gamepad.update();
},
2021-02-12 00:37:49 -06:00
2021-02-05 03:19:09 -06:00
incDeciframes() {
2021-02-12 00:37:49 -06:00
this.keyboardButtonsDeciframes++;
this.keyboardDirectionArrowsDeciframes++;
this.gamepadButtonsDeciFrames++;
this.gamepadDirectionPadDeciFrames++;
2021-02-05 03:19:09 -06:00
},
2021-02-21 20:43:05 -06:00
incTickCounter() {
this.ticks++;
},
getTickCounter() {
return this.ticks;
},
2021-02-12 19:02:01 -06:00
2021-02-05 03:19:09 -06:00
processGamepadInput() {
2021-02-25 17:05:22 -06:00
// this.gamepadButtonsDown("RB"); // hard drop
// this.gamepadButtonsDown("LB"); // hold
// this.gamepadButtonsDown("A"); // rotate counter
// this.gamepadButtonsDown("B"); // rotate cwise
// this.gamepadButtonsDown("DPad-Up"); // Pop hold stack
// this.gamepadButtonsDown("Back"); // reset
2021-02-05 03:19:09 -06:00
//this.gamepadButtonsDown("X");
//this.gamepadButtonsDown("Y");
2021-02-12 00:37:49 -06:00
2021-02-25 17:05:22 -06:00
this.gamepadButtonsDown(this.settingsMap.get("gamepad_harddrop")); // hard drop
this.gamepadButtonsDown(this.settingsMap.get("gamepad_hold")); // hold
this.gamepadButtonsDown(this.settingsMap.get("gamepad_rotateccw")); // rotate counter
this.gamepadButtonsDown(this.settingsMap.get("gamepad_rotate")); // rotate cwise
this.gamepadButtonsDown(this.settingsMap.get("gamepad_pophold")); // Pop hold stack
this.gamepadButtonsDown(this.settingsMap.get("gamepad_reset")); // reset
2021-02-12 19:02:01 -06:00
return;
},
processGamepadDPad()
{
2021-02-25 17:05:22 -06:00
this.gamepadDPadDown(this.settingsMap.get("gamepad_left")); // shift left
this.gamepadDPadDown(this.settingsMap.get("gamepad_right")); // shift right
this.gamepadDPadDown(this.settingsMap.get("gamepad_down")); // down
2021-02-12 00:37:49 -06:00
2021-02-05 03:19:09 -06:00
return;
},
2021-02-12 19:02:01 -06:00
2021-02-05 09:11:17 -06:00
// X, Y, A, B , RB, LB Buttons
2021-02-05 03:19:09 -06:00
gamepadButtonsDown(finds) {
2021-02-12 00:37:49 -06:00
var deciDAS = 50.0;
var deciARR = 10.0;
2021-02-05 03:19:09 -06:00
var isContained = this.gpButtons.includes(finds);
2021-02-05 09:11:17 -06:00
var isPrevContained = this.prevGpButtons.includes(finds);
if(isPrevContained != isContained ) {
this.isGamepadButtonDown = false;
// Do once
if(isContained)
this.gamepadQueue.push(finds);
}
2021-02-12 00:37:49 -06:00
var gamepadDASFrames = this.gamepadButtonsDeciFrames / 1.0;
2021-02-05 09:11:17 -06:00
2021-02-05 03:19:09 -06:00
if (!this.isGamepadButtonDown) {
2021-02-05 09:11:17 -06:00
2021-02-12 00:37:49 -06:00
if (gamepadDASFrames >= deciDAS) {
this.gamepadButtonsDeciFrames = 0;
2021-02-05 03:19:09 -06:00
this.isGamepadButtonDown = true;
}
2021-02-05 09:11:17 -06:00
2021-02-05 03:19:09 -06:00
} else {
2021-02-12 00:37:49 -06:00
if (gamepadDASFrames >= deciARR && isContained) {
2021-02-13 08:57:33 -06:00
//this.gamepadQueue.push(finds);
2021-02-12 00:37:49 -06:00
this.gamepadButtonsDeciFrames = 0;
2021-02-05 03:19:09 -06:00
}
}
},
2021-02-05 09:11:17 -06:00
// Direction Pad
2021-02-12 00:37:49 -06:00
gamepadDPadDown(finds) {
2021-02-25 17:05:22 -06:00
var DAS = parseInt(this.settingsMap.get("gamepad_das")); //65.0;
var ARR = parseInt(this.settingsMap.get("gamepad_arr")); //20.0;
2021-02-05 03:19:09 -06:00
var isContained = this.gpButtons.includes(finds);
2021-02-05 09:11:17 -06:00
var isPrevContained = this.prevGpButtons.includes(finds);
2021-02-18 02:51:08 -06:00
2021-02-05 09:11:17 -06:00
if(isPrevContained != isContained ) {
this.isGamepadDown = false;
// Do once
2021-02-13 08:57:33 -06:00
if(isContained)
this.gamepadQueue.push(finds);
2021-02-05 09:11:17 -06:00
}
2021-02-25 11:00:02 -06:00
var gamepadDirectionDasFrames = this.gamepadDirectionPadDeciFrames;
2021-02-05 03:19:09 -06:00
if (!this.isGamepadDown) {
2021-02-12 19:02:01 -06:00
if (gamepadDirectionDasFrames >= DAS) {
this.gamepadDirectionPadDeciFrames = 0;
2021-02-05 03:19:09 -06:00
this.isGamepadDown = true;
2021-02-18 02:51:08 -06:00
2021-02-05 03:19:09 -06:00
}
2021-02-12 19:02:01 -06:00
}
else
{
if (gamepadDirectionDasFrames >= ARR && isContained) {
2021-02-05 03:19:09 -06:00
this.gamepadQueue.push(finds);
2021-02-12 19:02:01 -06:00
this.gamepadDirectionPadDeciFrames = 0;
2021-02-05 03:19:09 -06:00
}
}
2021-02-05 09:11:17 -06:00
2021-02-05 03:19:09 -06:00
return;
},
processKeys() {
2021-02-25 17:05:22 -06:00
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_harddrop"))); //32); // Space - hard drop
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_rotate"))); //88); // X - rotate
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_rotateccw"))); //90); // Z - rotateccw
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_hold"))); //16); // shift - push hold stack
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_pophold"))); // ctrl - pop hold stack
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_background"))); // q - turn off background
this.processKeyDown(parseInt(this.settingsMap.get("keyboard_reset"))); // r - reset
//this.processKeyDown(this.settingsMap.get("keyboard_hold"))); // c - pop hold stack
},
2021-02-12 00:37:49 -06:00
2021-02-05 14:46:41 -06:00
// keyboard keys z,x,space
processKeyDown(key)
{
2021-02-17 18:58:50 -06:00
var deciDAS = 50.0;
var deciARR = 50.0;
2021-02-12 00:37:49 -06:00
2021-02-17 18:58:50 -06:00
// todo: fix this mess
if(this.prevKeyboardKeys[key] != this.keyboardKeys[key] && this.isKeyBoardKeyDown == true) {
2021-02-12 00:37:49 -06:00
this.isKeyboardKeyDown = false;
if(this.keyboardKeys[key] == true)
this.inputqueue.push(key);
2021-02-17 18:58:50 -06:00
this.keyboardKeys[key] = false;
2021-02-12 00:37:49 -06:00
}
var keyboardDASFrames = this.keyboardButtonsDeciframes;
2021-02-12 00:37:49 -06:00
if (!this.isKeyboardKeyDown) {
if (keyboardDASFrames >= deciDAS) {
this.keyboardButtonsDeciframes = 0;
this.isKeyboardKeyDown = true;
}
} else {
2021-02-12 00:37:49 -06:00
if (keyboardDASFrames >= deciARR && this.keyboardKeys[key] == true) {
2021-02-13 08:57:33 -06:00
//this.inputqueue.push(key);
2021-02-12 00:37:49 -06:00
this.keyboardButtonsDeciframes = 0;
}
}
2021-02-12 00:37:49 -06:00
},
processKeyShift() {
2021-02-25 17:05:22 -06:00
this.processKeyboardArrowKeys(parseInt(this.settingsMap.get("keyboard_left"))); //39); // right
this.processKeyboardArrowKeys(parseInt(this.settingsMap.get("keyboard_right"))); //37); // left
this.processKeyboardArrowKeys(parseInt(this.settingsMap.get("keyboard_down"))); // down
},
2021-02-05 14:46:41 -06:00
// Direction arrows
2021-02-12 00:37:49 -06:00
processKeyboardArrowKeys(key) {
2021-02-25 17:05:22 -06:00
var DAS = parseInt(this.settingsMap.get("keyboard_das")); //65.0;
var ARR = parseInt(this.settingsMap.get("keyboard_arr")); //20.0;
2021-02-05 03:19:09 -06:00
2021-02-13 08:57:33 -06:00
2021-02-05 14:46:41 -06:00
if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) {
2021-02-12 00:37:49 -06:00
this.isDirectionArrowDown = false;
2021-02-05 14:46:41 -06:00
if(this.keyboardKeys[key] == true)
this.inputqueue.push(key);
}
2021-02-13 08:57:33 -06:00
2021-02-18 02:51:08 -06:00
2021-02-25 11:00:02 -06:00
var keyboardDASFrames = this.keyboardDirectionArrowsDeciframes;
2021-02-18 02:51:08 -06:00
2021-02-12 00:37:49 -06:00
if (!this.isDirectionArrowDown) {
if (keyboardDASFrames >= DAS) {
this.keyboardDirectionArrowsDeciframes = 0;
this.isDirectionArrowDown = true;
2021-02-05 03:19:09 -06:00
}
} else {
2021-02-12 00:37:49 -06:00
if (keyboardDASFrames >= ARR && this.keyboardKeys[key] == true) {
this.inputqueue.push(key);
2021-02-12 00:37:49 -06:00
this.keyboardDirectionArrowsDeciframes = 0;
2021-02-05 03:19:09 -06:00
}
}
//}
2021-02-05 03:19:09 -06:00
},
keyDown(event) {
2021-02-25 17:05:22 -06:00
if (! ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8))
event.preventDefault();
this.keyboardKeys[event.keyCode] = true;
2021-02-17 18:58:50 -06:00
this.isKeyBoardKeyDown = true;
2021-02-05 03:19:09 -06:00
},
keyUp(event) {
this.isKeyDown = false;
this.keyboardKeys[event.keyCode] = false;
2021-02-17 18:58:50 -06:00
this.isKeyBoardKeyDown = false;
2021-02-05 03:19:09 -06:00
},
gamepadButtonClear() {
gpButtons = [];
isGamepadDown = false;
isGamepadButtonDown = false;
2021-02-05 09:11:17 -06:00
gamepadQueue = [];
},
saveButtons() {
this.prevGpButtons = this.gpButtons;
},
2021-02-05 14:46:41 -06:00
saveKeyboardKeys() {
this.prevKeyboardKeys = {...this.keyboardKeys};
},
2021-02-12 00:37:49 -06:00
// button states
isDirectionArrowDown: false,
isKeyboardKeyDown: false,
2021-02-05 03:19:09 -06:00
isGamepadDown: false,
isGamepadButtonDown: false,
2021-02-12 00:37:49 -06:00
// das frame counters
keyboardButtonsDeciframes: 0, // DAS controlled frames/10 for non-shifted keys
keyboardDirectionArrowsDeciframes: 0, // DAS controlled frames/10 for mino shifting keys
gamepadButtonsDeciFrames: 0, // DAS controlled frames/10 for non-shifted keys
gamepadDirectionPadDeciFrames: 0, // DAS controlled frames/10 for mino shifting keys
// buttons state contatiners
2021-02-05 03:19:09 -06:00
gpButtons: [],
2021-02-05 09:11:17 -06:00
prevGpButtons:[],
keyboardKeys: [],
2021-02-05 14:46:41 -06:00
prevKeyboardKeys: [],
2021-02-12 00:37:49 -06:00
// button pressed containers
inputqueue: [],
2021-02-21 20:43:05 -06:00
gamepadQueue: [],
2021-02-25 17:05:22 -06:00
ticks: 0,
// todo: change to human readable
settingsList: ["init",
"keyboard_das", "keyboard_arr", "keyboard_harddrop", "keyboard_hold",
"keyboard_left", "keyboard_right", "keyboard_rotateccw", "keyboard_rotate",
"keyboard_down", "keyboard_pophold", "keyboard_reset", "keyboard_background",
"gamepad_das", "gamepad_arr", "gamepad_harddrop", "gamepad_hold",
"gamepad_left", "gamepad_right", "gamepad_rotateccw", "gamepad_rotate",
"gamepad_down","gamepad_pophold", "gamepad_reset", "gamepad_background",
"path", "SameSite"],
settingsDefault: ["true",
"65.0", "20.0", "32", "16",
"37", "39", "90", "88",
"40", "17", "82", "81",
"65.0", "10.0", "RB", "LB",
"DPad-Left", "DPad-Right", "A", "B",
"DPad-Down", "DPad-Up", "Back", "",
"=/", "Strict"],
settingsMap: []
2021-02-05 03:19:09 -06:00
};
module.exports = UserInputs;
2021-02-24 13:43:52 -06:00
// export UserInputs;
2021-02-25 17:05:22 -06:00
},{"./gamepad.js":3,"./utils.js":8}],5:[function(require,module,exports){
2021-02-05 03:19:09 -06:00
var utils = require('./utils.js');
var consts = require('./consts.js');
var shapes = require('./shapes.js');
var views = require('./views.js');
var canvas = require('./canvas.js');
var inputs = require('./input.js');
2021-02-12 19:02:01 -06:00
var openers = require('./openers.js');
2021-02-24 13:43:52 -06:00
// import * as utils from './utils.js';
// import * as consts from './const.js';
// import * as shapes from './shapes.js';
// import * as views from './views.js';
// import * as canvas from './canvas.js';
// import * as inputs from './input.js';
// import * as openers from './openers.js';
//import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r125/build/three.module.js';
2021-02-05 03:19:09 -06:00
/**
Init game matrix
*/
var initMatrix = function(rowCount, columnCount) {
var result = [];
for (var i = 0; i < rowCount; i++) {
var row = [];
result.push(row);
for (var j = 0; j < columnCount; j++) {
row.push(0);
}
}
return result;
};
/**
Clear game matrix
*/
var clearMatrix = function(matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix[i].length; j++) {
matrix[i][j] = 0;
}
}
};
/**
Check all full rows in game matrix
return rows number array. eg: [18,19];
*/
var checkFullRows = function(matrix) {
var rowNumbers = [];
for (var i = 0; i < matrix.length; i++) {
var row = matrix[i];
var full = true;
for (var j = 0; j < row.length; j++) {
full = full && row[j] !== 0;
}
if (full) {
rowNumbers.push(i);
}
}
return rowNumbers;
};
/**
Remove one row from game matrix.
copy each previous row data to next row which row number less than row;
*/
var removeOneRow = function(matrix, row) {
var colCount = matrix[0].length;
for (var i = row; i >= 0; i--) {
for (var j = 0; j < colCount; j++) {
if (i > 0) {
matrix[i][j] = matrix[i - 1][j];
} else {
matrix[i][j] = 0;
}
}
}
};
/**
Remove rows from game matrix by row numbers.
*/
var removeRows = function(matrix, rows) {
for (var i in rows) {
removeOneRow(matrix, rows[i]);
}
};
/**
Check game data to determin wether the game is over
*/
var checkGameOver = function(matrix) {
var firstRow = matrix[0];
for (var i = 0; i < firstRow.length; i++) {
if (firstRow[i] !== 0) {
return true;
};
}
return false;
};
/**
Calculate the extra rewards add to the score
*/
2021-02-21 20:43:05 -06:00
var calcRewards = function(rows, tspinType) {
if(tspinType == 2)
rows*=2+1;
2021-02-05 03:19:09 -06:00
if (rows && rows.length > 1) {
return Math.pow(2, rows.length - 1) * 100;
}
return 0;
};
/**
Calculate game score
*/
var calcScore = function(rows) {
if (rows && rows.length) {
return rows.length * 100;
}
return 0;
};
/**
Calculate time interval by level, the higher the level,the faster shape moves
*/
var calcIntervalByLevel = function(level) {
return consts.DEFAULT_INTERVAL - (level - 1) * 60;
};
// Default max scene size
var defaults = {
maxHeight: 700,
maxWidth: 600
};
/**
Tetris main object definition
*/
function Tetris(id) {
this.id = id;
this.init();
}
Tetris.prototype = {
init: function(options) {
2021-02-05 03:19:09 -06:00
var cfg = this.config = utils.extend(options, defaults);
this.interval = consts.DEFAULT_INTERVAL;
views.init(this.id, cfg.maxWidth, cfg.maxHeight);
2021-02-09 21:19:20 -06:00
canvas.init(views.scene, views.preview, views.hold);
2021-02-05 03:19:09 -06:00
inputs.init();
2021-02-25 17:05:22 -06:00
this.createSettings();
2021-02-24 13:43:52 -06:00
// if true no openers. just random tetrinos
this.isFreePlay = true;
this.currentOpener = 0;
2021-02-05 03:19:09 -06:00
this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT);
this.reset();
this._initEvents();
this._fireShape();
},
2021-02-24 13:43:52 -06:00
setFreePlay: function()
{
this.isFreePlay = true;
this.hintQueue = [];
this.shapeQueue = [];
this.hintMino = 0;
this._restartHandler();
this.currentOpener = 0;
2021-02-25 11:00:02 -06:00
2021-02-24 13:43:52 -06:00
},
setTKIFonzieVar: function()
{
2021-02-24 13:43:52 -06:00
this.isFreePlay = false;
this.currentOpener = 1;
2021-02-25 11:00:02 -06:00
this._restartHandler();
},
setDTCannonVar: function()
{
2021-02-24 13:43:52 -06:00
this.isFreePlay = false;
this.currentOpener = 2;
2021-02-25 11:00:02 -06:00
this._restartHandler();
2021-02-25 17:05:22 -06:00
},
createSettings: function () {
var list = document.getElementById("settings");
var settings = inputs.settingsList;
settings.forEach(function(item) {
var option = document.createElement('option');
option.text = item;
option.id = item;
list.add(option);
});
},
updateSettingTextBox: function() {
console.log(document.getElementById("setting_value").value = inputs.settingsDefault[document.getElementById("settings").selectedIndex-1]);
},
setSettings: function() {
//inputs.settingsDefault[document.getElementById("settings").selectedIndex-1] = document.getElementById("setting_value").value;
var newVal = document.getElementById("setting_value").value;
utils.setCookie(inputs.settingsList[document.getElementById("settings").selectedIndex-1], newVal, 30);
inputs.settingsMap.set(inputs.settingsList[document.getElementById("settings").selectedIndex-1], newVal);
//console.log("settings " + inputs.settingsList[document.getElementById("settings").selectedIndex-1] + " " + newVal);
},
2021-02-05 03:19:09 -06:00
//Reset game
reset: function() {
this.running = false;
this.isGameOver = false;
this.level = 1;
this.score = 0;
2021-02-09 21:19:20 -06:00
this.lines = 0;
2021-02-24 13:43:52 -06:00
// beginning of frame
2021-02-05 03:19:09 -06:00
this.startTime = new Date().getTime();
this.currentTime = this.startTime;
this.prevTime = this.startTime;
2021-02-24 13:43:52 -06:00
//todo:get rid of extra
2021-02-05 03:19:09 -06:00
this.levelTime = this.startTime;
2021-02-17 18:58:50 -06:00
this.prevInputTime = this.startTime;
2021-02-24 13:43:52 -06:00
// current tetrino index gets set to 0 at the end of opener sequence
this.currentMinoInx = 0;
this.shapeQueue = [];
this.hintQueue = [];
2021-02-25 11:00:02 -06:00
this.holdStack = [];
2021-02-24 13:43:52 -06:00
// gets set to false after mino has been popped from hold stack; set back to true on mino dropped
2021-02-25 11:00:02 -06:00
this.canPopFromHoldStack = false;
// manipulation counter for srs extended piece lockdown
this.manipulationCounter = 0;
2021-02-24 13:43:52 -06:00
// timer for srs extened piece lockdown
2021-02-25 11:00:02 -06:00
this.lockdownTimer = 0;
this.landed = false;
2021-02-05 03:19:09 -06:00
clearMatrix(this.matrix);
views.setLevel(this.level);
views.setScore(this.score);
views.setGameOver(this.isGameOver);
2021-02-18 02:51:08 -06:00
openers.reset();
2021-02-05 03:19:09 -06:00
this._draw();
},
//Start game
start: function() {
this.running = true;
2021-02-17 18:58:50 -06:00
window.requestAnimationFrame(utils.proxy(this._refresh, this));
2021-02-05 03:19:09 -06:00
},
//Pause game
pause: function() {
this.running = false;
this.currentTime = new Date().getTime();
this.prevTime = this.currentTime;
},
2021-02-09 21:19:20 -06:00
pushHoldStack: function()
{
2021-02-25 11:00:02 -06:00
if(this.holdStack.length < 4) {
this.holdStack.push(utils.deepClone(this.shape));
2021-02-09 21:19:20 -06:00
this.shape = this.shapeQueue.shift();
2021-02-25 11:00:02 -06:00
this.canPopFromHoldStack = false;
2021-02-12 00:37:49 -06:00
this.shape.resetOrigin();
2021-02-25 11:00:02 -06:00
//canvas.drawHoldShape(this.holdStack);
2021-02-09 21:19:20 -06:00
this._draw(); // update?
}
},
popHoldStack: function()
{
2021-02-25 11:00:02 -06:00
if(this.holdStack.length >= 1 && this.canPopFromHoldStack)
2021-02-09 21:19:20 -06:00
{
2021-02-25 11:00:02 -06:00
this.canPopFromHoldStack = false;
this.shapeQueue.unshift(utils.deepClone(this.shape));
this.shape = this.holdStack.pop();
2021-02-12 00:37:49 -06:00
this.shape.resetOrigin();
2021-02-25 11:00:02 -06:00
//canvas.drawHoldShape(this.holdStack);
2021-02-09 21:19:20 -06:00
this._draw();
}
},
2021-02-05 03:19:09 -06:00
// Restart game
_restartHandler: function() {
this.reset();
this.start();
2021-02-25 11:00:02 -06:00
this._fireShape();
2021-02-05 03:19:09 -06:00
},
// Bind game events
_initEvents: function() {
2021-02-25 11:00:02 -06:00
setInterval(() => {this._processTick();}, 1);
setInterval(() => {this.lockDownTimer++;}, 100 );
2021-02-05 03:19:09 -06:00
views.btnRestart.addEventListener('click', utils.proxy(this._restartHandler, this), false);
},
2021-02-25 11:00:02 -06:00
// Fill next queue and set next shape
2021-02-05 03:19:09 -06:00
_fireShape: function() {
2021-02-24 13:43:52 -06:00
2021-02-24 13:43:52 -06:00
if(this.isFreePlay == false) {
while(this.shapeQueue.length <= 4)
{
this.preparedShape = openers.getNextMino(this.currentOpener);
this.shapeQueue.push(this.preparedShape);
}
while(this.hintQueue.length <= 4)
{
this.preparedShape = openers.getNextHint(this.currentOpener);
this.hintQueue.push(this.preparedShape);
}
2021-02-24 13:43:52 -06:00
this.hintMino = this.hintQueue.shift();
this.shape = this.shapeQueue.shift();// shapes.randomShape();
this.currentMinoInx++;
if(this.currentMinoInx > openers.getLength()) {
this.hintQueue = [];
this.shapeQueue = [];
this._restartHandler();
}
} else {
while(this.shapeQueue.length <= 4)
{
this.preparedShape = shapes.randomShape();
this.shapeQueue.push(this.preparedShape);
}
this.shape = this.shapeQueue.shift() || randomShape();
this.currentMinoInx++;
}
2021-02-25 11:00:02 -06:00
//todo:should be in shapes.js
this.landed = false;
this.manipulationCounter = 0;
2021-02-21 20:43:05 -06:00
// Reset matrix at successful end of opener
//if(this.shapeQueue.length == openers.length) {
// this.matrix = [];
// new Audio("Tetris.ogg");
//}
2021-02-12 19:02:01 -06:00
this._draw();
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
},
2021-02-25 11:00:02 -06:00
// lockdown timer with centisecond resolution
resetLockdown: function() {
if(this.shape.canDown(this.matrix) == false)
this.landed = true;
this.lockDownTimer = 0;
if(this.landed)
this.manipulationCounter++;
},
// Return if the piece can be shifted or rotated
isPieceLocked: function() {
if(this.manipulationCounter > 15) return true;
if(this.lockDownTimer >= 5) return true;
return false;
},
2021-02-05 03:19:09 -06:00
// Draw game data
_draw: function() {
canvas.drawScene();
canvas.drawShape(this.shape);
2021-02-25 11:00:02 -06:00
canvas.drawHoldShape(this.holdStack);
2021-02-09 21:19:20 -06:00
canvas.drawPreviewShape(this.shapeQueue);
2021-02-21 22:01:28 -06:00
canvas.drawHintShape(this.hintMino);
2021-02-21 20:43:05 -06:00
2021-02-05 14:46:41 -06:00
if(this.shape != undefined) {
let clone = Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape);
2021-02-12 22:44:49 -06:00
2021-02-05 14:46:41 -06:00
var bottomY = clone.bottomAt(this.matrix);
canvas.drawGhostShape(clone, bottomY);
}
2021-02-05 03:19:09 -06:00
canvas.drawMatrix(this.matrix);
},
2021-02-25 11:00:02 -06:00
// tick input data
2021-02-24 13:43:52 -06:00
_processTick: async function() {
2021-02-17 18:58:50 -06:00
2021-02-21 20:43:05 -06:00
var deltaTime = 1.0; // 1 millisecond
2021-02-18 03:25:05 -06:00
var tenthOfFrame = 1.0//1;//1.6; // 1.6ms = 1 fram
var halfFrame = 5.0//5;//8.0;
2021-02-17 18:58:50 -06:00
var halfFramePlus = 10.0;//10.0;
2021-02-12 00:37:49 -06:00
2021-02-21 22:01:28 -06:00
inputs.incDeciframes();
inputs.incTickCounter();
2021-02-21 20:43:05 -06:00
if(inputs.getTickCounter() >= tenthOfFrame) {
2021-02-05 09:11:17 -06:00
inputs.updateGamepad();
2021-02-12 19:02:01 -06:00
inputs.processGamepadDPad();
inputs.processGamepadInput();
}
2021-02-12 00:37:49 -06:00
2021-02-25 11:00:02 -06:00
// Don't process game related events if game over
if(this.isGameOver) return;
2021-02-05 09:11:17 -06:00
// drain gamepad queue
2021-02-21 20:43:05 -06:00
if(inputs.getTickCounter() > halfFrame) // 8 millisecons
2021-02-05 03:19:09 -06:00
{
2021-02-05 09:11:17 -06:00
while((inputs.gamepadQueue != undefined && inputs.gamepadQueue.length >= 1)){
2021-02-09 21:19:20 -06:00
var curkey = inputs.gamepadQueue.shift();
2021-02-05 09:11:17 -06:00
if(curkey == "DPad-Left") {
this.shape.goLeft(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 09:11:17 -06:00
}
if(curkey == "DPad-Right") {
this.shape.goRight(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 09:11:17 -06:00
}
if(curkey == "A") {
2021-02-24 13:43:52 -06:00
this.rotationCounter++;
2021-02-05 09:11:17 -06:00
this.shape.rotate(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 09:11:17 -06:00
}
if(curkey == "B") {
2021-02-24 13:43:52 -06:00
this.rotationCounter++;
2021-02-17 18:58:50 -06:00
this.shape.rotateClockwise(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 09:11:17 -06:00
}
if(curkey == "DPad-Down") {
this.shape.goDown(this.matrix);
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 09:11:17 -06:00
}
if(curkey == "RB") {
this.shape.goBottom(this.matrix);
2021-02-25 11:00:02 -06:00
this.lockDownTimer = 5000;
2021-02-05 09:11:17 -06:00
this._update();
}
2021-02-09 21:19:20 -06:00
if(curkey == "LB") {
this.pushHoldStack();
2021-02-25 11:00:02 -06:00
this._draw();
2021-02-09 21:19:20 -06:00
}
if(curkey == "DPad-Up") {
this.popHoldStack();
2021-02-25 11:00:02 -06:00
this._draw();
2021-02-09 21:19:20 -06:00
}
if(curkey == "Back") {
this._restartHandler();
return;
}
2021-02-05 09:11:17 -06:00
}
2021-02-05 09:11:17 -06:00
inputs.gamepadQueue = [];
}
//inputs.gamepadButtonClear();
2021-02-05 14:46:41 -06:00
// Do keyboard
2021-02-21 20:43:05 -06:00
if(inputs.getTickCounter() > tenthOfFrame) // 120hz
{
inputs.processKeys();
}
2021-02-21 20:43:05 -06:00
if (inputs.getTickCounter() > tenthOfFrame) { // 60hz
2021-02-09 21:19:20 -06:00
inputs.processKeyShift();
2021-02-05 03:19:09 -06:00
// Keyboard inputs
while((inputs.inputqueue != undefined && inputs.inputqueue.length >= 1)){
2021-02-09 21:19:20 -06:00
var curkey = inputs.inputqueue.shift();
2021-02-05 03:19:09 -06:00
if(curkey == 37) {
this.shape.goLeft(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 03:19:09 -06:00
}
if(curkey == 39){
this.shape.goRight(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
2021-02-05 03:19:09 -06:00
}
if(curkey == 40) {
this.shape.goDown(this.matrix);
2021-02-24 13:43:52 -06:00
this._draw();
}
if(curkey == 90) {
2021-02-24 13:43:52 -06:00
this.rotationCounter++;
this.shape.rotate(this.matrix);
2021-02-25 11:00:02 -06:00
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
}
if(curkey == 88){
2021-02-24 13:43:52 -06:00
this.rotationCounter++;
2021-02-25 11:00:02 -06:00
this.shape.rotateClockwise(this.matrix);
this.resetLockdown();
2021-02-24 13:43:52 -06:00
this._draw();
}
if(curkey == 32) {
this.shape.goBottom(this.matrix);
2021-02-25 11:00:02 -06:00
this.lockDownTimer = 5000;
this._update();
}
2021-02-09 21:19:20 -06:00
if(curkey == 16) {
2021-02-12 19:02:01 -06:00
this.pushHoldStack();
2021-02-25 11:00:02 -06:00
//this._update();
this._draw();
2021-02-09 21:19:20 -06:00
}
2021-02-25 11:00:02 -06:00
if(curkey == 17 || curkey == 67) {
2021-02-12 19:02:01 -06:00
this.popHoldStack();
2021-02-25 11:00:02 -06:00
//this._update();
this._draw();
2021-02-09 21:19:20 -06:00
}
if(curkey == 81) {
2021-02-24 13:43:52 -06:00
if(document.getElementById("divbg").style.display == "none")
document.getElementById("divbg").style.display = "initial";
2021-02-13 08:57:33 -06:00
else
2021-02-24 13:43:52 -06:00
document.getElementById("divbg").style.display="none";
}
if(curkey == 82) {
this._restartHandler();
return;
}
2021-02-05 03:19:09 -06:00
}
inputs.inputqueue = [];
2021-02-05 03:19:09 -06:00
}
2021-02-21 20:43:05 -06:00
if(inputs.getTickCounter() >= halfFramePlus)
2021-02-05 14:46:41 -06:00
inputs.saveKeyboardKeys();
2021-02-09 21:19:20 -06:00
2021-02-21 20:43:05 -06:00
if(inputs.getTickCounter() >= tenthOfFrame)
2021-02-09 21:19:20 -06:00
inputs.saveButtons();
2021-02-17 18:58:50 -06:00
},
// Refresh game canvas
_refresh: async function() {
if (!this.running) {
return;
}
this.currentTime = new Date().getTime();
var curInputTime = new Date().getTime();
2021-02-17 18:58:50 -06:00
this.prevInputTime = curInputTime;
var deltaLevelTime = this.currentTime - this.prevTime;
if (deltaLevelTime > this.interval) {
this._update();
this._checkLevel(this.prevTime = this.currentTime);
2021-02-05 03:19:09 -06:00
}
2021-02-17 18:58:50 -06:00
// Draw Frame
2021-02-05 03:19:09 -06:00
if (!this.isGameOver) {
window.requestAnimationFrame(utils.proxy(this._refresh, this));
}
2021-02-17 18:58:50 -06:00
2021-02-05 03:19:09 -06:00
},
2021-02-25 11:00:02 -06:00
// check if the current piece is in the same location as the hint piece
2021-02-18 02:51:08 -06:00
_checkHint: function() {
2021-02-21 20:43:05 -06:00
2021-02-24 13:43:52 -06:00
if(this.isFreePlay)
return;
2021-02-21 20:43:05 -06:00
if(!this.shape.isSameSRS(this.hintMino))
{
2021-02-21 22:01:28 -06:00
new Audio('./dist/Failed.ogg').play();
2021-02-18 03:25:05 -06:00
this._restartHandler();
2021-02-25 11:00:02 -06:00
// Restart
return 1;
2021-02-18 03:25:05 -06:00
}
2021-02-18 02:51:08 -06:00
},
2021-02-05 03:19:09 -06:00
// Update game data
_update: function() {
if (this.shape.canDown(this.matrix)) {
this.shape.goDown(this.matrix);
2021-02-25 11:00:02 -06:00
} else if(this.isPieceLocked()){
this.canPopFromHoldStack = true;
2021-02-05 03:19:09 -06:00
this.shape.copyTo(this.matrix);
this._check();
2021-02-25 11:00:02 -06:00
if(this._checkHint()) return;
2021-02-05 03:19:09 -06:00
this._fireShape();
2021-02-13 08:57:33 -06:00
new Audio('./dist/Blop2.ogg').play();
2021-02-05 03:19:09 -06:00
}
this._draw();
this.isGameOver = checkGameOver(this.matrix);
views.setGameOver(this.isGameOver);
if (this.isGameOver) {
views.setFinalScore(this.score);
}
},
2021-02-21 20:43:05 -06:00
// 0 - none, 1 - mini, 2 - tspin
_tSpinType: function(tPiece, matrix) {
var side1 = 0;
var side2 = 0;
var side3 = 0;
var side4 = 0;
side1X = tPiece.x;
side1Y = tPiece.y;
side2X = tPiece.x + 2;
side2Y = tPiece.y;
side3X = tPiece.x;
side3Y = tPiece.y + 2;
side4X = tPiece.x + 2;
side4Y = tPiece.y + 2;
if(matrix[side1Y][side1X] != 0)
side1 = 1;
if(matrix[side2Y][side2X] != 0)
side2 = 1;
if(matrix[side3Y][side3X] != 0)
side3 = 1;
if(matrix[side4Y][side4X] != 0)
side4 = 1;
console.log("sides: " + side1+side2+side3+side4);
// if Sides A and B + (C or D) are touching a Surface
//considered a T-Spin
if((side1+side2+side3+side4) >= 3)
return 2;
//if Sides C and D + (A or B) are touching a Surface
//considered a Mini T-Spin
if((side1 || side2) && (side3 && side4))
return 1;
return 0;
},
2021-02-05 03:19:09 -06:00
// Check and update game data
_check: function() {
var rows = checkFullRows(this.matrix);
if (rows.length) {
2021-02-21 20:43:05 -06:00
var tspinType;
2021-02-24 13:43:52 -06:00
// if(rows.length >= 4)
// new Audio('./dist/Tetris.ogg').play();
2021-02-21 20:43:05 -06:00
if(this.shape.flag === 'T')
tspinType = this._tSpinType(this.shape, this.matrix);
2021-02-05 03:19:09 -06:00
removeRows(this.matrix, rows);
2021-02-21 20:43:05 -06:00
console.log("type: " + tspinType);
2021-02-05 03:19:09 -06:00
var score = calcScore(rows);
2021-02-21 20:43:05 -06:00
var reward = calcRewards(rows, tspinType);
2021-02-05 03:19:09 -06:00
this.score += score + reward;
2021-02-09 21:19:20 -06:00
this.lines += rows.length;
2021-02-05 03:19:09 -06:00
views.setScore(this.score);
views.setReward(reward);
2021-02-09 21:19:20 -06:00
views.setLines(this.lines);
2021-02-05 03:19:09 -06:00
}
},
// Check and update game level
_checkLevel: function() {
var currentTime = new Date().getTime();
if (currentTime - this.levelTime > consts.LEVEL_INTERVAL) {
this.level += 1;
this.interval = calcIntervalByLevel(this.level);
views.setLevel(this.level);
this.levelTime = currentTime;
}
}
}
window.Tetris = Tetris;
2021-02-24 13:43:52 -06:00
// export {Tetris};
2021-02-12 19:02:01 -06:00
},{"./canvas.js":1,"./consts.js":2,"./input.js":4,"./openers.js":6,"./shapes.js":7,"./utils.js":8,"./views.js":9}],6:[function(require,module,exports){
var shapes = require("./shapes.js");
2021-02-24 13:43:52 -06:00
// import * as shapes from './shapes.js';
2021-02-12 19:02:01 -06:00
var OpenerGenerator = {
shapeQueue: [],
hintQueue: [],
idx: 0,
2021-02-12 22:44:49 -06:00
hintIdx: 0,
2021-02-12 19:02:01 -06:00
isInit: 0,
isHintInit: 0,
// Current Tetriminos
init(opener) {
2021-02-12 19:02:01 -06:00
if(!this.isInit || this.shapeQueue == undefined) {
switch(opener) {
case 0:
case 1:
// Fonzie Variation
this.shapeQueue = new Array(
shapes.getShape(0),
shapes.getShape(6),
shapes.getShape(1),
shapes.getShape(5),
shapes.getShape(2),
shapes.getShape(4),
shapes.getShape(3));
break;
case 2:
// DTCannon -- O I L S J Z T O I L J T O T
this.shapeQueue = new Array(
shapes.getShape(1),
shapes.getShape(6),
shapes.getShape(0),
shapes.getShape(5),
shapes.getShape(4),
shapes.getShape(2),
shapes.getShape(3),
shapes.getShape(1),
shapes.getShape(6),
shapes.getShape(0),
shapes.getShape(4),
shapes.getShape(3),
shapes.getShape(1),
shapes.getShape(3));
break;
default:
return;
}
2021-02-12 19:02:01 -06:00
}
this.isInit = 1;
2021-02-18 02:51:08 -06:00
return;
2021-02-12 19:02:01 -06:00
},
getNextMino(opener) {
this.init(opener);
2021-02-12 19:02:01 -06:00
var mino = this.shapeQueue[this.idx];
this.idx++;
2021-02-21 22:01:28 -06:00
if(this.idx == this.shapeQueue.length) {
2021-02-12 19:02:01 -06:00
this.idx = 0;
this.isInit = 0;
}
return mino;
},
// Hint Tetrimions
initHint(opener) {
2021-02-21 22:01:28 -06:00
if(!this.isHintInit || this.hintQueue == undefined) {
switch(opener) {
case 0:
case 1:
// Fonzie Variation
this.hintQueue = new Array(
shapes.getShape(0),
shapes.getShape(6),
shapes.getShape(1),
shapes.getShape(5),
shapes.getShape(2),
shapes.getShape(4),
shapes.getShape(3));
// L
this.hintQueue[0].x = -1;
this.hintQueue[0].y = 17;
this.hintQueue[0].state = this.hintQueue[0].nextState(1);
// I
this.hintQueue[1].x = 3;
this.hintQueue[1].y = 17;
this.hintQueue[1].state = this.hintQueue[1].nextState(1);
// O
this.hintQueue[2].x = 6;
this.hintQueue[2].y = 18;
// S
this.hintQueue[3].x = 5;
this.hintQueue[3].y = 17;
this.hintQueue[3].state = this.hintQueue[3].nextState(1);
// Z
this.hintQueue[4].x = 3;
this.hintQueue[4].y = 17;
// J
this.hintQueue[5].x = 7;
this.hintQueue[5].y = 16;
// T
this.hintQueue[6].x = 1;
this.hintQueue[6].y = 17;
this.hintQueue[6].state = this.hintQueue[6].nextState(2);
break;
case 2:
this.hintQueue = new Array(
shapes.getShape(1),
shapes.getShape(6),
shapes.getShape(0),
shapes.getShape(5),
shapes.getShape(4),
shapes.getShape(2),
shapes.getShape(3),
shapes.getShape(1),
shapes.getShape(6),
shapes.getShape(0),
shapes.getShape(4),
shapes.getShape(3),
shapes.getShape(1),
shapes.getShape(3));
// DT Cannon -- O I L S J Z T O I L J T O T
// O
this.hintQueue[0].x = -2;
this.hintQueue[0].y = 18;
// I
this.hintQueue[1].x = 6;
this.hintQueue[1].y = 16;
// L
this.hintQueue[2].x = 6;
this.hintQueue[2].y = 17;
this.hintQueue[2].state = this.hintQueue[2].nextState(1);
// S
this.hintQueue[3].x = 7;
this.hintQueue[3].y = 17;
this.hintQueue[3].state = this.hintQueue[3].nextState(1);
// J
this.hintQueue[4].x = 4;
this.hintQueue[4].y = 17;
this.hintQueue[4].state = this.hintQueue[4].nextState(-1);
// Z
this.hintQueue[5].x = 3;
this.hintQueue[5].y = 17;
this.hintQueue[5].state = this.hintQueue[5].nextState(3);
// T
this.hintQueue[6].x = 3;
this.hintQueue[6].y = 15;
// O
this.hintQueue[7].x = 5;
this.hintQueue[7].y = 15;
// I
this.hintQueue[8].x = 9;
this.hintQueue[8].y = 14;
// L
this.hintQueue[9].x = 2;
this.hintQueue[9].y = 13;
this.hintQueue[9].state = this.hintQueue[9].nextState(-1);
// J
this.hintQueue[10].x = -1;
this.hintQueue[10].y = 15;
this.hintQueue[10].state = this.hintQueue[10].nextState(1);
// T
this.hintQueue[11].x = 1;
this.hintQueue[11].y = 16;
this.hintQueue[11].state = this.hintQueue[11].nextState(2);
// O
this.hintQueue[12].x = 3;
this.hintQueue[12].y = 16;
this.hintQueue[12].state = this.hintQueue[12].nextState(1);
// T
this.hintQueue[13].x = 1;
this.hintQueue[13].y = 17;
this.hintQueue[13].state = this.hintQueue[13].nextState(-1);
2021-02-21 22:01:28 -06:00
break;
default:
return;
}
2021-02-21 22:01:28 -06:00
}
this.isHintInit = 1;
2021-02-18 02:51:08 -06:00
return;
2021-02-12 19:02:01 -06:00
},
// End initHint
getNextHint(opener) {
this.initHint(opener);
2021-02-12 19:02:01 -06:00
var mino = this.hintQueue[this.hintIdx];
this.hintIdx++;
2021-02-21 22:01:28 -06:00
if(this.hintIdx == this.hintQueue.length) {
2021-02-12 19:02:01 -06:00
this.hintIdx = 0;
this.isHintInit = 0;
}
return mino;
2021-02-12 22:44:49 -06:00
},
2021-02-12 22:44:49 -06:00
reset() {
this.shapeQueue = [];
this.hintQueue = [];
this.idx = 0;
this.hintIdx = 0;
2021-02-18 02:51:08 -06:00
this.isInit = 0;
this.isHintInit = 0;
},
getLength() {
return this.hintQueue.length;
2021-02-12 19:02:01 -06:00
}
};
2021-02-12 22:44:49 -06:00
function reset() {
OpenerGenerator.reset();
}
function getNextMino(opener) {
var mino = OpenerGenerator.getNextMino(opener);
2021-02-12 19:02:01 -06:00
return mino;
}
function getNextHint(opener) {
var mino = OpenerGenerator.getNextHint(opener);
2021-02-12 19:02:01 -06:00
return mino;
}
function getLength() {
return OpenerGenerator.getLength();
}
2021-02-12 19:02:01 -06:00
module.exports.getNextMino = getNextMino;
2021-02-12 22:44:49 -06:00
module.exports.getNextHint = getNextHint;
module.exports.getLength = getLength;
2021-02-12 22:44:49 -06:00
module.exports.reset = reset;
2021-02-24 13:43:52 -06:00
// export getNextMino;
// export getNextHint;
// export getLength;
// export reset;
2021-02-12 19:02:01 -06:00
},{"./shapes.js":7}],7:[function(require,module,exports){
2021-02-05 03:19:09 -06:00
var consts = require('./consts.js');
2021-02-24 13:43:52 -06:00
// import * as consts from './const.js';
2021-02-05 03:19:09 -06:00
var COLORS = consts.COLORS;
var COLUMN_COUNT = consts.COLUMN_COUNT;
/**
Defined all shapes used in Tetris game.
You can add more shapes if you wish.
*/
2021-02-21 20:43:05 -06:00
2021-02-05 03:19:09 -06:00
function ShapeL() {
var state1 = [
2021-02-21 20:43:05 -06:00
[0, 0, 1, 0],
[1, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state3 = [
2021-02-21 20:43:05 -06:00
[0, 0, 0, 0],
[1, 1, 1, 0],
[1, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state4 = [
2021-02-21 20:43:05 -06:00
[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
// Rotation point offsets: clockwise<point1, point2>, counterclockwise<point3, point4>, <newline>
// In guidline Tetris each piece has 5 possible rotation points with respect to each state/orientation. Iterate through all every rotation.
var state1RotationPointsOffset = [
0, 0, 0, 0,
1, 0, -1, 0,
1, 1, -1, 1,
0, -2, 0, -2,
1, -2, -1, -2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 1, 0,
1, -1, 1, -1,
0, 2, 0, 2,
1, 2, 1, 2
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, 1, 0,
-1, 1, 1, 1,
0, -2, 0, -2,
-1, -2, 1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -1, 0,
-1, -1, -1, -1,
0, 2, 0, 2,
-1, 2, -1, 2
];
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
2021-02-05 03:19:09 -06:00
this.states = [state1, state2, state3, state4];
this.x = 4;
this.y = -3;
2021-02-12 00:37:49 -06:00
this.originY = -3;
2021-02-05 03:19:09 -06:00
this.flag = 'L';
}
function ShapeLR() {
var state1 = [
2021-02-21 20:43:05 -06:00
[1, 0, 0, 0],
[1, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state3 = [
2021-02-21 20:43:05 -06:00
[0, 0, 0, 0],
[1, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state4 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[0, 1, 0, 0],
[1, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state1RotationPointsOffset = [
0, 0, 0, 0,
1, 0, -1, 0,
1, 1, -1, 1,
0, -2, 0, -2,
1, -2, -1, -2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 1, 0,
1, -1, 1, -1,
0, 2, 0, 2,
1, 2, 1, 2
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, 1, 0,
-1, 1, 1, 1,
0, -2, 0, -2,
-1, -2, 1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -1, 0,
-1, -1, -1, -1,
0, 2, 0, 2,
2021-02-24 13:43:52 -06:00
-1, 2, -1, 2
];
2021-02-05 03:19:09 -06:00
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
2021-02-05 03:19:09 -06:00
this.states = [state1, state2, state3, state4];
this.x = 4;
this.y = -3;
2021-02-12 00:37:49 -06:00
this.originY = -3;
2021-02-05 03:19:09 -06:00
this.flag = 'LR';
}
function ShapeO() {
var state1 = [
2021-02-21 20:43:05 -06:00
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
var state2 = [
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
var state3 = [
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
var state4 = [
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state1RotationPointsOffset = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
];
2021-02-05 03:19:09 -06:00
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
this.states = [state1, state2, state3, state4];
this.x = 2;
2021-02-05 03:19:09 -06:00
this.y = -2;
2021-02-12 00:37:49 -06:00
this.originY = -2;
2021-02-05 03:19:09 -06:00
this.flag = 'O';
}
function ShapeI() {
2021-02-21 20:43:05 -06:00
// North
2021-02-05 03:19:09 -06:00
var state1 = [
2021-02-21 20:43:05 -06:00
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 0, 0, 0],
[1, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
2021-02-21 20:43:05 -06:00
// East
2021-02-05 03:19:09 -06:00
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 1, 1],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
2021-02-21 20:43:05 -06:00
// South
var state3 = [
[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 0, 1, 0]
];
// West
var state4 = [
[0, 0, 0, 0],
[1, 1, 1, 1],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
2021-02-21 20:43:05 -06:00
2021-02-24 13:43:52 -06:00
var state1RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -2, 0,
2, 0, 1, 0,
-1, 2, -2, -1,
2, -1, 1, 2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
2, 0, -1, 0,
-1, 0, 2, 0,
2, 1, -1, 2,
-1, -2, 2, -1
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 2, 0,
-2, 0, -1, 0,
1, -2, 2, 1,
-2, 1, -1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-2, 0, 1, 0,
1, 0, -2, 0,
-2, -1, 1, -2,
1, 2, -2, 1
];
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
2021-02-21 20:43:05 -06:00
this.states = [state1, state2, state3, state4];
2021-02-05 03:19:09 -06:00
this.x = 5;
this.y = -4;
2021-02-12 00:37:49 -06:00
this.originY = -4;
2021-02-05 03:19:09 -06:00
this.flag = 'I';
}
function ShapeT() {
var state1 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[1, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state3 = [
2021-02-21 20:43:05 -06:00
[0, 0, 0, 0],
[1, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state4 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
2021-02-21 20:43:05 -06:00
// rotation points clockwise<point1, point2>, counterclockwise<point1, point2>
var state1RotationPointsOffset = [
0, 0, 0, 0,
1, 0, -1, 0,
1, 1, -1, 1,
NaN, NaN, NaN, NaN,
1, -2, -1, -2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 1, 0,
1, -1, 1, -1,
0, 2, 0, 2,
1, 2, 1, 2
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, 1, 0,
NaN, NaN, NaN, NaN,
0, -2, 0, -2,
-1, -2, 1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -1, 0,
-1, -1, -1, -1,
0, 2, 0, 2,
-1, 2, -1, 2
];
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
this.states = [state1, state2, state3, state4];
2021-02-05 03:19:09 -06:00
this.x = 4;
this.y = -2;
2021-02-12 00:37:49 -06:00
this.originY = -2;
2021-02-05 03:19:09 -06:00
this.flag = 'T';
}
function ShapeZ() {
var state1 = [
2021-02-21 20:43:05 -06:00
[1, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
var state3 = [
[0, 0, 0, 0],
2021-02-21 20:43:05 -06:00
[1, 1, 0, 0],
[0, 1, 1, 0],
2021-02-21 20:43:05 -06:00
[0, 0, 0, 0]
];
var state4 = [
[0, 1, 0, 0],
[1, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
// Rotation point offsets: clockwise<point1, point2>, counterclockwise<point3, point4>, <newline>
// In guidline Tetris each piece has 5 possible rotation points with respect to each state/orientation. Iterate through all every rotation.
var state1RotationPointsOffset = [
0, 0, 0, 0,
1, 0, -1, 0,
1, 1, -1, 1,
0, -2, 0, -2,
1, -2, -1, -2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 1, 0,
1, -1, 1, -1,
0, 2, 0, 2,
1, 2, 1, 2
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, 1, 0,
-1, 1, 1, 1,
0, -2, 0, -2,
-1, -2, 1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -1, 0,
-1, -1, -1, -1,
0, 2, 0, 2,
-1, 2, -1, 2
];
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
2021-02-21 20:43:05 -06:00
this.states = [state1, state2, state3, state4];
2021-02-05 03:19:09 -06:00
this.x = 4;
this.y = -2;
2021-02-12 00:37:49 -06:00
this.originY = -2;
2021-02-05 03:19:09 -06:00
this.flag = 'Z';
}
function ShapeZR() {
var state1 = [
2021-02-21 20:43:05 -06:00
[0, 1, 1, 0],
[1, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
var state2 = [
2021-02-21 20:43:05 -06:00
[0, 1, 0, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]
];
var state3 = [
[0, 0, 0, 0],
[0, 1, 1, 0],
[1, 1, 0, 0],
[0, 0, 0, 0]
];
var state4 = [
[1, 0, 0, 0],
[1, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
2021-02-05 03:19:09 -06:00
];
// Rotation point offsets: clockwise<point1, point2>, counterclockwise<point3, point4>, <newline>
// In guidline Tetris each piece has 5 possible rotation points with respect to each state/orientation. Iterate through all every rotation.
var state1RotationPointsOffset = [
0, 0, 0, 0,
1, 0, -1, 0,
1, 1, -1, 1,
0, -2, 0, -2,
1, -2, -1, -2
];
var state2RotationPointsOffset = [
0, 0, 0, 0,
1, 0, 1, 0,
1, -1, 1, -1,
0, 2, 0, 2,
1, 2, 1, 2
];
var state3RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, 1, 0,
-1, 1, 1, 1,
0, -2, 0, -2,
-1, -2, 1, -2
];
var state4RotationPointsOffset = [
0, 0, 0, 0,
-1, 0, -1, 0,
-1, -1, -1, -1,
0, 2, 0, 2,
-1, 2, -1, 2
];
this.rotationPoints = [state1RotationPointsOffset, state2RotationPointsOffset, state3RotationPointsOffset, state4RotationPointsOffset];
2021-02-21 20:43:05 -06:00
this.states = [state1, state2, state3, state4];
2021-02-05 03:19:09 -06:00
this.x = 4;
2021-02-12 00:37:49 -06:00
this.y = -2
this.originY = -2;
2021-02-05 03:19:09 -06:00
this.flag = 'ZR';
}
2021-02-21 20:43:05 -06:00
/**
doesShapeOverlap
@param shape: tetris shape
@param matrix: game matrix
*/
var doesShapeOverlap = function(shape, matrix) {
var rows = matrix.length;
var cols = matrix[0].length;
var rotationDirection = 0;
var isBoxInMatrix = function(box) {
var x = shape.x + box.x;
var y = shape.y + box.y;
if(isNaN(x))return true;
if(isNaN(y))return true;
if(x < 0) return true;
if(x > matrix.cols)return true;
if(y > rows) return true;
2021-02-25 11:00:02 -06:00
// todo: why is matrix not defined when piece popped from hold stack
if(matrix[y] == undefined) return true;
2021-02-21 20:43:05 -06:00
//console.log("matrix X Y: " + " " + x + " "+ y);
return (matrix[y][x] != 0)
};
boxes = shape.getBoxes(shape.state);
for (var i in boxes)
if (isBoxInMatrix(boxes[i]))
return true;
return false;
};
/**
Is same on matrix
@param shape: tetris shape
@param hintPiece: hintPiece shape
@param matrix: game matrix
@param action: 'left','right','down','rotate'
*/
var isBoxesSame = function(shape, hintPiece) {
var isBoxSame = function(shapeBox, hintPieceBox) {
var shapeX = shape.x + shapeBox.x;
var shapeY = shape.y + shapeBox.y;
var hintPieceX = hintPiece.x + hintPieceBox.x;
var hintPieceY = hintPiece.y + hintPieceBox.y;
if(shapeX == hintPieceX && shapeY == hintPieceY)
return true;
return false;
};
//var boxes = action === 'rotate'?shape.getBoxes(shape.nextState()) : shape.getBoxes(shape.state);
var boxes;
var hintPieceBoxes;
boxes = shape.getBoxes(shape.state);
hintPieceBoxes = hintPiece.getBoxes(hintPiece.state);
for (var i in boxes) {
if (!isBoxSame(boxes[i], hintPieceBoxes[i])) {
return false;
}
}
return true;
};
2021-02-05 03:19:09 -06:00
/**
Is shape can move
@param shape: tetris shape
@param matrix: game matrix
@param action: 'left','right','down','rotate'
*/
var isShapeCanMove = function(shape, matrix, action) {
var rows = matrix.length;
var cols = matrix[0].length;
var rotationDirection = 0;
var isBoxCanMove = function(box) {
var x = shape.x + box.x;
var y = shape.y + box.y;
if (y < 0) {
return true;
}
if (action === 'left') {
x -= 1;
return x >= 0 && x < cols && matrix[y][x] == 0;
} else if (action === 'right') {
x += 1;
return x >= 0 && x < cols && matrix[y][x] == 0;
} else if (action === 'down') {
y += 1;
return y < rows && matrix[y][x] == 0;
} else if (action === 'rotate') {
rotationDirection = 1;
return y < rows && !matrix[y][x];
} else if (action === 'rotateclockwise') {
rotationDirection = -1;
return y < rows && !matrix[y][x];
}
};
//var boxes = action === 'rotate'?shape.getBoxes(shape.nextState()) : shape.getBoxes(shape.state);
var boxes;
if(rotationDirection != 0)
boxes = shape.getBoxes(shape.nextState(rotationDirection));
else
boxes = shape.getBoxes(shape.state);
for (var i in boxes) {
if (!isBoxCanMove(boxes[i])) {
return false;
}
}
return true;
};
/**
All shapes shares the same method, use prototype for memory optimized
*/
ShapeL.prototype =
ShapeLR.prototype =
ShapeO.prototype =
ShapeI.prototype =
ShapeT.prototype =
ShapeZ.prototype =
ShapeZR.prototype = {
init: function(result) {
this.color = COLORS[result];
this.state = 0;
this.allBoxes = {};
this.y = 0;
},
// Get boxes matrix which composite the shape
getBoxes: function(state) {
var boxes = this.allBoxes[state] || [];
if (boxes.length) {
return boxes;
}
var matrix = this.matrix(state);
for (var i = 0; i < matrix.length; i++) {
var row = matrix[i];
for (var j = 0; j < row.length; j++) {
if (row[j] === 1) {
boxes.push({
x: j,
y: i
});
}
}
}
this.allBoxes[state] = boxes;
return boxes;
},
//Get matrix for specified state
matrix: function(state) {
var st = state !== undefined ? state : this.state;
return this.states[st];
2021-02-21 20:43:05 -06:00
},
canMoveTo: function(shape, matrix) {
if(!doesShapeOverlap(shape, matrix))
return true;
return false;
},
// 0 - no, 1 - up,left, 2 - up,right, 3 - down,left, 4 - down, right
kickShape: function(matrix, rotationDirection) {
let clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
for(var j = 0; j < 4; j++) {
if(this.state == j) {
clone.state = this.nextState(rotationDirection);
var i = 0;
if(rotationDirection == -1)
i = 2;
for(; i < this.rotationPoints[j].length; i+=2)
{
var shiftX = this.rotationPoints[j][i];
var shiftY = this.rotationPoints[j][i+1];
if(!isNaN(shiftY) && !isNaN(shiftX)) {
//console.log("shiftxy: " + shiftX + " " + shiftY);
clone.x = this.x + shiftX;
clone.y = this.y - shiftY;
if(this.canMoveTo(clone, matrix) == true) {
this.state = clone.state;// = Object.assign(Object.create(Object.getPrototypeOf(clone)), clone);
this.x = clone.x;
this.y = clone.y;
return;
}
}
}
}
}
2021-02-05 03:19:09 -06:00
},
//Rotate shape
rotate: function(matrix) {
2021-02-21 20:43:05 -06:00
// TODO: rest of pieces
//if(this.flag == 'T' || this.flag == 'L')
2021-02-21 20:43:05 -06:00
this.kickShape(matrix, -1);
//else if (isShapeCanMove(this, matrix, 'rotate')){
//this.state = this.nextState(-1);
2021-02-05 03:19:09 -06:00
//fix position if shape is out of right border
//var right = this.getRight();
//if ( right >= COLUMN_COUNT){
// this.x -= right - COLUMN_COUNT + 1;
//}
2021-02-05 03:19:09 -06:00
/*var left = this.getLeft();
if(left <= 0)
this.x += 1;*/
//}
2021-02-05 03:19:09 -06:00
},
//Rotate shape clockwise
rotateClockwise: function(matrix) {
//if(this.flag == 'T')
2021-02-21 20:43:05 -06:00
this.kickShape(matrix, 1);
//else if (isShapeCanMove(this, matrix, 'rotateclockwise')) {
//this.state = this.nextState(1);
2021-02-05 03:19:09 -06:00
//fix position if shape is out of right border
//var right = this.getRight();
//if (right >= COLUMN_COUNT) {
// this.x -= right - COLUMN_COUNT + 1;
//}
//}
2021-02-05 03:19:09 -06:00
},
//Caculate the max column of the shape
getColumnCount: function() {
var mtx = this.matrix();
var colCount = 0;
for (var i = 0; i < mtx.length; i++) {
colCount = Math.max(colCount, mtx[i].length);
}
return colCount;
},
//Caculate the max row of the shape
getRowCount: function() {
return this.matrix().length;
},
//Get the right pos of the shape
getRight: function() {
var boxes = this.getBoxes(this.state);
var right = 0;
for (var i in boxes) {
right = Math.max(boxes[i].x, right);
}
return this.x + right;
},
//Return the next state of the shape
nextState: function(direction) {
var rotate = this.state;
rotate += direction;
if(rotate < 0)
return this.states.length - 1;
return rotate % this.states.length;
},
//Check if the shape can move down
canDown: function(matrix) {
return isShapeCanMove(this, matrix, 'down');
},
//Move the shape down
goDown: function(matrix) {
if (isShapeCanMove(this, matrix, 'down')) {
this.y += 1;
}
},
//Move the shape to the Bottommost
2021-02-05 14:46:41 -06:00
bottomAt: function(matrix) {
var save = this.y;
var ret;
while (isShapeCanMove(this, matrix, 'down')) {
this.y += 1;
}
ret = this.y;
this.y = save;
return ret;
},
//Move the shape to the Bottommost
2021-02-05 03:19:09 -06:00
goBottom: function(matrix) {
while (isShapeCanMove(this, matrix, 'down')) {
this.y += 1;
}
},
//Move the shape to the left
goLeft: function(matrix) {
if (isShapeCanMove(this, matrix, 'left')) {
2021-02-13 08:57:33 -06:00
new Audio('./dist/Click.ogg').play();
2021-02-05 03:19:09 -06:00
this.x -= 1;
}
},
//Move the shape to the right
goRight: function(matrix) {
if (isShapeCanMove(this, matrix, 'right')) {
2021-02-13 08:57:33 -06:00
new Audio('./dist/Click.ogg').play();
2021-02-05 03:19:09 -06:00
this.x += 1;
}
},
//Copy the shape data to the game data
copyTo: function(matrix) {
var smatrix = this.matrix();
for (var i = 0; i < smatrix.length; i++) {
var row = smatrix[i];
for (var j = 0; j < row.length; j++) {
if (row[j] === 1) {
var x = this.x + j;
var y = this.y + i;
if (x >= 0 && x < matrix[0].length && y >= 0 && y < matrix.length) {
matrix[y][x] = this.color;
}
}
}
}
2021-02-12 00:37:49 -06:00
},
2021-02-21 20:43:05 -06:00
// check if piece is same on matrix
isSameSRS: function(shape) {
return isBoxesSame(this, shape)
},
2021-02-12 00:37:49 -06:00
resetOrigin: function() {
this.y = this.originY + 1;
2021-02-05 03:19:09 -06:00
}
}
/**
Create a random shape for game
*/
// Handles randomly generating and returning a tetromino
var RandomGenerator = {
bag: [],
getTetrimino() {
if (this.bag.length === 0) {
this.bag = this.generateNewBag();
}
return this.bag.shift();
},
generateNewBag() {
//var tetrominoes = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];
var tetrominoes = ['0', '1', '2', '3', '4', '5', '6'];
//var tetrominoes = ['L','L','L','L','L','L','L',];
var bag = [];
for (var i = 7; i > 0; i--) {
var tetrominoIndex = Math.floor(Math.random() * i);
bag.push(tetrominoes[tetrominoIndex]);
tetrominoes.splice(tetrominoIndex, 1);
}
return bag;
}
};
2021-02-12 19:02:01 -06:00
2021-02-05 03:19:09 -06:00
function randomShape() {
var result = parseInt(RandomGenerator.getTetrimino(),10);//Math.floor(Math.random() * 7);
var shape;
2021-02-21 20:43:05 -06:00
shape = new ShapeT();
2021-02-05 03:19:09 -06:00
switch (result) {
case 0:
shape = new ShapeL();
break;
case 1:
shape = new ShapeO();
break;
case 2:
shape = new ShapeZ();
break;
case 3:
shape = new ShapeT();
break;
case 4:
shape = new ShapeLR();
break;
case 5:
shape = new ShapeZR();
break;
case 6:
shape = new ShapeI();
break;
}
shape.init(result);
return shape;
}
2021-02-12 19:02:01 -06:00
function getShape(shapei) {
var result = shapei
var shape;
switch (result) {
case 0:
shape = new ShapeL();
break;
case 1:
shape = new ShapeO();
break;
case 2:
shape = new ShapeZ();
break;
case 3:
shape = new ShapeT();
break;
case 4:
shape = new ShapeLR();
break;
case 5:
shape = new ShapeZR();
break;
case 6:
shape = new ShapeI();
break;
}
shape.init(result);
return shape;
}
2021-02-24 13:43:52 -06:00
2021-02-05 03:19:09 -06:00
module.exports.randomShape = randomShape;
2021-02-12 19:02:01 -06:00
module.exports.getShape = getShape;
2021-02-24 13:43:52 -06:00
// export randomShape;
// export getShape;
2021-02-12 19:02:01 -06:00
},{"./consts.js":2}],8:[function(require,module,exports){
2021-02-05 03:19:09 -06:00
var exports = module.exports = {};
2021-02-25 17:05:22 -06:00
var setCookie = function(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
};
var getCookie = function(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
};
2021-02-05 03:19:09 -06:00
var $ = function(id){
return document.getElementById(id);
};
//if object is plain object
var _isPlainObject = function(obj) {
if (typeof obj !== 'object') {
return false;
}
if (obj.constructor &&
!hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {
return false;
}
// If the function hasn't returned already, we're confident that
// |obj| is a plain object, created by {} or constructed with new Object
return true;
};
2021-02-25 11:00:02 -06:00
// Deeper clone
var deepClone = function(copyObject) {
return Object.assign(Object.create(Object.getPrototypeOf(copyObject)), copyObject);
};
2021-02-05 03:19:09 -06:00
// this method source code is from jquery 2.0.x
// merge object's value and return
var extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = true;
// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target;
// skip the boolean and the target
target = arguments[i] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if (typeof target !== 'object' && typeof obj !== 'function') {
target = {};
}
if (i === length) {
target = this;
i--;
}
for (; i < length; i++) {
// Only deal with non-null/undefined values
if ((options = arguments[i]) != null) {
// Extend the base object
for (name in options) {
src = target[name];
copy = options[name];
// Prevent never-ending loop
if (target === copy) {
continue;
}
// Recurse if we're merging plain objects or arrays
if (deep && copy && (_isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && Array.isArray(src) ? src : [];
} else {
clone = src && _isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
//console.log('abc');
target[name] = extend(deep, clone, copy);
// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
}
// Return the modified object
return target;
};
var proxy = function(fn,context){
var args = [].slice.call( arguments, 2 );
proxy = function() {
return fn.apply( context || this, args.concat( [].slice.call( arguments ) ) );
};
return proxy;
};
var aniFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = aniFrame;
exports.$ = $;
exports.extend = extend;
exports.proxy = proxy;
2021-02-25 11:00:02 -06:00
exports.deepClone = deepClone;
2021-02-25 17:05:22 -06:00
exports.setCookie = setCookie;
exports.getCookie = getCookie;
2021-02-24 13:43:52 -06:00
// export $;
// export extend;
// export proxy;
2021-02-12 19:02:01 -06:00
},{}],9:[function(require,module,exports){
2021-02-05 03:19:09 -06:00
/**
All dom definitions and actions
*/
var utils = require('./utils.js');
var consts = require('./consts.js');
2021-02-24 13:43:52 -06:00
// import * as utils from './utils.js';
// import * as consts from './const.js';
2021-02-05 03:19:09 -06:00
var $ = utils.$;
//doms
var scene = $('scene');
var side = $('side');
var info = $('info');
var preview = $('preview');
2021-02-09 21:19:20 -06:00
var hold = $('hold');
var leftSide = $('leftSide');
2021-02-05 03:19:09 -06:00
var level = $('level');
var score = $('score');
2021-02-09 21:19:20 -06:00
var lines = $('lines');
2021-02-05 03:19:09 -06:00
var rewardInfo = $('rewardInfo');
var reward = $('reward');
var gameOver = $('gameOver');
var btnRestart = $('restart');
var finalScore = $('finalScore');
//defaults
var SIDE_WIDTH = consts.SIDE_WIDTH;
/**
Caculate the game container size
*/
var getContainerSize = function(maxW,maxH){
var dw = document.documentElement.clientWidth;
var dh = document.documentElement.clientHeight;
var size = {};
if (dw>dh){
size.height = Math.min(maxH,dh);
2021-02-09 21:19:20 -06:00
size.width = Math.min(size.height /*/ 2*/ + SIDE_WIDTH,maxW);
2021-02-05 03:19:09 -06:00
}else{
size.width = Math.min(maxW,dw);
size.height = Math.min(maxH,dh);
}
return size;
};
/**
Layout game elements
*/
var layoutView = function(container,maxW,maxH){
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
var size = getContainerSize(maxW,maxH);
var st = container.style;
st.height = size.height + 'px';
st.width = size.width + 'px';
st.marginTop = (-(size.height/2)) + 'px';
st.marginLeft = (-(size.width/2)) + 'px';
//layout scene
2021-02-09 21:19:20 -06:00
//hold.width = 80;
//hold.height = 380;
2021-02-05 03:19:09 -06:00
scene.height = size.height;
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
scene.width = scene.height / 2;
2021-02-09 21:19:20 -06:00
var sideW = size.width - scene.width + leftSide.width;
side.style.width = sideW + 'px';
if (sideW < SIDE_WIDTH ){
2021-02-05 03:19:09 -06:00
info.style.width = side.style.width;
}
side.style.height = 500 + 'px';
hold.style.top = 10+'px';//preview.top + 10px pad
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
preview.width = 80;
2021-02-05 14:46:41 -06:00
preview.height = 380;
2021-02-09 21:19:20 -06:00
hold.width = 80;
hold.height = 380;
2021-02-05 03:19:09 -06:00
gameOver.style.width = scene.width +'px';
2021-02-09 21:19:20 -06:00
2021-02-05 03:19:09 -06:00
}
/**
Main tetris game view
*/
var tetrisView = {
init:function(id, maxW,maxH){
this.container = $(id);
this.scene = scene;
this.preview = preview;
2021-02-09 21:19:20 -06:00
this.hold = hold;
2021-02-05 03:19:09 -06:00
this.btnRestart = btnRestart;
layoutView(this.container,maxW,maxH);
this.scene.focus();
rewardInfo.addEventListener('animationEnd',function(e){
rewardInfo.className = 'invisible';
});
},
// Update the score
setScore:function(scoreNumber){
score.innerHTML = scoreNumber;
},
// Update the finnal score
setFinalScore:function(scoreNumber){
finalScore.innerHTML = scoreNumber;
},
// Update the level
setLevel:function(levelNumber){
level.innerHTML = levelNumber;
},
// Update the extra reward score
2021-02-09 21:19:20 -06:00
setLines:function(setlines){
lines.innerHTML = setlines;
},
2021-02-05 03:19:09 -06:00
setReward:function(rewardScore){
if (rewardScore>0){
reward.innerHTML = rewardScore;
rewardInfo.className = 'fadeOutUp animated';
}else{
rewardInfo.className = 'invisible';
}
},
// Set game over view
setGameOver:function(isGameOver){
gameOver.style.display = isGameOver?'block':'none';
}
};
module.exports = tetrisView;
2021-02-24 13:43:52 -06:00
// export tetrisView;
2021-02-12 19:02:01 -06:00
},{"./consts.js":2,"./utils.js":8}]},{},[5]);