diff --git a/cube2/assets/OutThere_0.ogg b/cube2/assets/OutThere_0.ogg
new file mode 100644
index 00000000..975ecb12
Binary files /dev/null and b/cube2/assets/OutThere_0.ogg differ
diff --git a/cube2/assets/alarmcreatemiltaryfoot_1.ogg b/cube2/assets/alarmcreatemiltaryfoot_1.ogg
new file mode 100644
index 00000000..7702df51
Binary files /dev/null and b/cube2/assets/alarmcreatemiltaryfoot_1.ogg differ
diff --git a/cube2/assets/bg.jpg b/cube2/assets/bg.jpg
new file mode 100644
index 00000000..2cb56189
Binary files /dev/null and b/cube2/assets/bg.jpg differ
diff --git a/cube2/assets/fonts/BEBAS___-webfont.eot b/cube2/assets/fonts/BEBAS___-webfont.eot
new file mode 100755
index 00000000..bf9d4313
Binary files /dev/null and b/cube2/assets/fonts/BEBAS___-webfont.eot differ
diff --git a/cube2/assets/fonts/BEBAS___-webfont.svg b/cube2/assets/fonts/BEBAS___-webfont.svg
new file mode 100755
index 00000000..e016b655
--- /dev/null
+++ b/cube2/assets/fonts/BEBAS___-webfont.svg
@@ -0,0 +1,132 @@
+
+
+
\ No newline at end of file
diff --git a/cube2/assets/fonts/BEBAS___-webfont.ttf b/cube2/assets/fonts/BEBAS___-webfont.ttf
new file mode 100755
index 00000000..bb74dd7c
Binary files /dev/null and b/cube2/assets/fonts/BEBAS___-webfont.ttf differ
diff --git a/cube2/assets/fonts/BEBAS___-webfont.woff b/cube2/assets/fonts/BEBAS___-webfont.woff
new file mode 100755
index 00000000..cf0fa4ce
Binary files /dev/null and b/cube2/assets/fonts/BEBAS___-webfont.woff differ
diff --git a/cube2/assets/fonts/OpenSans-Bold.ttf b/cube2/assets/fonts/OpenSans-Bold.ttf
new file mode 100755
index 00000000..fd79d43b
Binary files /dev/null and b/cube2/assets/fonts/OpenSans-Bold.ttf differ
diff --git a/cube2/assets/fonts/OpenSans-Italic.ttf b/cube2/assets/fonts/OpenSans-Italic.ttf
new file mode 100755
index 00000000..c90da48f
Binary files /dev/null and b/cube2/assets/fonts/OpenSans-Italic.ttf differ
diff --git a/cube2/assets/fonts/OpenSans-Regular.ttf b/cube2/assets/fonts/OpenSans-Regular.ttf
new file mode 100755
index 00000000..db433349
Binary files /dev/null and b/cube2/assets/fonts/OpenSans-Regular.ttf differ
diff --git a/cube2/readme.txt b/cube2/assets/readme.txt
similarity index 100%
rename from cube2/readme.txt
rename to cube2/assets/readme.txt
diff --git a/cube2/assets/screenshots/01.png b/cube2/assets/screenshots/01.png
new file mode 100644
index 00000000..0802fddc
Binary files /dev/null and b/cube2/assets/screenshots/01.png differ
diff --git a/cube2/assets/screenshots/02.png b/cube2/assets/screenshots/02.png
new file mode 100644
index 00000000..5a7a0e81
Binary files /dev/null and b/cube2/assets/screenshots/02.png differ
diff --git a/cube2/assets/screenshots/03.png b/cube2/assets/screenshots/03.png
new file mode 100644
index 00000000..d55477f4
Binary files /dev/null and b/cube2/assets/screenshots/03.png differ
diff --git a/cube2/assets/screenshots/04.jpg b/cube2/assets/screenshots/04.jpg
new file mode 100644
index 00000000..236bd7fe
Binary files /dev/null and b/cube2/assets/screenshots/04.jpg differ
diff --git a/cube2/assets/screenshots/05.jpg b/cube2/assets/screenshots/05.jpg
new file mode 100644
index 00000000..bfb24cd3
Binary files /dev/null and b/cube2/assets/screenshots/05.jpg differ
diff --git a/cube2/assets/screenshots/06.jpg b/cube2/assets/screenshots/06.jpg
new file mode 100644
index 00000000..ad1d7e07
Binary files /dev/null and b/cube2/assets/screenshots/06.jpg differ
diff --git a/cube2/assets/screenshots/07.jpg b/cube2/assets/screenshots/07.jpg
new file mode 100644
index 00000000..80edb2e7
Binary files /dev/null and b/cube2/assets/screenshots/07.jpg differ
diff --git a/cube2/assets/screenshots/08.jpg b/cube2/assets/screenshots/08.jpg
new file mode 100644
index 00000000..f4907358
Binary files /dev/null and b/cube2/assets/screenshots/08.jpg differ
diff --git a/cube2/assets/screenshots/09.jpg b/cube2/assets/screenshots/09.jpg
new file mode 100644
index 00000000..bc1beed3
Binary files /dev/null and b/cube2/assets/screenshots/09.jpg differ
diff --git a/cube2/assets/screenshots/10.jpg b/cube2/assets/screenshots/10.jpg
new file mode 100644
index 00000000..498e2e93
Binary files /dev/null and b/cube2/assets/screenshots/10.jpg differ
diff --git a/cube2/assets/screenshots/11.jpg b/cube2/assets/screenshots/11.jpg
new file mode 100644
index 00000000..1fd114b4
Binary files /dev/null and b/cube2/assets/screenshots/11.jpg differ
diff --git a/cube2/assets/screenshots/12.jpg b/cube2/assets/screenshots/12.jpg
new file mode 100644
index 00000000..cf90baaf
Binary files /dev/null and b/cube2/assets/screenshots/12.jpg differ
diff --git a/cube2/assets/screenshots/13.jpg b/cube2/assets/screenshots/13.jpg
new file mode 100644
index 00000000..a3777971
Binary files /dev/null and b/cube2/assets/screenshots/13.jpg differ
diff --git a/cube2/assets/screenshots/14.jpg b/cube2/assets/screenshots/14.jpg
new file mode 100644
index 00000000..f1fa63f6
Binary files /dev/null and b/cube2/assets/screenshots/14.jpg differ
diff --git a/cube2/assets/screenshots/15.jpg b/cube2/assets/screenshots/15.jpg
new file mode 100644
index 00000000..d23b7fff
Binary files /dev/null and b/cube2/assets/screenshots/15.jpg differ
diff --git a/cube2/assets/screenshots/16.jpg b/cube2/assets/screenshots/16.jpg
new file mode 100644
index 00000000..9720b939
Binary files /dev/null and b/cube2/assets/screenshots/16.jpg differ
diff --git a/cube2/assets/screenshots/21.jpg b/cube2/assets/screenshots/21.jpg
new file mode 100644
index 00000000..92d212b8
Binary files /dev/null and b/cube2/assets/screenshots/21.jpg differ
diff --git a/cube2/assets/screenshots/22.jpg b/cube2/assets/screenshots/22.jpg
new file mode 100644
index 00000000..72b0c674
Binary files /dev/null and b/cube2/assets/screenshots/22.jpg differ
diff --git a/cube2/assets/screenshots/23.jpg b/cube2/assets/screenshots/23.jpg
new file mode 100644
index 00000000..bca5100b
Binary files /dev/null and b/cube2/assets/screenshots/23.jpg differ
diff --git a/cube2/assets/screenshots/24.jpg b/cube2/assets/screenshots/24.jpg
new file mode 100644
index 00000000..e1f1a043
Binary files /dev/null and b/cube2/assets/screenshots/24.jpg differ
diff --git a/cube2/assets/screenshots/25.jpg b/cube2/assets/screenshots/25.jpg
new file mode 100644
index 00000000..d6f123b3
Binary files /dev/null and b/cube2/assets/screenshots/25.jpg differ
diff --git a/cube2/assets/screenshots/26.jpg b/cube2/assets/screenshots/26.jpg
new file mode 100644
index 00000000..45bd9844
Binary files /dev/null and b/cube2/assets/screenshots/26.jpg differ
diff --git a/cube2/css/style.css b/cube2/css/style.css
new file mode 100644
index 00000000..e4a18d53
--- /dev/null
+++ b/cube2/css/style.css
@@ -0,0 +1,481 @@
+@font-face {
+ font-family: 'Open Sans';
+ font-style: italic;
+ font-weight: 400;
+ src: local('Open Sans Italic'), local('Open-Sans-Italic'),
+ url('../assets/fonts/OpenSans-Italic.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Open Sans Bold'), local('Open-Sans-Bold'),
+ url('../assets/fonts/OpenSans-Bold.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: 'Open Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Open Sans Regular'), local('Open-Sans-Regular'),
+ url('../assets/fonts/OpenSans-Regular.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: 'Bebas';
+ font-weight: 400;
+ src: local('Bebas'), local('Bebas'),
+ url('../assets/fonts/BEBAS___-webfont.ttf') format('truetype');
+}
+
+html {
+}
+
+body {
+ font: 14pt 'Open Sans';
+ background: url('../assets/bg.jpg');
+ background: -moz-linear-gradient(left, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 20%, rgba(0,0,0,0) 80%, rgba(0,0,0,1) 100%), url('../assets/bg.jpg'); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,1)), color-stop(20%,rgba(0,0,0,0)), color-stop(80%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,1))), url('../assets/bg.jpg'); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(left, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0) 80%,rgba(0,0,0,1) 100%), url('../assets/bg.jpg'); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(left, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0) 80%,rgba(0,0,0,1) 100%), url('../assets/bg.jpg'); /* Opera 11.10+ */
+ background: -ms-linear-gradient(left, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0) 80%,rgba(0,0,0,1) 100%), url('../assets/bg.jpg'); /* IE10+ */
+ background: linear-gradient(to right, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0) 80%,rgba(0,0,0,1) 100%), url('../assets/bg.jpg'); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#000000',GradientType=1 ); /* IE6-9 */
+ color: rgb(200, 200, 200);
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #fff;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+
+#main-container {
+ margin: 0 auto;
+ width: 1150px;
+ position: relative;
+}
+
+#gallery {
+ width: 1150px;
+ height: 400px;
+ border: 1px solid rgba(25, 25, 25, 0.5);
+ box-shadow: 0 2px 10px rgba(25, 25, 25, 0.9);
+ margin-top: 30px;
+ margin-bottom: 10px;
+ overflow: hidden;
+ position: relative;
+ transition: height 0.5s ease-in-out;
+ -moz-transition: height 0.5s ease-ouin-out;
+ -webkit-transition: height 0.5s ease-in-out;
+ -o-transition: height 0.5s ease-in-out;
+ -ms-transition: height 0.5s ease-in-out;
+}
+
+#gallery .title {
+ text-shadow: rgba(25, 25, 25, 0.9) 0.1em 0.1em 0.1em;
+ font-family: 'Bebas';
+ font-size: 3.4em;
+ position: absolute;
+ left: 0.2em;
+ top: 0em;
+ z-index: 20;
+}
+
+#gallery .slide {
+ width: 1150px;
+ height: 400px;
+ background-size: cover;
+ display: block;
+ padding: 0;
+ margin: 0;
+ position: absolute;
+}
+
+#slide-container {
+ position: relative;
+}
+
+#gallery .slide {
+ background: #000;
+ text-align: center;
+}
+
+#gallery .slide img {
+ width: 100%;
+ position: relative;
+ top: -40%;
+}
+
+#gallery .slide video {
+ height: 100%;
+}
+
+#gallery .slide .video-overlay {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: rgba();
+}
+
+.slideable {
+ transition: all 0.5s ease-in-out;
+ -moz-transition: all 0.5s ease-ouin-out;
+ -webkit-transition: all 0.5s ease-in-out;
+ -o-transition: all 0.5s ease-in-out;
+ -ms-transition: all 0.5s ease-in-out;
+}
+
+#menu {
+ margin-top: 25px;
+ margin-left: 1.3%;
+}
+
+#menu .menu-item {
+ position: relative;
+ width: 32%;
+ height: 152px;
+ border: 1px solid rgba(25, 25, 25, 0.5);
+ box-shadow: 0 2px 10px rgba(25, 25, 25, 0.9);
+ display: inline-block;
+ background-size: 100% auto;
+ background-image: url('../assets/screenshots/22.jpg');
+ background-repeat: no-repeat;
+ font-family: 'Bebas';
+ overflow: hidden;
+}
+
+#menu .menu-item:nth-child(2),
+#menu .menu-item:nth-child(3) {
+ margin-left: 1%;
+}
+
+#menu .menu-item:nth-child(2) {
+ background-image: url('../assets/screenshots/15.jpg');
+}
+
+#menu .menu-item:nth-child(3) {
+ background-image: url('../assets/screenshots/14.jpg');
+}
+
+#menu .title {
+ font-size: 1.3em;
+ position: relative;
+ text-shadow: rgba(25, 25, 25, 0.9) 0.1em 0.1em 0.2em;
+ left: 0;
+ top: 0;
+ padding: 10px;
+ transition: all 0.25s ease-out;
+ -moz-transition: all 0.25s ease-out;
+ -webkit-transition: all 0.25s ease-out;
+ -o-transition: all 0.25s ease-out;
+ -ms-transition: all 0.25s;
+ z-index: 4;
+ cursor: pointer;
+}
+
+#menu .overlay {
+ opacity: 1;
+ transition: all 0.25s;
+ -moz-transition: all 0.25s;
+ -webkit-transition: all 0.25s;
+ -o-transition: all 0.25s;
+ -ms-transition: all 0.25s;
+ background: rgba(0, 0, 0, 0.5);
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8), -1px -1px 1px rgba(0, 0, 0, 0.8);
+ width: 100%;
+ height: 100%;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+}
+
+#menu .menu-item:hover .overlay {
+ opacity: 0;
+}
+
+#menu .menu-item .sub-title {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ font-size: 3em;
+ color: rgb(200, 200, 200);
+ transition: text-shadow 0.25s;
+ -moz-transition: text-shadow 0.25s;
+ -webkit-transition: text-shadow 0.25s;
+ -o-transition: text-shadow 0.25s;
+ -ms-transition: text-shadow 0.25s;
+}
+
+#menu .menu-item:hover .sub-title {
+ text-shadow: rgba(5, 5, 5, 0.95) 0.1em 0.1em 0.8em,
+ rgba(5, 5, 5, 0.95) 0.1em 0.1em 0.8em;
+}
+
+.section .title {
+ font-size: 2.0em;
+ text-shadow: rgba(25, 25, 25, 0.9) 0.1em 0.1em 0.2em;
+ padding-top: 10px;
+ font-family: 'Bebas';
+}
+
+.section {
+ margin: 5px;
+ margin-top: 25px;
+ box-shadow: 0px -1px 0 rgba(25, 25, 25, 0.5);
+}
+
+.section p, .section ul {
+ margin-left: 50px;
+ margin-right: 50px;
+}
+
+.section .more-button {
+ float: right;
+ font-size: 1.1em;
+}
+
+#slide-counter {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ padding: 5px;
+ padding-left: 0;
+}
+
+#slide-counter .slide-counter-node {
+ border-radius: 8px;
+ width: 7px;
+ height: 7px;
+ border: 1px solid #fff;
+ box-shadow: 1px 1px 3px rgba(5, 5, 5, 0.9);
+ float: right;
+ margin-left: 4px;
+ cursor: pointer;
+ background: transparent;
+ transition: background 0.5s;
+ -moz-transition: background 0.5s;
+ -webkit-transition: background 0.5s;
+ -o-transition: background 0.5s;
+ -ms-transition: background 0.5s;
+}
+
+#slide-counter .slide-counter-node:hover {
+ background: rgba(255, 255, 255, 0.8);
+}
+
+#slide-counter .slide-counter-node.on {
+ background: #fff;
+}
+
+#credits .role {
+ font-size: 1.2em;
+ margin-left: 2em;
+ margin-top: 1em;
+}
+
+#credits .name {
+ font-family: 'Bebas';
+ font-size: 1.6em;
+ margin-left: 1.3em;
+}
+
+#credits .sub-name {
+ font-family: 'Open Sans';
+ font-size: 0.5em;
+}
+
+footer {
+ height: 100px;
+ width: 100%;
+}
+
+.demo-title {
+ text-shadow: rgba(25, 25, 25, 0.9) 0.1em 0.1em 0.1em;
+ font-family: 'Bebas';
+ font-size: 3.4em;
+}
+
+.progress-area {
+ box-shadow: none;
+}
+
+canvas.paused {
+ opacity: 0.4;
+}
+
+.status {
+ position: relative;
+ margin: 0 auto;
+ width: 960px;
+ height: 600px;
+ text-align: center;
+ background: rgba(0, 0, 0, 0.4);
+ margin-top: 20px;
+}
+
+.status-content {
+ width: 960px;
+ height: 600px;
+ position: absolute;
+ display: block;
+ top: 0;
+ left: 0;
+}
+
+.status .hide {
+ display: none;
+}
+
+.status .resolution-message {
+ margin-top: 140px;
+ margin-bottom: 30px;
+}
+
+.status .fullscreen-button {
+ display: inline-block;
+ width: 300px;
+ height: 200px;
+ box-shadow: 0 2px 10px rgba(25, 25, 25, 0.9);
+ line-height: 200px;
+ cursor: pointer;
+ font-family: 'Bebas';
+ background: rgb(206,220,231); /* Old browsers */
+ background: -moz-linear-gradient(top, rgba(206,220,231,1) 0%, rgba(89,106,114,1) 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(206,220,231,1)), color-stop(100%,rgba(89,106,114,1))); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, rgba(206,220,231,1) 0%,rgba(89,106,114,1) 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, rgba(206,220,231,1) 0%,rgba(89,106,114,1) 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, rgba(206,220,231,1) 0%,rgba(89,106,114,1) 100%); /* IE10+ */
+ background: linear-gradient(to bottom, rgba(206,220,231,1) 0%,rgba(89,106,114,1) 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cedce7', endColorstr='#596a72',GradientType=0 ); /* IE6-9 */
+ margin-bottom: 2em;
+}
+
+.status-content.resume {
+ z-index: 30;
+ margin-top: 200px;
+}
+
+.status .loading .preview {
+ width: 100%;
+ height: 100%;
+}
+
+.status .loading .progress-container {
+ position: absolute;
+ width: 100%;
+ bottom: 10px;
+}
+
+.status .loading .progress-container.hide {
+ display: none;
+}
+
+.status .loading {
+ position: relative;
+}
+
+.status .loading progress {
+ display: block;
+ width: 600px;
+ margin: 10px auto;
+ z-index: 2;
+}
+
+.level-title {
+ text-shadow: rgba(25, 25, 25, 1.0) 0.1em 0.1em 0.1em;
+ position: absolute;
+ text-align: right;
+ font-family: 'Bebas';
+ font-size: 1.8em;
+ top: 0;
+ right: 20px;
+}
+
+.level-title span {
+ font-size: 2.0em;
+ margin-left: 10px;
+ position: relative;
+ top: 0.2em;
+}
+
+.preview-content {
+ width: 100%;
+ height: 100%;
+ display: none;
+}
+
+.preview-content.show {
+ display: block;
+}
+
+.preview-content.low {
+ background: url('../assets/screenshots/22.jpg');
+ background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.8) 10%, rgba(0,0,0,0.2) 30%, rgba(0,0,0,0) 60%), url('../assets/screenshots/22.jpg');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(10%,rgba(0,0,0,0.8)), color-stop(30%,rgba(0,0,0,0.2)), color-stop(60%,rgba(0,0,0,0))), url('../assets/screenshots/22.jpg');
+ background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/22.jpg');
+ background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/22.jpg');
+ background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/22.jpg');
+ background: linear-gradient(to bottom, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/22.jpg');
+ background-position: 5% 5%;
+ background-size: 110% 110%;
+}
+
+.preview-content.medium {
+ background: url('../assets/screenshots/02.png');
+ background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.8) 10%, rgba(0,0,0,0.2) 30%, rgba(0,0,0,0) 60%), url('../assets/screenshots/02.png');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(10%,rgba(0,0,0,0.8)), color-stop(30%,rgba(0,0,0,0.2)), color-stop(60%,rgba(0,0,0,0))), url('../assets/screenshots/02.png');
+ background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/02.png');
+ background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/02.png');
+ background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/02.png');
+ background: linear-gradient(to bottom, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/02.png');
+ background-position: 5% 5%;
+ background-size: 110% 110%;
+}
+
+.preview-content.high {
+ background: url('../assets/screenshots/14.jpg');
+ background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.8) 10%, rgba(0,0,0,0.2) 30%, rgba(0,0,0,0) 60%), url('../assets/screenshots/14.jpg');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(10%,rgba(0,0,0,0.8)), color-stop(30%,rgba(0,0,0,0.2)), color-stop(60%,rgba(0,0,0,0))), url('../assets/screenshots/14.jpg');
+ background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/14.jpg');
+ background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/14.jpg');
+ background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/14.jpg');
+ background: linear-gradient(to bottom, rgba(0,0,0,1) 0%,rgba(0,0,0,0.8) 10%,rgba(0,0,0,0.2) 30%,rgba(0,0,0,0) 60%), url('../assets/screenshots/14.jpg');
+ background-position: 5% 5%;
+ background-size: 110% 110%;
+}
+
+.preview-content .description {
+ color: rgb(240, 240, 240);
+ text-shadow: rgba(0, 0, 0, 1.0) 2px 2px 2px, rgba(0, 0, 0, 1.0) 2px 2px 2px;
+ font-size: 18pt;
+ width: 550px;
+ position: absolute;
+ top: 5em;
+ right: 20px;
+ text-align: left;
+ padding-top: 10px;
+}
+
+.status-content.error {
+ z-index: 50;
+ background: rgba(20, 20, 20, 0.9);
+}
+
+.status-content.error .title {
+ font-family: 'Bebas';
+ font-size: 7em;
+}
+
+.status-content.error p a {
+ font-weight: bold;
+}
diff --git a/cube2/js/game-setup.js b/cube2/js/game-setup.js
new file mode 100644
index 00000000..a0549d36
--- /dev/null
+++ b/cube2/js/game-setup.js
@@ -0,0 +1,453 @@
+
+// Setup compiled code parameters and interaction with the web page
+var Module = {
+ failed: false,
+ preRun: [],
+ postRun: [],
+ preloadPlugins: [],
+ print: function(text) {
+ console.log('[STDOUT] ' + text);
+ },
+ printErr: function(text) {
+ console.log(text);
+ },
+ canvas: document.getElementById('canvas'),
+ statusMessage: 'Starting...',
+ setStatus: function(text) {
+ if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var statusElement = document.getElementById('status-text');
+ var progressElement = document.getElementById('progress');
+ if (m) {
+ text = m[1];
+ progressElement.value = parseInt(m[2])*100;
+ progressElement.max = parseInt(m[4])*100;
+ progressElement.hidden = false;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ }
+ statusElement.innerHTML = text;
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+ },
+ onFullScreen: function(isFullScreen) {
+ if (isFullScreen) {
+ Module.resumeMainLoop();
+ Module.setOpacity(1);
+ Module.setStatus('');
+ document.querySelector('.status .resume').classList.add( 'hide' );
+ document.querySelector('canvas').classList.remove( 'paused' );
+ //BananaBread.execute('musicvol $oldmusicvol'); // XXX TODO: need to restart the music by name here
+ } else {
+ Module.pauseMainLoop();
+ Module.setOpacity(0.333);
+ Module.setStatus('paused (enter fullscreen to resume)');
+ document.querySelector('canvas').classList.add( 'paused' );
+ document.querySelector('.status .resume').classList.remove( 'hide' );
+ //BananaBread.execute('oldmusicvol = $musicvol ; musicvol 0');
+ }
+ }
+};
+
+// Checks for features we cannot run without
+// Note: Modify this for your needs. If your level does not use
+// texture compression, remove the check for it here.
+
+(function() {
+ function fail(text) {
+ Module._main = null;
+ document.querySelector('.status-content.error .details').innerHTML = text + ' is missing.';
+ document.querySelector('.status-content.loading .progress-container').classList.add('hide');
+ document.querySelector('.status-content.error').classList.remove('hide');
+ Module.failed = true;
+ }
+ var canvas = document.createElement('canvas');
+ if (!canvas) fail('canvas element');
+ var context = canvas.getContext('experimental-webgl');
+ if (!context) fail('WebGL');
+ var s3tc = context.getExtension('WEBGL_compressed_texture_s3tc') ||
+ context.getExtension('MOZ_WEBGL_compressed_texture_s3tc') ||
+ context.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
+ if (!s3tc) fail('texture compression');
+ var pointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'];
+ if (!pointerLock) fail('pointer lock/mouse lock');
+})();
+
+// Loading music. Will be stopped once the first frame of the game runs
+
+Module.loadingMusic = new Audio();
+Module.loadingMusic.src = 'assets/OutThere_0.ogg';
+Module.loadingMusic.play();
+
+Module.readySound = new Audio();
+Module.readySound.src = 'assets/alarmcreatemiltaryfoot_1.ogg';
+
+// Pre-unzip ogz files, we can do this in parallel in a worker during preload
+
+(function() {
+ var zeeWorker = new Worker('game/zee-worker.js');
+
+ var zeeCallbacks = [];
+
+ zeeWorker.onmessage = function(msg) {
+ zeeCallbacks[msg.data.callbackID](msg.data.data);
+ console.log("zee'd " + msg.data.filename + ' in ' + msg.data.time + ' ms, ' + msg.data.data.length + ' bytes');
+ zeeCallbacks[msg.data.callbackID] = null;
+ };
+
+ function requestZee(filename, data, callback) {
+ zeeWorker.postMessage({
+ filename: filename,
+ data: data,
+ callbackID: zeeCallbacks.length
+ });
+ zeeCallbacks.push(callback);
+ }
+
+ Module.postRun.push(function() {
+ zeeWorker.terminate();
+ });
+
+ Module.preloadPlugins.push({
+ canHandle: function(name) {
+ return name.substr(-4) == '.ogz';
+ },
+ handle: function(byteArray, name, onload, onerror) {
+ requestZee(name, byteArray, function(byteArray) {
+ onload(byteArray);
+ });
+ }
+ });
+})();
+
+// Hooks
+
+Module.setOpacity = function(opacity) {
+ var rule = 'canvas.emscripten';
+ var more = 'border: 1px solid black';
+ var styleSheet = document.styleSheets[0];
+ var rules = styleSheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].cssText.substr(0, rule.length) == rule) {
+ styleSheet.deleteRule(i);
+ i--;
+ }
+ }
+ styleSheet.insertRule(rule + ' { opacity: ' + opacity + '; ' + (more || '') + ' }', 0);
+}
+
+Module.setOpacity(0.1);
+
+Module.postLoadWorld = function() {
+ document.title = 'BananaBread';
+
+ if (Module.loadingMusic) {
+ Module.loadingMusic.pause();
+ Module.loadingMusic = null;
+ }
+ Module.tweakDetail();
+
+ BananaBread.execute('sensitivity 10');
+ BananaBread.execute('clearconsole');
+
+ setTimeout(function() {
+ BananaBread.execute('oldmusicvol = $musicvol ; musicvol 0');
+ }, 1); // Do after startup finishes so music will be prepared up
+
+ // Pause and fade out until the user presses fullscreen
+
+ Module.pauseMainLoop();
+ setTimeout(function() {
+ document.querySelector('.status-content.loading').classList.add('hide');
+ document.querySelector('.status-content.fullscreen-buttons').classList.remove('hide');
+ }, 0);
+
+ Module.resume = function() {
+ Module.requestFullScreen();
+ Module.setOpacity(1);
+ Module.setStatus('');
+ Module.resumeMainLoop();
+ };
+
+ Module.fullscreenLow = function() {
+ document.querySelector('.status-content.fullscreen-buttons').classList.add('hide');
+ document.querySelector('canvas').classList.remove('hide');
+ Module.requestFullScreen();
+ Module.setOpacity(1);
+ Module.setStatus('');
+ Module.resumeMainLoop();
+ };
+
+ Module.fullscreenHigh = function() {
+ document.querySelector('.status-content.fullscreen-buttons').classList.add('hide');
+ document.querySelector('canvas').classList.remove('hide');
+ Module.requestFullScreen();
+ Module.setOpacity(1);
+ Module.setStatus('');
+ BananaBread.execute('screenres ' + screen.width + ' ' + screen.height);
+ Module.resumeMainLoop();
+ };
+
+ // All set!
+ Module.readySound.play();
+ Module.readySound = null;
+};
+
+Module.autoexec = function(){}; // called during autoexec on load, so useful to tweak settings that require gl restart
+Module.tweakDetail = function(){}; // called from postLoadWorld, so useful to make changes after the map has been loaded
+
+(function() {
+ var fraction = 0.70;
+ var desired = Math.min(fraction*screen.availWidth, fraction*screen.availHeight, 600);
+ var w, h;
+ if (screen.width >= screen.height) {
+ h = desired;
+ w = Math.floor(desired * screen.width / screen.height);
+ } else {
+ w = desired;
+ h = Math.floor(desired * screen.height / screen.width);
+ }
+ Module.desiredWidth = w;
+ Module.desiredHeight = h;
+})();
+
+// Public API
+
+var BananaBread = {
+ init: function() {
+ BananaBread.setPlayerModelInfo = Module.cwrap('_ZN4game18setplayermodelinfoEPKcS1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_b', null,
+ ['string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'number']);
+ BananaBread.execute = Module.cwrap('_Z7executePKc', 'number', ['string']);
+ BananaBread.executeString = Module.cwrap('_Z10executestrPKc', 'string', ['string']);
+
+ var forceCamera = Module.cwrap('setforcecamera', null, ['number', 'number', 'number', 'number', 'number', 'number']);
+ BananaBread.forceCamera = function(position, orientation) {
+ forceCamera(position[0], position[1], position[2], orientation[0], orientation[1], orientation[2]);
+ };
+
+ BananaBread.PARTICLE = {};
+ var i = 0;
+ BananaBread.PARTICLE.BLOOD = (i++);
+ BananaBread.PARTICLE.WATER = (i++);
+ BananaBread.PARTICLE.SMOKE = (i++);
+ BananaBread.PARTICLE.STEAM = (i++);
+ BananaBread.PARTICLE.FLAME = (i++);
+ BananaBread.PARTICLE.FIREBALL1 = (i++);
+ BananaBread.PARTICLE.FIREBALL2 = (i++);
+ BananaBread.PARTICLE.FIREBALL3 = (i++);
+ BananaBread.PARTICLE.STREAK = (i++);
+ BananaBread.PARTICLE.LIGHTNING = (i++);
+ BananaBread.PARTICLE.EXPLOSION = (i++);
+ BananaBread.PARTICLE.EXPLOSION_BLUE = (i++);
+ BananaBread.PARTICLE.SPARK = (i++);
+ BananaBread.PARTICLE.EDIT = (i++);
+ BananaBread.PARTICLE.SNOW = (i++);
+ BananaBread.PARTICLE.MUZZLE_FLASH1 = (i++);
+ BananaBread.PARTICLE.MUZZLE_FLASH2 = (i++);
+ BananaBread.PARTICLE.MUZZLE_FLASH3 = (i++);
+ BananaBread.PARTICLE.HUD_ICON = (i++);
+ BananaBread.PARTICLE.HUD_ICON_GREY = (i++);
+ BananaBread.PARTICLE.TEXT = (i++);
+ BananaBread.PARTICLE.METER = (i++);
+ BananaBread.PARTICLE.METER_VS = (i++);
+ BananaBread.PARTICLE.LENS_FLARE = (i++);
+ var splash = Module.cwrap('bb_splash', null, ['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number']);
+ BananaBread.splash = function(type, color, radius, num, fade, p, size, gravity) {
+ splash(type, color, radius, num, fade, p[0], p[1], p[2], size, gravity);
+ };
+
+ var playSoundName = Module.cwrap('bb_playsoundname', null, ['string', 'number', 'number', 'number']);
+ BananaBread.playSound = function(name, position) {
+ playSoundName(name, position[0], position[1], position[2]);
+ };
+ },
+};
+
+Module.postRun.push(BananaBread.init);
+Module.postRun.push(function() {
+ var n = 0;
+ for (var x in Module.preloadedAudios) n++;
+ console.log('successfully preloaded audios: ' + n);
+ if (n == 0) alert('Your browser could not load the audio files. Running will continue without sound effects.');
+});
+
+// Additional APIs
+
+BananaBread.Utils = {
+ randomPick: function(items) {
+ return items[Math.floor(Math.random()*items.length)];
+ },
+};
+
+BananaBread.Event = function(data) {
+ this.run = function() {
+ var start = Date.now();
+ var last = start;
+ function iteration() {
+ var now = Date.now();
+ var ms = now - last;
+ last = now;
+ if (ms > data.totalMs) return;
+ data.onFrame(ms);
+ Module.requestAnimationFrame(iteration);
+ }
+ iteration();
+ };
+ if (data.onInit) data.onInit(data);
+}
+
+BananaBread.Effects = {
+ Fireworks: function(shots) {
+ var event = new BananaBread.Event({
+ totalMs: Infinity,
+
+ onFrame: function(ms) {
+
+ var secs = ms/1000;
+ var newShots = [];
+
+ shots = shots.filter(function(shot) {
+ LinearMath.vec3.add(shot.position, LinearMath.vec3.scale(LinearMath.vec3.create(shot.velocity), secs));
+ shot.velocity[2] -= secs * 200; // gravity
+ shot.msLeft -= ms;
+ if (shot.msLeft > 0) {
+ BananaBread.splash(BananaBread.PARTICLE.SPARK, 0xffffff, 1, 20, Math.max(50, ms*2), shot.position, 1, 1);
+ return true;
+ } else {
+ var size = Math.ceil(Math.random()*3); // 1, 2 or 3
+ var color;
+ for (var i = 0; i < 2; i++) {
+ color = Math.floor(Math.random()*255) + (Math.floor(Math.random()*255) << 8) + (Math.floor(Math.random()*255) << 16);
+ BananaBread.splash(BananaBread.PARTICLE.SPARK, color, 100+25*size, 7+3*size, Math.max(300, ms*7), shot.position, 1+size, 1);
+ }
+ if (size > 1) {
+ BananaBread.splash(BananaBread.PARTICLE.EXPLOSION, color, 0, 1, Math.max(175, ms*3), shot.position, 5*size, 0);
+ }
+ BananaBread.playSound(size == 3 ? 'q009/explosion.ogg' : 'olpc/MichaelBierylo/sfx_DoorSlam.wav', shot.position);
+ return false;
+ }
+ });
+
+ shots.push.apply(shots, newShots);
+
+ if (shots.length == 0) this.totalMs = 0;
+ },
+ });
+
+ event.run();
+ }
+};
+
+function CameraPath(data) { // TODO: namespace this
+ var steps = data.steps;
+ var n = data.steps.length;
+ var timeScale = data.timeScale;
+ var position = LinearMath.vec3.create();
+ var temp = LinearMath.vec3.create();
+ var orientation = LinearMath.vec3.create();
+ var cancelled = false;
+ var sigma = data.sigma || 0.75;
+ var lasti = -1;
+ var debug = data.debug;
+ var loop = data.loop;
+
+ if (!data.uncancellable) addEventListener('keydown', function() { cancelled = true });
+
+ this.execute = function() {
+ var startTime = Date.now();
+ function moveCamera() {
+ if (cancelled) return;
+ var now = Date.now();
+ var t = (Date.now() - startTime)/(timeScale*1000);
+ if (t > n-1 && !loop) return;
+ var i = Math.round(t);
+ if (debug && i != lasti) {
+ lasti = i;
+ alert('now on ' + i);
+ startTime += (Date.now() - now); // ignore alert wait time
+ }
+ var factors = 0;
+ position[0] = position[1] = position[2] = orientation[0] = orientation[1] = orientation[2] = 0;
+ for (var j = i-2; j <= i+2; j++) {
+ var jj = j;
+ if (loop && jj >= n) jj = jj % n;
+ var curr = steps[jj];
+ if (!curr) continue;
+ var factor = Math.exp(-Math.pow((j-t)/sigma, 2));
+ LinearMath.vec3.scale(curr.position, factor, temp);
+ LinearMath.vec3.add(position, temp);
+ LinearMath.vec3.scale(curr.orientation, factor, temp);
+ LinearMath.vec3.add(orientation, temp);
+ factors += factor;
+ }
+ LinearMath.vec3.scale(position, 1/factors);
+ LinearMath.vec3.scale(orientation, 1/factors);
+ BananaBread.forceCamera(position, orientation);
+ Module.requestAnimationFrame(moveCamera);
+ }
+ moveCamera();
+ }
+}
+
+// Load scripts
+
+(function() {
+ function loadChildScript(name, then) {
+ var js = document.createElement('script');
+ if (then) js.onload = then;
+ js.src = name;
+ document.body.appendChild(js);
+ }
+
+ var queryString = window.location.search ? window.location.search.substring(1) : "";
+ var urlParts, debug;
+
+ try {
+ urlParts = queryString.split(',');
+ debug = queryString.indexOf('debug') >= 0;
+ }
+ catch(e){
+ // default to sanity if url parsing fails
+ urlParts = 'low,low';
+ debug = false;
+ }
+
+ var setup = urlParts[0], preload = urlParts[1];
+
+ var levelTitleContainer = document.querySelector('.level-title span');
+ var levelTitle = setup === 'high' ? 'Lava Chamber' : setup === 'medium' ? 'Two Towers' : 'Arena';
+ levelTitleContainer.innerHTML = levelTitle;
+
+ var previewContainer = document.querySelector('.preview-content.' + setup );
+ previewContainer.classList.add('show');
+
+ if(!Module.failed){
+ loadChildScript('game/setup_' + setup + '.js', function() {
+ loadChildScript('game/preload_' + preload + '.js', function() {
+ loadChildScript('game/bb' + (debug ? '.debug' : '') + '.js');
+ });
+ });
+ }
+})();
+
+(function(){
+ var lowResButton = document.querySelector('.fullscreen-button.low-res');
+ var highResButton = document.querySelector('.fullscreen-button.high-res');
+ var resumeButton = document.querySelector('.resume .fullscreen-button');
+ lowResButton.addEventListener('click', function(e){
+ Module.fullscreenLow();
+ }, false);
+ highResButton.addEventListener('click', function(e){
+ Module.fullscreenHigh();
+ }, false);
+ resumeButton.addEventListener('click', function(e){
+ Module.resume();
+ }, false);
+})();
diff --git a/cube2/js/main.js b/cube2/js/main.js
new file mode 100644
index 00000000..0e7fbf08
--- /dev/null
+++ b/cube2/js/main.js
@@ -0,0 +1,121 @@
+(function(){
+
+ var SLIDE_DURATION = 5000;
+
+ function makeAnchor(element){
+ element.addEventListener('click', function(){
+ // set to null first to make browser jump here regardless of whether or not hash is already set
+ window.location.hash = null;
+ window.location.hash = element.getAttribute('data-anchor');
+ }, false);
+ }
+
+ function setupGallery(){
+ var interval = -1;
+ var external;
+ var slides = [];
+
+ function Slide(element, left, counterNode){
+ element.style.top = '0px';
+ element.style.left = left + 'px';
+
+ var video = element.querySelector('video');
+
+ function onVideoPlay(){
+ external.stop();
+ }
+
+ function onVideoPause(){
+ }
+
+ function onVideoEnded(){
+ external.start();
+ }
+
+ return {
+ enter: function(skipSlideIn){
+ counterNode.className = 'slide-counter-node on';
+ if(video){
+ if(video.readyState > 0){
+ video.currentTime = 0;
+ }
+ video.setAttribute('disabled', true);
+ video.addEventListener('play', onVideoPlay, false);
+ video.addEventListener('ended', onVideoEnded, false);
+ video.addEventListener('pause', onVideoPause, false);
+ }
+ },
+ exit: function(){
+ counterNode.className = 'slide-counter-node';
+ if(video){
+ video.pause();
+ video.setAttribute('disabled', true);
+ video.removeEventListener('play', onVideoPlay, false);
+ video.removeEventListener('ended', onVideoEnded, false);
+ video.removeEventListener('pause', onVideoPause, false);
+ }
+ }
+ };
+ }
+
+ var gallery = document.getElementById('gallery');
+ var slidesElements = gallery.querySelectorAll('.slide');
+ var container = document.getElementById('slide-container');
+ var counter = document.getElementById('slide-counter');
+ var slideWidth = slidesElements[0].getBoundingClientRect().width;
+ var slideIndex = 0;
+
+ container.style.width = slideWidth * (slides.length + 1) + 'px';
+ slidesElements = Array.prototype.slice.apply(slidesElements);
+ slidesElements.forEach(function(slide, index){
+ var counterNode = document.createElement('div');
+ counterNode.className = 'slide-counter-node';
+ slides.push(new Slide(slide, index * slideWidth, counterNode, generateCounterNodeClickFunction(index, counterNode)));
+ counter.insertBefore(counterNode, counter.firstChild);
+ });
+
+ function generateCounterNodeClickFunction(index, counterNode){
+ counterNode.addEventListener('click', function(e){
+ external.stop();
+ goToSlide(index);
+ external.start();
+ }, false);
+ }
+
+ function goToSlide(nextIndex){
+ var oldSlideIndex = slideIndex;
+ slides[oldSlideIndex].exit();
+ slides[nextIndex].enter();
+ slideIndex = nextIndex;
+ container.style.left = -nextIndex * slideWidth + 'px';
+ }
+
+ function nextGallerySlide(){
+ goToSlide((slideIndex + 1) % slides.length);
+ }
+
+ slides[0].enter();
+
+ external = {
+ start: function(){
+ interval = setInterval(nextGallerySlide, SLIDE_DURATION);
+ },
+ stop: function(){
+ clearInterval(interval);
+ }
+ };
+
+ return external;
+ }
+
+ document.addEventListener('DOMContentLoaded', function(e){
+ var anchors = document.querySelectorAll('[data-anchor]');
+ for(var i=0, l=anchors.length; i