2014-05-31 23:37:23 +00:00
var textShown = false ;
2014-06-24 00:55:04 +00:00
$ ( document ) . ready ( function ( ) {
scaleCanvas ( ) ;
2014-06-24 02:26:00 +00:00
$ ( '#startBtn' ) . on ( 'touchstart mousedown' , function ( ) {
2014-06-27 02:19:41 +00:00
if ( importing == 1 ) {
2014-06-28 02:09:36 +00:00
init ( 1 ) ;
2014-06-28 15:48:45 +00:00
} else {
2014-06-28 17:44:43 +00:00
resumeGame ( ) ;
2014-06-27 02:19:41 +00:00
}
2014-06-24 02:26:00 +00:00
setTimeout ( function ( ) {
2014-07-05 04:32:54 +00:00
if ( settings . platform == "mobile" ) {
document . body . addEventListener ( 'touchstart' , function ( e ) {
handleClickTap ( e . changedTouches [ 0 ] . clientX ) ;
} , false ) ;
}
else {
document . body . addEventListener ( 'mousedown' , function ( e ) {
handleClickTap ( e . clientX ) ;
} , false ) ;
}
2014-06-24 02:26:00 +00:00
} , 1 ) ;
} ) ;
2014-07-07 01:28:34 +00:00
document . addEventListener ( 'touchmove' , function ( e ) { e . preventDefault ( ) ; } , false ) ;
2014-06-24 00:55:04 +00:00
} ) ;
2014-06-24 02:26:00 +00:00
2014-05-25 05:11:24 +00:00
$ ( window ) . resize ( scaleCanvas ) ;
2014-06-28 16:01:41 +00:00
$ ( window ) . unload ( function ( ) {
2014-07-05 04:32:54 +00:00
if ( gameState == 1 || gameState == - 1 ) localStorage . setItem ( "saveState" , exportSaveState ( ) ) ;
else localStorage . clear ( ) ;
2014-06-28 16:01:41 +00:00
} ) ;
2014-05-25 05:11:24 +00:00
2014-05-25 14:41:06 +00:00
function scaleCanvas ( ) {
canvas . width = $ ( window ) . width ( ) ;
canvas . height = $ ( window ) . height ( ) ;
2014-05-25 22:27:25 +00:00
2014-05-25 15:16:33 +00:00
if ( canvas . height > canvas . width ) {
2014-05-25 22:27:25 +00:00
settings . scale = ( canvas . width / 800 ) * settings . baseScale ;
2014-05-25 15:16:33 +00:00
} else {
2014-05-25 22:27:25 +00:00
settings . scale = ( canvas . height / 800 ) * settings . baseScale ;
2014-05-25 15:16:33 +00:00
}
2014-05-25 22:27:25 +00:00
trueCanvas = {
width : canvas . width ,
height : canvas . height
} ;
2014-05-25 16:02:22 +00:00
if ( window . devicePixelRatio ) {
2014-05-25 22:27:25 +00:00
//from https://gist.github.com/joubertnel/870190
var cw = $ ( "#canvas" ) . attr ( 'width' ) ;
var ch = $ ( "#canvas" ) . attr ( 'height' ) ;
$ ( "#canvas" ) . attr ( 'width' , cw * window . devicePixelRatio ) ;
$ ( "#canvas" ) . attr ( 'height' , ch * window . devicePixelRatio ) ;
$ ( "#canvas" ) . css ( 'width' , cw ) ;
$ ( "#canvas" ) . css ( 'height' , ch ) ;
trueCanvas = {
width : cw ,
height : ch
} ;
ctx . scale ( window . devicePixelRatio , window . devicePixelRatio ) ;
2014-05-25 16:02:22 +00:00
}
2014-05-25 05:11:24 +00:00
}
2014-05-23 20:50:18 +00:00
2014-05-17 14:26:55 +00:00
var canvas = document . getElementById ( 'canvas' ) ;
var ctx = canvas . getContext ( '2d' ) ;
2014-05-25 22:27:25 +00:00
var trueCanvas = { width : canvas . width , height : canvas . height } ;
2014-05-17 21:15:55 +00:00
2014-05-20 12:30:14 +00:00
window . requestAnimFrame = ( function ( ) {
2014-05-22 23:30:40 +00:00
return window . requestAnimationFrame || window . webkitRequestAnimationFrame || window . mozRequestAnimationFrame || function ( callback ) {
window . setTimeout ( callback , 1000 / framerate ) ;
} ;
2014-05-20 12:30:14 +00:00
} ) ( ) ;
2014-05-22 21:04:57 +00:00
$ ( '#clickToExit' ) . bind ( 'click' , toggleDevTools ) ;
function toggleDevTools ( ) {
2014-05-22 23:30:40 +00:00
$ ( '#devtools' ) . toggle ( ) ;
2014-05-22 21:04:57 +00:00
}
2014-05-25 05:11:24 +00:00
var settings ;
if ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i . test ( navigator . userAgent ) ) {
settings = {
2014-07-04 18:09:14 +00:00
platform : "mobile" ,
2014-05-25 22:27:25 +00:00
startDist : 227 ,
creationDt : 40 ,
baseScale : 1.4 ,
2014-05-25 14:41:06 +00:00
scale : 1 ,
2014-05-25 23:53:02 +00:00
prevScale : 1 ,
2014-05-25 14:41:06 +00:00
baseHexWidth : 87 ,
2014-05-25 05:11:24 +00:00
hexWidth : 87 ,
2014-05-25 14:41:06 +00:00
baseBlockHeight : 20 ,
2014-05-25 05:11:24 +00:00
blockHeight : 20 ,
rows : 6 ,
2014-05-25 22:32:49 +00:00
speedModifier : 0.7 ,
2014-06-23 23:21:09 +00:00
creationSpeedModifier : 0.7 ,
2014-07-04 16:42:22 +00:00
comboTime : 240
2014-05-25 05:11:24 +00:00
} ;
} else {
settings = {
2014-07-04 18:09:14 +00:00
platform : "nonmobile" ,
2014-05-25 22:27:25 +00:00
baseScale : 1 ,
startDist : 340 ,
2014-05-25 23:53:02 +00:00
creationDt : 9 ,
2014-05-25 14:41:06 +00:00
scale : 1 ,
prevScale : 1 ,
2014-05-25 05:11:24 +00:00
hexWidth : 65 ,
2014-05-25 14:41:06 +00:00
baseHexWidth : 87 ,
baseBlockHeight : 20 ,
2014-05-25 05:11:24 +00:00
blockHeight : 15 ,
rows : 8 ,
2014-07-04 19:05:38 +00:00
speedModifier : 0.65 ,
creationSpeedModifier : 0.55 ,
2014-07-04 16:42:22 +00:00
comboTime : 240
2014-05-25 05:11:24 +00:00
} ;
2014-07-05 02:23:19 +00:00
$ ( "#inst_main_body" ) . html ( "The goal of Hextris is to stop blocks from leaving the inside of the outer gray hexagon<br><br>Either press the right and left arrow keys or tap the left and right sides of the screen to rotate the Hexagon<br><br>Clear blocks by making 3 or more blocks of the same color touch<br><br>Get points by clearing blocks<br><br>Time left before your combo streak disappears is indicated shown by <span style='color:#f1c40f;'>the</span> <span style='color:#e74c3c'>colored<span> <span style='color:#3498db'>lines</span> <span style='color:#2ecc71'>in</span> the outer hexagon<br><br>Pause by pressing <i class = 'fa fa-pause'></i> or the letter <b>p</b><br>Restart by pressing <i class = 'fa fa-refresh'></i> or <b>enter</b><br>Bring up this menu by pressing <i class = 'fa fa-info-circle'><br><br><a href = 'url'>Found a bug? Go here</a" ) ;
2014-05-25 05:11:24 +00:00
}
2014-05-17 21:10:35 +00:00
var framerate = 60 ;
2014-05-22 20:36:32 +00:00
var history = { } ;
2014-05-17 21:38:11 +00:00
var score = 0 ;
2014-05-25 02:10:12 +00:00
var isGameOver = 3 ;
2014-05-20 12:30:14 +00:00
var scoreAdditionCoeff = 1 ;
2014-05-23 04:51:03 +00:00
var prevScore = 0 ;
2014-05-23 05:51:16 +00:00
var numHighScores = 3 ;
2014-05-23 17:01:51 +00:00
2014-05-24 00:22:53 +00:00
var highscores = [ 0 , 0 , 0 ] ;
2014-05-23 17:01:51 +00:00
if ( localStorage . getItem ( 'highscores' ) )
2014-05-24 19:42:40 +00:00
highscores = localStorage . getItem ( 'highscores' ) . split ( ',' ) . map ( Number ) ;
2014-05-23 17:01:51 +00:00
2014-05-23 05:51:16 +00:00
localStorage . setItem ( 'highscores' , highscores ) ;
2014-05-17 21:10:35 +00:00
2014-05-17 16:42:56 +00:00
var blocks = [ ] ;
2014-07-04 16:42:44 +00:00
var MainHex ;
2014-05-20 12:30:14 +00:00
2014-05-22 23:01:39 +00:00
var gdx = 0 ;
var gdy = 0 ;
2014-07-04 23:08:49 +00:00
var devMode = 0 ;
2014-05-17 22:47:37 +00:00
var lastGen ;
2014-05-23 04:51:03 +00:00
var prevTimeScored ;
2014-05-17 22:47:37 +00:00
var nextGen ;
2014-05-20 12:30:14 +00:00
var spawnLane = 0 ;
2014-05-22 20:36:32 +00:00
var importing = 0 ;
var importedHistory ;
2014-05-23 20:13:23 +00:00
var startTime ;
2014-05-17 18:46:14 +00:00
2014-05-26 05:11:13 +00:00
var gameState ;
2014-06-24 02:26:00 +00:00
setStartScreen ( ) ;
2014-05-26 03:52:35 +00:00
2014-06-28 17:44:43 +00:00
function resumeGame ( ) {
gameState = 1 ;
hideUIElements ( ) ;
2014-06-29 18:25:40 +00:00
$ ( '#pauseBtn' ) . show ( ) ;
2014-06-30 17:34:55 +00:00
$ ( '#restartBtn' ) . show ( ) ;
2014-06-28 17:44:43 +00:00
importing = 0 ;
startTime = Date . now ( ) ;
2014-07-04 23:08:49 +00:00
setTimeout ( function ( ) {
$ ( '#helpText' ) . fadeOut ( 150 , "linear" ) ;
} , 7000 ) ;
2014-07-05 04:32:54 +00:00
if ( $ ( '#helpScreen' ) . is ( ":visible" ) ) {
$ ( '#helpScreen' ) . fadeOut ( 150 , "linear" ) ;
}
2014-06-28 17:44:43 +00:00
}
function hideUIElements ( ) {
$ ( '#pauseBtn' ) . hide ( ) ;
2014-06-30 16:29:26 +00:00
$ ( '#restartBtn' ) . hide ( ) ;
2014-06-28 17:44:43 +00:00
$ ( '#startBtn' ) . hide ( ) ;
}
2014-06-24 13:42:38 +00:00
function init ( b ) {
if ( b ) {
2014-07-04 23:08:49 +00:00
if ( ! $ ( '#helpText' ) . is ( ":visible" ) ) {
$ ( '#helpText' ) . fadeIn ( 150 , "linear" ) ;
}
2014-07-05 04:32:54 +00:00
if ( $ ( '#helpScreen' ) . is ( ":visible" ) ) {
$ ( '#helpScreen' ) . fadeOut ( 150 , "linear" ) ;
}
2014-07-04 23:08:49 +00:00
setTimeout ( function ( ) {
$ ( '#helpText' ) . fadeOut ( 150 , "linear" ) ;
} , 7000 ) ;
2014-06-24 13:42:38 +00:00
clearSaveState ( ) ;
}
2014-07-05 20:07:34 +00:00
hideUIElements ( ) ;
2014-05-26 03:52:35 +00:00
var saveState = localStorage . getItem ( "saveState" ) || "{}" ;
saveState = JSONfn . parse ( saveState ) ;
2014-06-24 00:55:04 +00:00
document . getElementById ( "canvas" ) . className = "" ;
2014-05-22 23:30:40 +00:00
history = { } ;
importedHistory = undefined ;
importing = 0 ;
2014-05-25 01:12:05 +00:00
isGameOver = 2 ;
2014-05-26 03:52:35 +00:00
score = saveState . score || 0 ;
2014-05-23 04:51:03 +00:00
prevScore = 0 ;
2014-05-22 23:30:40 +00:00
spawnLane = 0 ;
2014-06-24 02:26:00 +00:00
op = 0 ;
scoreOpacity = 0 ;
2014-07-01 15:02:52 +00:00
gameState = 1 ;
2014-07-04 18:52:14 +00:00
$ ( "#restartBtn" ) . show ( ) ;
$ ( "#pauseBtn" ) . show ( ) ;
2014-07-04 16:47:37 +00:00
if ( saveState . hex !== undefined ) gameState = 1 ;
2014-05-26 05:11:13 +00:00
2014-06-28 01:19:57 +00:00
scaleCanvas ( ) ;
settings . blockHeight = settings . baseBlockHeight * settings . scale ;
settings . hexWidth = settings . baseHexWidth * settings . scale ;
2014-07-04 16:47:37 +00:00
MainHex = saveState . hex || new Hex ( settings . hexWidth ) ;
if ( saveState . hex ) {
2014-07-04 16:42:44 +00:00
MainHex . playThrough += 1 ;
2014-07-03 20:30:56 +00:00
}
2014-07-04 16:42:44 +00:00
MainHex . sideLength = settings . hexWidth ;
2014-06-28 01:19:57 +00:00
2014-06-22 20:52:51 +00:00
var i ;
var block ;
2014-05-26 03:52:35 +00:00
if ( saveState . blocks ) {
2014-06-28 01:31:59 +00:00
saveState . blocks . map ( function ( o ) {
if ( rgbToHex [ o . color ] ) {
o . color = rgbToHex [ o . color ] ;
}
} ) ;
2014-06-22 20:52:51 +00:00
for ( i = 0 ; i < saveState . blocks . length ; i ++ ) {
block = saveState . blocks [ i ] ;
2014-05-26 03:52:35 +00:00
blocks . push ( block ) ;
}
}
2014-05-26 05:11:13 +00:00
else {
blocks = [ ] ;
}
2014-05-26 03:52:35 +00:00
gdx = saveState . gdx || 0 ;
gdy = saveState . gdy || 0 ;
2014-07-04 16:42:22 +00:00
comboTime = saveState . comboTime || 0 ;
2014-05-26 03:52:35 +00:00
2014-07-04 16:42:44 +00:00
for ( i = 0 ; i < MainHex . blocks . length ; i ++ ) {
for ( var j = 0 ; j < MainHex . blocks [ i ] . length ; j ++ ) {
MainHex . blocks [ i ] [ j ] . height = settings . blockHeight ;
MainHex . blocks [ i ] [ j ] . settled = 0 ;
2014-05-26 03:52:35 +00:00
}
}
2014-05-26 05:11:13 +00:00
2014-07-04 16:42:44 +00:00
MainHex . blocks . map ( function ( i ) {
2014-06-28 01:31:59 +00:00
i . map ( function ( o ) {
if ( rgbToHex [ o . color ] ) {
o . color = rgbToHex [ o . color ] ;
}
2014-06-28 01:39:32 +00:00
} ) ;
2014-06-28 01:31:59 +00:00
} ) ;
2014-06-24 04:15:03 +00:00
2014-07-04 16:42:44 +00:00
MainHex . y = - 100 ;
2014-05-26 05:11:13 +00:00
2014-05-23 20:13:23 +00:00
startTime = Date . now ( ) ;
2014-07-04 16:42:44 +00:00
waveone = saveState . wavegen || new waveGen ( MainHex , Date . now ( ) , [ 1 , 1 , 0 ] , [ 1 , 1 ] , [ 1 , 1 ] ) ;
2014-05-26 03:52:35 +00:00
2014-07-04 16:42:44 +00:00
MainHex . texts = [ ] ; //clear texts
MainHex . delay = 15 ;
2014-06-24 00:55:04 +00:00
hideText ( ) ;
2014-05-17 22:47:37 +00:00
}
2014-05-18 18:15:13 +00:00
2014-05-24 00:22:53 +00:00
function addNewBlock ( blocklane , color , iter , distFromHex , settled ) { //last two are optional parameters
2014-05-25 22:27:25 +00:00
iter *= settings . speedModifier ;
2014-07-05 21:44:31 +00:00
if ( ! history [ MainHex . ct ] ) {
history [ MainHex . ct ] = { } ;
2014-05-22 23:30:40 +00:00
}
2014-07-05 21:44:31 +00:00
history [ MainHex . ct ] . block = {
2014-05-22 23:30:40 +00:00
blocklane : blocklane ,
2014-05-24 18:12:01 +00:00
color : color ,
iter : iter
2014-05-22 23:30:40 +00:00
} ;
if ( distFromHex ) {
2014-07-05 21:44:31 +00:00
history [ MainHex . ct ] . distFromHex = distFromHex ;
2014-05-22 23:30:40 +00:00
}
if ( settled ) {
2014-07-05 21:44:31 +00:00
blockHist [ MainHex . ct ] . settled = settled ;
2014-05-22 23:30:40 +00:00
}
2014-05-24 00:22:53 +00:00
blocks . push ( new Block ( blocklane , color , iter , distFromHex , settled ) ) ;
2014-05-22 20:36:32 +00:00
}
2014-06-24 00:55:04 +00:00
function importHistory ( j ) {
if ( ! j ) {
try {
var ih = JSON . parse ( prompt ( "Import JSON" ) ) ;
if ( ih ) {
2014-06-24 15:44:40 +00:00
init ( 1 ) ;
2014-06-24 00:55:04 +00:00
importing = 1 ;
importedHistory = ih ;
}
2014-05-22 23:30:40 +00:00
}
2014-06-24 00:55:04 +00:00
catch ( e ) {
alert ( "Error importing JSON" ) ;
}
} else {
2014-06-24 17:16:46 +00:00
init ( ) ;
2014-06-24 00:55:04 +00:00
importing = 1 ;
importedHistory = j ;
2014-05-22 23:30:40 +00:00
}
2014-05-22 20:36:32 +00:00
}
function exportHistory ( ) {
2014-05-22 23:30:40 +00:00
$ ( '#devtoolsText' ) . html ( JSON . stringify ( history ) ) ;
toggleDevTools ( ) ;
2014-05-22 20:36:32 +00:00
}
2014-06-24 00:55:04 +00:00
function setStartScreen ( ) {
$ ( '#startBtn' ) . show ( ) ;
2014-07-04 18:52:14 +00:00
if ( isStateSaved ( ) ) {
2014-06-28 02:15:16 +00:00
init ( ) ;
2014-06-24 02:26:00 +00:00
importing = 0 ;
2014-07-05 02:23:19 +00:00
} else {
importHistory ( introJSON ) ;
2014-06-24 02:26:00 +00:00
}
gameState = 0 ;
2014-07-05 02:23:19 +00:00
requestAnimFrame ( animLoop ) ;
2014-06-24 00:55:04 +00:00
}
2014-05-23 20:13:23 +00:00
//t: current time, b: begInnIng value, c: change In value, d: duration
function getStepDY ( t , b , c , d ) {
if ( ( t /= d ) < ( 1 / 2.75 ) ) {
return c * ( 7.5625 * t * t ) + b ;
} else if ( t < ( 2 / 2.75 ) ) {
return c * ( 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75 ) + b ;
} else if ( t < ( 2.5 / 2.75 ) ) {
return c * ( 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375 ) + b ;
} else {
return c * ( 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375 ) + b ;
2014-05-23 04:51:03 +00:00
}
2014-05-23 20:50:18 +00:00
}
2014-05-23 20:13:23 +00:00
function animLoop ( ) {
2014-06-28 02:15:16 +00:00
switch ( gameState ) {
case 1 :
requestAnimFrame ( animLoop ) ;
2014-07-04 16:42:44 +00:00
if ( ! MainHex . delay ) {
2014-07-03 20:30:56 +00:00
update ( ) ;
} else {
2014-07-04 16:42:44 +00:00
MainHex . delay -- ;
2014-07-03 20:30:56 +00:00
}
2014-06-28 02:15:16 +00:00
render ( ) ;
2014-06-28 18:42:55 +00:00
if ( checkGameOver ( ) && ! importing ) {
2014-07-05 14:21:07 +00:00
$ ( '#helpText' ) . fadeIn ( 200 , "linear" ) ;
2014-06-28 02:15:16 +00:00
gameState = 2 ;
2014-07-05 14:21:07 +00:00
setTimeout ( function ( ) {
enableRestart ( ) ;
} , 200 )
canRestart = 0 ;
2014-06-28 02:15:16 +00:00
clearSaveState ( ) ;
}
break ;
case 0 :
requestAnimFrame ( animLoop ) ;
if ( importing ) {
update ( ) ;
}
render ( ) ;
break ;
case - 1 :
requestAnimFrame ( animLoop ) ;
render ( ) ;
break ;
case 2 :
requestAnimFrame ( animLoop ) ;
update ( ) ;
render ( ) ;
break ;
2014-06-28 15:24:47 +00:00
case 3 :
requestAnimFrame ( animLoop ) ;
fadeOutObjectsOnScreen ( ) ;
render ( ) ;
2014-07-03 20:30:56 +00:00
break ;
2014-06-28 15:24:47 +00:00
2014-06-28 02:15:16 +00:00
default :
setStartScreen ( ) ;
break ;
2014-05-25 14:41:06 +00:00
}
2014-05-17 23:02:28 +00:00
}
2014-05-25 01:12:05 +00:00
2014-07-05 14:21:07 +00:00
function enableRestart ( ) {
canRestart = 1 ;
}
2014-06-24 02:21:36 +00:00
function updateHighScore ( ) {
2014-06-28 02:15:16 +00:00
if ( localStorage . getItem ( 'highscores' ) ) {
highscores = localStorage . getItem ( 'highscores' ) . split ( ',' ) . map ( Number ) ;
}
for ( var i = 0 ; i < numHighScores ; i ++ ) {
if ( highscores [ i ] <= score ) {
highscores . splice ( i , 0 , score ) ;
highscores = highscores . slice ( 0 , - 1 ) ;
break ;
}
}
localStorage . setItem ( 'highscores' , highscores ) ;
2014-06-24 02:21:36 +00:00
}
2014-07-04 16:47:37 +00:00
function isInfringing ( hex ) {
for ( var i = 0 ; i < hex . sides ; i ++ ) {
2014-05-26 00:34:56 +00:00
var subTotal = 0 ;
2014-07-04 16:47:37 +00:00
for ( var j = 0 ; j < hex . blocks [ i ] . length ; j ++ ) {
subTotal += hex . blocks [ i ] [ j ] . deleted ;
2014-05-26 00:34:56 +00:00
}
2014-07-04 16:47:37 +00:00
if ( hex . blocks [ i ] . length - subTotal > settings . rows ) {
2014-06-04 18:33:40 +00:00
return true ;
2014-05-26 00:34:56 +00:00
}
}
return false ;
}
2014-06-24 00:55:04 +00:00
2014-05-22 23:01:39 +00:00
function checkGameOver ( ) {
2014-07-04 16:42:44 +00:00
for ( var i = 0 ; i < MainHex . sides ; i ++ ) {
if ( isInfringing ( MainHex ) ) {
2014-06-28 02:15:16 +00:00
updateHighScore ( ) ;
gameOverDisplay ( ) ;
2014-05-22 23:30:40 +00:00
return true ;
}
}
return false ;
2014-05-24 01:36:59 +00:00
}
2014-05-24 18:52:21 +00:00
2014-05-25 02:10:12 +00:00
window . onblur = function ( e ) {
2014-06-24 00:55:04 +00:00
if ( gameState == 1 ) {
2014-06-04 18:33:40 +00:00
pause ( ) ;
2014-06-24 00:55:04 +00:00
}
2014-05-25 05:12:06 +00:00
} ;
2014-05-27 01:05:58 +00:00
function showHelp ( ) {
2014-07-04 18:09:14 +00:00
if ( gameState != 0 ) {
2014-07-04 20:42:55 +00:00
pause ( 1 ) ;
2014-05-27 01:05:58 +00:00
}
2014-07-04 18:09:14 +00:00
$ ( '#helpScreen' ) . fadeToggle ( 150 , "linear" ) ;
2014-06-23 23:21:09 +00:00
}