diff --git a/README.md b/README.md index c9da637bc..76d40fae0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ +CPEN 321 L1A Group Members: + +Team 06 + +1. Bo Hu +2. Xin Wei (Patrick) Tee +3. William (Will) Tang + + +Original Project Infomration: + Hextris ========== @@ -7,19 +18,6 @@ Contributors: - Noah Moroze (@nmoroze) - Michael Yang (@themichaelyang) -#Conribtions -Please submit pull requests to clay-improvements - -# Releases -#### iOS: https://itunes.apple.com/us/app/hextris/id903769553?mt=8 -![](http://i.imgur.com/KBYZcf5.png) - -#### Android: https://play.google.com/store/apps/details?id=com.hextris.hextris -![](http://i.imgur.com/mxj8yKs.png) - -#### Firefox OS: https://marketplace.firefox.com/app/hextris-app -![](http://i.imgur.com/RhECXPg.png) - ## Press kit http://hextris.github.io/presskit/info.html diff --git a/docs/scenarios.txt b/docs/scenarios.txt new file mode 100644 index 000000000..7d4f84575 --- /dev/null +++ b/docs/scenarios.txt @@ -0,0 +1,107 @@ +Github issue: +Please allow for a more gradual increase of speed +#129 opened on Mar 3, 2015 by EricViala + +1. User Story: +As a player +I want to have the ability to speed up or slow down the game +So that I am able to adjust the game for my skill level + +Acceptance Criteria: + +Scenario 1.1: Game is currently at 40% of its original speed or higher +Given that the game has started + And the player is currently playing the game + And the game is at 40% of its original playing speed or higher +When the player presses the "Down" arrow key +Then the speed of the dropping blocks will be slowed down by 10% + And the rate of generation of blocks will be slowed down by 10% + And the game continues. + +Scenario 1.2: Game is currently at 30% of its original speed (game is very slow) +Given that the game has started + And the player is currently playing the game + And the game is at 30% of its original playing speed +When the player presses the "Down" arrow key +Then the speed of the dropping blocks will remain the same + And the rate of generation of blocks blocks will remain the same + And the game continues. + +Scenario 1.3: Game is currently at 170% of its original speed or lower +Given that the game has started + And the player is currently playing the game + And the game is at 170% of its original playing speed or lower +When the player presses the "UP" arrow key +Then the speed of the dropping blocks will be sped up by 10% + And the rate of generation of blocks will be sped up by 10% + And the game continues. + +Scenario 1.4: Game is currently at 180% of its original speed (game is very fast) +Given that the game has started + And the player is currently playing the game + And the game is at 180% of its original playing speed +When the player presses the "UP" arrow key +Then the speed of the dropping blocks will remain the same + And the rate of generation of blocks will remain the same + And the game continues. + + +===================================================== +Github issue: +Alternate color combination to Red/Green, Color blind people may face issue. enhancement +#74 opened on Aug 17, 2014 by tripples + +2. User Story: +As a colourblind player +I want to have the ability change the appearence of the colours of the block +So that I am able to distinguish the blocks from each other + +Scenario 2.1: User Press Colourblind Toggle Button when in the default colour +Given that the game has started + And the player is currently playing the game +When the player presses the "T" key +Then the colour of the blocks will change to another colour that is friendly for the colourblind + And the game continues. + +Scenario 2.2: User Press Colourblind Toggle Button when in a colourblind mode +Given that the game has started + And the player is currently playing the game + And the blocks are currently in a colourblind colour +When the player presses the "T" key +Then the colour of the blocks will change to anothe set of colours that is friendly for the colourblind, + if the player has not cycled through all the colourblind colours yet, otherwise the colour of the blocks + will revert back to the default colour. + And the game continues. + +===================================================== +Additional Feature: +Block falls immediately onto center hex upon keypress + +3. User Story: +As a player +I want to be able to drop the closest falling block immediately onto the side of the center hex I have rotated to immediately +So that I am able to play the game at a faster pace + +Scenario 3.1: User presses Drop Block Toggle Button when a single block is falling +Given that the game has started + And the player is currently playing the game + And a single-block is currently falling +When the player presses the "space" key +Then the currently falling single-block will fall instantly onto the side of the center hex the player has rotated to + And the game continues. + +Scenario 3.2: User presses Drop Block Toggle Button when a doubly-joint block is falling +Given that the game has started + And the player is currently playing the game + And a doubly-joint block is currently falling +When the player presses the "space" key +Then the whole joint block will fall instantly onto the side of the center hex the player has rotated to as a single piece + And the game continues. + +Scenario 3.3: User presses Drop Block Toggle Button when multiple blocks are falling on the screen +Given taht the game has started + And the player is currently playing the game + And there are 2 blocks both falling onto the center hex on the same lane +Whe the player presses the "space" key +Then only the block closest to the center hex falls instantly while the other falling block remains falling at its original speed + And the game continues. diff --git a/index.html b/index.html index a8287cc56..0d1966ad7 100644 --- a/index.html +++ b/index.html @@ -54,7 +54,7 @@ - + diff --git a/js/Block_test.js b/js/Block_test.js new file mode 100644 index 000000000..0efc23e78 --- /dev/null +++ b/js/Block_test.js @@ -0,0 +1,214 @@ +function Block(fallingLane, color, iter, distFromHex, settled) { + settings = { + os: "other", + platform: "nonmobile", + baseScale: 1, + startDist: 340, + creationDt: 9, + scale: 1, + prevScale: 1, + hexWidth: 65, + baseHexWidth: 87, + baseBlockHeight: 20, + blockHeight: 15, + rows: 8, + speedModifier: 0.65, + creationSpeedModifier: 0.65, + comboTime: 310 + }; + // whether or not a block is rested on the center hex or another block + this.settled = (settled === undefined) ? 0 : 1; + this.height = settings.blockHeight; + //the lane which the block was shot from + this.fallingLane = fallingLane; + + this.checked=0; + //the angle at which the block falls + this.angle = 90 - (30 + 60 * fallingLane); + //for calculating the rotation of blocks attached to the center hex + this.angularVelocity = 0; + this.targetAngle = this.angle; + this.color = color; + //blocks that are slated to be deleted after a valid score has happened + this.deleted = 0; + //blocks slated to be removed from falling and added to the hex + this.removed = 0; + //value for the opacity of the white blcok drawn over falling block to give it the glow as it attaches to the hex + this.tint = 0; + //value used for deletion animation + this.opacity = 1; + //boolean for when the block is expanding + this.initializing = 1; + //speed of block + this.iter = iter; + //number of iterations before starting to drop + this.initLen = settings.creationDt; + //side which block is attached too + this.attachedLane = 0; + //distance from center hex + this.distFromHex = distFromHex || settings.startDist * settings.scale ; + + this.incrementOpacity = function() { + if (this.deleted) { + //add shakes + if (this.opacity >= 0.925) { + var tLane = this.attachedLane - MainHex.position; + tLane = MainHex.sides - tLane; + while (tLane < 0) { + tLane += MainHex.sides; + } + + tLane %= MainHex.sides; + MainHex.shakes.push({lane:tLane, magnitude:3 * (window.devicePixelRatio ? window.devicePixelRatio : 1) * (settings.scale)}); + } + //fade out the opacity + this.opacity = this.opacity - 0.075 * MainHex.dt; + if (this.opacity <= 0) { + //slate for final deletion + this.opacity = 0; + this.deleted = 2; + if (gameState == 1 || gameState==0) { + localStorage.setItem("saveState", exportSaveState()); + } + } + } + }; + + this.getIndex = function (){ + //get the index of the block in its stack + var parentArr = MainHex.blocks[this.attachedLane]; + for (var i = 0; i < parentArr.length; i++) { + if (parentArr[i] == this) { + return i; + } + } + }; + + this.draw = function(attached, index) { + this.height = settings.blockHeight; + if (Math.abs(settings.scale - settings.prevScale) > 0.000000001) { + this.distFromHex *= (settings.scale/settings.prevScale); + } + + this.incrementOpacity(); + if(attached === undefined) + attached = false; + + if(this.angle > this.targetAngle) { + this.angularVelocity -= angularVelocityConst * MainHex.dt; + } + else if(this.angle < this.targetAngle) { + this.angularVelocity += angularVelocityConst * MainHex.dt; + } + + if (Math.abs(this.angle - this.targetAngle + this.angularVelocity) <= Math.abs(this.angularVelocity)) { //do better soon + this.angle = this.targetAngle; + this.angularVelocity = 0; + } + else { + this.angle += this.angularVelocity; + } + + this.width = 2 * this.distFromHex / Math.sqrt(3); + this.widthWide = 2 * (this.distFromHex + this.height) / Math.sqrt(3); + //this.widthWide = this.width + this.height + 3; + var p1; + var p2; + var p3; + var p4; + if (this.initializing) { + var rat = ((MainHex.ct - this.ict)/this.initLen); + if (rat > 1) { + rat = 1; + } + p1 = rotatePoint((-this.width / 2) * rat, this.height / 2, this.angle); + p2 = rotatePoint((this.width / 2) * rat, this.height / 2, this.angle); + p3 = rotatePoint((this.widthWide / 2) * rat, -this.height / 2, this.angle); + p4 = rotatePoint((-this.widthWide / 2) * rat, -this.height / 2, this.angle); + if ((MainHex.ct - this.ict) >= this.initLen) { + this.initializing = 0; + } + } else { + p1 = rotatePoint(-this.width / 2, this.height / 2, this.angle); + p2 = rotatePoint(this.width / 2, this.height / 2, this.angle); + p3 = rotatePoint(this.widthWide / 2, -this.height / 2, this.angle); + p4 = rotatePoint(-this.widthWide / 2, -this.height / 2, this.angle); + } + + if (this.deleted) { + ctx.fillStyle = "#FFF"; + } else if (gameState === 0) { + if (this.color.charAt(0) == 'r') { + ctx.fillStyle = rgbColorsToTintedColors[this.color]; + } + else { + ctx.fillStyle = hexColorsToTintedColors[this.color]; + } + } + else { + ctx.fillStyle = this.color; + } + + ctx.globalAlpha = this.opacity; + var baseX = trueCanvas.width / 2 + Math.sin((this.angle) * (Math.PI / 180)) * (this.distFromHex + this.height / 2) + gdx; + var baseY = trueCanvas.height / 2 - Math.cos((this.angle) * (Math.PI / 180)) * (this.distFromHex + this.height / 2) + gdy; + ctx.beginPath(); + ctx.moveTo(baseX + p1.x, baseY + p1.y); + ctx.lineTo(baseX + p2.x, baseY + p2.y); + ctx.lineTo(baseX + p3.x, baseY + p3.y); + ctx.lineTo(baseX + p4.x, baseY + p4.y); + //ctx.lineTo(baseX + p1.x, baseY + p1.y); + ctx.closePath(); + ctx.fill(); + + if (this.tint) { + if (this.opacity < 1) { + if (gameState == 1 || gameState==0) { + localStorage.setItem("saveState", exportSaveState()); + } + + this.iter = 2.25; + this.tint = 0; + } + + ctx.fillStyle = "#FFF"; + ctx.globalAlpha = this.tint; + ctx.beginPath(); + ctx.moveTo(baseX + p1.x, baseY + p1.y); + ctx.lineTo(baseX + p2.x, baseY + p2.y); + ctx.lineTo(baseX + p3.x, baseY + p3.y); + ctx.lineTo(baseX + p4.x, baseY + p4.y); + ctx.lineTo(baseX + p1.x, baseY + p1.y); + ctx.closePath(); + ctx.fill(); + this.tint -= 0.02 * MainHex.dt; + if (this.tint < 0) { + this.tint = 0; + } + } + + ctx.globalAlpha = 1; + }; +} + +function findCenterOfBlocks(arr) { + var avgDFH = 0; + var avgAngle = 0; + for (var i = 0; i < arr.length; i++) { + avgDFH += arr[i].distFromHex; + var ang = arr[i].angle; + while (ang < 0) { + ang += 360; + } + + avgAngle += ang % 360; + } + + avgDFH /= arr.length; + avgAngle /= arr.length; + + return { + x:trueCanvas.width/2 + Math.cos(avgAngle * (Math.PI / 180)) * avgDFH, + y:trueCanvas.height/2 + Math.sin(avgAngle * (Math.PI / 180)) * avgDFH + }; +} diff --git a/js/Hex.js b/js/Hex.js index 64f917b0c..3f6fc7e4b 100644 --- a/js/Hex.js +++ b/js/Hex.js @@ -20,7 +20,7 @@ function Hex(sideLength) { this.lastColorScored = "#000"; this.comboTime = 1; this.texts = []; - this.lastRotate = Date.now(); + this.lastRotate = Date.now(); for (var i = 0; i < this.sides; i++) { this.blocks.push([]); } @@ -57,6 +57,8 @@ function Hex(sideLength) { }; this.doesBlockCollide = function(block, position, tArr) { + + //block has rested on either the center of hex or on another block. Collision happened if (block.settled) { return; } @@ -64,38 +66,57 @@ function Hex(sideLength) { if (position !== undefined) { arr = tArr; if (position <= 0) { + //current block has hit the center hex + if (block.distFromHex - block.iter * this.dt * settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); block.settled = 1; block.checked = 1; - } else { + } + + //current block is still falling, increment iterations + else { block.settled = 0; block.iter = 1.5 + (waveone.difficulty/15) * 3; } - } else { + } + + else { + + //current block is above an existing settled block and hits the existing block + if (arr[position - 1].settled && block.distFromHex - block.iter * this.dt * settings.scale - arr[position - 1].distFromHex - arr[position - 1].height <= 0) { block.distFromHex = arr[position - 1].distFromHex + arr[position - 1].height; block.settled = 1; block.checked = 1; } + + //either the lower block has not settled yet OR current block has not settled (still falling) else { block.settled = 0; block.iter = 1.5 + (waveone.difficulty/15) * 3; } } - } else { + } + + //block is yet created (position is not defined) + else { var lane = this.sides - block.fallingLane;// -this.position; lane += this.position; lane = (lane+this.sides) % this.sides; var arr = this.blocks[lane]; + // + if (arr.length > 0) { if (block.distFromHex + block.iter * this.dt * settings.scale - arr[arr.length - 1].distFromHex - arr[arr.length - 1].height <= 0) { block.distFromHex = arr[arr.length - 1].distFromHex + arr[arr.length - 1].height; this.addBlock(block); } - } else { + } + + else { if (block.distFromHex + block.iter * this.dt * settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); this.addBlock(block); @@ -105,7 +126,7 @@ function Hex(sideLength) { }; this.rotate = function(steps) { - if(Date.now()-this.lastRotate<75 && !(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ) return; + if(Date.now()-this.lastRotate<75 && !(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ) return; if (!(gameState === 1 || gameState === 0)) return; this.position += steps; if (!history[this.ct]) { @@ -131,7 +152,7 @@ function Hex(sideLength) { }); this.targetAngle = this.targetAngle - steps * 60; - this.lastRotate = Date.now(); + this.lastRotate = Date.now(); }; this.draw = function() { @@ -160,7 +181,7 @@ function Hex(sideLength) { else { this.angle += this.angularVelocity; } - + drawPolygon(this.x + gdx, this.y + gdy + this.dy, this.sides, this.sideLength, this.angle,arrayToColor(this.fillColor) , 0, 'rgba(0,0,0,0)'); }; } @@ -168,3 +189,4 @@ function Hex(sideLength) { function arrayToColor(arr){ return 'rgb(' + arr[0]+ ','+arr[1]+','+arr[2]+')'; } + diff --git a/js/Hex_test.js b/js/Hex_test.js new file mode 100644 index 000000000..fef2aadfd --- /dev/null +++ b/js/Hex_test.js @@ -0,0 +1,157 @@ +function Hex(sideLength) { + window.settings = { + os: "other", + platform: "nonmobile", + baseScale: 1, + startDist: 340, + creationDt: 9, + scale: 1, + prevScale: 1, + hexWidth: 65, + baseHexWidth: 87, + baseBlockHeight: 20, + blockHeight: 15, + rows: 8, + speedModifier: 0.65, + creationSpeedModifier: 0.65, + comboTime: 310 + }; + this.playThrough = 0; + this.fillColor = [44,62,80]; + this.tempColor = [44,62,80]; + this.angularVelocity = 0; + this.position = 0; + this.dy = 0; + this.dt = 1; + this.sides = 6; + this.blocks = []; + this.angle = 180 / this.sides; + this.targetAngle = this.angle; + this.shakes = []; + this.sideLength = sideLength; + this.strokeColor = 'blue'; + this.ct = 0; + this.lastCombo = this.ct - window.settings.comboTime; + this.lastColorScored = "#000"; + this.comboTime = 1; + this.texts = []; + this.lastRotate = Date.now(); + for (var i = 0; i < this.sides; i++) { + this.blocks.push([]); + } + + this.shake = function(obj) { //lane as in particle lane + var angle = 30 + obj.lane * 60; + angle *= Math.PI / 180; + var dx = Math.cos(angle) * obj.magnitude; + var dy = Math.sin(angle) * obj.magnitude; + gdx -= dx; + gdy += dy; + obj.magnitude /= 2 * this.dt; + if (obj.magnitude < 1) { + for (var i = 0; i < this.shakes.length; i++) { + if (this.shakes[i] == obj) { + this.shakes.splice(i, 1); + } + } + } + }; + + this.addBlock = function(block) { + if (!(gameState == 1 || gameState === 0)) return; + block.settled = 1; + block.tint = 0.6; + var lane = this.sides - block.fallingLane;// -this.position; + this.shakes.push({lane:block.fallingLane, magnitude:4.5 * (window.devicePixelRatio ? window.devicePixelRatio : 1) * (window.settings.scale)}); + lane += this.position; + lane = (lane + this.sides) % this.sides; + block.distFromHex = MainHex.sideLength / 2 * Math.sqrt(3) + block.height * this.blocks[lane].length; + this.blocks[lane].push(block); + block.attachedLane = lane; + block.checked = 1; + }; + + this.doesBlockCollide = function(block, position, tArr) { + if (block.settled) { + return; + } + + if (position !== undefined) { + arr = tArr; + if (position <= 0) { + if (block.distFromHex - block.iter * this.dt * window.settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { + block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); + block.settled = 1; + block.checked = 1; + } else { + block.settled = 0; + block.iter = 1.5 + (waveone.difficulty/15) * 3; + } + } else { + if (arr[position - 1].settled && block.distFromHex - block.iter * this.dt * window.settings.scale - arr[position - 1].distFromHex - arr[position - 1].height <= 0) { + block.distFromHex = arr[position - 1].distFromHex + arr[position - 1].height; + block.settled = 1; + block.checked = 1; + } + else { + block.settled = 0; + block.iter = 1.5 + (waveone.difficulty/15) * 3; + } + } + } else { + var lane = this.sides - block.fallingLane;// -this.position; + lane += this.position; + + lane = (lane+this.sides) % this.sides; + var arr = this.blocks[lane]; + + if (arr.length > 0) { + if (block.distFromHex + block.iter * this.dt * window.settings.scale - arr[arr.length - 1].distFromHex - arr[arr.length - 1].height <= 0) { + block.distFromHex = arr[arr.length - 1].distFromHex + arr[arr.length - 1].height; + this.addBlock(block); + } + } else { + if (block.distFromHex + block.iter * this.dt * window.settings.scale - (this.sideLength / 2) * Math.sqrt(3) <= 0) { + block.distFromHex = (this.sideLength / 2) * Math.sqrt(3); + this.addBlock(block); + } + } + } + }; + + this.rotate = function(steps) { + if(Date.now()-this.lastRotate<75 && !(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ) return; + if (!(gameState === 1 || gameState === 0)) return; + this.position += steps; + if (!history[this.ct]) { + history[this.ct] = {}; + } + + if (!history[this.ct].rotate) { + history[this.ct].rotate = steps; + } + else { + history[this.ct].rotate += steps; + } + + while (this.position < 0) { + this.position += 6; + } + + this.position = this.position % this.sides; + this.blocks.forEach(function(blocks) { + blocks.forEach(function(block) { + block.targetAngle = block.targetAngle - steps * 60; + }); + }); + + this.targetAngle = this.targetAngle - steps * 60; + this.lastRotate = Date.now(); + }; + +} + +function arrayToColor(arr){ + return 'rgb(' + arr[0]+ ','+arr[1]+','+arr[2]+')'; +} + diff --git a/js/initialization.js b/js/initialization.js index 64d0e6680..e54865bd8 100644 --- a/js/initialization.js +++ b/js/initialization.js @@ -2,10 +2,27 @@ $(document).ready(function() { initialize(); }); function initialize(a) { + // color blind mode variables + // max amount of color blind modes + window.currcb = 0; + window.prevcb = 0; + + window.cbcolors = [ + ["#e74c3c", "#f1c40f", "#3498db", "#2ecc71"], + ["#8e44ad", "#f1c41f", "#3499db", "#d35400"], + ["#000000", "#445555", "#c0c0c0", "#ffffff"] + ] + + // variables to adjust speed of game + window.speedscale = 1; + window.oldspeedscale = 1; + window.rush = 1; window.lastTime = Date.now(); window.iframHasLoaded = false; - window.colors = ["#e74c3c", "#f1c40f", "#3498db", "#2ecc71"]; + + window.colors = window.cbcolors[0]; + window.hexColorsToTintedColors = { "#e74c3c": "rgb(241,163,155)", "#f1c40f": "rgb(246,223,133)", diff --git a/js/initialization_test.js b/js/initialization_test.js new file mode 100644 index 000000000..6eb2e0e91 --- /dev/null +++ b/js/initialization_test.js @@ -0,0 +1,102 @@ +/* This code in this function is identical to that of initialization.js with the exception: + - UI methods are stripped as this is to test the colour change functionality on + the backbone of the game, ensuring that the blocks change colour correctly. + */ +function initialize(a) { + // color blind mode variables + // max amount of color blind modes + window.currcb = 0; + window.prevcb = 0; + + window.cbcolors = [ + ["#e74c3c", "#f1c40f", "#3498db", "#2ecc71"], + ["#8e44ad", "#f1c41f", "#3499db", "#d35400"], + ["#000000", "#445555", "#c0c0c0", "#ffffff"] + ] + + // variables to adjust speed of game + window.speedscale = 1; + window.oldspeedscale = 1; + + window.rush = 1; + window.lastTime = Date.now(); + window.iframHasLoaded = false; + + window.colors = window.cbcolors[0]; + + window.hexColorsToTintedColors = { + "#e74c3c": "rgb(241,163,155)", + "#f1c40f": "rgb(246,223,133)", + "#3498db": "rgb(151,201,235)", + "#2ecc71": "rgb(150,227,183)" + }; + + window.rgbToHex = { + "rgb(231,76,60)": "#e74c3c", + "rgb(241,196,15)": "#f1c40f", + "rgb(52,152,219)": "#3498db", + "rgb(46,204,113)": "#2ecc71" + }; + + window.rgbColorsToTintedColors = { + "rgb(231,76,60)": "rgb(241,163,155)", + "rgb(241,196,15)": "rgb(246,223,133)", + "rgb(52,152,219)": "rgb(151,201,235)", + "rgb(46,204,113)": "rgb(150,227,183)" + }; + + window.hexagonBackgroundColor = 'rgb(236, 240, 241)'; + window.hexagonBackgroundColorClear = 'rgba(236, 240, 241, 0.5)'; + window.centerBlue = 'rgb(44,62,80)'; + window.angularVelocityConst = 4; + window.scoreOpacity = 0; + window.textOpacity = 0; + window.prevGameState = undefined; + window.op = 0; + window.saveState = localStorage.getItem("saveState") || "{}"; + if (saveState !== "{}") { + op = 1; + } + + + window.framerate = 60; + window.history = {}; + window.score = 0; + window.scoreAdditionCoeff = 1; + window.prevScore = 0; + window.numHighScores = 3; + + highscores = []; + + window.blocks = []; + window.MainHex; + window.gdx = 0; + window.gdy = 0; + window.devMode = 0; + window.lastGen = undefined; + window.prevTimeScored = undefined; + window.nextGen = undefined; + window.spawnLane = 0; + window.importing = 0; + window.importedHistory = undefined; + window.startTime = undefined; + window.gameState; + + window.settings = { + os: "other", + platform: "nonmobile", + baseScale: 1, + startDist: 340, + creationDt: 9, + scale: 1, + prevScale: 1, + hexWidth: 65, + baseHexWidth: 87, + baseBlockHeight: 20, + blockHeight: 15, + rows: 8, + speedModifier: 0.65, + creationSpeedModifier: 0.65, + comboTime: 310 + }; +} \ No newline at end of file diff --git a/js/input.js b/js/input.js index c559fb003..f153e0e65 100644 --- a/js/input.js +++ b/js/input.js @@ -41,7 +41,7 @@ function addKeyListeners() { keypress.register_combo({ keys: "space", - on_keydown: function(){pause();} + on_keydown: function(){toggleDrop(window.blocks, MainHex);} }); keypress.register_combo({ @@ -51,6 +51,30 @@ function addKeyListeners() { } }); + // speed up key + keypress.register_combo({ + keys: "up", + on_keydown: function() { + togglespeed(0.1, window.blocks, MainHex); + } + }); + + // slow down key + keypress.register_combo({ + keys: "down", + on_keydown: function() { + togglespeed(-0.1, window.blocks, MainHex); + } + }); + + // colour blind toggle key + keypress.register_combo({ + keys: "t", + on_keydown: function(){ + togglecolor(window.blocks, MainHex); + } + }); + keypress.register_combo({ keys: "enter", on_keydown: function() { @@ -79,32 +103,6 @@ function addKeyListeners() { return false; }); - $("#colorBlindBtn").on('touchstart mousedown', function() { - window.colors = ["#8e44ad", "#f1c40f", "#3498db", "#d35400"]; - - window.hexColorsToTintedColors = { - "#8e44ad": "rgb(229,152,102)", - "#f1c40f": "rgb(246,223,133)", - "#3498db": "rgb(151,201,235)", - "#d35400": "rgb(210,180,222)" - }; - - window.rgbToHex = { - "rgb(142,68,173)": "#8e44ad", - "rgb(241,196,15)": "#f1c40f", - "rgb(52,152,219)": "#3498db", - "rgb(211,84,0)": "#d35400" - }; - - window.rgbColorsToTintedColors = { - "rgb(142,68,173)": "rgb(229,152,102)", - "rgb(241,196,15)": "rgb(246,223,133)", - "rgb(52,152,219)": "rgb(151,201,235)", - "rgb(46,204,113)": "rgb(210,180,222)" - }; - }); - - if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { $("#restart").on('touchstart', function() { init(); @@ -189,3 +187,100 @@ function handleClickTap(x,y) { } } +function togglecolor(blocks, hex){ + // compute the current and next color + window.prevcb = window.currcb; + window.currcb = (window.prevcb + 1) % window.cbcolors.length; + + // set the current window color to the one we need + window.colors = window.cbcolors[currcb]; + + // obtain all the current falling blocks + for (var i = 0; i < blocks.length; i++){ + + // find the colour of the block and change accordingly + for (var j = 0; j < window.cbcolors[window.prevcb].length; j++){ + if (blocks[i].color == window.cbcolors[window.prevcb][j]){ + blocks[i].color = window.cbcolors[window.currcb][j] + } + } + } + + // obtain all colours from the hex and change them + for(var k = 0; k < hex.blocks.length; k++) { + for (var l = 0; l < hex.blocks[k].length; l++) { + for (var m = 0; m < window.cbcolors[window.prevcb].length; m++){ + // find the colour of the block and change accordingly + if (hex.blocks[k][l].color == window.cbcolors[window.prevcb][m]){ + hex.blocks[k][l].color = window.cbcolors[window.currcb][m]; + } + } + } + } +} + +function togglespeed(increment, blocks, hex) { + + // check if we are incrementing or decrementing the game speed + if (increment < 0) { + + // if incrementing, adjust the speed accordingly + if (window.speedscale >= 0.3) { + window.speedscale -= 0.1; + } + } + else { // increment is positive + // if decrementing, adjust the speed accordingly + if (window.speedscale < 1.4) { + window.speedscale += 0.1; + } + } + + // slow down the generation of the wave , if necessary. + if (window.speedscale >= 1){ + waveone.nextGen = waveone.nextGen * (1 / window.speedscale) / (1 / window.oldspeedscale); + } + + if (waveone.nextGen > 3500){ + waveone.nextGen = 3500; + } + + var iterfactor = window.speedscale / window.oldspeedscale; + + // slow down speed of falling blocks + for (var k = 0; k < blocks.length; k++){ + blocks[k].iter = blocks[k].iter * iterfactor; + } + + // obtain all speeds from the hex and change thems + for(var k = 0; k < hex.blocks.length; k++) { + for (var l = 0; l < hex.blocks[k].length; l++) { + hex.blocks[k][l].iter = hex.blocks[k][l].iter*iterfactor; + } + } + + // store the old value of so speed can be adjusted in future + window.oldspeedscale = window.speedscale; +} + +// When called, the currently falling blocks will immediately fall towards the center of hex +function toggleDrop(blocks, hex){ + + // tolerance for comparing doubles + var tolearnce = 0.01; + + // extract only the closest block to the + var minDist = 999999; + for (var i = 0; i < blocks.length; i++){ + if (blocks[i].distFromHex < minDist){ + minDist = blocks[i].distFromHex; + } + } + + //obtain current falling blocks; blocks[0] for a single falling block, [1] for a joint falling block... + for (var i = 0; i < blocks.length; i++){ + if (blocks[i].distFromHex >= (minDist - tolearnce) && blocks[i].distFromHex <= (minDist + tolearnce)){ + hex.addBlock(blocks[i]); + } + } +} diff --git a/js/main.js b/js/main.js index afc8515d6..1a227c908 100644 --- a/js/main.js +++ b/js/main.js @@ -184,6 +184,10 @@ function init(b) { function addNewBlock(blocklane, color, iter, distFromHex, settled) { //last two are optional parameters iter *= settings.speedModifier; + + // PRJ: this line will scale the speed of the block by its respective amount specified in scale + iter *= window.speedscale; + if (!history[MainHex.ct]) { history[MainHex.ct] = {}; } diff --git a/js/wavegen.js b/js/wavegen.js index a4e85ff77..57c3224a9 100644 --- a/js/wavegen.js +++ b/js/wavegen.js @@ -1,17 +1,40 @@ function blockDestroyed() { - if (waveone.nextGen > 1350) { + + // PRJ: all * window.speedscale + + var wavescalespeed; + if (window.speedscale <= 1.3){ + wavescalespeed = window.speedscale; + } + else { + wavescalespeed = 1; + } + + if (waveone.nextGen*wavescalespeed > 1350) { waveone.nextGen -= 30 * settings.creationSpeedModifier; - } else if (waveone.nextGen > 600) { + } else if (waveone.nextGen*wavescalespeed > 600) { waveone.nextGen -= 8 * settings.creationSpeedModifier; } else { waveone.nextGen = 600; } + // PRJ: this function scales down nextGen + if (wavescalespeed > 0.001) { + waveone.nextGen = waveone.nextGen / wavescalespeed; + } + if (waveone.difficulty < 35) { waveone.difficulty += 0.085 * settings.speedModifier; } else { waveone.difficulty = 35; } + + if (waveone.nextGen > 3500){ + waveone.nextGen = 3500; + } + else if (waveone.nextGen < 400){ + waveone.nextGen = 400; + } } function waveGen(hex) { @@ -29,9 +52,14 @@ function waveGen(hex) { this.dt = (settings.platform == 'mobile' ? 14 : 16.6667) * MainHex.ct; this.computeDifficulty(); if ((this.dt - this.lastGen) * settings.creationSpeedModifier > this.nextGen) { - if (this.nextGen > 600) { + + // PRJ: * window.speedscale + if (this.nextGen*window.speedscale > 600) { this.nextGen -= 11 * ((this.nextGen / 1300)) * settings.creationSpeedModifier; } + + // PRJ + this.nextGen = this.nextGen/window.speedscale; } }; diff --git a/qunit.htm b/qunit.htm new file mode 100644 index 000000000..259d12f58 --- /dev/null +++ b/qunit.htm @@ -0,0 +1,299 @@ + + +
+ +