From 5093a568f622ac2f74962907b5fcfaffff0bb456 Mon Sep 17 00:00:00 2001 From: "PolicyChanges1@gmail.com" Date: Tue, 4 May 2021 22:44:48 -0400 Subject: [PATCH] c spin --- LICENSE | 42 +- README.md | 44 +- dist/tetrion.js | 3667 ++++++++++++++++++++++---------------------- index.html | 434 +++--- src/gamepad.js | 168 +- src/input.js | 498 +++--- src/main.js | 1728 ++++++++++----------- src/openers.js | 1273 ++++++++------- src/sequence.js | 140 +- startserver.sh.bat | 2 +- 10 files changed, 4000 insertions(+), 3996 deletions(-) diff --git a/LICENSE b/LICENSE index fbb7662..e6a5fe8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2021 PolicyChanges - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2021 PolicyChanges + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index d38f49e..7927fd6 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ -# Tetrion Opening Trainer -# PolicyChanges (2021) - -# MIT Liecense - -# [Tetrion](http://policychanges.github.io) - -Tetris - -This is a small html5 tetris game , written by pure javascript and html5 canvas,modular by browserify. - -Just a practice, if you are interested in writing html5 games,check the code and have fun! - - -Demo - -[Tetris Game](http://sandywalker.github.io/Tetris/) - -License - -MIT © Sandy Duan - +# Tetrion Opening Trainer +# PolicyChanges (2021) + +# MIT Liecense + +# [Tetrion](http://policychanges.github.io) + +Tetris + +This is a small html5 tetris game , written by pure javascript and html5 canvas,modular by browserify. + +Just a practice, if you are interested in writing html5 games,check the code and have fun! + + +Demo + +[Tetris Game](http://sandywalker.github.io/Tetris/) + +License + +MIT © Sandy Duan + diff --git a/dist/tetrion.js b/dist/tetrion.js index 6a44fe9..97608ab 100644 --- a/dist/tetrion.js +++ b/dist/tetrion.js @@ -345,1846 +345,1845 @@ 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; - if(!isFirefox) { - for(var i = 0; i < 4; i++) - if((gp = window.navigator.getGamepads()[i]) != undefined) // dumb gamepad update. fix. - gamepadAPI.controller = gp; - } - - 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; + +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; + if(!isFirefox) { + for(var i = 0; i < 4; i++) + if((gp = window.navigator.getGamepads()[i]) != undefined) // dumb gamepad update. fix. + gamepadAPI.controller = gp; + } + + 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; // export gamepadAPI; },{}],4:[function(require,module,exports){ -var gamepad = require('./gamepad.js'); -var utils = require('./utils.js'); -// import * as gamepad from './gamepad.js'; - -var UserInputs = { - init() { - - this.settingsList = this.keyboardKeySettings.concat(this.keyboardShiftEvents.concat(this.keyboardKeyEvents.concat(this.gamepadSettings.concat(this.gamepadShiftEvents.concat(this.gamepadButtonEvents))))); - //;["Soft Drop Rate [1 - 100]"].concat(this.keyboardSettings.concat(this.gamepadSettings)); - this.gamepadShiftTimer = new Date(); - this.gamepadButtonTimer = new Date(); - this.keyboardKeyTimer = new Date(); - this.keyboardShiftTimer = new Date(); - this.settingsMap = new Map(); - this.gamepadEventMap = new Map(); - ///this.gamepadEventMap = new Map(); - // 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]); - - - this.gamepadEvents = this.gamepadShiftEvents.concat(this.gameButtonsEvents); - - var mapIdx = [14, 7, 13, 5, 4, 1, 2, 12, 8, 3]; - for(var i in mapIdx) { - this.gamepadEventMap.set(this.gamepadEvents[i], gamepad.buttons[mapIdx[i]]); - } - - - document.addEventListener('keydown', this.keyDown.bind(this)); - document.addEventListener('keyup', this.keyUp.bind(this)); - }, - - updateGamepad() { - this.gpButtons = gamepad.update(); - }, - gamepadEnabled() { - return gamepad.controller || false; - }, - processGamepadInput() { - this.gamepadButtonEvents.forEach(gamepadButton => this.gamepadButtonsDown(this.settingsMap.get(gamepadButton))); - }, - processGamepadDPad() { - this.gamepadShiftEvents.forEach(dpadButton => this.gamepadDPadDown(this.settingsMap.get(dpadButton))); - }, - // Single press gamepad buttons - gamepadButtonsDown(finds) { - var DAS = 167.0; - var ARR = 300.0; - var isContained = this.gpButtons.includes(finds); - var isPrevContained = this.prevGpButtons.includes(finds); - - if(isPrevContained != isContained ) { - // Not being held yet - this.gamepadButtonTimer = new Date(); - this.isPassedDelayGamepadShift = false; - // Add button to queue on pressed input - if(isContained) - this.gamepadQueue.push(finds); - } - - var deltaTime = (new Date()).getTime() - this.gamepadButtonTimer.getTime(); - - if (!this.isPassedDelayGamepadShift) { - if (deltaTime >= DAS) { - this.gamepadButtonTimer = new Date(); - this.isPassedDelayGamepadShift = true; - } - - } else { - if (deltaTime >= ARR && isContained) { - this.gamepadQueue.push(finds); - this.gamepadButtonTimer = new Date(); - } - } - - }, - - // Direction Pad - gamepadDPadDown(finds) { - var DAS = parseInt(this.settingsMap.get("Gamepad DAS")); - var ARR = parseInt(this.settingsMap.get("Gamepad ARR")); - - var isContained = this.gpButtons.includes(finds); - var isPrevContained = this.prevGpButtons.includes(finds); - - if(isPrevContained != isContained ) { - // Not being held yet - this.gamepadShiftTimer = new Date(); - this.isDelayedPassedGamepadShift = false; - // Add button to queue on pressed input - if(isContained) - this.gamepadQueue.push(finds); - } - - var deltaTime = (new Date()).getTime() - this.gamepadShiftTimer.getTime(); - - if (!this.isDelayedPassedGamepadShift) { - if (deltaTime >= DAS) { - this.gamepadShiftTimer = new Date(); - this.isDelayedPassedGamepadShift = true; - } - } - else { - if (deltaTime >= ARR && isContained) { - this.gamepadQueue.push(finds); - this.gamepadShiftTimer = new Date(); - } - } - return; - }, - - processKeys() { - this.keyboardKeyEvents.forEach( key => this.settingsMap.get(key).split(',').forEach( idx => this.processKeyDown( parseInt(idx) ) ) ); - }, - - // keyboard keys z,x,space - processKeyDown(key) - { - var DAS = 167.0; - var ARR = 300.0; - - if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { - // Not being held yet - this.keyboardKeyTimer = new Date(); - this.isPassedDelayKeyboardKey = false; - // Add shift to queue on pressed input - if(this.keyboardKeys[key] == true) - this.inputQueue.push(key); - } - - var deltaTime = (new Date()).getTime() - this.keyboardKeyTimer.getTime(); - - if (!this.isPassedDelayKeyboardKey) { - if (deltaTime >= DAS) { - this.keyboardKeyTimer = new Date(); - this.keyboardButtonsDeciframes = 0; - this.isPassedDelayKeyboardKey = true; - } - } else { - if (deltaTime >= ARR && this.keyboardKeys[key] == true) { - this.inputQueue.push(key); - this.keyboardKeyTimer = new Date(); - } - } - }, - // Process applicable key inputs - processKeyShift() { - this.keyboardShiftEvents.forEach(arrowKey => arrowKey.split(',').forEach(option => this.processKeyboardArrowKeys(parseInt(this.settingsMap.get(option))))); - }, - // Direction arrows - processKeyboardArrowKeys(key) { - var DAS = parseInt(this.settingsMap.get("Keyboard DAS")); - var ARR = parseInt(this.settingsMap.get("Keyboard ARR")); - - if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { - // Not being held yet - this.isPassedDelayKeyboardShift = false; - this.keyboardShiftTimer = new Date(); - - // Do shift if key has been pushed down - if(this.keyboardKeys[key] == true) - this.inputQueue.push(key); - } - - var deltaTime = (new Date()).getTime() - this.keyboardShiftTimer.getTime(); - - if (!this.isPassedDelayKeyboardShift) { - - if (deltaTime >= DAS) { - this.keyboardShiftTimer = new Date(); - this.isPassedDelayKeyboardShift = true; - } - } - else if(deltaTime >= ARR && this.keyboardKeys[key] == true) { - this.inputQueue.push(key); - this.keyboardShiftTimer = new Date(); - } - - - }, - keyDown(event) { - if(event.keyCode != 38) - if (! ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8)) - event.preventDefault(); - - this.keyboardKeys[event.keyCode] = true; - this.isKeyBoardKeyDown = true; - }, - keyUp(event) { - this.isKeyDown = false; - this.keyboardKeys[event.keyCode] = false; - this.isKeyBoardKeyDown = false; - }, - gamepadClear() { - //this.gpButtons = []; - //this.gamepadQueue = []; - }, - saveButtons() { - this.prevGpButtons = this.gpButtons; - }, - saveKeyboardKeys() { - //this.prevKeyboardKeys = utils.deepClone(this.keyboardKeys); - this.prevKeyboardKeys = {...this.keyboardKeys}; - }, - // button states - isPassedDelayKeyboardShift: false, - isPassedDelayKeyboardKey: false, - isPassedDelayGamepadShift: false, - isPassedDelayGamepadButton: false, - - // buttons state contatiners - gpButtons: [], - prevGpButtons:[], - keyboardKeys: [], - prevKeyboardKeys: [], - - // button pressed containers - inputQueue: [], - gamepadQueue: [], - - keyboardKeySettings: ["Keyboard DAS", "Keyboard ARR"], - keyboardShiftEvents: ["Keyboard Left", "Keyboard Right", "Keyboard Down", "Keyboard Up"], - keyboardKeyEvents: ["Keyboard Harddrop", "Keyboard Hold", "Keyboard Rotateccw", "Keyboard Rotate", "Keyboard Pophold", "Keyboard Reset", "Keyboard Background"], - - gamepadSettings: ["Gamepad DAS", "Gamepad ARR"], - gamepadShiftEvents: ["Gamepad Left", "Gamepad Right","Gamepad Down"], - gamepadButtonEvents: ["Gamepad Harddrop", "Gamepad Hold", "Gamepad Rotateccw", "Gamepad Rotate", "Gamepad Pophold", "Gamepad Reset", "Gamepad Background"], - - settingsList: [], - - settingsDefault: [ "167.0", "33.0", - "37", "39", "40", "38", - "32", "16", "90", "88", "17", "82", "81", - - "167.0", "33.0", - "DPad-Left", "DPad-Right", "DPad-Down", - "RB", "LB", "A", "B", "DPad-Up", "Back", ""], - settingsMap: [] -}; - -module.exports = UserInputs; +var gamepad = require('./gamepad.js'); +var utils = require('./utils.js'); +// import * as gamepad from './gamepad.js'; + +var UserInputs = { + init() { + + this.settingsList = this.keyboardKeySettings.concat(this.keyboardShiftEvents.concat(this.keyboardKeyEvents.concat(this.gamepadSettings.concat(this.gamepadShiftEvents.concat(this.gamepadButtonEvents))))); + //;["Soft Drop Rate [1 - 100]"].concat(this.keyboardSettings.concat(this.gamepadSettings)); + this.gamepadShiftTimer = new Date(); + this.gamepadButtonTimer = new Date(); + this.keyboardKeyTimer = new Date(); + this.keyboardShiftTimer = new Date(); + this.settingsMap = new Map(); + this.gamepadEventMap = new Map(); + ///this.gamepadEventMap = new Map(); + // 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]); + + + this.gamepadEvents = this.gamepadShiftEvents.concat(this.gameButtonsEvents); + + var mapIdx = [14, 7, 13, 5, 4, 1, 2, 12, 8, 3]; + for(var i in mapIdx) { + this.gamepadEventMap.set(this.gamepadEvents[i], gamepad.buttons[mapIdx[i]]); + } + + + document.addEventListener('keydown', this.keyDown.bind(this)); + document.addEventListener('keyup', this.keyUp.bind(this)); + }, + + updateGamepad() { + this.gpButtons = gamepad.update(); + }, + gamepadEnabled() { + return gamepad.controller || false; + }, + processGamepadInput() { + this.gamepadButtonEvents.forEach(gamepadButton => this.gamepadButtonsDown(this.settingsMap.get(gamepadButton))); + }, + processGamepadDPad() { + this.gamepadShiftEvents.forEach(dpadButton => this.gamepadDPadDown(this.settingsMap.get(dpadButton))); + }, + // Single press gamepad buttons + gamepadButtonsDown(finds) { + var DAS = 167.0; + var ARR = 300.0; + var isContained = this.gpButtons.includes(finds); + var isPrevContained = this.prevGpButtons.includes(finds); + + if(isPrevContained != isContained ) { + // Not being held yet + this.gamepadButtonTimer = new Date(); + this.isPassedDelayGamepadShift = false; + // Add button to queue on pressed input + if(isContained) + this.gamepadQueue.push(finds); + } + + var deltaTime = (new Date()).getTime() - this.gamepadButtonTimer.getTime(); + + if (!this.isPassedDelayGamepadShift) { + if (deltaTime >= DAS) { + this.gamepadButtonTimer = new Date(); + this.isPassedDelayGamepadShift = true; + } + + } else { + if (deltaTime >= ARR && isContained) { + this.gamepadQueue.push(finds); + this.gamepadButtonTimer = new Date(); + } + } + + }, + + // Direction Pad + gamepadDPadDown(finds) { + var DAS = parseInt(this.settingsMap.get("Gamepad DAS")); + var ARR = parseInt(this.settingsMap.get("Gamepad ARR")); + + var isContained = this.gpButtons.includes(finds); + var isPrevContained = this.prevGpButtons.includes(finds); + + if(isPrevContained != isContained ) { + // Not being held yet + this.gamepadShiftTimer = new Date(); + this.isDelayedPassedGamepadShift = false; + // Add button to queue on pressed input + if(isContained) + this.gamepadQueue.push(finds); + } + + var deltaTime = (new Date()).getTime() - this.gamepadShiftTimer.getTime(); + + if (!this.isDelayedPassedGamepadShift) { + if (deltaTime >= DAS) { + this.gamepadShiftTimer = new Date(); + this.isDelayedPassedGamepadShift = true; + } + } + else { + if (deltaTime >= ARR && isContained) { + this.gamepadQueue.push(finds); + this.gamepadShiftTimer = new Date(); + } + } + return; + }, + + processKeys() { + this.keyboardKeyEvents.forEach( key => this.settingsMap.get(key).split(',').forEach( idx => this.processKeyDown( parseInt(idx) ) ) ); + }, + + // keyboard keys z,x,space + processKeyDown(key) + { + var DAS = 167.0; + var ARR = 300.0; + + if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { + // Not being held yet + this.keyboardKeyTimer = new Date(); + this.isPassedDelayKeyboardKey = false; + // Add shift to queue on pressed input + if(this.keyboardKeys[key] == true) + this.inputQueue.push(key); + } + + var deltaTime = (new Date()).getTime() - this.keyboardKeyTimer.getTime(); + + if (!this.isPassedDelayKeyboardKey) { + if (deltaTime >= DAS) { + this.keyboardKeyTimer = new Date(); + this.keyboardButtonsDeciframes = 0; + this.isPassedDelayKeyboardKey = true; + } + } else { + if (deltaTime >= ARR && this.keyboardKeys[key] == true) { + this.inputQueue.push(key); + this.keyboardKeyTimer = new Date(); + } + } + }, + // Process applicable key inputs + processKeyShift() { + this.keyboardShiftEvents.forEach(arrowKey => arrowKey.split(',').forEach(option => this.processKeyboardArrowKeys(parseInt(this.settingsMap.get(option))))); + }, + // Direction arrows + processKeyboardArrowKeys(key) { + var DAS = parseInt(this.settingsMap.get("Keyboard DAS")); + var ARR = parseInt(this.settingsMap.get("Keyboard ARR")); + + if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { + // Not being held yet + this.isPassedDelayKeyboardShift = false; + this.keyboardShiftTimer = new Date(); + + // Do shift if key has been pushed down + if(this.keyboardKeys[key] == true) + this.inputQueue.push(key); + } + + var deltaTime = (new Date()).getTime() - this.keyboardShiftTimer.getTime(); + + if (!this.isPassedDelayKeyboardShift) { + + if (deltaTime >= DAS) { + this.keyboardShiftTimer = new Date(); + this.isPassedDelayKeyboardShift = true; + } + } + else if(deltaTime >= ARR && this.keyboardKeys[key] == true) { + this.inputQueue.push(key); + this.keyboardShiftTimer = new Date(); + } + + + }, + keyDown(event) { + if(event.keyCode != 38) + if (! ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8)) + event.preventDefault(); + + this.keyboardKeys[event.keyCode] = true; + this.isKeyBoardKeyDown = true; + }, + keyUp(event) { + this.isKeyDown = false; + this.keyboardKeys[event.keyCode] = false; + this.isKeyBoardKeyDown = false; + }, + gamepadClear() { + //this.gpButtons = []; + //this.gamepadQueue = []; + }, + saveButtons() { + this.prevGpButtons = this.gpButtons; + }, + saveKeyboardKeys() { + //this.prevKeyboardKeys = utils.deepClone(this.keyboardKeys); + this.prevKeyboardKeys = {...this.keyboardKeys}; + }, + // button states + isPassedDelayKeyboardShift: false, + isPassedDelayKeyboardKey: false, + isPassedDelayGamepadShift: false, + isPassedDelayGamepadButton: false, + + // buttons state contatiners + gpButtons: [], + prevGpButtons:[], + keyboardKeys: [], + prevKeyboardKeys: [], + + // button pressed containers + inputQueue: [], + gamepadQueue: [], + + keyboardKeySettings: ["Keyboard DAS", "Keyboard ARR"], + keyboardShiftEvents: ["Keyboard Left", "Keyboard Right", "Keyboard Down", "Keyboard Up"], + keyboardKeyEvents: ["Keyboard Harddrop", "Keyboard Hold", "Keyboard Rotateccw", "Keyboard Rotate", "Keyboard Pophold", "Keyboard Reset", "Keyboard Background"], + + gamepadSettings: ["Gamepad DAS", "Gamepad ARR"], + gamepadShiftEvents: ["Gamepad Left", "Gamepad Right","Gamepad Down"], + gamepadButtonEvents: ["Gamepad Harddrop", "Gamepad Hold", "Gamepad Rotateccw", "Gamepad Rotate", "Gamepad Pophold", "Gamepad Reset", "Gamepad Background"], + + settingsList: [], + + settingsDefault: [ "167.0", "33.0", + "37", "39", "40", "38", + "32", "16", "90", "88", "17", "82", "81", + + "167.0", "33.0", + "DPad-Left", "DPad-Right", "DPad-Down", + "RB", "LB", "A", "B", "DPad-Up", "Back", ""], + settingsMap: [] +}; + +module.exports = UserInputs; // export UserInputs; },{"./gamepad.js":3,"./utils.js":8}],5:[function(require,module,exports){ -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'); -var openers = require('./openers.js'); -// 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'; - - - - -/** - 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 -*/ -var calcRewards = function(rows, tspinType) { - if(tspinType == 2) - rows*=2+1; - 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: 560 -}; - -/** - Tetris main object definition -*/ -function Tetris(id) { - this.id = id; - this.init(); -} - -Tetris.prototype = { - init: function(options) { - var cfg = this.config = utils.extend(options, defaults); - this.interval = consts.DEFAULT_INTERVAL; - - views.init(this.id, cfg.maxWidth, cfg.maxHeight); - canvas.init(views.scene, views.preview, views.hold); - inputs.init(); - this.createSettings(); - - // if true no openers. just random tetrinos - this.gameState = consts.DEFAULT_GAMESTATE; - - this.isTimerOn = false; - this.currentOpener = 0; - this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); - this.eventTimer = new Date(); - this.debugTimer = new Date(); - this.gamepadEnabled = false; - this.reset(); - - this._initEvents(); - //this._fireShape(); - // ewww - this._recurseGameState(); - - }, - toggleTimer: function() { - document.getElementById("Timer").value = (this.isTimerOn = !this.isTimerOn) ? "Seconds:" : "Timer Off"; - }, - toggleGamepad: function(){ - document.getElementById("enablegamepad").value = ((this.gamepadEnabled = !this.gamepadEnabled) ? "Disable Gamepad" : "Enable Gamepad"); - }, - // Gamestate 1 - setFreePlay: function() - { - - this.gameState = consts.GAMESTATES[0]; - - document.getElementById("Timer").value = "Timer Off"; - document.getElementById("Time").value = ""; - document.getElementById("besttime").value = ""; - this.isTimerOn = false; - - this.hintQueue = []; - this.shapeQueue = []; - this.hintMino = 0; - this._restartHandler(); - this.currentOpener = 0; - - }, - // Gamestate 2 - setCurrentOpener(opener) - { - document.getElementById("besttime").value = ""; - - this.gameState = consts.GAMESTATES[1]; - this.currentOpener = opener; - this._restartHandler(); - - }, - // Gamestate 3 - setDoTest: function() - { - - if(this.gameState != consts.GAMESTATES[1]) return; - - // set game state to do test - this.gameState = consts.GAMESTATES[2]; - - this._restartHandler(); - }, - // Gamestate 4 - setGameStateSequenceEditor: function() - { - document.getElementById("side").display = "none"; - - // change to editor gamestate - this.gameState = consts.GAMESTATES[3]; - this.hintQueue = []; - this.shapeQueue = []; - this.hintMino = 0; - this._restartHandler(); - this.currentOpener = 0; - this.pushHoldStack(); - }, - - 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() { - // var setting = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; - // var doKeyToAlpha = inputs.keyboardShiftEvents.included(setting) || inputs.keyboardKeyEvents.included(setting); - - // if(doKeyToAlpha) - // document.getElementById("setting_value").value = inputs.settingsMap.get(setting).fromCharCode(); - // else - // document.getElementById("setting_value").value = inputs.settingsMap.get(setting); - - document.getElementById("setting_value").value = - inputs.settingsMap.get(inputs.settingsList[document.getElementById("settings").selectedIndex-1]); - - - }, - addOpener: function() { - - var newOpener = document.createElement('li'); - //
  • Mr. T-Spin's STD (reversed)
  • - //newOpener.text = "New Sequence"; - //newOpener.id = this.currentMinoInx; - newOpener.style="color:powderblue;text-decoration:underline;font-size:12px;padding-left:1em"; - - - newOpener.appendChild(document.createTextNode("New Sequence: " + this.currentMinoInx)); - document.getElementById("Openers").appendChild(newOpener); - - - - // Print Sequence Data to console - // console.log("this.hintQueue = new Array("); - // this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { console.log("shapes.getShape("+shape.nType()+ ((idx === arr.length-1) ? "));" : "),") ); } ); - - - var shapes = []; - this.shapeQueue.slice().reverse().forEach( function(shape, idx) { shapes.push(shape.x); shapes.push(shape.y); shapes.push(shape.state); } ); - - // console.log("var hintDataList = [" + shapes.join(",") + "];"); - // console.log("this.createHintQueue(hintDataList);"); - - var sequenceCode = []; - - var shapeArrayStr = []; - this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { shapeArrayStr += "shapes.getShape("+shape.nType() + ((idx === arr.length-1) ? "));" : "), ") } ); - sequenceCode += "case :\n\tthis.shapeQueue = new Array(" + shapeArrayStr + "\nbreak;" + "\n\n"; - - sequenceCode += "case :\n\tthis.hintQueue = new Array(" + shapeArrayStr; - sequenceCode += "\n\nvar hintDataList = [" + shapes.join(",") + "];" + "\nthis.createHintQueue(hintDataList);" + "\nbreak;"; - - prompt("Generated Code:", sequenceCode); - - - //openers.addSequence(this.shapeQueue); - //this.setFreePlay(); - //this.gameState = consts.GAMESTATES[1]; - this.currentMinoInx = 0; - //this.setCurrentOpener(99999);//this.currentMinoInx); - clearMatrix(this.matrix); - this.currentOpener = 9999; - this.shapeQueue = []; - this.hintQueue = []; - //this._recurseGameState(); - }, - setSettings: function() { - var newVal = document.getElementById("setting_value").value; - var key = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; - utils.setCookie(key, newVal, 30); - inputs.settingsMap.set(key, newVal); - }, - //Reset game - reset: function() { - this.numlefts = 0; - this.running = false; - this.isGameOver = false; - this.level = 1; - this.score = 0; - this.lines = 0; - // beginning of frame - this.startTime = new Date().getTime(); - this.currentTime = this.startTime; - this.prevTime = this.startTime; - this.sequencePrevTime = this.startTime; - //todo:get rid of extra - this.levelTime = this.startTime; - this.prevInputTime = this.startTime; - // current tetrino index gets set to 0 at the end of opener sequence - this.currentMinoInx = 0; - this.shapeQueue = []; - this.hintQueue = []; - this.holdStack = []; - this.shape = shapes.getShape(0); - // gets set to false after mino has been popped from hold stack; set back to true on mino dropped - this.canPopFromHoldStack = false; - // manipulation counter for srs extended piece lockdown - this.manipulationCounter = 0; - // timer for srs extened piece lockdown - this.lockdownTimer = 0; - this.landed = false; - this.isSequenceCompleted = false; - - clearMatrix(this.matrix); - views.setLevel(this.level); - views.setScore(this.score); - views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); - openers.reset(); - shapes.resetMinoRNG(); - - this._draw(); - }, - //Start game - start: function() { - this.running = true; - window.requestAnimationFrame(utils.proxy(this._refresh, this)); - - }, - //Pause game - pause: function() { - this.running = false; - this.currentTime = new Date().getTime(); - this.prevTime = this.currentTime; - }, - pushHoldStack: function() - { - if(this.gameState == consts.GAMESTATES[3]) { - while(this.holdStack.length < 7) - this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); - this.shape = this.holdStack.pop(); - this._draw(); - return; - } - // 1 shape hold queue - if(this.holdStack.length > 0) { - this.canPopFromHoldStack = false; - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = utils.deepClone(this.holdStack.pop()); - this.shape.resetOrigin(); - this._draw(); - }else if(this.holdStack.length < 4) { - this.holdStack.push(utils.deepClone(this.shape)); - this.shape = this.shapeQueue.shift(); - this.canPopFromHoldStack = false; - this.shape.resetOrigin(); - this._draw(); - } - /* 4 shape hold queue - if(this.holdStack.length < 4) { - this.holdStack.push(utils.deepClone(this.shape)); - this.shape = this.shapeQueue.shift(); - this.canPopFromHoldStack = false; - this.shape.resetOrigin(); - this._draw(); - }*/ - }, - popHoldStack: function() - { - if(this.gameState == consts.GAMESTATES[3]) { - if(this.holdStack.length < 7) - while(this.holdStack.length < 7) - this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); - // piece needs to be able to be placed - if(this.shape.canDown(this.matrix)) return; - this.shape.copyTo(this.matrix); - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = utils.deepClone(this.holdStack.pop()); - this._check(); - this._draw(); - return; - } - // todo: disable if 1 shape hold queue - if(this.holdStack.length >= 1 && this.canPopFromHoldStack) - { - this.canPopFromHoldStack = false; - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = this.holdStack.pop(); - this.shape.resetOrigin(); - this._draw(); - } - }, - - // Restart game - _restartHandler: function() { - this.reset(); - this.start(); - //this._fireShape(); - this._recurseGameState(); - }, - // Bind game events - _initEvents: function() { - setInterval(() => {this._processTick();}, 1); - setInterval(() => {this.lockDownTimer++;}, 100 ); - views.btnRestart.addEventListener('click', utils.proxy(this._restartHandler, this), false); - }, - // Process freeplay queue - _processFreeplayQueue: function() { - while(this.shapeQueue.length <= 4) - { - this.preparedShape = shapes.randomShape(); - this.shapeQueue.push(this.preparedShape); - } - - this.shape = this.shapeQueue.shift();// || shapes.randomShape(); - this.currentMinoInx++; - }, - // Process opener trainer queue - _processOpenerTrainerQueue: function() { - while(this.shapeQueue.length <= 4) - { - this.preparedShape = utils.deepClone(openers.getNextMino(this.currentOpener)); - this.shapeQueue.push(this.preparedShape); - } - while(this.hintQueue.length <= 4) - { - this.preparedShape = utils.deepClone(openers.getNextHint(this.currentOpener)); - this.hintQueue.push(this.preparedShape); - } - - this.hintMino = this.hintQueue.shift(); - this.shape = this.shapeQueue.shift(); - - this.currentMinoInx++; - - // Opener sequence completed - if(this.currentMinoInx > openers.getLength()) { - //new Audio("./dist/sound/Affirm2.ogg").play(); - if(this.isTimerOn) { - var besttime = document.getElementById("besttime").value; - var deltaTime = new Date().getTime() - this.sequencePrevTime; - if(besttime == "" || deltaTime/1000.0 < parseFloat(besttime)) { - document.getElementById("besttime").value = (deltaTime/1000.0).toString(); - } - } - - this.hintQueue = []; - this.shapeQueue = []; - - this.isSequenceCompleted = true; - - // Recursion warning - if(this.currentOpener < 1000) // getting real hacky - this._restartHandler(); - else clearMatrix(this.matrix); - // this.reset(); - // this.start(); - return; - } - }, - // Process sequence editor - _processSequenceEditor: function () { - return; - }, - - // Fill next queue and set next shape - _fireShape: function() { - //todo:should be in shapes.js - this.landed = false; - this.manipulationCounter = 0; - - this._draw(); - - }, - _recurseGameState: function (){ - switch(this.gameState) { - case consts.GAMESTATES[0]: - this._processFreeplayQueue(); - this._fireShape(); - break; - case consts.GAMESTATES[1]: - this._processOpenerTrainerQueue(); - this._fireShape(); - break; - case consts.GAMESTATES[2]: - this._processOpenerTrainerQueue(); - this._fireShape(); - case consts.GAMESTATES[3]: - this._processSequenceEditor(); - break; - - default: - break; - } - }, - // 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; - }, - // Draw game data - _draw: function() { - canvas.drawScene(); - canvas.drawShape(this.shape); - canvas.drawHoldShape(this.holdStack); - canvas.drawPreviewShape(this.shapeQueue); - if(this.gameState != consts.GAMESTATES[2]) - canvas.drawHintShape(this.hintMino); - - if(this.shape != undefined) { - let clone = Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape); - - var bottomY = clone.bottomAt(this.matrix); - canvas.drawGhostShape(clone, bottomY); - } - canvas.drawMatrix(this.matrix); - - - }, - - // tick input data -- wont have better than 4-15ms resolution since javascript is single theaded and any ARR or DAS below 15ms will likely be broken - _processTick: async function() { - - - if(this.isTimerOn) { - var deltaPlayTime = new Date().getTime() - this.sequencePrevTime; - document.getElementById("Time").value = (deltaPlayTime/1000).toString(); - - } - - // Don't process game related events if game over - if(this.isGameOver) return; - - - - if(this.gamepadEnabled && inputs.gamepadEnabled()) { - inputs.updateGamepad(); - inputs.processGamepadDPad(); - inputs.processGamepadInput(); - - while((inputs.gamepadQueue != undefined && inputs.gamepadQueue.length >= 1)){ - var curkey = inputs.gamepadQueue.shift(); - if(inputs.settingsMap.get("Gamepad Left").includes(curkey)) { - this.shape.goLeft(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Right").includes(curkey)) { - this.shape.goRight(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Rotateccw").includes(curkey)) { - this.shape.rotate(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Rotate").includes(curkey)) { - this.shape.rotateClockwise(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Down").includes(curkey)) { - this.shape.goDown(this.matrix); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Harddrop").includes(curkey)) { - // if editor - if(this.gameState == consts.GAMESTATES[3]) { - this.popHoldStack(); - this._draw(); - }else { - this.shape.goBottom(this.matrix); - this.lockDownTimer = 5000; - this._update(); - } - } - else if(inputs.settingsMap.get("Gamepad Hold").includes(curkey)) { - this.pushHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Pophold").includes(curkey)) { - this.popHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Reset").includes(curkey)) { - this._restartHandler(); - return; - } - } - inputs.saveButtons(); - inputs.gamepadClear(); - } - - - // Do keyboard - inputs.processKeys(); - inputs.processKeyShift(); - // Keyboard inputs - while((inputs.inputQueue != undefined && inputs.inputQueue.length >= 1)){ - var curkey = inputs.inputQueue.shift(); - if(inputs.settingsMap.get("Keyboard Left").includes(curkey)) { - this.shape.goLeft(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Right").includes(curkey)) { - this.shape.goRight(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Down").includes(curkey)) { - - this.shape.goDown(this.matrix); - this._draw(); - } - else if(this.gameState == consts.GAMESTATES[3] && inputs.settingsMap.get("Keyboard Up").includes(curkey)) { - - this.shape.goUp(this.matrix); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Rotateccw").includes(curkey)) { - this.shape.rotate(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Rotate").includes(curkey)) { - this.shape.rotateClockwise(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Harddrop").includes(curkey)) { - // if editor - if(this.gameState == consts.GAMESTATES[3]) { - this.popHoldStack(); - this._draw(); - }else { - this.shape.goBottom(this.matrix); - this.lockDownTimer = 5000; - this._update(); - } - } - else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { - this.pushHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Pophold").includes(curkey)) { - this.popHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { - if(document.getElementById("divbg").style.display == "none") - document.getElementById("divbg").style.display = "initial"; - else - document.getElementById("divbg").style.display="none"; - } - if(inputs.settingsMap.get("Keyboard Reset").includes(curkey)) { - this._restartHandler(); - return; - } - - } - inputs.inputQueue = []; - - - inputs.saveKeyboardKeys(); - - inputs.saveButtons(); - }, - // Refresh game canvas - _refresh: function() { - if (!this.running) - return; - - this.currentTime = new Date().getTime(); - var deltaLevelTime = this.currentTime - this.prevTime; - if (deltaLevelTime > this.interval) { // every .6 seconds? - this._update(); - this._checkLevel(this.prevTime = this.currentTime); - } - - // Draw Frame - if (!this.isGameOver) { - window.requestAnimationFrame(utils.proxy(this._refresh, this)); - } - }, - // check if the current piece is in the same location as the hint piece - _checkHint: function() { - - if(this.gameState == consts.GAMESTATES[0]) - return; - - if(!this.shape.isSameSRS(this.hintMino)) - { - //new Audio('./dist/Failed.ogg').play(); - this._restartHandler(); - // Restart - return 1; - } - }, - // Update game data - _update: function() { - - switch(this.gameState) { - case consts.GAMESTATES[0]: - case consts.GAMESTATES[1]: - case consts.GAMESTATES[2]: - if(this.shape == undefined) break; - if (this.shape.canDown(this.matrix)) { - this.shape.goDown(this.matrix); - } else if(this.isPieceLocked()){ - this.canPopFromHoldStack = true; - this.shape.copyTo(this.matrix); - this._check(); - if(this._checkHint()) return; - //this._fireShape(); - this._recurseGameState(); - new Audio('./dist/sound/Blop2.ogg').play(); - } - this._draw(); - this.isGameOver = checkGameOver(this.matrix); - - // if game over and gamestate is free play - views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); - - if (this.isGameOver) - views.setFinalScore(this.score); - break; - case consts.GAMESTATES[3]: - break; - default: - break; - } - - }, - // 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[side4Y] != undefined && matrix[side3Y] != undefined) { - if(matrix[side1Y][side1X] != 0) - side1 = 1; - if(matrix[side2Y][side2X] != 0) - side2 = 1; - // TODO: figure out why this occasionally is undefined - 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; - }, - // Check and update game data - _check: function() { - var rows = checkFullRows(this.matrix); - if (rows.length) { - var tspinType; - - if(this.shape.flag === 'T') - tspinType = this._tSpinType(this.shape, this.matrix); - - removeRows(this.matrix, rows); - - console.log("type: " + tspinType); - var score = calcScore(rows); - var reward = calcRewards(rows, tspinType); - this.score += score + reward; - this.lines += rows.length; - - views.setScore(this.score); - views.setReward(reward); - views.setLines(this.lines); - - } - }, - // 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; +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'); +var openers = require('./openers.js'); +// 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'; + + + + +/** + 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 +*/ +var calcRewards = function(rows, tspinType) { + if(tspinType == 2) + rows*=2+1; + 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: 560 +}; + +/** + Tetris main object definition +*/ +function Tetris(id) { + this.id = id; + this.init(); +} + +Tetris.prototype = { + init: function(options) { + var cfg = this.config = utils.extend(options, defaults); + this.interval = consts.DEFAULT_INTERVAL; + + views.init(this.id, cfg.maxWidth, cfg.maxHeight); + canvas.init(views.scene, views.preview, views.hold); + inputs.init(); + this.createSettings(); + + // if true no openers. just random tetrinos + this.gameState = consts.DEFAULT_GAMESTATE; + + this.isTimerOn = false; + this.currentOpener = 0; + this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); + this.eventTimer = new Date(); + this.debugTimer = new Date(); + this.gamepadEnabled = false; + this.reset(); + + this._initEvents(); + //this._fireShape(); + // ewww + this._recurseGameState(); + + }, + toggleTimer: function() { + document.getElementById("Timer").value = (this.isTimerOn = !this.isTimerOn) ? "Seconds:" : "Timer Off"; + }, + toggleGamepad: function(){ + document.getElementById("enablegamepad").value = ((this.gamepadEnabled = !this.gamepadEnabled) ? "Disable Gamepad" : "Enable Gamepad"); + }, + // Gamestate 1 + setFreePlay: function() + { + + this.gameState = consts.GAMESTATES[0]; + + document.getElementById("Timer").value = "Timer Off"; + document.getElementById("Time").value = ""; + document.getElementById("besttime").value = ""; + this.isTimerOn = false; + + this.hintQueue = []; + this.shapeQueue = []; + this.hintMino = 0; + this._restartHandler(); + this.currentOpener = 0; + + }, + // Gamestate 2 + setCurrentOpener(opener) + { + document.getElementById("besttime").value = ""; + + this.gameState = consts.GAMESTATES[1]; + this.currentOpener = opener; + this._restartHandler(); + + }, + // Gamestate 3 + setDoTest: function() + { + + if(this.gameState != consts.GAMESTATES[1]) return; + + // set game state to do test + this.gameState = consts.GAMESTATES[2]; + + this._restartHandler(); + }, + // Gamestate 4 + setGameStateSequenceEditor: function() + { + document.getElementById("side").display = "none"; + + // change to editor gamestate + this.gameState = consts.GAMESTATES[3]; + this.hintQueue = []; + this.shapeQueue = []; + this.hintMino = 0; + this._restartHandler(); + this.currentOpener = 0; + this.pushHoldStack(); + }, + + 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() { + // var setting = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; + // var doKeyToAlpha = inputs.keyboardShiftEvents.included(setting) || inputs.keyboardKeyEvents.included(setting); + + // if(doKeyToAlpha) + // document.getElementById("setting_value").value = inputs.settingsMap.get(setting).fromCharCode(); + // else + // document.getElementById("setting_value").value = inputs.settingsMap.get(setting); + + document.getElementById("setting_value").value = + inputs.settingsMap.get(inputs.settingsList[document.getElementById("settings").selectedIndex-1]); + + + }, + addOpener: function() { + + var newOpener = document.createElement('li'); + //
  • Mr. T-Spin's STD (reversed)
  • + //newOpener.text = "New Sequence"; + //newOpener.id = this.currentMinoInx; + newOpener.style="color:powderblue;text-decoration:underline;font-size:12px;padding-left:1em"; + + + newOpener.appendChild(document.createTextNode("New Sequence: " + this.currentMinoInx)); + document.getElementById("Openers").appendChild(newOpener); + + + + // Print Sequence Data to console + // console.log("this.hintQueue = new Array("); + // this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { console.log("shapes.getShape("+shape.nType()+ ((idx === arr.length-1) ? "));" : "),") ); } ); + + + var shapes = []; + this.shapeQueue.slice().reverse().forEach( function(shape, idx) { shapes.push(shape.x); shapes.push(shape.y); shapes.push(shape.state); } ); + + // console.log("var hintDataList = [" + shapes.join(",") + "];"); + // console.log("this.createHintQueue(hintDataList);"); + + var sequenceCode = []; + + var shapeArrayStr = []; + this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { shapeArrayStr += "shapes.getShape("+shape.nType() + ((idx === arr.length-1) ? "));" : "), ") } ); + sequenceCode += "case :\n\tthis.shapeQueue = new Array(" + shapeArrayStr + "\nbreak;" + "\n\n"; + + sequenceCode += "case :\n\tthis.hintQueue = new Array(" + shapeArrayStr; + sequenceCode += "\n\nvar hintDataList = [" + shapes.join(",") + "];" + "\nthis.createHintQueue(hintDataList);" + "\nbreak;"; + + prompt("Generated Code:", sequenceCode); + + + //openers.addSequence(this.shapeQueue); + //this.setFreePlay(); + //this.gameState = consts.GAMESTATES[1]; + this.currentMinoInx = 0; + //this.setCurrentOpener(99999);//this.currentMinoInx); + clearMatrix(this.matrix); + this.currentOpener = 9999; + this.shapeQueue = []; + this.hintQueue = []; + //this._recurseGameState(); + }, + setSettings: function() { + var newVal = document.getElementById("setting_value").value; + var key = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; + utils.setCookie(key, newVal, 30); + inputs.settingsMap.set(key, newVal); + }, + //Reset game + reset: function() { + this.numlefts = 0; + this.running = false; + this.isGameOver = false; + this.level = 1; + this.score = 0; + this.lines = 0; + // beginning of frame + this.startTime = new Date().getTime(); + this.currentTime = this.startTime; + this.prevTime = this.startTime; + this.sequencePrevTime = this.startTime; + //todo:get rid of extra + this.levelTime = this.startTime; + this.prevInputTime = this.startTime; + // current tetrino index gets set to 0 at the end of opener sequence + this.currentMinoInx = 0; + this.shapeQueue = []; + this.hintQueue = []; + this.holdStack = []; + this.shape = shapes.getShape(0); + // gets set to false after mino has been popped from hold stack; set back to true on mino dropped + this.canPopFromHoldStack = false; + // manipulation counter for srs extended piece lockdown + this.manipulationCounter = 0; + // timer for srs extened piece lockdown + this.lockdownTimer = 0; + this.landed = false; + this.isSequenceCompleted = false; + + clearMatrix(this.matrix); + views.setLevel(this.level); + views.setScore(this.score); + views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); + openers.reset(); + shapes.resetMinoRNG(); + + this._draw(); + }, + //Start game + start: function() { + this.running = true; + window.requestAnimationFrame(utils.proxy(this._refresh, this)); + + }, + //Pause game + pause: function() { + this.running = false; + this.currentTime = new Date().getTime(); + this.prevTime = this.currentTime; + }, + pushHoldStack: function() + { + if(this.gameState == consts.GAMESTATES[3]) { + while(this.holdStack.length < 7) + this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); + this.shape = this.holdStack.pop(); + this._draw(); + return; + } + // 1 shape hold queue + if(this.holdStack.length > 0) { + this.canPopFromHoldStack = false; + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = utils.deepClone(this.holdStack.pop()); + this.shape.resetOrigin(); + this._draw(); + }else if(this.holdStack.length < 4) { + this.holdStack.push(utils.deepClone(this.shape)); + this.shape = this.shapeQueue.shift(); + this.canPopFromHoldStack = false; + this.shape.resetOrigin(); + this._draw(); + } + /* 4 shape hold queue + if(this.holdStack.length < 4) { + this.holdStack.push(utils.deepClone(this.shape)); + this.shape = this.shapeQueue.shift(); + this.canPopFromHoldStack = false; + this.shape.resetOrigin(); + this._draw(); + }*/ + }, + popHoldStack: function() + { + if(this.gameState == consts.GAMESTATES[3]) { + if(this.holdStack.length < 7) + while(this.holdStack.length < 7) + this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); + // piece needs to be able to be placed + if(this.shape.canDown(this.matrix)) return; + this.shape.copyTo(this.matrix); + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = utils.deepClone(this.holdStack.pop()); + this._check(); + this._draw(); + return; + } + // todo: disable if 1 shape hold queue + if(this.holdStack.length >= 1 && this.canPopFromHoldStack) + { + this.canPopFromHoldStack = false; + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = this.holdStack.pop(); + this.shape.resetOrigin(); + this._draw(); + } + }, + + // Restart game + _restartHandler: function() { + this.reset(); + this.start(); + //this._fireShape(); + this._recurseGameState(); + }, + // Bind game events + _initEvents: function() { + setInterval(() => {this._processTick();}, 1); + setInterval(() => {this.lockDownTimer++;}, 100 ); + views.btnRestart.addEventListener('click', utils.proxy(this._restartHandler, this), false); + }, + // Process freeplay queue + _processFreeplayQueue: function() { + while(this.shapeQueue.length <= 4) + { + this.preparedShape = shapes.randomShape(); + this.shapeQueue.push(this.preparedShape); + } + + this.shape = this.shapeQueue.shift();// || shapes.randomShape(); + this.currentMinoInx++; + }, + // Process opener trainer queue + _processOpenerTrainerQueue: function() { + while(this.shapeQueue.length <= 4) + { + this.preparedShape = utils.deepClone(openers.getNextMino(this.currentOpener)); + this.shapeQueue.push(this.preparedShape); + } + while(this.hintQueue.length <= 4) + { + this.preparedShape = utils.deepClone(openers.getNextHint(this.currentOpener)); + this.hintQueue.push(this.preparedShape); + } + + this.hintMino = this.hintQueue.shift(); + this.shape = this.shapeQueue.shift(); + + this.currentMinoInx++; + + // Opener sequence completed + if(this.currentMinoInx > openers.getLength()) { + //new Audio("./dist/sound/Affirm2.ogg").play(); + if(this.isTimerOn) { + var besttime = document.getElementById("besttime").value; + var deltaTime = new Date().getTime() - this.sequencePrevTime; + if(besttime == "" || deltaTime/1000.0 < parseFloat(besttime)) { + document.getElementById("besttime").value = (deltaTime/1000.0).toString(); + } + } + + this.hintQueue = []; + this.shapeQueue = []; + + this.isSequenceCompleted = true; + + // Recursion warning + if(this.currentOpener < 1000) // getting real hacky + this._restartHandler(); + else clearMatrix(this.matrix); + // this.reset(); + // this.start(); + return; + } + }, + // Process sequence editor + _processSequenceEditor: function () { + return; + }, + + // Fill next queue and set next shape + _fireShape: function() { + //todo:should be in shapes.js + this.landed = false; + this.manipulationCounter = 0; + + this._draw(); + + }, + _recurseGameState: function (){ + switch(this.gameState) { + case consts.GAMESTATES[0]: + this._processFreeplayQueue(); + this._fireShape(); + break; + case consts.GAMESTATES[1]: + this._processOpenerTrainerQueue(); + this._fireShape(); + break; + case consts.GAMESTATES[2]: + this._processOpenerTrainerQueue(); + this._fireShape(); + case consts.GAMESTATES[3]: + this._processSequenceEditor(); + break; + + default: + break; + } + }, + // 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; + }, + // Draw game data + _draw: function() { + canvas.drawScene(); + canvas.drawShape(this.shape); + canvas.drawHoldShape(this.holdStack); + canvas.drawPreviewShape(this.shapeQueue); + if(this.gameState != consts.GAMESTATES[2]) + canvas.drawHintShape(this.hintMino); + + if(this.shape != undefined) { + let clone = Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape); + + var bottomY = clone.bottomAt(this.matrix); + canvas.drawGhostShape(clone, bottomY); + } + canvas.drawMatrix(this.matrix); + + + }, + + // tick input data -- wont have better than 4-15ms resolution since javascript is single theaded and any ARR or DAS below 15ms will likely be broken + _processTick: async function() { + + + if(this.isTimerOn) { + var deltaPlayTime = new Date().getTime() - this.sequencePrevTime; + document.getElementById("Time").value = (deltaPlayTime/1000).toString(); + + } + + // Don't process game related events if game over + if(this.isGameOver) return; + + + + if(this.gamepadEnabled && inputs.gamepadEnabled()) { + inputs.updateGamepad(); + inputs.processGamepadDPad(); + inputs.processGamepadInput(); + + while((inputs.gamepadQueue != undefined && inputs.gamepadQueue.length >= 1)){ + var curkey = inputs.gamepadQueue.shift(); + if(inputs.settingsMap.get("Gamepad Left").includes(curkey)) { + this.shape.goLeft(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Right").includes(curkey)) { + this.shape.goRight(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Rotateccw").includes(curkey)) { + this.shape.rotate(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Rotate").includes(curkey)) { + this.shape.rotateClockwise(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Down").includes(curkey)) { + this.shape.goDown(this.matrix); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Harddrop").includes(curkey)) { + // if editor + if(this.gameState == consts.GAMESTATES[3]) { + this.popHoldStack(); + this._draw(); + }else { + this.shape.goBottom(this.matrix); + this.lockDownTimer = 5000; + this._update(); + } + } + else if(inputs.settingsMap.get("Gamepad Hold").includes(curkey)) { + this.pushHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Pophold").includes(curkey)) { + this.popHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Reset").includes(curkey)) { + this._restartHandler(); + return; + } + } + inputs.saveButtons(); + inputs.gamepadClear(); + } + + + // Do keyboard + inputs.processKeys(); + inputs.processKeyShift(); + // Keyboard inputs + while((inputs.inputQueue != undefined && inputs.inputQueue.length >= 1)){ + var curkey = inputs.inputQueue.shift(); + if(inputs.settingsMap.get("Keyboard Left").includes(curkey)) { + this.shape.goLeft(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Right").includes(curkey)) { + this.shape.goRight(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Down").includes(curkey)) { + + this.shape.goDown(this.matrix); + this._draw(); + } + else if(this.gameState == consts.GAMESTATES[3] && inputs.settingsMap.get("Keyboard Up").includes(curkey)) { + + this.shape.goUp(this.matrix); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Rotateccw").includes(curkey)) { + this.shape.rotate(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Rotate").includes(curkey)) { + this.shape.rotateClockwise(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Harddrop").includes(curkey)) { + // if editor + if(this.gameState == consts.GAMESTATES[3]) { + this.popHoldStack(); + this._draw(); + }else { + this.shape.goBottom(this.matrix); + this.lockDownTimer = 5000; + this._update(); + } + } + else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { + this.pushHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Pophold").includes(curkey)) { + this.popHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { + if(document.getElementById("divbg").style.display == "none") + document.getElementById("divbg").style.display = "initial"; + else + document.getElementById("divbg").style.display="none"; + } + if(inputs.settingsMap.get("Keyboard Reset").includes(curkey)) { + this._restartHandler(); + return; + } + + } + inputs.inputQueue = []; + + + inputs.saveKeyboardKeys(); + + inputs.saveButtons(); + }, + // Refresh game canvas + _refresh: function() { + if (!this.running) + return; + + this.currentTime = new Date().getTime(); + var deltaLevelTime = this.currentTime - this.prevTime; + if (deltaLevelTime > this.interval) { // every .6 seconds? + this._update(); + this._checkLevel(this.prevTime = this.currentTime); + } + + // Draw Frame + if (!this.isGameOver) { + window.requestAnimationFrame(utils.proxy(this._refresh, this)); + } + }, + // check if the current piece is in the same location as the hint piece + _checkHint: function() { + + if(this.gameState == consts.GAMESTATES[0]) + return; + + if(!this.shape.isSameSRS(this.hintMino)) + { + //new Audio('./dist/Failed.ogg').play(); + this._restartHandler(); + // Restart + return 1; + } + }, + // Update game data + _update: function() { + + switch(this.gameState) { + case consts.GAMESTATES[0]: + case consts.GAMESTATES[1]: + case consts.GAMESTATES[2]: + if(this.shape == undefined) break; + if (this.shape.canDown(this.matrix)) { + this.shape.goDown(this.matrix); + } else if(this.isPieceLocked()){ + this.canPopFromHoldStack = true; + this.shape.copyTo(this.matrix); + this._check(); + if(this._checkHint()) return; + //this._fireShape(); + this._recurseGameState(); + new Audio('./dist/sound/Blop2.ogg').play(); + } + this._draw(); + this.isGameOver = checkGameOver(this.matrix); + + // if game over and gamestate is free play + views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); + + if (this.isGameOver) + views.setFinalScore(this.score); + break; + case consts.GAMESTATES[3]: + break; + default: + break; + } + + }, + // 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[side4Y] != undefined && matrix[side3Y] != undefined) { + if(matrix[side1Y][side1X] != 0) + side1 = 1; + if(matrix[side2Y][side2X] != 0) + side2 = 1; + // TODO: figure out why this occasionally is undefined + 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; + }, + // Check and update game data + _check: function() { + var rows = checkFullRows(this.matrix); + if (rows.length) { + var tspinType; + + if(this.shape.flag === 'T') + tspinType = this._tSpinType(this.shape, this.matrix); + + removeRows(this.matrix, rows); + + console.log("type: " + tspinType); + var score = calcScore(rows); + var reward = calcRewards(rows, tspinType); + this.score += score + reward; + this.lines += rows.length; + + views.setScore(this.score); + views.setReward(reward); + views.setLines(this.lines); + + } + }, + // 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; // export {Tetris}; },{"./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"); -var utils = require("./utils.js"); -// import * as shapes from './shapes.js'; - -// https://harddrop.com/wiki/Opener -// https://four.lol/ -var openerGenerator = { - shapeQueue: [], - hintQueue: [], - idx: 0, - hintIdx: 0, - isInit: 0, - isHintInit: 0, - customShapeQueue: [], - customHintQueue: [], - // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 - // Current Tetriminos - init(opener) { - 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 - 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; - case 3: - this.shapeQueue = new Array( - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(3)); - break; - case 4: - //Pokemino's STD - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(3)); - break; - case 5: - // Mr TSpins STD reversed - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - break; - case 6: - // Hachispin - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(3)); - break; - case 7: - // Albatross - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(3)); - break; - case 8: - // Number One - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3)); - break; - case 9: - // Pelican - this.shapeQueue = new Array( - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(3)); - break; - case 10: - // DT Cannon TSZ base - this.shapeQueue = new Array( - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - break; - case 11: - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(1), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6)); - break; - case 12: - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3)); - break; - case 13: - this.shapeQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); - break; - - default: - this.shapeQueue.unshift(utils.deepClone(shapes.randomShape())); - return; - } - } - this.isInit = 1; - - return; - }, - - getNextMino(opener) { - if(this.customShapeQueue.length > 0) return this.customShapeQueue[this.idx++%this.customShapeQueue.length]; - this.init(opener); - var mino = this.shapeQueue[this.idx]; - this.idx++; - if(this.idx >= this.shapeQueue.length) { - this.idx = 0; - if(opener < 1000) - this.isInit = 0; - else this.isInit = 1; - } - - return mino; - }, - - createHintQueue(hintDataList) { - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - }, - // Hint Tetrimions - initHint(opener) { - if(!this.isHintInit || this.hintQueue == undefined) { - - switch(opener) { - case 0: - this.hintQueue = []; - break; - 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)); - - // position x, position y, orientation, position x,... - var hintDataList = [-1,17,1, 3,18,0, 6,18,0, 5,17,1, 3,17,0, 7,16,0, 1,17,2]; - - this.createHintQueue(hintDataList); - - break; - case 2: - // DT Cannon - 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)); - - // position x, position y, orientation, position x,... - var hintDataList = [-2,18,0, 4,16,1, 6,17,1, 7,17,1, 4,17,-1, 3,17,3, 3,15,0, 5,15,0, 7,14,1, 2,13,-1, -1,15,1, 1,16,2, 3,16,1, 1,17,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 3: - //MKO Stacking - this.hintQueue = new Array( - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(3)); - - // position x, position y, orientation, position x,... - var hintDataList = [0,18,0, 0,16,-1, 8,16,-1, 4,18,0, 4,16,1, 5,18,0, 1,15,-1, 2,17,2, 5,18,0, 3,17,1, 6,16,0, 0,15,2, 0,14,0, 2,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 4: - //Pokemino's STD - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(3)); - - var hintDataList = [0,17,1, -2,16,1, 4,18,0, 4,17,-1, 3,15,1, 8,17,-1, 2,17,2, 0,17,0, 0,15,-1, - 1,15,0, 8,16,-2, 5,15,-1, 3,14,1, 6,12,-1, 6,16,1, 2,16,-1, 7,17,2 ]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 5: - // Mr TSpins STD reversed - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - - var hintDataList = [4,18,0, 0,18,0, 7,17,1, 0,15,1, 4,17,-1, 5,14,-1, 2,17,2, 1,17,0, -1,16,-1, 2,15,-1, - 0,14,0, 3,15,1, 8,16,-1, 5,13,2, 6,16,1, 7,17,2 ]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - - break; - case 6: - // Hachispin - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(3)); - - var hintDataList = [1,18,0, 0,18,0, 8,16,-1, 2,15,1, 6,17,2, 5,16,2, 1,16,2, -1,16,-1, -1,16,0, 5,16,0, 0,14,0, 3,15,0, 8,14,-1, 7,16,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 7: - // Albatross - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(3)); - - var hintDataList = [1,18,0, 0,17,-1, 8,16,-1, 5,17,2, 6,16,2, 3,16,0, 1,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 8: - // Number One - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3)); - - var hintDataList = [3,18,0, 0,17,2, 0,16,0, 4,15,-1, 6,17,0, 8,16,-1, 3,17,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 9: - // Pelican - this.hintQueue = new Array( - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(3)); - - var hintDataList = [0,17,-1, 1,16,2, 5,18,0, 5,16,-1, 8,16,-1, 5,17,0, 3,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 10: // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 - // DT Cannon TSZ base - this.hintQueue = new Array( - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - - var hintDataList = [4,18,0, -2,18,0, 2,17,1, 8,16,-1, 6,17,-1, 7,17,-1, 3,15,2, -1,15,1, 2,13,-1, 1,16,2, 1,17,3]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 11: - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(1), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6)); - var hintDataList = [3,17,1,6,18,0,1,17,3,5,17,3,2,16,3,-1,17,1,4,15,0,5,13,1,3,14,0,-1,14,3,8,15,3,-1,15,0,0,13,0,6,16,2,0,13,2,4,14,0,2,13,3,6,17,1,7,18,0,3,16,1,7,17,2,6,18,0,1,18,0,-1,17,1,2,16,2,5,17,0,0,15,2,3,15,2,6,15,2,8,16,3]; - this.createHintQueue(hintDataList); - break - case 12: - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3)); - var hintDataList = [3,17,1,6,18,0,5,17,2,1,18,0]; - this.createHintQueue(hintDataList); - break; - case 13: - this.hintQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); - - var hintDataList = [0,18,0,3,18,0,-1,17,0,7,18,0,3,17,0,8,16,3,0,15,2,-2,14,0,3,15,2,3,14,0,1,13,3,8,14,3,7,12,2,5,16,2,3,14,3,6,17,3,5,18,0]; - this.createHintQueue(hintDataList); - break; - default: - this.hintQueue.unshift(utils.deepClone(shapes.randomShape())); - return; - } - - } - - this.isHintInit = 1; - - return; - }, - // End initHint - - getNextHint(opener) { - if(this.customHintQueue.length > 0) return this.customHintQueue[this.hintIdx++%this.customHintQueue.length]; - this.initHint(opener); - var mino = this.hintQueue[this.hintIdx]; - this.hintIdx++; - if(this.hintIdx >= this.hintQueue.length) { - this.hintIdx = 0; - if(opener < 1000) - this.isHintInit = 0; - else this.isHintInit = 1; - } - return mino; - }, - - reset() { - this.shapeQueue = []; - this.hintQueue = []; - this.idx = 0; - this.hintIdx = 0; - this.isInit = 0; - this.isHintInit = 0; - }, - getLength() { - return this.customHintQueue.length || this.hintQueue.length; - }, - addSequence(sequence) { - //this.reset(); - //this.shapeQueue = utils.deepClone(sequence); - //this.hintQueue = utils.deepClone(sequence); - for(var i in sequence) - { - var shape; - shape = sequence[i]; - shape.x = sequence[i].x; - shape.y = sequence[i].y; - shape.state = sequence[i].state; - this.customHintQueue.unshift(utils.deepClone(shape)); - shape.x = shape.originX; - shape.y = shape.originY; - this.customShapeQueue.unshift(utils.deepClone(shape)); - this.isInit = 1; - this.isHintInit = 1; - this.idx = 0; - this.hintIdx = 0; - } - } -}; - -function reset() { - openerGenerator.reset(); -} - -function getNextMino(opener) { - var mino = openerGenerator.getNextMino(opener); - return mino; -} -function getNextHint(opener) { - var mino = openerGenerator.getNextHint(opener); - return mino; -} -function getLength() { - return openerGenerator.getLength(); -} - -function addSequence(sequence) { - openerGenerator.addSequence(sequence); -} - -module.exports.addSequence = addSequence; -module.exports.getNextMino = getNextMino; -module.exports.getNextHint = getNextHint; -module.exports.getLength = getLength; -module.exports.reset = reset; -// export getNextMino; -// export getNextHint; -// export getLength; -// export reset; - - +var shapes = require("./shapes.js"); +var utils = require("./utils.js"); +// import * as shapes from './shapes.js'; + +// https://harddrop.com/wiki/Opener +// https://four.lol/ +var openerGenerator = { + shapeQueue: [], + hintQueue: [], + idx: 0, + hintIdx: 0, + isInit: 0, + isHintInit: 0, + customShapeQueue: [], + customHintQueue: [], + // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 + // Current Tetriminos + init(opener) { + 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 + 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; + case 3: + this.shapeQueue = new Array( + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(3)); + break; + case 4: + //Pokemino's STD + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(3)); + break; + case 5: + // Mr TSpins STD reversed + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + break; + case 6: + // Hachispin + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(3)); + break; + case 7: // Albatross + this.shapeQueue = new Array(shapes.getShape(1), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(4), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(1), shapes.getShape(6), shapes.getShape(0), shapes.getShape(2), shapes.getShape(3)); + break; + case 8: + // Number One + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3)); + break; + case 9: + // Pelican + this.shapeQueue = new Array( + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(3)); + break; + case 10: + // DT Cannon TSZ base + this.shapeQueue = new Array( + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + break; + case 11: + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(1), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6)); + break; + case 12: + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3)); + break; + case 13: + this.shapeQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); + break; + case 14: + this.shapeQueue = new Array(shapes.getShape(0), shapes.getShape(6), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(0), shapes.getShape(4), shapes.getShape(6), shapes.getShape(0), shapes.getShape(0), shapes.getShape(3), shapes.getShape(5)); + break; + case 15: + this.shapeQueue = new Array(shapes.getShape(0), shapes.getShape(2), shapes.getShape(5), shapes.getShape(6), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(2), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(6), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3)); + break; + + + + default: + this.shapeQueue.unshift(utils.deepClone(shapes.randomShape())); + return; + } + } + this.isInit = 1; + + return; + }, + + getNextMino(opener) { + if(this.customShapeQueue.length > 0) return this.customShapeQueue[this.idx++%this.customShapeQueue.length]; + this.init(opener); + var mino = this.shapeQueue[this.idx]; + this.idx++; + if(this.idx >= this.shapeQueue.length) { + this.idx = 0; + if(opener < 1000) + this.isInit = 0; + else this.isInit = 1; + } + + return mino; + }, + + createHintQueue(hintDataList) { + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + }, + // Hint Tetrimions + initHint(opener) { + if(!this.isHintInit || this.hintQueue == undefined) { + + switch(opener) { + case 0: + this.hintQueue = []; + break; + 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)); + + // position x, position y, orientation, position x,... + var hintDataList = [-1,17,1, 3,18,0, 6,18,0, 5,17,1, 3,17,0, 7,16,0, 1,17,2]; + + this.createHintQueue(hintDataList); + + break; + case 2: + // DT Cannon + 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)); + + // position x, position y, orientation, position x,... + var hintDataList = [-2,18,0, 4,16,1, 6,17,1, 7,17,1, 4,17,-1, 3,17,3, 3,15,0, 5,15,0, 7,14,1, 2,13,-1, -1,15,1, 1,16,2, 3,16,1, 1,17,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 3: + //MKO Stacking + this.hintQueue = new Array( + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(3)); + + // position x, position y, orientation, position x,... + var hintDataList = [0,18,0, 0,16,-1, 8,16,-1, 4,18,0, 4,16,1, 5,18,0, 1,15,-1, 2,17,2, 5,18,0, 3,17,1, 6,16,0, 0,15,2, 0,14,0, 2,16,2]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 4: + //Pokemino's STD + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(3)); + + var hintDataList = [0,17,1, -2,16,1, 4,18,0, 4,17,-1, 3,15,1, 8,17,-1, 2,17,2, 0,17,0, 0,15,-1, + 1,15,0, 8,16,-2, 5,15,-1, 3,14,1, 6,12,-1, 6,16,1, 2,16,-1, 7,17,2 ]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 5: + // Mr TSpins STD reversed + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + + var hintDataList = [4,18,0, 0,18,0, 7,17,1, 0,15,1, 4,17,-1, 5,14,-1, 2,17,2, 1,17,0, -1,16,-1, 2,15,-1, + 0,14,0, 3,15,1, 8,16,-1, 5,13,2, 6,16,1, 7,17,2 ]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + + break; + case 6: + // Hachispin + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(3)); + + var hintDataList = [1,18,0, 0,18,0, 8,16,-1, 2,15,1, 6,17,2, 5,16,2, 1,16,2, -1,16,-1, -1,16,0, 5,16,0, 0,14,0, 3,15,0, 8,14,-1, 7,16,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 7: // Albatross + this.hintQueue = new Array(shapes.getShape(1), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(4), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(1), shapes.getShape(6), shapes.getShape(0), shapes.getShape(2), shapes.getShape(3)); + + var hintDataList = [1,18,0,0,17,3,8,16,3,5,17,2,6,16,2,3,16,0,1,16,2,-1,17,1,5,17,3,5,18,0,6,16,0,2,15,3,3,15,1,1,17,3]; + this.createHintQueue(hintDataList); + break; + case 8: + // Number One + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3)); + + var hintDataList = [3,18,0, 0,17,2, 0,16,0, 4,15,-1, 6,17,0, 8,16,-1, 3,17,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 9: + // Pelican + this.hintQueue = new Array( + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(3)); + + var hintDataList = [0,17,-1, 1,16,2, 5,18,0, 5,16,-1, 8,16,-1, 5,17,0, 3,16,2]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 10: // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 + // DT Cannon TSZ base + this.hintQueue = new Array( + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + + var hintDataList = [4,18,0, -2,18,0, 2,17,1, 8,16,-1, 6,17,-1, 7,17,-1, 3,15,2, -1,15,1, 2,13,-1, 1,16,2, 1,17,3]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 11: + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(1), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6)); + var hintDataList = [3,17,1,6,18,0,1,17,3,5,17,3,2,16,3,-1,17,1,4,15,0,5,13,1,3,14,0,-1,14,3,8,15,3,-1,15,0,0,13,0,6,16,2,0,13,2,4,14,0,2,13,3,6,17,1,7,18,0,3,16,1,7,17,2,6,18,0,1,18,0,-1,17,1,2,16,2,5,17,0,0,15,2,3,15,2,6,15,2,8,16,3]; + this.createHintQueue(hintDataList); + break + case 12: + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3)); + var hintDataList = [3,17,1,6,18,0,5,17,2,1,18,0]; + this.createHintQueue(hintDataList); + break; + case 13: + this.hintQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); + + var hintDataList = [0,18,0,3,18,0,-1,17,0,7,18,0,3,17,0,8,16,3,0,15,2,-2,14,0,3,15,2,3,14,0,1,13,3,8,14,3,7,12,2,5,16,2,3,14,3,6,17,3,5,18,0]; + this.createHintQueue(hintDataList); + break; + case 14: + this.hintQueue = new Array(shapes.getShape(0), shapes.getShape(6), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(0), shapes.getShape(4), shapes.getShape(6), shapes.getShape(0), shapes.getShape(0), shapes.getShape(3), shapes.getShape(5)); + + var hintDataList = [-1,17,1,3,18,0,3,17,0,7,18,0,6,16,3,8,16,3,0,16,3,0,14,0,8,13,3,4,15,1,6,14,2,1,17,1,2,17,2]; + this.createHintQueue(hintDataList); + break; + case 15: + this.hintQueue = new Array(shapes.getShape(0), shapes.getShape(2), shapes.getShape(5), shapes.getShape(6), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(2), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(6), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3)); + + var hintDataList = [-1,17,1,2,18,0,4,17,3,6,18,0,6,17,0,2,15,2,-1,14,1,5,17,0,4,14,3,5,14,3,6,15,0,6,14,3,8,12,3,0,16,1,6,15,0,0,15,0,-1,12,3,6,13,1,2,15,0,3,13,0,1,17,2,5,14,1,6,15,0,2,17,3,3,15,2,1,17,2]; + this.createHintQueue(hintDataList); + break; + default: + this.hintQueue.unshift(utils.deepClone(shapes.randomShape())); + return; + } + + } + + this.isHintInit = 1; + + return; + }, + // End initHint + + getNextHint(opener) { + if(this.customHintQueue.length > 0) return this.customHintQueue[this.hintIdx++%this.customHintQueue.length]; + this.initHint(opener); + var mino = this.hintQueue[this.hintIdx]; + this.hintIdx++; + if(this.hintIdx >= this.hintQueue.length) { + this.hintIdx = 0; + if(opener < 1000) + this.isHintInit = 0; + else this.isHintInit = 1; + } + return mino; + }, + + reset() { + this.shapeQueue = []; + this.hintQueue = []; + this.idx = 0; + this.hintIdx = 0; + this.isInit = 0; + this.isHintInit = 0; + }, + getLength() { + return this.customHintQueue.length || this.hintQueue.length; + }, + addSequence(sequence) { + //this.reset(); + //this.shapeQueue = utils.deepClone(sequence); + //this.hintQueue = utils.deepClone(sequence); + for(var i in sequence) + { + var shape; + shape = sequence[i]; + shape.x = sequence[i].x; + shape.y = sequence[i].y; + shape.state = sequence[i].state; + this.customHintQueue.unshift(utils.deepClone(shape)); + shape.x = shape.originX; + shape.y = shape.originY; + this.customShapeQueue.unshift(utils.deepClone(shape)); + this.isInit = 1; + this.isHintInit = 1; + this.idx = 0; + this.hintIdx = 0; + } + } +}; + +function reset() { + openerGenerator.reset(); +} + +function getNextMino(opener) { + var mino = openerGenerator.getNextMino(opener); + return mino; +} +function getNextHint(opener) { + var mino = openerGenerator.getNextHint(opener); + return mino; +} +function getLength() { + return openerGenerator.getLength(); +} + +function addSequence(sequence) { + openerGenerator.addSequence(sequence); +} + +module.exports.addSequence = addSequence; +module.exports.getNextMino = getNextMino; +module.exports.getNextHint = getNextHint; +module.exports.getLength = getLength; +module.exports.reset = reset; +// export getNextMino; +// export getNextHint; +// export getLength; +// export reset; + + },{"./shapes.js":7,"./utils.js":8}],7:[function(require,module,exports){ var consts = require('./consts.js'); diff --git a/index.html b/index.html index 68d29de..d6a458e 100644 --- a/index.html +++ b/index.html @@ -1,214 +1,220 @@ - - - - - - - - Tetrion Opening Trainer - - - - - - - - - - - - - -
    - - - - - - - - - - - -
    - - -
    - - -
    -
    - - - - -
    - - -
    -
    - - - - - -
    - -
    -

    Game Over !

    -

    Score: 0

    -

    Restart

    - -
    -
    -
    -

    Level:
    1

    -

    Score:
    0

    - - - - -
    - - - -
    - - - - -
    - - -
    -
    - - - - - - + + + + + + + + Tetrion Opening Trainer + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + +
    + + +
    +
    + + + + +
    + + +
    +
    + + + + + +
    + +
    +

    Game Over !

    +

    Score: 0

    +

    Restart

    + +
    +
    +
    +

    Level:
    1

    +

    Score:
    0

    + + + + +
    + + + +
    + + + + +
    + + +
    +
    + + + + + + diff --git a/src/gamepad.js b/src/gamepad.js index 06ec482..9151108 100644 --- a/src/gamepad.js +++ b/src/gamepad.js @@ -1,85 +1,85 @@ - -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; - if(!isFirefox) { - for(var i = 0; i < 4; i++) - if((gp = window.navigator.getGamepads()[i]) != undefined) // dumb gamepad update. fix. - gamepadAPI.controller = gp; - } - - 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; + +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; + if(!isFirefox) { + for(var i = 0; i < 4; i++) + if((gp = window.navigator.getGamepads()[i]) != undefined) // dumb gamepad update. fix. + gamepadAPI.controller = gp; + } + + 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; // export gamepadAPI; \ No newline at end of file diff --git a/src/input.js b/src/input.js index 1001217..a85ce3f 100644 --- a/src/input.js +++ b/src/input.js @@ -1,250 +1,250 @@ -var gamepad = require('./gamepad.js'); -var utils = require('./utils.js'); -// import * as gamepad from './gamepad.js'; - -var UserInputs = { - init() { - - this.settingsList = this.keyboardKeySettings.concat(this.keyboardShiftEvents.concat(this.keyboardKeyEvents.concat(this.gamepadSettings.concat(this.gamepadShiftEvents.concat(this.gamepadButtonEvents))))); - //;["Soft Drop Rate [1 - 100]"].concat(this.keyboardSettings.concat(this.gamepadSettings)); - this.gamepadShiftTimer = new Date(); - this.gamepadButtonTimer = new Date(); - this.keyboardKeyTimer = new Date(); - this.keyboardShiftTimer = new Date(); - this.settingsMap = new Map(); - this.gamepadEventMap = new Map(); - ///this.gamepadEventMap = new Map(); - // 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]); - - - this.gamepadEvents = this.gamepadShiftEvents.concat(this.gameButtonsEvents); - - var mapIdx = [14, 7, 13, 5, 4, 1, 2, 12, 8, 3]; - for(var i in mapIdx) { - this.gamepadEventMap.set(this.gamepadEvents[i], gamepad.buttons[mapIdx[i]]); - } - - - document.addEventListener('keydown', this.keyDown.bind(this)); - document.addEventListener('keyup', this.keyUp.bind(this)); - }, - - updateGamepad() { - this.gpButtons = gamepad.update(); - }, - gamepadEnabled() { - return gamepad.controller || false; - }, - processGamepadInput() { - this.gamepadButtonEvents.forEach(gamepadButton => this.gamepadButtonsDown(this.settingsMap.get(gamepadButton))); - }, - processGamepadDPad() { - this.gamepadShiftEvents.forEach(dpadButton => this.gamepadDPadDown(this.settingsMap.get(dpadButton))); - }, - // Single press gamepad buttons - gamepadButtonsDown(finds) { - var DAS = 167.0; - var ARR = 300.0; - var isContained = this.gpButtons.includes(finds); - var isPrevContained = this.prevGpButtons.includes(finds); - - if(isPrevContained != isContained ) { - // Not being held yet - this.gamepadButtonTimer = new Date(); - this.isPassedDelayGamepadShift = false; - // Add button to queue on pressed input - if(isContained) - this.gamepadQueue.push(finds); - } - - var deltaTime = (new Date()).getTime() - this.gamepadButtonTimer.getTime(); - - if (!this.isPassedDelayGamepadShift) { - if (deltaTime >= DAS) { - this.gamepadButtonTimer = new Date(); - this.isPassedDelayGamepadShift = true; - } - - } else { - if (deltaTime >= ARR && isContained) { - this.gamepadQueue.push(finds); - this.gamepadButtonTimer = new Date(); - } - } - - }, - - // Direction Pad - gamepadDPadDown(finds) { - var DAS = parseInt(this.settingsMap.get("Gamepad DAS")); - var ARR = parseInt(this.settingsMap.get("Gamepad ARR")); - - var isContained = this.gpButtons.includes(finds); - var isPrevContained = this.prevGpButtons.includes(finds); - - if(isPrevContained != isContained ) { - // Not being held yet - this.gamepadShiftTimer = new Date(); - this.isDelayedPassedGamepadShift = false; - // Add button to queue on pressed input - if(isContained) - this.gamepadQueue.push(finds); - } - - var deltaTime = (new Date()).getTime() - this.gamepadShiftTimer.getTime(); - - if (!this.isDelayedPassedGamepadShift) { - if (deltaTime >= DAS) { - this.gamepadShiftTimer = new Date(); - this.isDelayedPassedGamepadShift = true; - } - } - else { - if (deltaTime >= ARR && isContained) { - this.gamepadQueue.push(finds); - this.gamepadShiftTimer = new Date(); - } - } - return; - }, - - processKeys() { - this.keyboardKeyEvents.forEach( key => this.settingsMap.get(key).split(',').forEach( idx => this.processKeyDown( parseInt(idx) ) ) ); - }, - - // keyboard keys z,x,space - processKeyDown(key) - { - var DAS = 167.0; - var ARR = 300.0; - - if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { - // Not being held yet - this.keyboardKeyTimer = new Date(); - this.isPassedDelayKeyboardKey = false; - // Add shift to queue on pressed input - if(this.keyboardKeys[key] == true) - this.inputQueue.push(key); - } - - var deltaTime = (new Date()).getTime() - this.keyboardKeyTimer.getTime(); - - if (!this.isPassedDelayKeyboardKey) { - if (deltaTime >= DAS) { - this.keyboardKeyTimer = new Date(); - this.keyboardButtonsDeciframes = 0; - this.isPassedDelayKeyboardKey = true; - } - } else { - if (deltaTime >= ARR && this.keyboardKeys[key] == true) { - this.inputQueue.push(key); - this.keyboardKeyTimer = new Date(); - } - } - }, - // Process applicable key inputs - processKeyShift() { - this.keyboardShiftEvents.forEach(arrowKey => arrowKey.split(',').forEach(option => this.processKeyboardArrowKeys(parseInt(this.settingsMap.get(option))))); - }, - // Direction arrows - processKeyboardArrowKeys(key) { - var DAS = parseInt(this.settingsMap.get("Keyboard DAS")); - var ARR = parseInt(this.settingsMap.get("Keyboard ARR")); - - if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { - // Not being held yet - this.isPassedDelayKeyboardShift = false; - this.keyboardShiftTimer = new Date(); - - // Do shift if key has been pushed down - if(this.keyboardKeys[key] == true) - this.inputQueue.push(key); - } - - var deltaTime = (new Date()).getTime() - this.keyboardShiftTimer.getTime(); - - if (!this.isPassedDelayKeyboardShift) { - - if (deltaTime >= DAS) { - this.keyboardShiftTimer = new Date(); - this.isPassedDelayKeyboardShift = true; - } - } - else if(deltaTime >= ARR && this.keyboardKeys[key] == true) { - this.inputQueue.push(key); - this.keyboardShiftTimer = new Date(); - } - - - }, - keyDown(event) { - if(event.keyCode != 38) - if (! ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8)) - event.preventDefault(); - - this.keyboardKeys[event.keyCode] = true; - this.isKeyBoardKeyDown = true; - }, - keyUp(event) { - this.isKeyDown = false; - this.keyboardKeys[event.keyCode] = false; - this.isKeyBoardKeyDown = false; - }, - gamepadClear() { - //this.gpButtons = []; - //this.gamepadQueue = []; - }, - saveButtons() { - this.prevGpButtons = this.gpButtons; - }, - saveKeyboardKeys() { - //this.prevKeyboardKeys = utils.deepClone(this.keyboardKeys); - this.prevKeyboardKeys = {...this.keyboardKeys}; - }, - // button states - isPassedDelayKeyboardShift: false, - isPassedDelayKeyboardKey: false, - isPassedDelayGamepadShift: false, - isPassedDelayGamepadButton: false, - - // buttons state contatiners - gpButtons: [], - prevGpButtons:[], - keyboardKeys: [], - prevKeyboardKeys: [], - - // button pressed containers - inputQueue: [], - gamepadQueue: [], - - keyboardKeySettings: ["Keyboard DAS", "Keyboard ARR"], - keyboardShiftEvents: ["Keyboard Left", "Keyboard Right", "Keyboard Down", "Keyboard Up"], - keyboardKeyEvents: ["Keyboard Harddrop", "Keyboard Hold", "Keyboard Rotateccw", "Keyboard Rotate", "Keyboard Pophold", "Keyboard Reset", "Keyboard Background"], - - gamepadSettings: ["Gamepad DAS", "Gamepad ARR"], - gamepadShiftEvents: ["Gamepad Left", "Gamepad Right","Gamepad Down"], - gamepadButtonEvents: ["Gamepad Harddrop", "Gamepad Hold", "Gamepad Rotateccw", "Gamepad Rotate", "Gamepad Pophold", "Gamepad Reset", "Gamepad Background"], - - settingsList: [], - - settingsDefault: [ "167.0", "33.0", - "37", "39", "40", "38", - "32", "16", "90", "88", "17", "82", "81", - - "167.0", "33.0", - "DPad-Left", "DPad-Right", "DPad-Down", - "RB", "LB", "A", "B", "DPad-Up", "Back", ""], - settingsMap: [] -}; - -module.exports = UserInputs; +var gamepad = require('./gamepad.js'); +var utils = require('./utils.js'); +// import * as gamepad from './gamepad.js'; + +var UserInputs = { + init() { + + this.settingsList = this.keyboardKeySettings.concat(this.keyboardShiftEvents.concat(this.keyboardKeyEvents.concat(this.gamepadSettings.concat(this.gamepadShiftEvents.concat(this.gamepadButtonEvents))))); + //;["Soft Drop Rate [1 - 100]"].concat(this.keyboardSettings.concat(this.gamepadSettings)); + this.gamepadShiftTimer = new Date(); + this.gamepadButtonTimer = new Date(); + this.keyboardKeyTimer = new Date(); + this.keyboardShiftTimer = new Date(); + this.settingsMap = new Map(); + this.gamepadEventMap = new Map(); + ///this.gamepadEventMap = new Map(); + // 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]); + + + this.gamepadEvents = this.gamepadShiftEvents.concat(this.gameButtonsEvents); + + var mapIdx = [14, 7, 13, 5, 4, 1, 2, 12, 8, 3]; + for(var i in mapIdx) { + this.gamepadEventMap.set(this.gamepadEvents[i], gamepad.buttons[mapIdx[i]]); + } + + + document.addEventListener('keydown', this.keyDown.bind(this)); + document.addEventListener('keyup', this.keyUp.bind(this)); + }, + + updateGamepad() { + this.gpButtons = gamepad.update(); + }, + gamepadEnabled() { + return gamepad.controller || false; + }, + processGamepadInput() { + this.gamepadButtonEvents.forEach(gamepadButton => this.gamepadButtonsDown(this.settingsMap.get(gamepadButton))); + }, + processGamepadDPad() { + this.gamepadShiftEvents.forEach(dpadButton => this.gamepadDPadDown(this.settingsMap.get(dpadButton))); + }, + // Single press gamepad buttons + gamepadButtonsDown(finds) { + var DAS = 167.0; + var ARR = 300.0; + var isContained = this.gpButtons.includes(finds); + var isPrevContained = this.prevGpButtons.includes(finds); + + if(isPrevContained != isContained ) { + // Not being held yet + this.gamepadButtonTimer = new Date(); + this.isPassedDelayGamepadShift = false; + // Add button to queue on pressed input + if(isContained) + this.gamepadQueue.push(finds); + } + + var deltaTime = (new Date()).getTime() - this.gamepadButtonTimer.getTime(); + + if (!this.isPassedDelayGamepadShift) { + if (deltaTime >= DAS) { + this.gamepadButtonTimer = new Date(); + this.isPassedDelayGamepadShift = true; + } + + } else { + if (deltaTime >= ARR && isContained) { + this.gamepadQueue.push(finds); + this.gamepadButtonTimer = new Date(); + } + } + + }, + + // Direction Pad + gamepadDPadDown(finds) { + var DAS = parseInt(this.settingsMap.get("Gamepad DAS")); + var ARR = parseInt(this.settingsMap.get("Gamepad ARR")); + + var isContained = this.gpButtons.includes(finds); + var isPrevContained = this.prevGpButtons.includes(finds); + + if(isPrevContained != isContained ) { + // Not being held yet + this.gamepadShiftTimer = new Date(); + this.isDelayedPassedGamepadShift = false; + // Add button to queue on pressed input + if(isContained) + this.gamepadQueue.push(finds); + } + + var deltaTime = (new Date()).getTime() - this.gamepadShiftTimer.getTime(); + + if (!this.isDelayedPassedGamepadShift) { + if (deltaTime >= DAS) { + this.gamepadShiftTimer = new Date(); + this.isDelayedPassedGamepadShift = true; + } + } + else { + if (deltaTime >= ARR && isContained) { + this.gamepadQueue.push(finds); + this.gamepadShiftTimer = new Date(); + } + } + return; + }, + + processKeys() { + this.keyboardKeyEvents.forEach( key => this.settingsMap.get(key).split(',').forEach( idx => this.processKeyDown( parseInt(idx) ) ) ); + }, + + // keyboard keys z,x,space + processKeyDown(key) + { + var DAS = 167.0; + var ARR = 300.0; + + if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { + // Not being held yet + this.keyboardKeyTimer = new Date(); + this.isPassedDelayKeyboardKey = false; + // Add shift to queue on pressed input + if(this.keyboardKeys[key] == true) + this.inputQueue.push(key); + } + + var deltaTime = (new Date()).getTime() - this.keyboardKeyTimer.getTime(); + + if (!this.isPassedDelayKeyboardKey) { + if (deltaTime >= DAS) { + this.keyboardKeyTimer = new Date(); + this.keyboardButtonsDeciframes = 0; + this.isPassedDelayKeyboardKey = true; + } + } else { + if (deltaTime >= ARR && this.keyboardKeys[key] == true) { + this.inputQueue.push(key); + this.keyboardKeyTimer = new Date(); + } + } + }, + // Process applicable key inputs + processKeyShift() { + this.keyboardShiftEvents.forEach(arrowKey => arrowKey.split(',').forEach(option => this.processKeyboardArrowKeys(parseInt(this.settingsMap.get(option))))); + }, + // Direction arrows + processKeyboardArrowKeys(key) { + var DAS = parseInt(this.settingsMap.get("Keyboard DAS")); + var ARR = parseInt(this.settingsMap.get("Keyboard ARR")); + + if(this.prevKeyboardKeys[key] != this.keyboardKeys[key]) { + // Not being held yet + this.isPassedDelayKeyboardShift = false; + this.keyboardShiftTimer = new Date(); + + // Do shift if key has been pushed down + if(this.keyboardKeys[key] == true) + this.inputQueue.push(key); + } + + var deltaTime = (new Date()).getTime() - this.keyboardShiftTimer.getTime(); + + if (!this.isPassedDelayKeyboardShift) { + + if (deltaTime >= DAS) { + this.keyboardShiftTimer = new Date(); + this.isPassedDelayKeyboardShift = true; + } + } + else if(deltaTime >= ARR && this.keyboardKeys[key] == true) { + this.inputQueue.push(key); + this.keyboardShiftTimer = new Date(); + } + + + }, + keyDown(event) { + if(event.keyCode != 38) + if (! ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8)) + event.preventDefault(); + + this.keyboardKeys[event.keyCode] = true; + this.isKeyBoardKeyDown = true; + }, + keyUp(event) { + this.isKeyDown = false; + this.keyboardKeys[event.keyCode] = false; + this.isKeyBoardKeyDown = false; + }, + gamepadClear() { + //this.gpButtons = []; + //this.gamepadQueue = []; + }, + saveButtons() { + this.prevGpButtons = this.gpButtons; + }, + saveKeyboardKeys() { + //this.prevKeyboardKeys = utils.deepClone(this.keyboardKeys); + this.prevKeyboardKeys = {...this.keyboardKeys}; + }, + // button states + isPassedDelayKeyboardShift: false, + isPassedDelayKeyboardKey: false, + isPassedDelayGamepadShift: false, + isPassedDelayGamepadButton: false, + + // buttons state contatiners + gpButtons: [], + prevGpButtons:[], + keyboardKeys: [], + prevKeyboardKeys: [], + + // button pressed containers + inputQueue: [], + gamepadQueue: [], + + keyboardKeySettings: ["Keyboard DAS", "Keyboard ARR"], + keyboardShiftEvents: ["Keyboard Left", "Keyboard Right", "Keyboard Down", "Keyboard Up"], + keyboardKeyEvents: ["Keyboard Harddrop", "Keyboard Hold", "Keyboard Rotateccw", "Keyboard Rotate", "Keyboard Pophold", "Keyboard Reset", "Keyboard Background"], + + gamepadSettings: ["Gamepad DAS", "Gamepad ARR"], + gamepadShiftEvents: ["Gamepad Left", "Gamepad Right","Gamepad Down"], + gamepadButtonEvents: ["Gamepad Harddrop", "Gamepad Hold", "Gamepad Rotateccw", "Gamepad Rotate", "Gamepad Pophold", "Gamepad Reset", "Gamepad Background"], + + settingsList: [], + + settingsDefault: [ "167.0", "33.0", + "37", "39", "40", "38", + "32", "16", "90", "88", "17", "82", "81", + + "167.0", "33.0", + "DPad-Left", "DPad-Right", "DPad-Down", + "RB", "LB", "A", "B", "DPad-Up", "Back", ""], + settingsMap: [] +}; + +module.exports = UserInputs; // export UserInputs; \ No newline at end of file diff --git a/src/main.js b/src/main.js index 9506031..30d735b 100644 --- a/src/main.js +++ b/src/main.js @@ -1,865 +1,865 @@ -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'); -var openers = require('./openers.js'); -// 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'; - - - - -/** - 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 -*/ -var calcRewards = function(rows, tspinType) { - if(tspinType == 2) - rows*=2+1; - 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: 560 -}; - -/** - Tetris main object definition -*/ -function Tetris(id) { - this.id = id; - this.init(); -} - -Tetris.prototype = { - init: function(options) { - var cfg = this.config = utils.extend(options, defaults); - this.interval = consts.DEFAULT_INTERVAL; - - views.init(this.id, cfg.maxWidth, cfg.maxHeight); - canvas.init(views.scene, views.preview, views.hold); - inputs.init(); - this.createSettings(); - - // if true no openers. just random tetrinos - this.gameState = consts.DEFAULT_GAMESTATE; - - this.isTimerOn = false; - this.currentOpener = 0; - this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); - this.eventTimer = new Date(); - this.debugTimer = new Date(); - this.gamepadEnabled = false; - this.reset(); - - this._initEvents(); - //this._fireShape(); - // ewww - this._recurseGameState(); - - }, - toggleTimer: function() { - document.getElementById("Timer").value = (this.isTimerOn = !this.isTimerOn) ? "Seconds:" : "Timer Off"; - }, - toggleGamepad: function(){ - document.getElementById("enablegamepad").value = ((this.gamepadEnabled = !this.gamepadEnabled) ? "Disable Gamepad" : "Enable Gamepad"); - }, - // Gamestate 1 - setFreePlay: function() - { - - this.gameState = consts.GAMESTATES[0]; - - document.getElementById("Timer").value = "Timer Off"; - document.getElementById("Time").value = ""; - document.getElementById("besttime").value = ""; - this.isTimerOn = false; - - this.hintQueue = []; - this.shapeQueue = []; - this.hintMino = 0; - this._restartHandler(); - this.currentOpener = 0; - - }, - // Gamestate 2 - setCurrentOpener(opener) - { - document.getElementById("besttime").value = ""; - - this.gameState = consts.GAMESTATES[1]; - this.currentOpener = opener; - this._restartHandler(); - - }, - // Gamestate 3 - setDoTest: function() - { - - if(this.gameState != consts.GAMESTATES[1]) return; - - // set game state to do test - this.gameState = consts.GAMESTATES[2]; - - this._restartHandler(); - }, - // Gamestate 4 - setGameStateSequenceEditor: function() - { - document.getElementById("side").display = "none"; - - // change to editor gamestate - this.gameState = consts.GAMESTATES[3]; - this.hintQueue = []; - this.shapeQueue = []; - this.hintMino = 0; - this._restartHandler(); - this.currentOpener = 0; - this.pushHoldStack(); - }, - - 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() { - // var setting = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; - // var doKeyToAlpha = inputs.keyboardShiftEvents.included(setting) || inputs.keyboardKeyEvents.included(setting); - - // if(doKeyToAlpha) - // document.getElementById("setting_value").value = inputs.settingsMap.get(setting).fromCharCode(); - // else - // document.getElementById("setting_value").value = inputs.settingsMap.get(setting); - - document.getElementById("setting_value").value = - inputs.settingsMap.get(inputs.settingsList[document.getElementById("settings").selectedIndex-1]); - - - }, - addOpener: function() { - - var newOpener = document.createElement('li'); - //
  • Mr. T-Spin's STD (reversed)
  • - //newOpener.text = "New Sequence"; - //newOpener.id = this.currentMinoInx; - newOpener.style="color:powderblue;text-decoration:underline;font-size:12px;padding-left:1em"; - - - newOpener.appendChild(document.createTextNode("New Sequence: " + this.currentMinoInx)); - document.getElementById("Openers").appendChild(newOpener); - - - - // Print Sequence Data to console - // console.log("this.hintQueue = new Array("); - // this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { console.log("shapes.getShape("+shape.nType()+ ((idx === arr.length-1) ? "));" : "),") ); } ); - - - var shapes = []; - this.shapeQueue.slice().reverse().forEach( function(shape, idx) { shapes.push(shape.x); shapes.push(shape.y); shapes.push(shape.state); } ); - - // console.log("var hintDataList = [" + shapes.join(",") + "];"); - // console.log("this.createHintQueue(hintDataList);"); - - var sequenceCode = []; - - var shapeArrayStr = []; - this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { shapeArrayStr += "shapes.getShape("+shape.nType() + ((idx === arr.length-1) ? "));" : "), ") } ); - sequenceCode += "case :\n\tthis.shapeQueue = new Array(" + shapeArrayStr + "\nbreak;" + "\n\n"; - - sequenceCode += "case :\n\tthis.hintQueue = new Array(" + shapeArrayStr; - sequenceCode += "\n\nvar hintDataList = [" + shapes.join(",") + "];" + "\nthis.createHintQueue(hintDataList);" + "\nbreak;"; - - prompt("Generated Code:", sequenceCode); - - - //openers.addSequence(this.shapeQueue); - //this.setFreePlay(); - //this.gameState = consts.GAMESTATES[1]; - this.currentMinoInx = 0; - //this.setCurrentOpener(99999);//this.currentMinoInx); - clearMatrix(this.matrix); - this.currentOpener = 9999; - this.shapeQueue = []; - this.hintQueue = []; - //this._recurseGameState(); - }, - setSettings: function() { - var newVal = document.getElementById("setting_value").value; - var key = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; - utils.setCookie(key, newVal, 30); - inputs.settingsMap.set(key, newVal); - }, - //Reset game - reset: function() { - this.numlefts = 0; - this.running = false; - this.isGameOver = false; - this.level = 1; - this.score = 0; - this.lines = 0; - // beginning of frame - this.startTime = new Date().getTime(); - this.currentTime = this.startTime; - this.prevTime = this.startTime; - this.sequencePrevTime = this.startTime; - //todo:get rid of extra - this.levelTime = this.startTime; - this.prevInputTime = this.startTime; - // current tetrino index gets set to 0 at the end of opener sequence - this.currentMinoInx = 0; - this.shapeQueue = []; - this.hintQueue = []; - this.holdStack = []; - this.shape = shapes.getShape(0); - // gets set to false after mino has been popped from hold stack; set back to true on mino dropped - this.canPopFromHoldStack = false; - // manipulation counter for srs extended piece lockdown - this.manipulationCounter = 0; - // timer for srs extened piece lockdown - this.lockdownTimer = 0; - this.landed = false; - this.isSequenceCompleted = false; - - clearMatrix(this.matrix); - views.setLevel(this.level); - views.setScore(this.score); - views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); - openers.reset(); - shapes.resetMinoRNG(); - - this._draw(); - }, - //Start game - start: function() { - this.running = true; - window.requestAnimationFrame(utils.proxy(this._refresh, this)); - - }, - //Pause game - pause: function() { - this.running = false; - this.currentTime = new Date().getTime(); - this.prevTime = this.currentTime; - }, - pushHoldStack: function() - { - if(this.gameState == consts.GAMESTATES[3]) { - while(this.holdStack.length < 7) - this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); - this.shape = this.holdStack.pop(); - this._draw(); - return; - } - // 1 shape hold queue - if(this.holdStack.length > 0) { - this.canPopFromHoldStack = false; - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = utils.deepClone(this.holdStack.pop()); - this.shape.resetOrigin(); - this._draw(); - }else if(this.holdStack.length < 4) { - this.holdStack.push(utils.deepClone(this.shape)); - this.shape = this.shapeQueue.shift(); - this.canPopFromHoldStack = false; - this.shape.resetOrigin(); - this._draw(); - } - /* 4 shape hold queue - if(this.holdStack.length < 4) { - this.holdStack.push(utils.deepClone(this.shape)); - this.shape = this.shapeQueue.shift(); - this.canPopFromHoldStack = false; - this.shape.resetOrigin(); - this._draw(); - }*/ - }, - popHoldStack: function() - { - if(this.gameState == consts.GAMESTATES[3]) { - if(this.holdStack.length < 7) - while(this.holdStack.length < 7) - this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); - // piece needs to be able to be placed - if(this.shape.canDown(this.matrix)) return; - this.shape.copyTo(this.matrix); - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = utils.deepClone(this.holdStack.pop()); - this._check(); - this._draw(); - return; - } - // todo: disable if 1 shape hold queue - if(this.holdStack.length >= 1 && this.canPopFromHoldStack) - { - this.canPopFromHoldStack = false; - this.shapeQueue.unshift(utils.deepClone(this.shape)); - this.shape = this.holdStack.pop(); - this.shape.resetOrigin(); - this._draw(); - } - }, - - // Restart game - _restartHandler: function() { - this.reset(); - this.start(); - //this._fireShape(); - this._recurseGameState(); - }, - // Bind game events - _initEvents: function() { - setInterval(() => {this._processTick();}, 1); - setInterval(() => {this.lockDownTimer++;}, 100 ); - views.btnRestart.addEventListener('click', utils.proxy(this._restartHandler, this), false); - }, - // Process freeplay queue - _processFreeplayQueue: function() { - while(this.shapeQueue.length <= 4) - { - this.preparedShape = shapes.randomShape(); - this.shapeQueue.push(this.preparedShape); - } - - this.shape = this.shapeQueue.shift();// || shapes.randomShape(); - this.currentMinoInx++; - }, - // Process opener trainer queue - _processOpenerTrainerQueue: function() { - while(this.shapeQueue.length <= 4) - { - this.preparedShape = utils.deepClone(openers.getNextMino(this.currentOpener)); - this.shapeQueue.push(this.preparedShape); - } - while(this.hintQueue.length <= 4) - { - this.preparedShape = utils.deepClone(openers.getNextHint(this.currentOpener)); - this.hintQueue.push(this.preparedShape); - } - - this.hintMino = this.hintQueue.shift(); - this.shape = this.shapeQueue.shift(); - - this.currentMinoInx++; - - // Opener sequence completed - if(this.currentMinoInx > openers.getLength()) { - //new Audio("./dist/sound/Affirm2.ogg").play(); - if(this.isTimerOn) { - var besttime = document.getElementById("besttime").value; - var deltaTime = new Date().getTime() - this.sequencePrevTime; - if(besttime == "" || deltaTime/1000.0 < parseFloat(besttime)) { - document.getElementById("besttime").value = (deltaTime/1000.0).toString(); - } - } - - this.hintQueue = []; - this.shapeQueue = []; - - this.isSequenceCompleted = true; - - // Recursion warning - if(this.currentOpener < 1000) // getting real hacky - this._restartHandler(); - else clearMatrix(this.matrix); - // this.reset(); - // this.start(); - return; - } - }, - // Process sequence editor - _processSequenceEditor: function () { - return; - }, - - // Fill next queue and set next shape - _fireShape: function() { - //todo:should be in shapes.js - this.landed = false; - this.manipulationCounter = 0; - - this._draw(); - - }, - _recurseGameState: function (){ - switch(this.gameState) { - case consts.GAMESTATES[0]: - this._processFreeplayQueue(); - this._fireShape(); - break; - case consts.GAMESTATES[1]: - this._processOpenerTrainerQueue(); - this._fireShape(); - break; - case consts.GAMESTATES[2]: - this._processOpenerTrainerQueue(); - this._fireShape(); - case consts.GAMESTATES[3]: - this._processSequenceEditor(); - break; - - default: - break; - } - }, - // 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; - }, - // Draw game data - _draw: function() { - canvas.drawScene(); - canvas.drawShape(this.shape); - canvas.drawHoldShape(this.holdStack); - canvas.drawPreviewShape(this.shapeQueue); - if(this.gameState != consts.GAMESTATES[2]) - canvas.drawHintShape(this.hintMino); - - if(this.shape != undefined) { - let clone = Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape); - - var bottomY = clone.bottomAt(this.matrix); - canvas.drawGhostShape(clone, bottomY); - } - canvas.drawMatrix(this.matrix); - - - }, - - // tick input data -- wont have better than 4-15ms resolution since javascript is single theaded and any ARR or DAS below 15ms will likely be broken - _processTick: async function() { - - - if(this.isTimerOn) { - var deltaPlayTime = new Date().getTime() - this.sequencePrevTime; - document.getElementById("Time").value = (deltaPlayTime/1000).toString(); - - } - - // Don't process game related events if game over - if(this.isGameOver) return; - - - - if(this.gamepadEnabled && inputs.gamepadEnabled()) { - inputs.updateGamepad(); - inputs.processGamepadDPad(); - inputs.processGamepadInput(); - - while((inputs.gamepadQueue != undefined && inputs.gamepadQueue.length >= 1)){ - var curkey = inputs.gamepadQueue.shift(); - if(inputs.settingsMap.get("Gamepad Left").includes(curkey)) { - this.shape.goLeft(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Right").includes(curkey)) { - this.shape.goRight(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Rotateccw").includes(curkey)) { - this.shape.rotate(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Rotate").includes(curkey)) { - this.shape.rotateClockwise(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Down").includes(curkey)) { - this.shape.goDown(this.matrix); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Harddrop").includes(curkey)) { - // if editor - if(this.gameState == consts.GAMESTATES[3]) { - this.popHoldStack(); - this._draw(); - }else { - this.shape.goBottom(this.matrix); - this.lockDownTimer = 5000; - this._update(); - } - } - else if(inputs.settingsMap.get("Gamepad Hold").includes(curkey)) { - this.pushHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Pophold").includes(curkey)) { - this.popHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Gamepad Reset").includes(curkey)) { - this._restartHandler(); - return; - } - } - inputs.saveButtons(); - inputs.gamepadClear(); - } - - - // Do keyboard - inputs.processKeys(); - inputs.processKeyShift(); - // Keyboard inputs - while((inputs.inputQueue != undefined && inputs.inputQueue.length >= 1)){ - var curkey = inputs.inputQueue.shift(); - if(inputs.settingsMap.get("Keyboard Left").includes(curkey)) { - this.shape.goLeft(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Right").includes(curkey)) { - this.shape.goRight(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Down").includes(curkey)) { - - this.shape.goDown(this.matrix); - this._draw(); - } - else if(this.gameState == consts.GAMESTATES[3] && inputs.settingsMap.get("Keyboard Up").includes(curkey)) { - - this.shape.goUp(this.matrix); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Rotateccw").includes(curkey)) { - this.shape.rotate(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Rotate").includes(curkey)) { - this.shape.rotateClockwise(this.matrix); - this.resetLockdown(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Harddrop").includes(curkey)) { - // if editor - if(this.gameState == consts.GAMESTATES[3]) { - this.popHoldStack(); - this._draw(); - }else { - this.shape.goBottom(this.matrix); - this.lockDownTimer = 5000; - this._update(); - } - } - else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { - this.pushHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Pophold").includes(curkey)) { - this.popHoldStack(); - this._draw(); - } - else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { - if(document.getElementById("divbg").style.display == "none") - document.getElementById("divbg").style.display = "initial"; - else - document.getElementById("divbg").style.display="none"; - } - if(inputs.settingsMap.get("Keyboard Reset").includes(curkey)) { - this._restartHandler(); - return; - } - - } - inputs.inputQueue = []; - - - inputs.saveKeyboardKeys(); - - inputs.saveButtons(); - }, - // Refresh game canvas - _refresh: function() { - if (!this.running) - return; - - this.currentTime = new Date().getTime(); - var deltaLevelTime = this.currentTime - this.prevTime; - if (deltaLevelTime > this.interval) { // every .6 seconds? - this._update(); - this._checkLevel(this.prevTime = this.currentTime); - } - - // Draw Frame - if (!this.isGameOver) { - window.requestAnimationFrame(utils.proxy(this._refresh, this)); - } - }, - // check if the current piece is in the same location as the hint piece - _checkHint: function() { - - if(this.gameState == consts.GAMESTATES[0]) - return; - - if(!this.shape.isSameSRS(this.hintMino)) - { - //new Audio('./dist/Failed.ogg').play(); - this._restartHandler(); - // Restart - return 1; - } - }, - // Update game data - _update: function() { - - switch(this.gameState) { - case consts.GAMESTATES[0]: - case consts.GAMESTATES[1]: - case consts.GAMESTATES[2]: - if(this.shape == undefined) break; - if (this.shape.canDown(this.matrix)) { - this.shape.goDown(this.matrix); - } else if(this.isPieceLocked()){ - this.canPopFromHoldStack = true; - this.shape.copyTo(this.matrix); - this._check(); - if(this._checkHint()) return; - //this._fireShape(); - this._recurseGameState(); - new Audio('./dist/sound/Blop2.ogg').play(); - } - this._draw(); - this.isGameOver = checkGameOver(this.matrix); - - // if game over and gamestate is free play - views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); - - if (this.isGameOver) - views.setFinalScore(this.score); - break; - case consts.GAMESTATES[3]: - break; - default: - break; - } - - }, - // 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[side4Y] != undefined && matrix[side3Y] != undefined) { - if(matrix[side1Y][side1X] != 0) - side1 = 1; - if(matrix[side2Y][side2X] != 0) - side2 = 1; - // TODO: figure out why this occasionally is undefined - 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; - }, - // Check and update game data - _check: function() { - var rows = checkFullRows(this.matrix); - if (rows.length) { - var tspinType; - - if(this.shape.flag === 'T') - tspinType = this._tSpinType(this.shape, this.matrix); - - removeRows(this.matrix, rows); - - console.log("type: " + tspinType); - var score = calcScore(rows); - var reward = calcRewards(rows, tspinType); - this.score += score + reward; - this.lines += rows.length; - - views.setScore(this.score); - views.setReward(reward); - views.setLines(this.lines); - - } - }, - // 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; +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'); +var openers = require('./openers.js'); +// 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'; + + + + +/** + 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 +*/ +var calcRewards = function(rows, tspinType) { + if(tspinType == 2) + rows*=2+1; + 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: 560 +}; + +/** + Tetris main object definition +*/ +function Tetris(id) { + this.id = id; + this.init(); +} + +Tetris.prototype = { + init: function(options) { + var cfg = this.config = utils.extend(options, defaults); + this.interval = consts.DEFAULT_INTERVAL; + + views.init(this.id, cfg.maxWidth, cfg.maxHeight); + canvas.init(views.scene, views.preview, views.hold); + inputs.init(); + this.createSettings(); + + // if true no openers. just random tetrinos + this.gameState = consts.DEFAULT_GAMESTATE; + + this.isTimerOn = false; + this.currentOpener = 0; + this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); + this.eventTimer = new Date(); + this.debugTimer = new Date(); + this.gamepadEnabled = false; + this.reset(); + + this._initEvents(); + //this._fireShape(); + // ewww + this._recurseGameState(); + + }, + toggleTimer: function() { + document.getElementById("Timer").value = (this.isTimerOn = !this.isTimerOn) ? "Seconds:" : "Timer Off"; + }, + toggleGamepad: function(){ + document.getElementById("enablegamepad").value = ((this.gamepadEnabled = !this.gamepadEnabled) ? "Disable Gamepad" : "Enable Gamepad"); + }, + // Gamestate 1 + setFreePlay: function() + { + + this.gameState = consts.GAMESTATES[0]; + + document.getElementById("Timer").value = "Timer Off"; + document.getElementById("Time").value = ""; + document.getElementById("besttime").value = ""; + this.isTimerOn = false; + + this.hintQueue = []; + this.shapeQueue = []; + this.hintMino = 0; + this._restartHandler(); + this.currentOpener = 0; + + }, + // Gamestate 2 + setCurrentOpener(opener) + { + document.getElementById("besttime").value = ""; + + this.gameState = consts.GAMESTATES[1]; + this.currentOpener = opener; + this._restartHandler(); + + }, + // Gamestate 3 + setDoTest: function() + { + + if(this.gameState != consts.GAMESTATES[1]) return; + + // set game state to do test + this.gameState = consts.GAMESTATES[2]; + + this._restartHandler(); + }, + // Gamestate 4 + setGameStateSequenceEditor: function() + { + document.getElementById("side").display = "none"; + + // change to editor gamestate + this.gameState = consts.GAMESTATES[3]; + this.hintQueue = []; + this.shapeQueue = []; + this.hintMino = 0; + this._restartHandler(); + this.currentOpener = 0; + this.pushHoldStack(); + }, + + 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() { + // var setting = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; + // var doKeyToAlpha = inputs.keyboardShiftEvents.included(setting) || inputs.keyboardKeyEvents.included(setting); + + // if(doKeyToAlpha) + // document.getElementById("setting_value").value = inputs.settingsMap.get(setting).fromCharCode(); + // else + // document.getElementById("setting_value").value = inputs.settingsMap.get(setting); + + document.getElementById("setting_value").value = + inputs.settingsMap.get(inputs.settingsList[document.getElementById("settings").selectedIndex-1]); + + + }, + addOpener: function() { + + var newOpener = document.createElement('li'); + //
  • Mr. T-Spin's STD (reversed)
  • + //newOpener.text = "New Sequence"; + //newOpener.id = this.currentMinoInx; + newOpener.style="color:powderblue;text-decoration:underline;font-size:12px;padding-left:1em"; + + + newOpener.appendChild(document.createTextNode("New Sequence: " + this.currentMinoInx)); + document.getElementById("Openers").appendChild(newOpener); + + + + // Print Sequence Data to console + // console.log("this.hintQueue = new Array("); + // this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { console.log("shapes.getShape("+shape.nType()+ ((idx === arr.length-1) ? "));" : "),") ); } ); + + + var shapes = []; + this.shapeQueue.slice().reverse().forEach( function(shape, idx) { shapes.push(shape.x); shapes.push(shape.y); shapes.push(shape.state); } ); + + // console.log("var hintDataList = [" + shapes.join(",") + "];"); + // console.log("this.createHintQueue(hintDataList);"); + + var sequenceCode = []; + + var shapeArrayStr = []; + this.shapeQueue.slice().reverse().forEach( function(shape, idx, arr) { shapeArrayStr += "shapes.getShape("+shape.nType() + ((idx === arr.length-1) ? "));" : "), ") } ); + sequenceCode += "case :\n\tthis.shapeQueue = new Array(" + shapeArrayStr + "\nbreak;" + "\n\n"; + + sequenceCode += "case :\n\tthis.hintQueue = new Array(" + shapeArrayStr; + sequenceCode += "\n\nvar hintDataList = [" + shapes.join(",") + "];" + "\nthis.createHintQueue(hintDataList);" + "\nbreak;"; + + prompt("Generated Code:", sequenceCode); + + + //openers.addSequence(this.shapeQueue); + //this.setFreePlay(); + //this.gameState = consts.GAMESTATES[1]; + this.currentMinoInx = 0; + //this.setCurrentOpener(99999);//this.currentMinoInx); + clearMatrix(this.matrix); + this.currentOpener = 9999; + this.shapeQueue = []; + this.hintQueue = []; + //this._recurseGameState(); + }, + setSettings: function() { + var newVal = document.getElementById("setting_value").value; + var key = inputs.settingsList[document.getElementById("settings").selectedIndex-1]; + utils.setCookie(key, newVal, 30); + inputs.settingsMap.set(key, newVal); + }, + //Reset game + reset: function() { + this.numlefts = 0; + this.running = false; + this.isGameOver = false; + this.level = 1; + this.score = 0; + this.lines = 0; + // beginning of frame + this.startTime = new Date().getTime(); + this.currentTime = this.startTime; + this.prevTime = this.startTime; + this.sequencePrevTime = this.startTime; + //todo:get rid of extra + this.levelTime = this.startTime; + this.prevInputTime = this.startTime; + // current tetrino index gets set to 0 at the end of opener sequence + this.currentMinoInx = 0; + this.shapeQueue = []; + this.hintQueue = []; + this.holdStack = []; + this.shape = shapes.getShape(0); + // gets set to false after mino has been popped from hold stack; set back to true on mino dropped + this.canPopFromHoldStack = false; + // manipulation counter for srs extended piece lockdown + this.manipulationCounter = 0; + // timer for srs extened piece lockdown + this.lockdownTimer = 0; + this.landed = false; + this.isSequenceCompleted = false; + + clearMatrix(this.matrix); + views.setLevel(this.level); + views.setScore(this.score); + views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); + openers.reset(); + shapes.resetMinoRNG(); + + this._draw(); + }, + //Start game + start: function() { + this.running = true; + window.requestAnimationFrame(utils.proxy(this._refresh, this)); + + }, + //Pause game + pause: function() { + this.running = false; + this.currentTime = new Date().getTime(); + this.prevTime = this.currentTime; + }, + pushHoldStack: function() + { + if(this.gameState == consts.GAMESTATES[3]) { + while(this.holdStack.length < 7) + this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); + this.shape = this.holdStack.pop(); + this._draw(); + return; + } + // 1 shape hold queue + if(this.holdStack.length > 0) { + this.canPopFromHoldStack = false; + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = utils.deepClone(this.holdStack.pop()); + this.shape.resetOrigin(); + this._draw(); + }else if(this.holdStack.length < 4) { + this.holdStack.push(utils.deepClone(this.shape)); + this.shape = this.shapeQueue.shift(); + this.canPopFromHoldStack = false; + this.shape.resetOrigin(); + this._draw(); + } + /* 4 shape hold queue + if(this.holdStack.length < 4) { + this.holdStack.push(utils.deepClone(this.shape)); + this.shape = this.shapeQueue.shift(); + this.canPopFromHoldStack = false; + this.shape.resetOrigin(); + this._draw(); + }*/ + }, + popHoldStack: function() + { + if(this.gameState == consts.GAMESTATES[3]) { + if(this.holdStack.length < 7) + while(this.holdStack.length < 7) + this.holdStack.unshift(utils.deepClone(shapes.getShape(this.currentMinoInx++%7))); + // piece needs to be able to be placed + if(this.shape.canDown(this.matrix)) return; + this.shape.copyTo(this.matrix); + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = utils.deepClone(this.holdStack.pop()); + this._check(); + this._draw(); + return; + } + // todo: disable if 1 shape hold queue + if(this.holdStack.length >= 1 && this.canPopFromHoldStack) + { + this.canPopFromHoldStack = false; + this.shapeQueue.unshift(utils.deepClone(this.shape)); + this.shape = this.holdStack.pop(); + this.shape.resetOrigin(); + this._draw(); + } + }, + + // Restart game + _restartHandler: function() { + this.reset(); + this.start(); + //this._fireShape(); + this._recurseGameState(); + }, + // Bind game events + _initEvents: function() { + setInterval(() => {this._processTick();}, 1); + setInterval(() => {this.lockDownTimer++;}, 100 ); + views.btnRestart.addEventListener('click', utils.proxy(this._restartHandler, this), false); + }, + // Process freeplay queue + _processFreeplayQueue: function() { + while(this.shapeQueue.length <= 4) + { + this.preparedShape = shapes.randomShape(); + this.shapeQueue.push(this.preparedShape); + } + + this.shape = this.shapeQueue.shift();// || shapes.randomShape(); + this.currentMinoInx++; + }, + // Process opener trainer queue + _processOpenerTrainerQueue: function() { + while(this.shapeQueue.length <= 4) + { + this.preparedShape = utils.deepClone(openers.getNextMino(this.currentOpener)); + this.shapeQueue.push(this.preparedShape); + } + while(this.hintQueue.length <= 4) + { + this.preparedShape = utils.deepClone(openers.getNextHint(this.currentOpener)); + this.hintQueue.push(this.preparedShape); + } + + this.hintMino = this.hintQueue.shift(); + this.shape = this.shapeQueue.shift(); + + this.currentMinoInx++; + + // Opener sequence completed + if(this.currentMinoInx > openers.getLength()) { + //new Audio("./dist/sound/Affirm2.ogg").play(); + if(this.isTimerOn) { + var besttime = document.getElementById("besttime").value; + var deltaTime = new Date().getTime() - this.sequencePrevTime; + if(besttime == "" || deltaTime/1000.0 < parseFloat(besttime)) { + document.getElementById("besttime").value = (deltaTime/1000.0).toString(); + } + } + + this.hintQueue = []; + this.shapeQueue = []; + + this.isSequenceCompleted = true; + + // Recursion warning + if(this.currentOpener < 1000) // getting real hacky + this._restartHandler(); + else clearMatrix(this.matrix); + // this.reset(); + // this.start(); + return; + } + }, + // Process sequence editor + _processSequenceEditor: function () { + return; + }, + + // Fill next queue and set next shape + _fireShape: function() { + //todo:should be in shapes.js + this.landed = false; + this.manipulationCounter = 0; + + this._draw(); + + }, + _recurseGameState: function (){ + switch(this.gameState) { + case consts.GAMESTATES[0]: + this._processFreeplayQueue(); + this._fireShape(); + break; + case consts.GAMESTATES[1]: + this._processOpenerTrainerQueue(); + this._fireShape(); + break; + case consts.GAMESTATES[2]: + this._processOpenerTrainerQueue(); + this._fireShape(); + case consts.GAMESTATES[3]: + this._processSequenceEditor(); + break; + + default: + break; + } + }, + // 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; + }, + // Draw game data + _draw: function() { + canvas.drawScene(); + canvas.drawShape(this.shape); + canvas.drawHoldShape(this.holdStack); + canvas.drawPreviewShape(this.shapeQueue); + if(this.gameState != consts.GAMESTATES[2]) + canvas.drawHintShape(this.hintMino); + + if(this.shape != undefined) { + let clone = Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape); + + var bottomY = clone.bottomAt(this.matrix); + canvas.drawGhostShape(clone, bottomY); + } + canvas.drawMatrix(this.matrix); + + + }, + + // tick input data -- wont have better than 4-15ms resolution since javascript is single theaded and any ARR or DAS below 15ms will likely be broken + _processTick: async function() { + + + if(this.isTimerOn) { + var deltaPlayTime = new Date().getTime() - this.sequencePrevTime; + document.getElementById("Time").value = (deltaPlayTime/1000).toString(); + + } + + // Don't process game related events if game over + if(this.isGameOver) return; + + + + if(this.gamepadEnabled && inputs.gamepadEnabled()) { + inputs.updateGamepad(); + inputs.processGamepadDPad(); + inputs.processGamepadInput(); + + while((inputs.gamepadQueue != undefined && inputs.gamepadQueue.length >= 1)){ + var curkey = inputs.gamepadQueue.shift(); + if(inputs.settingsMap.get("Gamepad Left").includes(curkey)) { + this.shape.goLeft(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Right").includes(curkey)) { + this.shape.goRight(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Rotateccw").includes(curkey)) { + this.shape.rotate(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Rotate").includes(curkey)) { + this.shape.rotateClockwise(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Down").includes(curkey)) { + this.shape.goDown(this.matrix); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Harddrop").includes(curkey)) { + // if editor + if(this.gameState == consts.GAMESTATES[3]) { + this.popHoldStack(); + this._draw(); + }else { + this.shape.goBottom(this.matrix); + this.lockDownTimer = 5000; + this._update(); + } + } + else if(inputs.settingsMap.get("Gamepad Hold").includes(curkey)) { + this.pushHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Pophold").includes(curkey)) { + this.popHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Gamepad Reset").includes(curkey)) { + this._restartHandler(); + return; + } + } + inputs.saveButtons(); + inputs.gamepadClear(); + } + + + // Do keyboard + inputs.processKeys(); + inputs.processKeyShift(); + // Keyboard inputs + while((inputs.inputQueue != undefined && inputs.inputQueue.length >= 1)){ + var curkey = inputs.inputQueue.shift(); + if(inputs.settingsMap.get("Keyboard Left").includes(curkey)) { + this.shape.goLeft(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Right").includes(curkey)) { + this.shape.goRight(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Down").includes(curkey)) { + + this.shape.goDown(this.matrix); + this._draw(); + } + else if(this.gameState == consts.GAMESTATES[3] && inputs.settingsMap.get("Keyboard Up").includes(curkey)) { + + this.shape.goUp(this.matrix); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Rotateccw").includes(curkey)) { + this.shape.rotate(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Rotate").includes(curkey)) { + this.shape.rotateClockwise(this.matrix); + this.resetLockdown(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Harddrop").includes(curkey)) { + // if editor + if(this.gameState == consts.GAMESTATES[3]) { + this.popHoldStack(); + this._draw(); + }else { + this.shape.goBottom(this.matrix); + this.lockDownTimer = 5000; + this._update(); + } + } + else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { + this.pushHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Pophold").includes(curkey)) { + this.popHoldStack(); + this._draw(); + } + else if(inputs.settingsMap.get("Keyboard Hold").includes(curkey)) { + if(document.getElementById("divbg").style.display == "none") + document.getElementById("divbg").style.display = "initial"; + else + document.getElementById("divbg").style.display="none"; + } + if(inputs.settingsMap.get("Keyboard Reset").includes(curkey)) { + this._restartHandler(); + return; + } + + } + inputs.inputQueue = []; + + + inputs.saveKeyboardKeys(); + + inputs.saveButtons(); + }, + // Refresh game canvas + _refresh: function() { + if (!this.running) + return; + + this.currentTime = new Date().getTime(); + var deltaLevelTime = this.currentTime - this.prevTime; + if (deltaLevelTime > this.interval) { // every .6 seconds? + this._update(); + this._checkLevel(this.prevTime = this.currentTime); + } + + // Draw Frame + if (!this.isGameOver) { + window.requestAnimationFrame(utils.proxy(this._refresh, this)); + } + }, + // check if the current piece is in the same location as the hint piece + _checkHint: function() { + + if(this.gameState == consts.GAMESTATES[0]) + return; + + if(!this.shape.isSameSRS(this.hintMino)) + { + //new Audio('./dist/Failed.ogg').play(); + this._restartHandler(); + // Restart + return 1; + } + }, + // Update game data + _update: function() { + + switch(this.gameState) { + case consts.GAMESTATES[0]: + case consts.GAMESTATES[1]: + case consts.GAMESTATES[2]: + if(this.shape == undefined) break; + if (this.shape.canDown(this.matrix)) { + this.shape.goDown(this.matrix); + } else if(this.isPieceLocked()){ + this.canPopFromHoldStack = true; + this.shape.copyTo(this.matrix); + this._check(); + if(this._checkHint()) return; + //this._fireShape(); + this._recurseGameState(); + new Audio('./dist/sound/Blop2.ogg').play(); + } + this._draw(); + this.isGameOver = checkGameOver(this.matrix); + + // if game over and gamestate is free play + views.setGameOver(this.gameState == consts.GAMESTATES[0] && this.isGameOver); + + if (this.isGameOver) + views.setFinalScore(this.score); + break; + case consts.GAMESTATES[3]: + break; + default: + break; + } + + }, + // 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[side4Y] != undefined && matrix[side3Y] != undefined) { + if(matrix[side1Y][side1X] != 0) + side1 = 1; + if(matrix[side2Y][side2X] != 0) + side2 = 1; + // TODO: figure out why this occasionally is undefined + 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; + }, + // Check and update game data + _check: function() { + var rows = checkFullRows(this.matrix); + if (rows.length) { + var tspinType; + + if(this.shape.flag === 'T') + tspinType = this._tSpinType(this.shape, this.matrix); + + removeRows(this.matrix, rows); + + console.log("type: " + tspinType); + var score = calcScore(rows); + var reward = calcRewards(rows, tspinType); + this.score += score + reward; + this.lines += rows.length; + + views.setScore(this.score); + views.setReward(reward); + views.setLines(this.lines); + + } + }, + // 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; // export {Tetris}; \ No newline at end of file diff --git a/src/openers.js b/src/openers.js index a1f3074..683d3af 100644 --- a/src/openers.js +++ b/src/openers.js @@ -1,637 +1,636 @@ -var shapes = require("./shapes.js"); -var utils = require("./utils.js"); -// import * as shapes from './shapes.js'; - -// https://harddrop.com/wiki/Opener -// https://four.lol/ -var openerGenerator = { - shapeQueue: [], - hintQueue: [], - idx: 0, - hintIdx: 0, - isInit: 0, - isHintInit: 0, - customShapeQueue: [], - customHintQueue: [], - // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 - // Current Tetriminos - init(opener) { - 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 - 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; - case 3: - this.shapeQueue = new Array( - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(3)); - break; - case 4: - //Pokemino's STD - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(3)); - break; - case 5: - // Mr TSpins STD reversed - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - break; - case 6: - // Hachispin - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(3)); - break; - case 7: - // Albatross - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(3)); - break; - case 8: - // Number One - this.shapeQueue = new Array( - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3)); - break; - case 9: - // Pelican - this.shapeQueue = new Array( - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(3)); - break; - case 10: - // DT Cannon TSZ base - this.shapeQueue = new Array( - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - break; - case 11: - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(1), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6)); - break; - case 12: - this.shapeQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3)); - break; - case 13: - this.shapeQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); - break; - - default: - this.shapeQueue.unshift(utils.deepClone(shapes.randomShape())); - return; - } - } - this.isInit = 1; - - return; - }, - - getNextMino(opener) { - if(this.customShapeQueue.length > 0) return this.customShapeQueue[this.idx++%this.customShapeQueue.length]; - this.init(opener); - var mino = this.shapeQueue[this.idx]; - this.idx++; - if(this.idx >= this.shapeQueue.length) { - this.idx = 0; - if(opener < 1000) - this.isInit = 0; - else this.isInit = 1; - } - - return mino; - }, - - createHintQueue(hintDataList) { - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - }, - // Hint Tetrimions - initHint(opener) { - if(!this.isHintInit || this.hintQueue == undefined) { - - switch(opener) { - case 0: - this.hintQueue = []; - break; - 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)); - - // position x, position y, orientation, position x,... - var hintDataList = [-1,17,1, 3,18,0, 6,18,0, 5,17,1, 3,17,0, 7,16,0, 1,17,2]; - - this.createHintQueue(hintDataList); - - break; - case 2: - // DT Cannon - 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)); - - // position x, position y, orientation, position x,... - var hintDataList = [-2,18,0, 4,16,1, 6,17,1, 7,17,1, 4,17,-1, 3,17,3, 3,15,0, 5,15,0, 7,14,1, 2,13,-1, -1,15,1, 1,16,2, 3,16,1, 1,17,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 3: - //MKO Stacking - this.hintQueue = new Array( - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(3)); - - // position x, position y, orientation, position x,... - var hintDataList = [0,18,0, 0,16,-1, 8,16,-1, 4,18,0, 4,16,1, 5,18,0, 1,15,-1, 2,17,2, 5,18,0, 3,17,1, 6,16,0, 0,15,2, 0,14,0, 2,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 4: - //Pokemino's STD - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(3)); - - var hintDataList = [0,17,1, -2,16,1, 4,18,0, 4,17,-1, 3,15,1, 8,17,-1, 2,17,2, 0,17,0, 0,15,-1, - 1,15,0, 8,16,-2, 5,15,-1, 3,14,1, 6,12,-1, 6,16,1, 2,16,-1, 7,17,2 ]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 5: - // Mr TSpins STD reversed - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - - var hintDataList = [4,18,0, 0,18,0, 7,17,1, 0,15,1, 4,17,-1, 5,14,-1, 2,17,2, 1,17,0, -1,16,-1, 2,15,-1, - 0,14,0, 3,15,1, 8,16,-1, 5,13,2, 6,16,1, 7,17,2 ]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - - break; - case 6: - // Hachispin - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(0), - shapes.getShape(3)); - - var hintDataList = [1,18,0, 0,18,0, 8,16,-1, 2,15,1, 6,17,2, 5,16,2, 1,16,2, -1,16,-1, -1,16,0, 5,16,0, 0,14,0, 3,15,0, 8,14,-1, 7,16,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 7: - // Albatross - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(2), - shapes.getShape(3)); - - var hintDataList = [1,18,0, 0,17,-1, 8,16,-1, 5,17,2, 6,16,2, 3,16,0, 1,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 8: - // Number One - this.hintQueue = new Array( - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(5), - shapes.getShape(3)); - - var hintDataList = [3,18,0, 0,17,2, 0,16,0, 4,15,-1, 6,17,0, 8,16,-1, 3,17,-1]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 9: - // Pelican - this.hintQueue = new Array( - shapes.getShape(5), - shapes.getShape(2), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6), - shapes.getShape(1), - shapes.getShape(3)); - - var hintDataList = [0,17,-1, 1,16,2, 5,18,0, 5,16,-1, 8,16,-1, 5,17,0, 3,16,2]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 10: // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 - // DT Cannon TSZ base - this.hintQueue = new Array( - shapes.getShape(3), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(6), - shapes.getShape(5), - shapes.getShape(0), - shapes.getShape(4), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(3), - shapes.getShape(3)); - - var hintDataList = [4,18,0, -2,18,0, 2,17,1, 8,16,-1, 6,17,-1, 7,17,-1, 3,15,2, -1,15,1, 2,13,-1, 1,16,2, 1,17,3]; - - for(var i = 0; i < this.hintQueue.length; i++) { - this.hintQueue[i].x = hintDataList[i * 3]; - this.hintQueue[i].y = hintDataList[i * 3 + 1]; - this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); - } - break; - case 11: - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(6), - shapes.getShape(3), - shapes.getShape(0), - shapes.getShape(2), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(5), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(1), - shapes.getShape(3), - shapes.getShape(4), - shapes.getShape(0), - shapes.getShape(6)); - var hintDataList = [3,17,1,6,18,0,1,17,3,5,17,3,2,16,3,-1,17,1,4,15,0,5,13,1,3,14,0,-1,14,3,8,15,3,-1,15,0,0,13,0,6,16,2,0,13,2,4,14,0,2,13,3,6,17,1,7,18,0,3,16,1,7,17,2,6,18,0,1,18,0,-1,17,1,2,16,2,5,17,0,0,15,2,3,15,2,6,15,2,8,16,3]; - this.createHintQueue(hintDataList); - break - case 12: - this.hintQueue = new Array( - shapes.getShape(0), - shapes.getShape(1), - shapes.getShape(2), - shapes.getShape(3)); - var hintDataList = [3,17,1,6,18,0,5,17,2,1,18,0]; - this.createHintQueue(hintDataList); - break; - case 13: - this.hintQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); - - var hintDataList = [0,18,0,3,18,0,-1,17,0,7,18,0,3,17,0,8,16,3,0,15,2,-2,14,0,3,15,2,3,14,0,1,13,3,8,14,3,7,12,2,5,16,2,3,14,3,6,17,3,5,18,0]; - this.createHintQueue(hintDataList); - break; - default: - this.hintQueue.unshift(utils.deepClone(shapes.randomShape())); - return; - } - - } - - this.isHintInit = 1; - - return; - }, - // End initHint - - getNextHint(opener) { - if(this.customHintQueue.length > 0) return this.customHintQueue[this.hintIdx++%this.customHintQueue.length]; - this.initHint(opener); - var mino = this.hintQueue[this.hintIdx]; - this.hintIdx++; - if(this.hintIdx >= this.hintQueue.length) { - this.hintIdx = 0; - if(opener < 1000) - this.isHintInit = 0; - else this.isHintInit = 1; - } - return mino; - }, - - reset() { - this.shapeQueue = []; - this.hintQueue = []; - this.idx = 0; - this.hintIdx = 0; - this.isInit = 0; - this.isHintInit = 0; - }, - getLength() { - return this.customHintQueue.length || this.hintQueue.length; - }, - addSequence(sequence) { - //this.reset(); - //this.shapeQueue = utils.deepClone(sequence); - //this.hintQueue = utils.deepClone(sequence); - for(var i in sequence) - { - var shape; - shape = sequence[i]; - shape.x = sequence[i].x; - shape.y = sequence[i].y; - shape.state = sequence[i].state; - this.customHintQueue.unshift(utils.deepClone(shape)); - shape.x = shape.originX; - shape.y = shape.originY; - this.customShapeQueue.unshift(utils.deepClone(shape)); - this.isInit = 1; - this.isHintInit = 1; - this.idx = 0; - this.hintIdx = 0; - } - } -}; - -function reset() { - openerGenerator.reset(); -} - -function getNextMino(opener) { - var mino = openerGenerator.getNextMino(opener); - return mino; -} -function getNextHint(opener) { - var mino = openerGenerator.getNextHint(opener); - return mino; -} -function getLength() { - return openerGenerator.getLength(); -} - -function addSequence(sequence) { - openerGenerator.addSequence(sequence); -} - -module.exports.addSequence = addSequence; -module.exports.getNextMino = getNextMino; -module.exports.getNextHint = getNextHint; -module.exports.getLength = getLength; -module.exports.reset = reset; -// export getNextMino; -// export getNextHint; -// export getLength; -// export reset; - - +var shapes = require("./shapes.js"); +var utils = require("./utils.js"); +// import * as shapes from './shapes.js'; + +// https://harddrop.com/wiki/Opener +// https://four.lol/ +var openerGenerator = { + shapeQueue: [], + hintQueue: [], + idx: 0, + hintIdx: 0, + isInit: 0, + isHintInit: 0, + customShapeQueue: [], + customHintQueue: [], + // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 + // Current Tetriminos + init(opener) { + 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 + 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; + case 3: + this.shapeQueue = new Array( + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(3)); + break; + case 4: + //Pokemino's STD + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(3)); + break; + case 5: + // Mr TSpins STD reversed + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + break; + case 6: + // Hachispin + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(3)); + break; + case 7: // Albatross + this.shapeQueue = new Array(shapes.getShape(1), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(4), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(1), shapes.getShape(6), shapes.getShape(0), shapes.getShape(2), shapes.getShape(3)); + break; + case 8: + // Number One + this.shapeQueue = new Array( + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3)); + break; + case 9: + // Pelican + this.shapeQueue = new Array( + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(3)); + break; + case 10: + // DT Cannon TSZ base + this.shapeQueue = new Array( + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + break; + case 11: + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(1), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6)); + break; + case 12: + this.shapeQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3)); + break; + case 13: + this.shapeQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); + break; + case 14: + this.shapeQueue = new Array(shapes.getShape(0), shapes.getShape(6), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(0), shapes.getShape(4), shapes.getShape(6), shapes.getShape(0), shapes.getShape(0), shapes.getShape(3), shapes.getShape(5)); + break; + case 15: + this.shapeQueue = new Array(shapes.getShape(0), shapes.getShape(2), shapes.getShape(5), shapes.getShape(6), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(2), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(6), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3)); + break; + + + + default: + this.shapeQueue.unshift(utils.deepClone(shapes.randomShape())); + return; + } + } + this.isInit = 1; + + return; + }, + + getNextMino(opener) { + if(this.customShapeQueue.length > 0) return this.customShapeQueue[this.idx++%this.customShapeQueue.length]; + this.init(opener); + var mino = this.shapeQueue[this.idx]; + this.idx++; + if(this.idx >= this.shapeQueue.length) { + this.idx = 0; + if(opener < 1000) + this.isInit = 0; + else this.isInit = 1; + } + + return mino; + }, + + createHintQueue(hintDataList) { + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + }, + // Hint Tetrimions + initHint(opener) { + if(!this.isHintInit || this.hintQueue == undefined) { + + switch(opener) { + case 0: + this.hintQueue = []; + break; + 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)); + + // position x, position y, orientation, position x,... + var hintDataList = [-1,17,1, 3,18,0, 6,18,0, 5,17,1, 3,17,0, 7,16,0, 1,17,2]; + + this.createHintQueue(hintDataList); + + break; + case 2: + // DT Cannon + 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)); + + // position x, position y, orientation, position x,... + var hintDataList = [-2,18,0, 4,16,1, 6,17,1, 7,17,1, 4,17,-1, 3,17,3, 3,15,0, 5,15,0, 7,14,1, 2,13,-1, -1,15,1, 1,16,2, 3,16,1, 1,17,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 3: + //MKO Stacking + this.hintQueue = new Array( + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(3)); + + // position x, position y, orientation, position x,... + var hintDataList = [0,18,0, 0,16,-1, 8,16,-1, 4,18,0, 4,16,1, 5,18,0, 1,15,-1, 2,17,2, 5,18,0, 3,17,1, 6,16,0, 0,15,2, 0,14,0, 2,16,2]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 4: + //Pokemino's STD + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(3)); + + var hintDataList = [0,17,1, -2,16,1, 4,18,0, 4,17,-1, 3,15,1, 8,17,-1, 2,17,2, 0,17,0, 0,15,-1, + 1,15,0, 8,16,-2, 5,15,-1, 3,14,1, 6,12,-1, 6,16,1, 2,16,-1, 7,17,2 ]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 5: + // Mr TSpins STD reversed + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + + var hintDataList = [4,18,0, 0,18,0, 7,17,1, 0,15,1, 4,17,-1, 5,14,-1, 2,17,2, 1,17,0, -1,16,-1, 2,15,-1, + 0,14,0, 3,15,1, 8,16,-1, 5,13,2, 6,16,1, 7,17,2 ]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + + break; + case 6: + // Hachispin + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(5), + shapes.getShape(4), + shapes.getShape(2), + shapes.getShape(0), + shapes.getShape(3)); + + var hintDataList = [1,18,0, 0,18,0, 8,16,-1, 2,15,1, 6,17,2, 5,16,2, 1,16,2, -1,16,-1, -1,16,0, 5,16,0, 0,14,0, 3,15,0, 8,14,-1, 7,16,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 7: // Albatross + this.hintQueue = new Array(shapes.getShape(1), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(4), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(1), shapes.getShape(6), shapes.getShape(0), shapes.getShape(2), shapes.getShape(3)); + + var hintDataList = [1,18,0,0,17,3,8,16,3,5,17,2,6,16,2,3,16,0,1,16,2,-1,17,1,5,17,3,5,18,0,6,16,0,2,15,3,3,15,1,1,17,3]; + this.createHintQueue(hintDataList); + break; + case 8: + // Number One + this.hintQueue = new Array( + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(5), + shapes.getShape(3)); + + var hintDataList = [3,18,0, 0,17,2, 0,16,0, 4,15,-1, 6,17,0, 8,16,-1, 3,17,-1]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 9: + // Pelican + this.hintQueue = new Array( + shapes.getShape(5), + shapes.getShape(2), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6), + shapes.getShape(1), + shapes.getShape(3)); + + var hintDataList = [0,17,-1, 1,16,2, 5,18,0, 5,16,-1, 8,16,-1, 5,17,0, 3,16,2]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 10: // O - 1, I - 6, L - 0, S - 5, J - 4, Z - 2, T - 3 + // DT Cannon TSZ base + this.hintQueue = new Array( + shapes.getShape(3), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(6), + shapes.getShape(5), + shapes.getShape(0), + shapes.getShape(4), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(3), + shapes.getShape(3)); + + var hintDataList = [4,18,0, -2,18,0, 2,17,1, 8,16,-1, 6,17,-1, 7,17,-1, 3,15,2, -1,15,1, 2,13,-1, 1,16,2, 1,17,3]; + + for(var i = 0; i < this.hintQueue.length; i++) { + this.hintQueue[i].x = hintDataList[i * 3]; + this.hintQueue[i].y = hintDataList[i * 3 + 1]; + this.hintQueue[i].state = this.hintQueue[i].nextState(hintDataList[i * 3 + 2]); + } + break; + case 11: + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(6), + shapes.getShape(3), + shapes.getShape(0), + shapes.getShape(2), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(5), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(1), + shapes.getShape(3), + shapes.getShape(4), + shapes.getShape(0), + shapes.getShape(6)); + var hintDataList = [3,17,1,6,18,0,1,17,3,5,17,3,2,16,3,-1,17,1,4,15,0,5,13,1,3,14,0,-1,14,3,8,15,3,-1,15,0,0,13,0,6,16,2,0,13,2,4,14,0,2,13,3,6,17,1,7,18,0,3,16,1,7,17,2,6,18,0,1,18,0,-1,17,1,2,16,2,5,17,0,0,15,2,3,15,2,6,15,2,8,16,3]; + this.createHintQueue(hintDataList); + break + case 12: + this.hintQueue = new Array( + shapes.getShape(0), + shapes.getShape(1), + shapes.getShape(2), + shapes.getShape(3)); + var hintDataList = [3,17,1,6,18,0,5,17,2,1,18,0]; + this.createHintQueue(hintDataList); + break; + case 13: + this.hintQueue = new Array(shapes.getShape(4), shapes.getShape(6), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(0), shapes.getShape(6), shapes.getShape(0), shapes.getShape(5), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4)); + + var hintDataList = [0,18,0,3,18,0,-1,17,0,7,18,0,3,17,0,8,16,3,0,15,2,-2,14,0,3,15,2,3,14,0,1,13,3,8,14,3,7,12,2,5,16,2,3,14,3,6,17,3,5,18,0]; + this.createHintQueue(hintDataList); + break; + case 14: + this.hintQueue = new Array(shapes.getShape(0), shapes.getShape(6), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(0), shapes.getShape(4), shapes.getShape(6), shapes.getShape(0), shapes.getShape(0), shapes.getShape(3), shapes.getShape(5)); + + var hintDataList = [-1,17,1,3,18,0,3,17,0,7,18,0,6,16,3,8,16,3,0,16,3,0,14,0,8,13,3,4,15,1,6,14,2,1,17,1,2,17,2]; + this.createHintQueue(hintDataList); + break; + case 15: + this.hintQueue = new Array(shapes.getShape(0), shapes.getShape(2), shapes.getShape(5), shapes.getShape(6), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(2), shapes.getShape(5), shapes.getShape(0), shapes.getShape(1), shapes.getShape(6), shapes.getShape(4), shapes.getShape(3), shapes.getShape(4), shapes.getShape(5), shapes.getShape(6), shapes.getShape(0), shapes.getShape(1), shapes.getShape(2), shapes.getShape(3), shapes.getShape(4), shapes.getShape(1), shapes.getShape(3), shapes.getShape(4), shapes.getShape(3)); + + var hintDataList = [-1,17,1,2,18,0,4,17,3,6,18,0,6,17,0,2,15,2,-1,14,1,5,17,0,4,14,3,5,14,3,6,15,0,6,14,3,8,12,3,0,16,1,6,15,0,0,15,0,-1,12,3,6,13,1,2,15,0,3,13,0,1,17,2,5,14,1,6,15,0,2,17,3,3,15,2,1,17,2]; + this.createHintQueue(hintDataList); + break; + default: + this.hintQueue.unshift(utils.deepClone(shapes.randomShape())); + return; + } + + } + + this.isHintInit = 1; + + return; + }, + // End initHint + + getNextHint(opener) { + if(this.customHintQueue.length > 0) return this.customHintQueue[this.hintIdx++%this.customHintQueue.length]; + this.initHint(opener); + var mino = this.hintQueue[this.hintIdx]; + this.hintIdx++; + if(this.hintIdx >= this.hintQueue.length) { + this.hintIdx = 0; + if(opener < 1000) + this.isHintInit = 0; + else this.isHintInit = 1; + } + return mino; + }, + + reset() { + this.shapeQueue = []; + this.hintQueue = []; + this.idx = 0; + this.hintIdx = 0; + this.isInit = 0; + this.isHintInit = 0; + }, + getLength() { + return this.customHintQueue.length || this.hintQueue.length; + }, + addSequence(sequence) { + //this.reset(); + //this.shapeQueue = utils.deepClone(sequence); + //this.hintQueue = utils.deepClone(sequence); + for(var i in sequence) + { + var shape; + shape = sequence[i]; + shape.x = sequence[i].x; + shape.y = sequence[i].y; + shape.state = sequence[i].state; + this.customHintQueue.unshift(utils.deepClone(shape)); + shape.x = shape.originX; + shape.y = shape.originY; + this.customShapeQueue.unshift(utils.deepClone(shape)); + this.isInit = 1; + this.isHintInit = 1; + this.idx = 0; + this.hintIdx = 0; + } + } +}; + +function reset() { + openerGenerator.reset(); +} + +function getNextMino(opener) { + var mino = openerGenerator.getNextMino(opener); + return mino; +} +function getNextHint(opener) { + var mino = openerGenerator.getNextHint(opener); + return mino; +} +function getLength() { + return openerGenerator.getLength(); +} + +function addSequence(sequence) { + openerGenerator.addSequence(sequence); +} + +module.exports.addSequence = addSequence; +module.exports.getNextMino = getNextMino; +module.exports.getNextHint = getNextHint; +module.exports.getLength = getLength; +module.exports.reset = reset; +// export getNextMino; +// export getNextHint; +// export getLength; +// export reset; + + diff --git a/src/sequence.js b/src/sequence.js index fae5c98..7fb59f9 100644 --- a/src/sequence.js +++ b/src/sequence.js @@ -1,71 +1,71 @@ -var consts = require('./consts.ds'); -var utils = require('./utils.js'); -var utils. = requre('./shapes.js'); - - -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; -}; - - -var sequence = { - this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); - this.minoList = []; - this.currentMino = []; - - addMino: function(mino) { - this.minoList.push (mino) - this.updateMatrix(); - }, - //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; - } - } - } - } - }, - - -}; - -/* -var sequences = { - this.sequenceList = []; - this.currentMino = []; - - init(setSequenceList){ - this.sequnceList = setSequenceList; - }, - addNewSequence: function(newsequence) { - this.sequenceList.push(newsequence); - }, - addMinoToCurrentSequence: function(mino) { - this.currentSequnce.addMino(mino); - }, - reset: function() { - sequenceList = []; - } -}; -*/ - -function getNextMino() { - currentSequence.popMino(); +var consts = require('./consts.ds'); +var utils = require('./utils.js'); +var utils. = requre('./shapes.js'); + + +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; +}; + + +var sequence = { + this.matrix = initMatrix(consts.ROW_COUNT, consts.COLUMN_COUNT); + this.minoList = []; + this.currentMino = []; + + addMino: function(mino) { + this.minoList.push (mino) + this.updateMatrix(); + }, + //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; + } + } + } + } + }, + + +}; + +/* +var sequences = { + this.sequenceList = []; + this.currentMino = []; + + init(setSequenceList){ + this.sequnceList = setSequenceList; + }, + addNewSequence: function(newsequence) { + this.sequenceList.push(newsequence); + }, + addMinoToCurrentSequence: function(mino) { + this.currentSequnce.addMino(mino); + }, + reset: function() { + sequenceList = []; + } +}; +*/ + +function getNextMino() { + currentSequence.popMino(); }; \ No newline at end of file diff --git a/startserver.sh.bat b/startserver.sh.bat index 846e510..5bc163b 100644 --- a/startserver.sh.bat +++ b/startserver.sh.bat @@ -1 +1 @@ -python3 -m http.server +python3 -m http.server