summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <Mike.Buland@mjfirm.com>2016-10-24 14:14:19 -0600
committerMike Buland <Mike.Buland@mjfirm.com>2016-10-24 14:14:19 -0600
commit39d593054de993469809170ebf53a231caac92fb (patch)
tree4dfec57800e0d994977b96491d44ad0cb6126c2d
parentaf8190aea9296ae82fbb08ebf01a15ce45faa8d1 (diff)
downloadlost-39d593054de993469809170ebf53a231caac92fb.tar.gz
lost-39d593054de993469809170ebf53a231caac92fb.tar.bz2
lost-39d593054de993469809170ebf53a231caac92fb.tar.xz
lost-39d593054de993469809170ebf53a231caac92fb.zip
It's all responsive now. Also it can loop.
-rw-r--r--js/lost.css46
-rw-r--r--js/lost.html27
-rw-r--r--js/lost.js266
3 files changed, 248 insertions, 91 deletions
diff --git a/js/lost.css b/js/lost.css
new file mode 100644
index 0000000..7c51760
--- /dev/null
+++ b/js/lost.css
@@ -0,0 +1,46 @@
1@media (orientation: portrait) {
2}
3
4@media (orientation: landscape) {
5 #maze-box {
6 display:inline-block;
7 vertical-align: middle;
8 }
9 #button-box {
10 display: inline-block;
11 vertical-align: middle;
12 }
13 #floor-box {
14 display: block;
15 vertical-align: top;
16 }
17 #sidebar {
18 display: inline-block;
19 vertical-align: top;
20 }
21 #ui-box {
22 text-align: center;
23 vertical-align: top;
24 }
25}
26
27#maze-box {
28 text-align: center;
29}
30
31#button-box {
32 text-align: center;
33}
34
35#button-box table {
36 margin-left: auto;
37 margin-right: auto;
38}
39
40.float-clear {
41 clear: both;
42}
43
44#floor-box {
45 text-align: center;
46}
diff --git a/js/lost.html b/js/lost.html
index 820b1fc..d4443ab 100644
--- a/js/lost.html
+++ b/js/lost.html
@@ -2,8 +2,35 @@
2<html> 2<html>
3 <head> 3 <head>
4 <title>Lost</title> 4 <title>Lost</title>
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <link rel="stylesheet" href="lost.css">
5 </head> 7 </head>
6 <body> 8 <body>
9 <div id="ui-box">
10 <div id="maze-box"></div>
11 <div id="button-box"></div>
12 </div>
13 <div id="floor-box"></div>
14 <div class="float-clear"></div>
15 <div id="editor-cont">
16 <p>Provide a number below for each dimension in the new maze. The numbers are the size of each dimension. Entering "10, 3" will create a maze that is 10 wide and 3 tall. Entering "5, 5, 5, 5, 5" will create a 5 dimensional maze, every dimension will be 5 wide.</p>
17 <div id="editor-box"></div>
18 </div>
19 <div id="share-box"></div>
7 <script src="lost.js"></script> 20 <script src="lost.js"></script>
21 <script type="text/javascript">
22lostInit({
23 'render': {
24 'name': 'RenderCanvas2D',
25 'params': {
26 'maze': 'maze-box',
27 'buttons': 'button-box',
28 'readout': 'floor-box'
29 }
30 },
31 'editor': 'editor-box',
32 'share': 'share-box'
33 });
34 </script>
8 </body> 35 </body>
9</html> 36</html>
diff --git a/js/lost.js b/js/lost.js
index a9d9556..20311f2 100644
--- a/js/lost.js
+++ b/js/lost.js
@@ -321,7 +321,7 @@ Map.prototype.get = function get( Position )
321 return this.aCell[this.getIndex( Position )]; 321 return this.aCell[this.getIndex( Position )];
322} 322}
323 323
324Map.prototype.addWorm = function addWorm( pStart ) 324Map.prototype.addWorm = function addWorm( pStart, dLoopChance )
325{ 325{
326 if( this.pPlayer === null ) 326 if( this.pPlayer === null )
327 { 327 {
@@ -337,7 +337,8 @@ Map.prototype.addWorm = function addWorm( pStart )
337 new Worm( 337 new Worm(
338 iNewId, 338 iNewId,
339 pStart, 339 pStart,
340 this 340 this,
341 dLoopChance
341 ) 342 )
342 ); 343 );
343 return iNewId; 344 return iNewId;
@@ -440,13 +441,14 @@ function Vector( pPos, iDir )
440// 441//
441// Class: Worm 442// Class: Worm
442// 443//
443function Worm( iId, pStart, rMap ) 444function Worm( iId, pStart, rMap, dLoopChance )
444{ 445{
445 // Initialize basic state, we start with distance set to 1 446 // Initialize basic state, we start with distance set to 1
446 this.iId = iId; 447 this.iId = iId;
447 this.pPosition = pStart; 448 this.pPosition = pStart;
448 this.rMap = rMap; 449 this.rMap = rMap;
449 this.iDist = 1; 450 this.iDist = 1;
451 this.dLoopChance = dLoopChance;
450 452
451 // Setup walls here to create an opening. We're only going to do 453 // Setup walls here to create an opening. We're only going to do
452 // this on the first two dimensions. This assumes that we have at least 454 // this on the first two dimensions. This assumes that we have at least
@@ -480,10 +482,14 @@ Worm.prototype.timestep = function timestep()
480 482
481 // Possible directions 483 // Possible directions
482 let pDirs = []; 484 let pDirs = [];
485 let pLoopDirs;
483 486
487 let cCur;
484 for(;;) 488 for(;;)
485 { 489 {
490 cCur = this.rMap.get( this.pPosition );
486 let pBack = null; 491 let pBack = null;
492 pLoopDirs = [];
487 for( let j = 0; j < iDims; j++ ) 493 for( let j = 0; j < iDims; j++ )
488 { 494 {
489 let iSize = this.rMap.getSize( j ); 495 let iSize = this.rMap.getSize( j );
@@ -500,6 +506,11 @@ Worm.prototype.timestep = function timestep()
500 { 506 {
501 pBack = pPos; 507 pBack = pPos;
502 } 508 }
509 else if( (cCur.iWalls&(1<<(j*2))) === 0 &&
510 xCell.iPath === this.iId )
511 {
512 pLoopDirs.push( new Vector( pPos, j*2 ) );
513 }
503 } 514 }
504 515
505 pPos = this.pPosition.translate( j, 1 ); 516 pPos = this.pPosition.translate( j, 1 );
@@ -515,6 +526,11 @@ Worm.prototype.timestep = function timestep()
515 { 526 {
516 pBack = pPos; 527 pBack = pPos;
517 } 528 }
529 else if( (cCur.iWalls&(1<<(j*2+1))) === 0 &&
530 xCell.iPath === this.iId )
531 {
532 pLoopDirs.push( new Vector( pPos, j*2+1 ) );
533 }
518 } 534 }
519 } 535 }
520 536
@@ -536,25 +552,34 @@ Worm.prototype.timestep = function timestep()
536 } 552 }
537 } 553 }
538 554
555 cCur = this.rMap.get( this.pPosition );
539 let iSel = randInt( pDirs.length ); 556 let iSel = randInt( pDirs.length );
540 let cCur = this.rMap.get( this.pPosition );
541 cCur.iWalls |= (1<<pDirs[iSel].iDir); 557 cCur.iWalls |= (1<<pDirs[iSel].iDir);
542 let cNext = this.rMap.get( pDirs[iSel].pPos ); 558 let cNext = this.rMap.get( pDirs[iSel].pPos );
543 cNext.iWalls |= (1<<oppositeDir( pDirs[iSel].iDir )); 559 cNext.iWalls |= (1<<oppositeDir( pDirs[iSel].iDir ));
544 cNext.iDist = ++this.iDist; 560 cNext.iDist = ++this.iDist;
545 cNext.iPath = this.iId; 561 cNext.iPath = this.iId;
562 let oldPosition = this.pPosition;
546 this.pPosition = pDirs[iSel].pPos; 563 this.pPosition = pDirs[iSel].pPos;
547 564
565 if( pLoopDirs.length > 0 && lRand.random() <= this.dLoopChance )
566 {
567 iSel = pLoopDirs[randInt( pLoopDirs.length )];
568 cCur.iWalls |= (1<<iSel.iDir);
569 cNext = this.rMap.get( iSel.pPos );
570 cNext.iWalls |= (1<<oppositeDir( iSel.iDir ));
571 }
572
548 return true; 573 return true;
549} 574}
550 575
551// 576//
552// Class: Render 577// Class: Render
553// 578//
554function Render( rMap, eParent ) 579function Render( rMap, eMazeContainer )
555{ 580{
556 this.rMap = rMap; 581 this.rMap = rMap;
557 this.eParent = eParent; 582 this.eMazeContainer = eMazeContainer;
558} 583}
559 584
560Render.prototype.render = function render() 585Render.prototype.render = function render()
@@ -590,15 +615,22 @@ function createMoveButton( rMap, iDim, iDir, sLabel )
590// 615//
591// Class: RenderCanvas2D 616// Class: RenderCanvas2D
592// 617//
593function RenderCanvas2D( rMap, eParent ) 618function RenderCanvas2D( rMap, params ) // eMazeContainer, eUIContainer )
594{ 619{
595 Render.call( this, rMap, eParent ); 620 let eMazeContainer = document.getElementById(params['maze']);
621 let eUIContainer = document.getElementById(params['buttons']);
622 let eReadoutBox = document.getElementById(params['readout']);
623
624 Render.call( this, rMap, eMazeContainer );
596 this.rMap.ePlayerMoved.connect( 625 this.rMap.ePlayerMoved.connect(
597 RenderCanvas2D.prototype.render.bind( this ) 626 RenderCanvas2D.prototype.render.bind( this )
598 ); 627 );
599 this.rMap.ePlayerMoved.connect( 628 this.rMap.ePlayerMoved.connect(
600 RenderCanvas2D.prototype.updateButtons.bind( this ) 629 RenderCanvas2D.prototype.updateButtons.bind( this )
601 ); 630 );
631 this.rMap.ePlayerMoved.connect(
632 RenderCanvas2D.prototype.updateReadout.bind( this )
633 );
602 this.rMap.eVictory.connect( 634 this.rMap.eVictory.connect(
603 RenderCanvas2D.prototype.setVictory.bind( this ) 635 RenderCanvas2D.prototype.setVictory.bind( this )
604 ); 636 );
@@ -609,12 +641,34 @@ function RenderCanvas2D( rMap, eParent )
609 641
610 this.pExtPosition = new Position( rMap.getDims() ); 642 this.pExtPosition = new Position( rMap.getDims() );
611 643
612 this.iIconSize = 11;
613 this.iBorder = 3;
614 this.iIconSquare = Math.ceil( 644 this.iIconSquare = Math.ceil(
615 Math.sqrt((this.rMap.getDims()-2)*2 + 1) 645 Math.sqrt((this.rMap.getDims()-2)*2 + 1)
616 ); 646 );
617 647
648 let iTargetSize = eMazeContainer.clientWidth;
649 if( eMazeContainer.clientHeight !== 0 &&
650 eMazeContainer.clientHeight < iTargetSize )
651 iTargetSize = eMazeContainer.clientHeight;
652
653 if( window.innerHeight < window.innerWidth )
654 {
655 // Portrait view
656 if( iTargetSize === 0 )
657 iTargetSize = window.innerHeight*0.9;
658 }
659 else
660 {
661 if( iTargetSize > window.innerHeight/2 )
662 iTargetSize = window.innerHeight/2;
663 }
664
665 this.iBorder = 3;
666 this.iIconSize = Math.floor(
667 ((iTargetSize/this.rMap.getSize( 0 ))-3-(this.iIconSquare*3))/this.iIconSquare
668 );
669 if( this.iIconSize > 15 )
670 this.iIconSize = 15;
671
618 this.iCellSize = 672 this.iCellSize =
619 this.iBorder + 673 this.iBorder +
620 this.iIconSquare*(this.iIconSize+this.iBorder); 674 this.iIconSquare*(this.iIconSize+this.iBorder);
@@ -622,7 +676,7 @@ function RenderCanvas2D( rMap, eParent )
622 this.eCanvas = document.createElement('canvas'); 676 this.eCanvas = document.createElement('canvas');
623 this.eCanvas.width = this.iCellSize*this.rMap.getSize( 0 ); 677 this.eCanvas.width = this.iCellSize*this.rMap.getSize( 0 );
624 this.eCanvas.height = this.iCellSize*this.rMap.getSize( 1 ); 678 this.eCanvas.height = this.iCellSize*this.rMap.getSize( 1 );
625 eParent.appendChild( this.eCanvas ); 679 eMazeContainer.appendChild( this.eCanvas );
626 this.ctx = this.eCanvas.getContext("2d"); 680 this.ctx = this.eCanvas.getContext("2d");
627 this.ctx.lineWidth = 1.0; 681 this.ctx.lineWidth = 1.0;
628 this.ctx.font = Math.ceil(this.iIconSize) + 'px sans serif'; 682 this.ctx.font = Math.ceil(this.iIconSize) + 'px sans serif';
@@ -632,10 +686,11 @@ function RenderCanvas2D( rMap, eParent )
632 686
633 this.render(); 687 this.render();
634 688
635 this.btnBox = document.createElement('div'); 689 this.btnBox = eUIContainer;
636 eParent.appendChild( document.createElement('br') ); 690 this.readoutBox = eReadoutBox;
637 eParent.appendChild( document.createElement('br') ); 691 this.readoutNode = document.createTextNode('');
638 eParent.appendChild( this.btnBox ); 692 this.readoutBox.appendChild( this.readoutNode );
693 this.updateReadout();
639 694
640 let cardTbl; 695 let cardTbl;
641 let cardRow; 696 let cardRow;
@@ -698,25 +753,28 @@ function RenderCanvas2D( rMap, eParent )
698 753
699 this.btnBox.appendChild( cardTbl ); 754 this.btnBox.appendChild( cardTbl );
700 755
701 cardTbl = document.createElement('table'); 756 if( this.rMap.getDims() >= 3 )
702 for( let j = 3; j < this.rMap.getDims(); j++ )
703 { 757 {
704 cardRow = document.createElement('tr'); 758 cardTbl = document.createElement('table');
705 cardTbl.appendChild( cardRow ); 759 for( let j = 3; j < this.rMap.getDims(); j++ )
760 {
761 cardRow = document.createElement('tr');
762 cardTbl.appendChild( cardRow );
706 763
707 cardTd = document.createElement('td'); 764 cardTd = document.createElement('td');
708 this.aMoveButtons[j*2] = cardTd.appendChild( 765 this.aMoveButtons[j*2] = cardTd.appendChild(
709 createMoveButton( this.rMap, j, -1, (j+1) + '-' ) 766 createMoveButton( this.rMap, j, -1, (j+1) + '-' )
710 ); 767 );
711 cardRow.appendChild( cardTd ); 768 cardRow.appendChild( cardTd );
712 769
713 cardTd = document.createElement('td'); 770 cardTd = document.createElement('td');
714 this.aMoveButtons[j*2+1] = cardTd.appendChild( 771 this.aMoveButtons[j*2+1] = cardTd.appendChild(
715 createMoveButton( this.rMap, j, 1, (j+1) + '+' ) 772 createMoveButton( this.rMap, j, 1, (j+1) + '+' )
716 ); 773 );
717 cardRow.appendChild( cardTd ); 774 cardRow.appendChild( cardTd );
775 }
776 this.btnBox.appendChild( cardTbl );
718 } 777 }
719 this.btnBox.appendChild( cardTbl );
720 778
721 this.updateButtons(); 779 this.updateButtons();
722} 780}
@@ -739,7 +797,23 @@ RenderCanvas2D.prototype.render = function render()
739 let iPlayerIcon = 797 let iPlayerIcon =
740 Math.floor(this.iIconSquare*0.5) + 798 Math.floor(this.iIconSquare*0.5) +
741 Math.floor(this.iIconSquare*0.5) * this.iIconSquare; 799 Math.floor(this.iIconSquare*0.5) * this.iIconSquare;
800
801 this.ctx.beginPath();
802 this.ctx.strokeStyle = 'whitesmoke';
803 for( let x = 0; x < this.rMap.getSize( 0 ); x++ )
804 {
805 this.ctx.moveTo( x*iSize, 0 );
806 this.ctx.lineTo( x*iSize, this.rMap.getSize( 1 )*iSize );
807 }
808 for( let y = 0; y < this.rMap.getSize( 1 ); y++ )
809 {
810 this.ctx.moveTo( 0, y*iSize );
811 this.ctx.lineTo( this.rMap.getSize( 0 )*iSize, y*iSize );
812 }
813 this.ctx.stroke();
742 814
815 this.ctx.beginPath();
816 this.ctx.strokeStyle = 'black';
743 for( let x = 0; x < this.rMap.getSize( 0 ); x++ ) 817 for( let x = 0; x < this.rMap.getSize( 0 ); x++ )
744 { 818 {
745 for( let y = 0; y < this.rMap.getSize( 1 ); y++ ) 819 for( let y = 0; y < this.rMap.getSize( 1 ); y++ )
@@ -887,6 +961,20 @@ RenderCanvas2D.prototype.updateButtons = function updateButtons()
887 } 961 }
888} 962}
889 963
964RenderCanvas2D.prototype.updateReadout = function updateReadout()
965{
966 if( this.rMap.getDims() <= 2 )
967 return;
968
969 let text = 'Floor: ' + this.rMap.pPlayer.get( 2 );
970 for( let j = 3; j < this.rMap.getDims(); j++ )
971 {
972 text += ', ' + this.rMap.pPlayer.get( j )
973 }
974
975 this.readoutNode.textContent = text;
976}
977
890RenderCanvas2D.prototype.setVictory = function setVictory() 978RenderCanvas2D.prototype.setVictory = function setVictory()
891{ 979{
892 while( this.btnBox.hasChildNodes() ) 980 while( this.btnBox.hasChildNodes() )
@@ -914,72 +1002,68 @@ RenderCanvas2D.prototype.setFloor = function setFloor( aFloor )
914// Initialize 1002// Initialize
915// 1003//
916 1004
917let p = new Position( 4, 3, 3, 3, 3 ); 1005function lostInit( properties )
918
919if( document.location.search !== '' )
920{ 1006{
921 let dat = document.location.search.slice(1); 1007 let p = new Position( 4, 3, 3, 3, 3 );
922 let datChunks = dat.split('&'); 1008
923 for( let j = 0; j < datChunks.length; j++ ) 1009 if( document.location.search !== '' )
924 { 1010 {
925 let pair = datChunks[j].split('='); 1011 let dat = document.location.search.slice(1);
926 if( pair.length == 2 ) 1012 let datChunks = dat.split('&');
1013 for( let j = 0; j < datChunks.length; j++ )
927 { 1014 {
928 if( pair[0] == 'seed' ) 1015 let pair = datChunks[j].split('=');
929 { 1016 if( pair.length == 2 )
930 lRand.setSeed( parseInt( decodeURIComponent( pair[1] ), 10 ) );
931 }
932 else if( pair[0] == 'dims' )
933 { 1017 {
934 p = new Position( decodeURIComponent( pair[1] ) ); 1018 if( pair[0] == 'seed' )
1019 {
1020 lRand.setSeed( parseInt( decodeURIComponent( pair[1] ), 10 ) );
1021 }
1022 else if( pair[0] == 'dims' )
1023 {
1024 p = new Position( decodeURIComponent( pair[1] ) );
1025 }
935 } 1026 }
936 } 1027 }
937 } 1028 }
1029
1030 let m = new Map( p );
1031 let exit1 = new Position( p.getDims() );
1032 let exit2 = new Position( p.getDims() );
1033 exit2.set( 1, p.get( 1 )-1 );
1034 m.addWorm( exit1, 0.05 );
1035 m.addWorm( exit2, 0.05 );
1036 m.buildMaze();
1037
1038 let eEditorBox = document.getElementById(properties['editor']);
1039 let eShareBox = document.getElementById(properties['share']);
1040
1041 let rend = new RenderCanvas2D( m, properties['render']['params'] );
1042
1043 let formDiv = eEditorBox;
1044 let form = document.createElement('form');
1045 let dims = document.createElement('input');
1046 dims.name = 'dims';
1047 dims.value = p.toString();
1048 let sub = document.createElement('input');
1049 sub.type = 'submit';
1050 sub.value = 'New maze!';
1051 form.appendChild( dims );
1052 form.appendChild( document.createTextNode(' ') );
1053 form.appendChild( sub );
1054 formDiv.appendChild( form );
1055
1056 let d = eShareBox;
1057 let dLink = document.createElement('a');
1058 let trgUrl = document.location.toString();
1059 let query = trgUrl.indexOf('?');
1060 if( query >= 0 )
1061 {
1062 trgUrl = trgUrl.substring(0, query);
1063 }
1064 trgUrl += '?seed=' + lRand.getSeed() + '&dims=' + p.toString();
1065 dLink.href = trgUrl;
1066 dLink.appendChild( document.createTextNode('Share this maze!') );
1067 d.appendChild(dLink);
938} 1068}
939 1069
940let m = new Map( p );
941let exit1 = new Position( p.getDims() );
942let exit2 = new Position( p.getDims() );
943exit2.set( 1, p.get( 1 )-1 );
944m.addWorm( exit1 );
945m.addWorm( exit2 );
946m.buildMaze();
947
948let rend = new RenderCanvas2D( m, document.body );
949
950let formDiv = document.createElement('div');
951let form = document.createElement('form');
952let dims = document.createElement('input');
953dims.name = 'dims';
954dims.value = p.toString();
955let sub = document.createElement('input');
956sub.type = 'submit';
957sub.value = 'New maze!';
958form.appendChild( dims );
959form.appendChild( document.createTextNode(' ') );
960form.appendChild( sub );
961let pExp = document.createElement('p');
962pExp.appendChild(
963 document.createTextNode(
964 'Provide a number below for each dimension in the new maze. The numbers are the size of each dimension. Entering "10, 3" will create a maze that is 10 wide and 3 tall. Entering "5, 5, 5, 5, 5" will create a 5 dimensional maze, every dimension will be 5 wide.'
965 )
966 );
967formDiv.appendChild( pExp );
968formDiv.appendChild( form );
969document.body.appendChild( document.createElement('br') );
970document.body.appendChild( formDiv );
971
972let d = document.createElement('div');
973let dLink = document.createElement('a');
974let trgUrl = document.location.toString();
975let query = trgUrl.indexOf('?');
976if( query >= 0 )
977{
978 trgUrl = trgUrl.substring(0, query);
979}
980trgUrl += '?seed=' + lRand.getSeed() + '&dims=' + p.toString();
981dLink.href = trgUrl;
982dLink.appendChild( document.createTextNode('Share this maze!') );
983d.appendChild(dLink);
984document.body.appendChild( document.createElement('br') );
985document.body.appendChild( d );