diff --git a/games/zelda.rom b/games/Zelda II.rom
similarity index 100%
rename from games/zelda.rom
rename to games/Zelda II.rom
diff --git a/static/css/main.css b/static/css/main.css
new file mode 100644
index 00000000..81e2cc66
--- /dev/null
+++ b/static/css/main.css
@@ -0,0 +1,455 @@
+#gamebody {
+ display: block;
+ width: 556px;
+ height: 278px;
+ background-color: #edf1f0;
+ -moz-border-radius: 30px;
+ -webkit-border-radius: 30px;
+ border-radius: 30px;
+ top: 50%;
+ left: 50%;
+ position: fixed;
+ transform: translate(-50%, -50%);
+
+ -webkit-box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+}
+
+
+#circle-pad-holder {
+ display: block;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 155px;
+ left: 30px;
+ background-color: #eaebeb;
+ -moz-border-radius: 50%;
+ -webkit-border-radius: 50%;
+ border-radius: 50%;
+ -webkit-box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: inset 0px 0px 2px 2px rgba(219, 222, 222, 1);
+}
+
+
+#circle-pad {
+ display: block;
+ width: 70px;
+ height: 70px;
+ position: absolute;
+ /* transform: translate(-50%, -50%);
+ -moz-transform: translate(-50%, -50%);
+ -webkit-transform: translate(-50%, -50%); */
+ top: 15px;
+ left: 15px;
+ background-color: #00f;
+ -moz-border-radius: 50%;
+ -webkit-border-radius: 50%;
+ border-radius: 50%;
+ -webkit-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+
+ opacity: 0.5;
+}
+
+
+.dpad {
+ width: 20px;
+ height: 20px;
+ display: block;
+ position: absolute;
+ background-color: #e4e5e5;
+ border: 2px solid rgba(219, 222, 222, 1);
+}
+
+
+#btn-up {
+ top: 18px;
+ left: 50%;
+ border-bottom: 0px;
+ transform: translateX(-50%);
+ -webkit-transform: translateX(-50%);
+ -moz-transform: translateX(-50%);
+}
+
+#btn-down {
+ bottom: 18px;
+ left: 50%;
+ border-top: 0px;
+ transform: translateX(-50%);
+ -webkit-transform: translateX(-50%);
+ -moz-transform: translateX(-50%);
+}
+
+
+#btn-left {
+ left: 18px;
+ top: 50%;
+ border-right: 0px;
+ transform: translateY(-50%);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+}
+
+#btn-right {
+ right: 18px;
+ top: 50%;
+ border-left: 0px;
+ transform: translateY(-50%);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+}
+
+
+#bottom-screen {
+ display: block;
+ width: 256px;
+ height: 240px;
+ position: absolute;
+ top: 20px;
+ left: 150px;
+ overflow: hidden;
+ background-color: #333;
+
+ -moz-border-radius: 5px 5px 5px 5px;
+ -webkit-border-radius: 5px 5px 5px 5px;
+ border-radius: 5px 5px 5px 5px;
+
+ -webkit-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+}
+
+#color-button-holder {
+ display: block;
+ width: 120px;
+ height: 120px;
+ position: absolute;
+ top: 135px;
+ left: 425px;
+}
+
+.btn {
+ display: block;
+ padding-top: 10px;
+ text-align: center;
+ width: 40px;
+ height: 30px;
+ position: absolute;
+ -moz-border-radius: 50%;
+ -webkit-border-radius: 50%;
+ border-radius: 50%;
+ -webkit-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+}
+
+
+.btn-big {
+ display: block;
+ padding-top: 5px;
+ text-align: center;
+ width: 100px;
+ height: 25px;
+ position: absolute;
+ -moz-border-radius: 25px;
+ -webkit-border-radius: 25px;
+ border-radius: 25px;
+ -webkit-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ -moz-box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+ box-shadow: 0px 0px 2px 2px rgba(219, 222, 222, 1);
+}
+
+#btn-load {
+ top: 30px;
+ left: 435px;
+ background-color: #f5a54b;
+}
+
+#btn-save {
+ top: 70px;
+ left: 435px;
+ background-color: #b844ee;
+}
+
+#btn-join {
+ background-color: #52f367;
+ top: 70px;
+ left: 20px;
+ border-radius: 25px 0 0 25px;
+ width: 55px;
+}
+
+#btn-quit {
+ background-color: #5947f5;
+ top: 70px;
+ left: 75px;
+ border-radius: 0px 25px 25px 0px;
+ width: 55px;
+}
+
+
+#btn-select {
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ -webkit-transform: translateX(-50%);
+ -moz-transform: translateX(-50%);
+ background-color: #6fa8eb;
+}
+
+#btn-start {
+ top: 50%;
+ left: 0;
+ transform: translateY(-50%);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ background-color: #43be85;
+}
+
+#btn-a {
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ -webkit-transform: translateX(-50%);
+ -moz-transform: translateX(-50%);
+ background-color: #ea6e4a;
+}
+
+
+#btn-b {
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ background-color: #d4b95e;
+}
+
+
+#lights-holder {
+ display: block;
+ width: 45px;
+ height: 10px;
+ position: absolute;
+ top: 0;
+ left: 460px;
+}
+
+#light-1 {
+ display: block;
+ width: 5px;
+ height: 10px;
+ background-color: #009BEB;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+#light-2 {
+ display: block;
+ width: 5px;
+ height: 10px;
+ background-color: #7a7e7d;
+ position: absolute;
+ top: 0;
+ left: 20px;
+}
+
+#light-3 {
+ display: block;
+ width: 5px;
+ height: 10px;
+ background-color: #7a7e7d;
+ position: absolute;
+ top: 0;
+ left: 40px;
+ animation: blink 1.5s cubic-bezier(1.0, 0, 0, 1.0) infinite;
+ -webkit-animation: blink 1.5s cubic-bezier(1.0, 0, 0, 1.0) infinite;
+ -moz-animation: blink 1.5s cubic-bezier(1.0, 0, 0, 1.0) infinite;
+}
+
+
+@-webkit-keyframes blink {
+ 0% {
+ background: #7a7e7d;
+ }
+
+ 100% {
+ background: yellow;
+ }
+}
+
+@-moz-keyframes blink {
+ 0% {
+ background: #7a7e7d;
+ }
+
+ 100% {
+ background: yellow;
+ }
+}
+
+@keyframes blink {
+ 0% {
+ background: #7a7e7d;
+ }
+
+ 100% {
+ background: yellow;
+ }
+}
+
+
+*.unselectable {
+ -moz-user-select: -moz-none;
+ -khtml-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+#room-txt {
+ position: absolute;
+ width: 110px;
+ top: 40px;
+ left: 25px;
+ padding-left: 2px;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
+ border-radius: 8px;
+}
+
+
+.pressed {
+ background-color: #333 !important;
+}
+
+
+#game-screen {
+ width: 100%;
+ height: 100%;
+ display: none;
+ background-color: #222222;
+}
+
+#menu-screen {
+ display:none;
+ width: 100%;
+ height: 100%;
+ background-image: url('https://data.whicdn.com/images/275493408/original.gif');
+ background-size: cover;
+}
+
+#menu-screen #box-art {
+ position: absolute;
+ width:55%;
+ height: 85%;
+ top: 5px;
+ left: 50%;
+ -webkit-transform: translate(-50%, -0%);
+ transform: translate(-50%, -0%);
+ border: 1px solid #ddd;
+}
+
+
+@font-face {
+ font-family: 'YourFontName'; /*a name to be used later*/
+ src: url('/static/fonts/8-Bit-Madness.ttf'); /*URL to font*/
+}
+
+#menu-screen #title {
+ position: absolute;
+ width:100%;
+ height: 10%;
+ bottom: 0px;
+ font-family: 'YourFontName';
+ overflow: hidden;
+}
+
+#menu-screen #title p {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ text-align: center;
+
+ /* Starting position */
+ -moz-transform:translateX(50%);
+ -webkit-transform:translateX(50%);
+ transform:translateX(50%);
+
+ /* Apply animation to this element */
+ -moz-animation: horizontally 5s linear infinite alternate;
+ -webkit-animation: horizontally 5s linear infinite alternate;
+ animation: horizontally 5s linear infinite alternate;
+}
+
+/* Move it (define the animation) */
+@-moz-keyframes horizontally {
+ 0% { -moz-transform: translateX(50%); }
+ 100% { -moz-transform: translateX(-50%); }
+}
+@-webkit-keyframes horizontally {
+ 0% { -webkit-transform: translateX(50%); }
+ 100% { -webkit-transform: translateX(-50%); }
+}
+@keyframes horizontally {
+ 0% { transform: translateX(50%); }
+ 100% { transform: translateX(-50%); }
+}
+
+
+#menu-screen .arrow {
+ position: absolute;
+ width:20px;
+ height: 20px;
+ right: 10px;
+ top: 50%;
+ -moz-transform: translate(0%, -50%);
+ -webkit-transform: translate(0%, -50%);
+ transform: translate(0%, -50%);
+
+ -moz-animation: breathing 1s infinite normal;
+ -webkit-animation: breathing 1s infinite normal;
+ animation: breathing 1s infinite normal;
+}
+
+#menu-screen .left {
+ left: 10px;
+ -webkit-transform: scaleX(-1) translate(0%, -50%);
+ -moz-transform: scaleX(-1) translate(0%, -50%);
+ transform: scaleX(-1) translate(0%, -50%);
+
+ -webkit-animation: breathing 1s infinite normal;
+ -moz-animation: breathing 1s infinite normal;
+ animation: breathing 1s infinite normal;
+}
+
+
+@-webkit-keyframes breathing {
+ 0% { opacity: 1; }
+ 25% { opacity: 0.5; }
+ 50% { opacity: 0; }
+ 75% { opacity: 0.5; }
+ 100% { opacity: 1; }
+}
+
+@-moz-keyframes breathing {
+ 0% { opacity: 1; }
+ 25% { opacity: 0.5; }
+ 50% { opacity: 0; }
+ 75% { opacity: 0.5; }
+ 100% { opacity: 1; }
+}
+
+@keyframes breathing {
+ 0% { opacity: 1; }
+ 25% { opacity: 0.5; }
+ 50% { opacity: 0; }
+ 75% { opacity: 0.5; }
+ 100% { opacity: 1; }
+}
diff --git a/static/gameboy2.html b/static/gameboy2.html
index bab93a9e..32400195 100644
--- a/static/gameboy2.html
+++ b/static/gameboy2.html
@@ -5,359 +5,47 @@
+
-
-
-
-
+
-
-
load
-
save
-
-
start
+
load
+
save
+
join
+
quit
@@ -372,60 +60,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+ DEBUG = true;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/img/404.jpg b/static/img/404.jpg
new file mode 100644
index 00000000..58e36fb1
Binary files /dev/null and b/static/img/404.jpg differ
diff --git a/static/img/boxarts/1943.png b/static/img/boxarts/1943.png
new file mode 100644
index 00000000..183f8e81
Binary files /dev/null and b/static/img/boxarts/1943.png differ
diff --git a/static/img/boxarts/Battle City.png b/static/img/boxarts/Battle City.png
new file mode 100644
index 00000000..f89ea028
Binary files /dev/null and b/static/img/boxarts/Battle City.png differ
diff --git a/static/img/boxarts/Bubble Bobble.png b/static/img/boxarts/Bubble Bobble.png
new file mode 100644
index 00000000..d74060e8
Binary files /dev/null and b/static/img/boxarts/Bubble Bobble.png differ
diff --git a/static/img/boxarts/Captain America and the Avengers.png b/static/img/boxarts/Captain America and the Avengers.png
new file mode 100644
index 00000000..7afd8a97
Binary files /dev/null and b/static/img/boxarts/Captain America and the Avengers.png differ
diff --git a/static/img/boxarts/Chip 'n Dale Rescue Rangers 2.png b/static/img/boxarts/Chip 'n Dale Rescue Rangers 2.png
new file mode 100644
index 00000000..01eb1b7e
Binary files /dev/null and b/static/img/boxarts/Chip 'n Dale Rescue Rangers 2.png differ
diff --git a/static/img/boxarts/Contra (USA).png b/static/img/boxarts/Contra.png
similarity index 100%
rename from static/img/boxarts/Contra (USA).png
rename to static/img/boxarts/Contra.png
diff --git a/static/img/boxarts/Gradius.png b/static/img/boxarts/Gradius.png
new file mode 100644
index 00000000..1ffdb1ac
Binary files /dev/null and b/static/img/boxarts/Gradius.png differ
diff --git a/static/img/boxarts/Ice Climber.png b/static/img/boxarts/Ice Climber.png
new file mode 100644
index 00000000..631dff84
Binary files /dev/null and b/static/img/boxarts/Ice Climber.png differ
diff --git a/static/img/boxarts/Kirby's Adventure (Canada).png b/static/img/boxarts/Kirby's Adventure.png
similarity index 100%
rename from static/img/boxarts/Kirby's Adventure (Canada).png
rename to static/img/boxarts/Kirby's Adventure.png
diff --git a/static/img/boxarts/Mega Man 2 (USA).png b/static/img/boxarts/Mega Man 2.png
similarity index 100%
rename from static/img/boxarts/Mega Man 2 (USA).png
rename to static/img/boxarts/Mega Man 2.png
diff --git a/static/img/boxarts/Mega Man 6.png b/static/img/boxarts/Mega Man 6.png
new file mode 100644
index 00000000..de8d504a
Binary files /dev/null and b/static/img/boxarts/Mega Man 6.png differ
diff --git a/static/img/boxarts/Mega Man.png b/static/img/boxarts/Mega Man.png
new file mode 100644
index 00000000..5fde9a5b
Binary files /dev/null and b/static/img/boxarts/Mega Man.png differ
diff --git a/static/img/boxarts/Metal Gear (USA).png b/static/img/boxarts/Metal Gear.png
similarity index 100%
rename from static/img/boxarts/Metal Gear (USA).png
rename to static/img/boxarts/Metal Gear.png
diff --git a/static/img/boxarts/Mike Tyson's Punch-Out!!.png b/static/img/boxarts/Mike Tyson's Punch-Out!!.png
new file mode 100644
index 00000000..6b0cfd86
Binary files /dev/null and b/static/img/boxarts/Mike Tyson's Punch-Out!!.png differ
diff --git a/static/img/boxarts/mortal-kombat-x-box-art-revealed-as-pre-orders-ope_5pxd.jpg b/static/img/boxarts/Mortal Kombat 4.png
similarity index 100%
rename from static/img/boxarts/mortal-kombat-x-box-art-revealed-as-pre-orders-ope_5pxd.jpg
rename to static/img/boxarts/Mortal Kombat 4.png
diff --git a/static/img/boxarts/Ninja Gaiden.png b/static/img/boxarts/Ninja Gaiden.png
new file mode 100644
index 00000000..f997cb75
Binary files /dev/null and b/static/img/boxarts/Ninja Gaiden.png differ
diff --git a/static/img/boxarts/Nintendo World Cup.png b/static/img/boxarts/Nintendo World Cup.png
new file mode 100644
index 00000000..74436c86
Binary files /dev/null and b/static/img/boxarts/Nintendo World Cup.png differ
diff --git a/static/img/boxarts/Super Mario Bros. 2 (USA).png b/static/img/boxarts/Super Mario Bros 2.png
similarity index 100%
rename from static/img/boxarts/Super Mario Bros. 2 (USA).png
rename to static/img/boxarts/Super Mario Bros 2.png
diff --git a/static/img/boxarts/Super Mario Bros. 3 (USA).png b/static/img/boxarts/Super Mario Bros 3.png
similarity index 100%
rename from static/img/boxarts/Super Mario Bros. 3 (USA).png
rename to static/img/boxarts/Super Mario Bros 3.png
diff --git a/static/img/boxarts/Super Mario Bros. (World).png b/static/img/boxarts/Super Mario Bros.png
similarity index 100%
rename from static/img/boxarts/Super Mario Bros. (World).png
rename to static/img/boxarts/Super Mario Bros.png
diff --git a/static/img/boxarts/Teenage Mutant Ninja Turtles III - The Manhattan Project (USA).png b/static/img/boxarts/Teenage Mutant Ninja Turtles 3.png
similarity index 100%
rename from static/img/boxarts/Teenage Mutant Ninja Turtles III - The Manhattan Project (USA).png
rename to static/img/boxarts/Teenage Mutant Ninja Turtles 3.png
diff --git a/static/img/boxarts/Zelda II - The Adventure of Link (Europe) (Rev A).png b/static/img/boxarts/Zelda II.png
similarity index 100%
rename from static/img/boxarts/Zelda II - The Adventure of Link (Europe) (Rev A).png
rename to static/img/boxarts/Zelda II.png
diff --git a/static/js/const.js b/static/js/const.js
deleted file mode 100644
index 528544c5..00000000
--- a/static/js/const.js
+++ /dev/null
@@ -1,84 +0,0 @@
-// list game
-GAME_LIST = [
- {
- name: "Contra",
- nes: "Contra.nes",
- art: "Contra (USA).png"
- },
-
- {
- name: "Kirby's Adventure",
- nes: "Kirby's Adventure.nes",
- art: "Kirby's Adventure (Canada).png"
- },
-
- {
- name: "Mega Man 2",
- nes: "Mega Man 2.nes",
- art: "Mega Man 2 (USA).png"
- },
-
- {
- name: "Metal Gear",
- nes: "Metal Gear.nes",
- art: "Metal Gear (USA).png"
- },
-
- {
- name: "Mortal Kombat 4",
- nes: "Mortal Kombat 4.nes",
- art: "mortal-kombat-x-box-art-revealed-as-pre-orders-ope_5pxd.jpg"
- },
-
- {
- name: "Super Mario Bros 2",
- nes: "Super Mario Bros 2.nes",
- art: "Super Mario Bros. 2 (USA).png"
- },
-
- {
- name: "Super Mario Bros 3",
- nes: "Super Mario Bros 3.nes",
- art: "Super Mario Bros. 3 (USA).png"
- },
-
- {
- name: "Super Mario Bros",
- nes: "Super Mario Bros.nes",
- art: "Super Mario Bros. (World).png"
- },
-
- {
- name: "TMNT 3",
- nes: "Teenage Mutant Ninja Turtles 3.nes",
- art: "Teenage Mutant Ninja Turtles III - The Manhattan Project (USA).png"
- },
-
- {
- name: "Zelda",
- nes: "zelda.rom",
- art: "Zelda II - The Adventure of Link (Europe) (Rev A).png"
- }
-];
-
-
-
-/*
- const (
- ButtonA = iota
- ButtonB
- ButtonSelect
- ButtonStart
- ButtonUp
- ButtonDown
- ButtonLeft
- ButtonRight
- )
- */
-// KEY_BIT = ["a", "b", "select", "start", "up", "down", "left", "right", "save", "load"];
-KEY_BIT = ["a", "b", "select", "start", "up", "down", "left", "right"];
-
-
-INPUT_FPS = 100;
-PINGPONGPS = 5;
-INPUT_STATE_PACKET = 5;
diff --git a/static/js/controller.js b/static/js/controller.js
new file mode 100644
index 00000000..f4f55b3a
--- /dev/null
+++ b/static/js/controller.js
@@ -0,0 +1,153 @@
+// menu screen
+function showMenuScreen() {
+ log("Clean up connection / frame");
+
+ $("#game-screen").hide();
+ $("#menu-screen").hide();
+ // show
+ $("#game-screen").show().delay(DEBUG?0:1000).fadeOut(400, () => {
+ log("Loading menu screen");
+ $("#menu-screen").fadeIn(400, () => {
+ chooseGame(gameIdx, true);
+ screenState = "menu";
+ });
+ });
+}
+
+
+// game menu
+function chooseGame(idx, force = false) {
+ if (idx < 0 || (idx == gameIdx && !force) || idx >= gameList.length) return false;
+
+ $("#menu-screen #box-art").fadeOut(DEBUG?0:400, function () {
+ $(this).attr("src", `/static/img/boxarts/${gameList[idx].name}.png`);
+ $(this).fadeIn(400, function () {
+ $("#menu-screen #title p").html(gameList[idx].name);
+ });
+ });
+
+ if (idx == 0) {
+ $("#menu-screen .left").hide();
+ } else {
+ $("#menu-screen .left").show();
+ }
+
+ if (idx == gameList.length - 1) {
+ $("#menu-screen .right").hide();
+ } else {
+ $("#menu-screen .right").show();
+ }
+
+ gameIdx = idx;
+ log(`> [Pick] game ${gameIdx + 1}/${gameList.length} - ${gameList[gameIdx].name}`);
+}
+
+
+// global func
+
+
+function sendInputData() {
+ // prepare key
+ if (unchangePacket > 0) {
+ bits = "";
+ KEY_BIT.slice().reverse().forEach(elem => {
+ bits += keyState[elem] ? 1 : 0;
+ });
+ data = parseInt(bits, 2);
+ console.log(`Key state string: ${bits} ==> ${data}`);
+
+ // send
+ arrBuf = new Uint8Array(1);
+ arrBuf[0] = data;
+ inputChannel.send(arrBuf);
+
+ unchangePacket--;
+ }
+}
+
+
+function startInputTimer() {
+ if (inputTimer == null) {
+ inputTimer = setInterval(sendInputData, 1000 / INPUT_FPS)
+ }
+}
+
+function stopInputTimer() {
+ clearInterval(inputTimer);
+ inputTimer = null;
+}
+
+
+function setState(name, bo) {
+ if (name in keyState) {
+ keyState[name] = bo;
+ unchangePacket = INPUT_STATE_PACKET;
+ }
+}
+
+function doButton(bo, name) {
+ if (bo == true) {
+ doButtonDown(name);
+ } else if (bo == false) {
+ doButtonUp(name);
+ }
+}
+
+function doButtonDown(name) {
+ $(`#btn-${name}`).addClass("pressed");
+
+ if (screenState === "game") {
+ // game keys
+ setState(name, true);
+ }
+}
+
+
+function doButtonUp(name) {
+ $(`#btn-${name}`).removeClass("pressed");
+
+ if (screenState === "menu") {
+ switch (name) {
+ case "left":
+ chooseGame(gameIdx - 1);
+ break;
+
+ case "right":
+ chooseGame(gameIdx + 1);
+ break;
+
+ case "join":
+ startGame();
+ // log("select game");
+ }
+ } else if (screenState === "game") {
+ setState(name, false);
+
+ switch (name) {
+ case "save":
+ conn.send(JSON.stringify({ "id": "save", "data": "" }));
+ break;
+ case "load":
+ conn.send(JSON.stringify({ "id": "load", "data": "" }));
+ break;
+ case "full":
+ // Fullscreen
+ screen = document.getElementById("game-screen");
+
+ console.log(screen.height, window.innerHeight);
+ if (screen.height === window.innerHeight) {
+ closeFullscreen();
+ } else {
+ openFullscreen(screen);
+ }
+ break;
+ }
+ }
+
+ // global reset
+ if (name === "quit") {
+ stopInputTimer();
+ showMenuScreen();
+ }
+}
+
diff --git a/static/js/gameboy_controller.js b/static/js/gameboy_controller.js
deleted file mode 100644
index 1ed575a9..00000000
--- a/static/js/gameboy_controller.js
+++ /dev/null
@@ -1,478 +0,0 @@
-// menu screen
-function showMenuScreen() {
- log("Clean up connection / frame");
-
- $("#game-screen").hide();
- if (!DEBUG) {
- $("#menu-screen").hide();
- // show
- $("#game-screen").show().delay(1000).fadeOut(400, () => {
- log("Loading menu screen");
- $("#menu-screen").fadeIn(400, () => {
- chooseGame(gameIdx, true);
- screenState = "menu";
- });
- });
-
- } else {
- screenState = "debug";
- }
-}
-
-
-// game menu
-function chooseGame(idx, force = false) {
- if (idx < 0 || (idx == gameIdx && !force) || idx >= GAME_LIST.length) return false;
-
- $("#menu-screen #box-art").fadeOut(400, function () {
- $(this).attr("src", `/static/img/boxarts/${GAME_LIST[idx].art}`);
- $(this).fadeIn(400, function () {
- $("#menu-screen #title p").html(GAME_LIST[idx].name);
- });
- });
-
- if (idx == 0) {
- $("#menu-screen .left").hide();
- } else {
- $("#menu-screen .left").show();
- }
-
- if (idx == GAME_LIST.length - 1) {
- $("#menu-screen .right").hide();
- } else {
- $("#menu-screen .right").show();
- }
-
- gameIdx = idx;
- log(`> [Pick] game ${gameIdx + 1}/${GAME_LIST.length} - ${GAME_LIST[gameIdx].name}`);
-}
-
-
-// global func
-
-function openFullscreen(elem) {
- if (elem.requestFullscreen) {
- elem.requestFullscreen();
- } else if (elem.mozRequestFullScreen) { /* Firefox */
- elem.mozRequestFullScreen();
- } else if (elem.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
- elem.webkitRequestFullscreen();
- } else if (elem.msRequestFullscreen) { /* IE/Edge */
- elem.msRequestFullscreen();
- }
-}
-
-function closeFullscreen() {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.mozCancelFullScreen) { /* Firefox */
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) { /* Chrome, Safari and Opera */
- document.webkitExitFullscreen();
- } else if (document.msExitFullscreen) { /* IE/Edge */
- document.msExitFullscreen();
- }
-}
-
-
-function sendInputData() {
- // prepare key
- if (unchangePacket > 0) {
- bits = "";
- KEY_BIT.slice().reverse().forEach(elem => {
- bits += keyState[elem] ? 1 : 0;
- });
- data = parseInt(bits, 2);
- console.log(`Key state string: ${bits} ==> ${data}`);
-
- // send
- arrBuf = new Uint8Array(1);
- arrBuf[0] = data;
- inputChannel.send(arrBuf);
-
- unchangePacket--;
- }
-}
-
-
-function startInputTimer() {
- if (inputTimer == null) {
- inputTimer = setInterval(sendInputData, 1000 / INPUT_FPS)
- }
-}
-
-function stopInputTimer() {
- clearInterval(inputTimer);
- inputTimer = null;
-}
-
-
-function setState(name, bo) {
- if (name in keyState) {
- keyState[name] = bo;
- unchangePacket = INPUT_STATE_PACKET;
- }
-}
-
-function doButton(bo, name) {
- if (bo == true) {
- doButtonDown(name);
- } else if (bo == false) {
- doButtonUp(name);
- }
-}
-
-function doButtonDown(name) {
- if (screenState === "game") {
- // game keys
- setState(name, true);
- }
-}
-
-
-function doButtonUp(name) {
- if (screenState === "menu") {
- switch (name) {
- case "left":
- chooseGame(gameIdx - 1);
- break;
-
- case "right":
- chooseGame(gameIdx + 1);
- break;
-
- case "select":
- startGame();
- }
- } else if (screenState === "game") {
- setState(name, false);
-
- switch (name) {
- case "save":
- conn.send(JSON.stringify({ "id": "save", "data": "" }));
- break;
- case "load":
- conn.send(JSON.stringify({ "id": "load", "data": "" }));
- break;
- case "full":
- // Fullscreen
- screen = document.getElementById("game-screen");
-
- console.log(screen.height, window.innerHeight);
- if (screen.height === window.innerHeight) {
- closeFullscreen();
- } else {
- openFullscreen(screen);
- }
- break;
- }
- }
-
- // global reset
- if (name === "quit") {
- stopInputTimer();
- showMenuScreen();
- }
-}
-
-// KEYBOARD
-
-KEYBOARD_MAP = {
- 37: "left",
- 38: "up",
- 39: "right",
- 40: "down",
-
- 90: "a", // z
- 88: "b", // x
- 67: "start", // c
- 86: "select", // v
-
- // non-game
- 81: "quit", // q
- 83: "save", // s
- 76: "load", // l
- 70: "full", // f
-}
-
-document.body.onkeyup = function (e) {
- if (e.keyCode in KEYBOARD_MAP) {
- doButtonUp(KEYBOARD_MAP[e.keyCode]);
- }
-}
-
-document.body.onkeydown = function (e) {
- if (e.keyCode in KEYBOARD_MAP) {
- doButtonDown(KEYBOARD_MAP[e.keyCode]);
- }
-};
-
-
-// JOYSTICK
-
-/*
- cross == a <--> a
- circle == b <--> b
- square == x <--> start
- triangle == y <--> select
- share <--> load
- option <--> save
- L2 == LT <--> full
- R2 == RT <--> quit
- dpad <--> up down left right
- axis 0, 1 <--> second dpad
-*/
-var padState, gamepadTimer;
-
-function getOS() {
- // linux? ios?
- var OSName = "unknown";
- if (navigator.appVersion.indexOf("Win") != -1) OSName = "win";
- else if (navigator.appVersion.indexOf("Mac") != -1) OSName = "mac";
- else if (navigator.userAgent.indexOf("Android") != -1) OSName = "android";
- return OSName;
-}
-
-function getBrowser() {
- var browserName = "unknown";
- if (navigator.userAgent.indexOf("Firefox") != -1) browserName = "firefox";
- if (navigator.userAgent.indexOf("Chrome") != -1) browserName = "chrome";
- if (navigator.userAgent.indexOf("Edge") != -1) browserName = "edge";
- if (navigator.userAgent.indexOf("Version/") != -1) browserName = "safari";
- if (navigator.userAgent.indexOf("UCBrowser") != -1) browserName = "uc";
- return browserName;
-}
-
-
-// only capture the last plugged joystick
-window.addEventListener("gamepadconnected", (e) => {
- gamepad = e.gamepad;
- log(`Gamepad connected at index ${gamepad.index}: ${gamepad.id}. ${gamepad.buttons.length} buttons, ${gamepad.axes.length} axes.`);
-
- padIdx = gamepad.index;
-
- // Ref: https://github.com/giongto35/cloud-game/issues/14
- // get mapping first (default KeyMap2)
- os = getOS();
- browser = getBrowser();
-
- console.log(os);
- console.log(browser);
-
- if (os == "android") {
- // default of android is KeyMap1
- padMap = { 2: "a", 0: "b", 3: "start", 4: "select", 10: "load", 11: "save", 8: "full", 9: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
- } else {
- // default of other OS is KeyMap2
- padMap = { 0: "a", 1: "b", 2: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
- }
-
- if (os == "android" && (browser == "firefox" || browser == "uc")) { //KeyMap2
- padMap = { 0: "a", 1: "b", 2: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
- }
-
- if (os == "win" && browser == "firefox") { //KeyMap3
- padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit" };
- }
-
- if (os == "mac" && browser == "safari") { //KeyMap4
- padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 14: "up", 15: "down", 16: "left", 17: "right" };
- }
-
- if (os == "mac" && browser == "firefox") { //KeyMap5
- padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 14: "up", 15: "down", 16: "left", 17: "right" };
- }
-
- // reset state
- padState = {
- left: false,
- right: false,
- up: false,
- down: false,
- };
- Object.keys(padMap).forEach(k => {
- padState[k] = false;
- });
-
-
- // looper, too intense?
- if (gamepadTimer) {
- clearInterval(gamepadTimer);
- }
-
- function checkAxis(bo, axis) {
- if (bo != padState[axis]) {
- padState[axis] = bo;
- doButton(bo, axis);
- }
- }
-
- gamepadTimer = setInterval(function () {
- gamepad = navigator.getGamepads()[padIdx];
- if (gamepad) {
- // axis pad
- corX = gamepad.axes[0]; // -1 -> 1, left -> right
- corY = gamepad.axes[1]; // -1 -> 1, up -> down
- checkAxis(corX <= -0.5, "left");
- checkAxis(corX >= 0.5, "right");
- checkAxis(corY <= -0.5, "up");
- checkAxis(corY >= 0.5, "down");
-
- // normal button
- Object.keys(padMap).forEach(k => {
- if (navigator.webkitGetGamepads) {
- curPressed = (gamepad.buttons[k] == 1);
- } else {
- curPressed = (gamepad.buttons[k].value > 0 || gamepad.buttons[k].pressed == true);
- }
-
- if (padState[k] != curPressed) {
- padState[k] = curPressed;
- doButton(curPressed, padMap[k]);
- }
- });
- }
-
- }, 10); // miliseconds per hit
-
-});
-
-window.addEventListener("gamepaddisconnected", (event) => {
- clearInterval(gamepadTimer);
- log(`Gamepad disconnected at index ${e.gamepad.index}`);
-});
-
-
-
-// VIRTUAL JOYSTICK
-// Ref: https://jsfiddle.net/aa0et7tr/5/
-
-var dpadState = {};
-var touchIdx = null;
-const maxDiff = 20;
-
-
-function resetDPad() {
- dpadState = {
- up: false,
- down: false,
- left: false,
- right: false,
- };
- $(".dpad").removeClass("pressed");
-}
-
-function checkDPadAxis(bo, axis) {
- if (bo != dpadState[axis]) {
- dpadState[axis] = bo;
-
- if (dpadState[axis]) {
- $(`#dpad-${axis}`).addClass("pressed");
- } else {
- $(`#dpad-${axis}`).removeClass("pressed");
- }
-
- // doButton(bo, axis);
- }
-}
-
-
-parent = $("#circle-pad-holder");
-stick = document.getElementById("circle-pad");
-
-// TODO: REMOVE MOUSE
-parent.on('mousedown', handleMouseDown);
-$(document).on('mousemove', handleMouseMove);
-$(document).on('mouseup', handleMouseUp);
-
-parent.on('touchstart', handleMouseDown);
-parent.on('touchmove', handleMouseMove);
-parent.on('touchend', handleMouseUp);
-
-let dragStart = null;
-let currentPos = { x: 0, y: 0 };
-
-function handleMouseDown(event) {
- // event.preventDefault();
- stick.style.transition = '0s';
- if (event.changedTouches) {
- touchIdx = event.changedTouches[0].identifier;
- dragStart = {
- x: event.changedTouches[0].clientX,
- y: event.changedTouches[0].clientY,
- };
- resetDPad();
- return;
- }
- dragStart = {
- x: event.clientX,
- y: event.clientY,
- };
-
-}
-
-function handleMouseMove(event) {
- // event.preventDefault();
- if (dragStart === null) return;
- if (event.changedTouches) {
- event.clientX = event.changedTouches[touchIdx].clientX;
- event.clientY = event.changedTouches[touchIdx].clientY;
- }
- const xDiff = event.clientX - dragStart.x;
- const yDiff = event.clientY - dragStart.y;
- const angle = Math.atan2(yDiff, xDiff);
- const distance = Math.min(maxDiff, Math.hypot(xDiff, yDiff));
- const xNew = distance * Math.cos(angle);
- const yNew = distance * Math.sin(angle);
- stick.style.transform = `translate(${xNew}px, ${yNew}px)`;
- currentPos = { x: xNew, y: yNew };
-
- const xRatio = xNew / maxDiff;
- const yRatio = yNew / maxDiff;
- checkDPadAxis(xRatio <= -0.5, "left");
- checkDPadAxis(xRatio >= 0.5, "right");
- checkDPadAxis(yRatio <= -0.5, "up");
- checkDPadAxis(yRatio >= 0.5, "down");
-}
-
-function handleMouseUp(event) {
- event.preventDefault();
- if (dragStart === null) return;
- stick.style.transition = '.2s';
- stick.style.transform = `translate3d(0px, 0px, 0px)`;
- dragStart = null;
- currentPos = { x: 0, y: 0 };
- resetDPad();
-
- // $(".abxy .button").removeClass("pressed");
-}
-
-
-
-
-
-
-
-function handleButtonDown(event) {
- $(this).addClass("pressed");
- // doButtonDown($(this).attr("value"));
-}
-
-function handleButtonUp(event) {
- $(this).removeClass("pressed");
- // doButtonUp($(this).attr("value"));
-}
-
-
-// TODO: REMOVE MOUSE
-// $(".abxy .button").on("mousedown", handleButtonDown);
-// $(".abxy .button").on("mouseup", handleButtonUp);
-$(".btn").on("mousedown", handleButtonDown);
-$(".btn").on("mouseup", handleButtonUp);
-$(".btn").on("touchstart", handleButtonDown);
-$(".btn").on("touchend", handleButtonUp);
-
-$(".btn-big").on("mousedown", handleButtonDown);
-$(".btn-big").on("mouseup", handleButtonUp);
-$(".btn-big").on("touchstart", handleButtonDown);
-$(".btn-big").on("touchend", handleButtonUp);
diff --git a/static/js/gameboy_loader.js b/static/js/gameboy_loader.js
deleted file mode 100644
index 30e148ad..00000000
--- a/static/js/gameboy_loader.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// A tiny bit of javascript code for color selection
-window.onload = function() {
- var colors = ['red', 'purple', 'green', 'yellow', 'teal', 'transparent'];
- var last = null;
- Array.prototype.slice.call(document.querySelectorAll('.color')).forEach(function(el) {
- el.addEventListener('click', function() {
- log("Starting gameboy");
- screenState = "loader";
-
- if (last) {
- last.classList.remove('active');
- }
- var color = el.getAttribute('data-color');
- var gameboy = document.querySelector('#gameboy');
- gameboy.style.opacity = 0;
- gameboy.classList.remove(gameboy.classList[0]);
- var clone = gameboy.cloneNode(true);
- gameboy.remove();
- clone.classList.add(color);
- clone.style.opacity = 1;
- var colors = document.querySelector('#colors');
- colors.parentNode.insertBefore(clone, colors);
- el.classList.add('active');
- last = el;
- });
- });
-
- document.querySelector('.color[data-color="green"]').dispatchEvent(new MouseEvent('click', {
- 'view': window,
- 'bubbles': true
- }));
-
- $("#screen-gameboy-text").on("webkitAnimationEnd", showMenuScreen);
- $("#screen-gameboy-text").on("animationend", showMenuScreen);
-}
diff --git a/static/js/gesture_joystick.js b/static/js/gesture_joystick.js
new file mode 100644
index 00000000..a2ade160
--- /dev/null
+++ b/static/js/gesture_joystick.js
@@ -0,0 +1,117 @@
+
+// JOYSTICK
+
+/*
+ cross == a <--> a
+ circle == b <--> b
+ square == x <--> start
+ triangle == y <--> select
+ share <--> load
+ option <--> save
+ L2 == LT <--> full
+ R2 == RT <--> quit
+ dpad <--> up down left right
+ axis 0, 1 <--> second dpad
+*/
+var padState, gamepadTimer;
+
+
+// only capture the last plugged joystick
+window.addEventListener("gamepadconnected", (e) => {
+ gamepad = e.gamepad;
+ log(`Gamepad connected at index ${gamepad.index}: ${gamepad.id}. ${gamepad.buttons.length} buttons, ${gamepad.axes.length} axes.`);
+
+ padIdx = gamepad.index;
+
+ // Ref: https://github.com/giongto35/cloud-game/issues/14
+ // get mapping first (default KeyMap2)
+ os = getOS();
+ browser = getBrowser();
+
+ console.log(os);
+ console.log(browser);
+
+ if (os == "android") {
+ // default of android is KeyMap1
+ padMap = { 2: "a", 0: "b", 3: "start", 4: "select", 10: "load", 11: "save", 8: "full", 9: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
+ } else {
+ // default of other OS is KeyMap2
+ padMap = { 0: "a", 1: "b", 2: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
+ }
+
+ if (os == "android" && (browser == "firefox" || browser == "uc")) { //KeyMap2
+ padMap = { 0: "a", 1: "b", 2: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 12: "up", 13: "down", 14: "left", 15: "right" };
+ }
+
+ if (os == "win" && browser == "firefox") { //KeyMap3
+ padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit" };
+ }
+
+ if (os == "mac" && browser == "safari") { //KeyMap4
+ padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 14: "up", 15: "down", 16: "left", 17: "right" };
+ }
+
+ if (os == "mac" && browser == "firefox") { //KeyMap5
+ padMap = { 1: "a", 2: "b", 0: "start", 3: "select", 8: "load", 9: "save", 6: "full", 7: "quit", 14: "up", 15: "down", 16: "left", 17: "right" };
+ }
+
+ // reset state
+ padState = {
+ left: false,
+ right: false,
+ up: false,
+ down: false,
+ };
+ Object.keys(padMap).forEach(k => {
+ padState[k] = false;
+ });
+
+
+ // looper, too intense?
+ if (gamepadTimer) {
+ clearInterval(gamepadTimer);
+ }
+
+ function checkAxis(bo, axis) {
+ if (bo != padState[axis]) {
+ padState[axis] = bo;
+ doButton(bo, axis);
+ }
+ }
+
+ gamepadTimer = setInterval(function () {
+ gamepad = navigator.getGamepads()[padIdx];
+ if (gamepad) {
+ // axis pad
+ corX = gamepad.axes[0]; // -1 -> 1, left -> right
+ corY = gamepad.axes[1]; // -1 -> 1, up -> down
+ checkAxis(corX <= -0.5, "left");
+ checkAxis(corX >= 0.5, "right");
+ checkAxis(corY <= -0.5, "up");
+ checkAxis(corY >= 0.5, "down");
+
+ // normal button
+ Object.keys(padMap).forEach(k => {
+ if (navigator.webkitGetGamepads) {
+ curPressed = (gamepad.buttons[k] == 1);
+ } else {
+ curPressed = (gamepad.buttons[k].value > 0 || gamepad.buttons[k].pressed == true);
+ }
+
+ if (padState[k] != curPressed) {
+ padState[k] = curPressed;
+ doButton(curPressed, padMap[k]);
+ }
+ });
+ }
+
+ }, 10); // miliseconds per hit
+
+});
+
+window.addEventListener("gamepaddisconnected", (event) => {
+ clearInterval(gamepadTimer);
+ log(`Gamepad disconnected at index ${e.gamepad.index}`);
+});
+
+
diff --git a/static/js/gesture_keyboard.js b/static/js/gesture_keyboard.js
new file mode 100644
index 00000000..546b0057
--- /dev/null
+++ b/static/js/gesture_keyboard.js
@@ -0,0 +1,33 @@
+// KEYBOARD
+
+KEYBOARD_MAP = {
+ 37: "left",
+ 38: "up",
+ 39: "right",
+ 40: "down",
+
+ 90: "a", // z
+ 88: "b", // x
+ 67: "start", // c
+ 86: "select", // v
+
+ // non-game
+ 81: "quit", // q
+ 83: "save", // s
+ 87: "join", // w
+ 65: "load", // a
+ 70: "full", // f
+}
+
+document.body.onkeyup = function (e) {
+ if (e.keyCode in KEYBOARD_MAP) {
+ doButtonUp(KEYBOARD_MAP[e.keyCode]);
+ }
+}
+
+document.body.onkeydown = function (e) {
+ if (e.keyCode in KEYBOARD_MAP) {
+ doButtonDown(KEYBOARD_MAP[e.keyCode]);
+ }
+};
+
diff --git a/static/js/gesture_touch.js b/static/js/gesture_touch.js
new file mode 100644
index 00000000..88294044
--- /dev/null
+++ b/static/js/gesture_touch.js
@@ -0,0 +1,133 @@
+
+// VIRTUAL JOYSTICK
+// Ref: https://jsfiddle.net/aa0et7tr/5/
+
+var dpadState = {};
+var touchIdx = null;
+const maxDiff = 20;
+
+
+function resetDPad() {
+ dpadState = {
+ up: false,
+ down: false,
+ left: false,
+ right: false,
+ };
+ $(".dpad").removeClass("pressed");
+}
+
+function checkDPadAxis(bo, axis) {
+ if (bo != dpadState[axis]) {
+ dpadState[axis] = bo;
+
+ if (dpadState[axis]) {
+ $(`#dpad-${axis}`).addClass("pressed");
+ } else {
+ $(`#dpad-${axis}`).removeClass("pressed");
+ }
+
+ // doButton(bo, axis);
+ }
+}
+
+
+parent = $("#circle-pad-holder");
+stick = document.getElementById("circle-pad");
+
+// TODO: REMOVE MOUSE
+parent.on('mousedown', handleMouseDown);
+$(document).on('mousemove', handleMouseMove);
+$(document).on('mouseup', handleMouseUp);
+
+parent.on('touchstart', handleMouseDown);
+parent.on('touchmove', handleMouseMove);
+parent.on('touchend', handleMouseUp);
+
+let dragStart = null;
+let currentPos = { x: 0, y: 0 };
+
+function handleMouseDown(event) {
+ // event.preventDefault();
+ stick.style.transition = '0s';
+ if (event.changedTouches) {
+ touchIdx = event.changedTouches[0].identifier;
+ dragStart = {
+ x: event.changedTouches[0].clientX,
+ y: event.changedTouches[0].clientY,
+ };
+ resetDPad();
+ return;
+ }
+ dragStart = {
+ x: event.clientX,
+ y: event.clientY,
+ };
+
+}
+
+function handleMouseMove(event) {
+ // event.preventDefault();
+ if (dragStart === null) return;
+ if (event.changedTouches) {
+ event.clientX = event.changedTouches[touchIdx].clientX;
+ event.clientY = event.changedTouches[touchIdx].clientY;
+ }
+ const xDiff = event.clientX - dragStart.x;
+ const yDiff = event.clientY - dragStart.y;
+ const angle = Math.atan2(yDiff, xDiff);
+ const distance = Math.min(maxDiff, Math.hypot(xDiff, yDiff));
+ const xNew = distance * Math.cos(angle);
+ const yNew = distance * Math.sin(angle);
+ stick.style.transform = `translate(${xNew}px, ${yNew}px)`;
+ currentPos = { x: xNew, y: yNew };
+
+ const xRatio = xNew / maxDiff;
+ const yRatio = yNew / maxDiff;
+ checkDPadAxis(xRatio <= -0.5, "left");
+ checkDPadAxis(xRatio >= 0.5, "right");
+ checkDPadAxis(yRatio <= -0.5, "up");
+ checkDPadAxis(yRatio >= 0.5, "down");
+}
+
+function handleMouseUp(event) {
+ event.preventDefault();
+ if (dragStart === null) return;
+ stick.style.transition = '.2s';
+ stick.style.transform = `translate3d(0px, 0px, 0px)`;
+ dragStart = null;
+ currentPos = { x: 0, y: 0 };
+ resetDPad();
+
+ // $(".abxy .button").removeClass("pressed");
+}
+
+
+
+
+
+
+
+function handleButtonDown(event) {
+ $(this).addClass("pressed");
+ // doButtonDown($(this).attr("value"));
+}
+
+function handleButtonUp(event) {
+ $(this).removeClass("pressed");
+ // doButtonUp($(this).attr("value"));
+}
+
+
+// TODO: REMOVE MOUSE
+// $(".abxy .button").on("mousedown", handleButtonDown);
+// $(".abxy .button").on("mouseup", handleButtonUp);
+$(".btn").on("mousedown", handleButtonDown);
+$(".btn").on("mouseup", handleButtonUp);
+$(".btn").on("touchstart", handleButtonDown);
+$(".btn").on("touchend", handleButtonUp);
+
+$(".btn-big").on("mousedown", handleButtonDown);
+$(".btn-big").on("mouseup", handleButtonUp);
+$(".btn-big").on("touchstart", handleButtonDown);
+$(".btn-big").on("touchend", handleButtonUp);
diff --git a/static/js/global.js b/static/js/global.js
index f52f7c5e..0670011d 100644
--- a/static/js/global.js
+++ b/static/js/global.js
@@ -1,17 +1,27 @@
+/*
+ GLOBAL CONSTS
+*/
+DEBUG = true;
+
+KEY_BIT = ["a", "b", "select", "start", "up", "down", "left", "right"];
+
+INPUT_FPS = 100;
+PINGPONGPS = 5;
+INPUT_STATE_PACKET = 5;
+
+
+//------------------------------------------------------------------------
/*
GLOBAL VARS
*/
-LOG = true;
-if (!("DEBUG" in window)) {
- window.DEBUG = false;
-}
// Game state
-screenState = "loader";
-gameIdx = 0;
+var screenState = "loader";
+var gameList = [];
+var gameIdx = 5;
// Input vars
-keyState = {
+var keyState = {
// controllers
a: false,
b: false,
@@ -22,34 +32,14 @@ keyState = {
up: false,
down: false,
left: false,
- right: false,
-
- // game meta keys
- // save: false,
- // load: false,
-
- // unofficial
- // quit: false
+ right: false
}
-unchangePacket = INPUT_STATE_PACKET;
-inputTimer = null;
+var unchangePacket = INPUT_STATE_PACKET;
+var inputTimer = null;
// Connection vars
var pc, inputChannel;
var localSessionDescription = "";
var remoteSessionDescription = "";
-var conn;
-
-
-/*
- FUNCTIONS
-*/
-
-// miscs
-function log(msg) {
- if (LOG) {
- document.getElementById('div').innerHTML += msg + '
'
- console.log(msg);
- }
-}
+var conn;
\ No newline at end of file
diff --git a/static/js/utils.js b/static/js/utils.js
new file mode 100644
index 00000000..55e57ea6
--- /dev/null
+++ b/static/js/utils.js
@@ -0,0 +1,69 @@
+function log(msg) {
+ // if (LOG) {
+ // document.getElementById('div').innerHTML += msg + '
'
+ // }
+ console.log(msg);
+}
+
+
+function openFullscreen(elem) {
+ if (elem.requestFullscreen) {
+ elem.requestFullscreen();
+ } else if (elem.mozRequestFullScreen) { /* Firefox */
+ elem.mozRequestFullScreen();
+ } else if (elem.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
+ elem.webkitRequestFullscreen();
+ } else if (elem.msRequestFullscreen) { /* IE/Edge */
+ elem.msRequestFullscreen();
+ }
+}
+
+function closeFullscreen() {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ } else if (document.mozCancelFullScreen) { /* Firefox */
+ document.mozCancelFullScreen();
+ } else if (document.webkitExitFullscreen) { /* Chrome, Safari and Opera */
+ document.webkitExitFullscreen();
+ } else if (document.msExitFullscreen) { /* IE/Edge */
+ document.msExitFullscreen();
+ }
+}
+
+
+function getOS() {
+ // linux? ios?
+ var OSName = "unknown";
+ if (navigator.appVersion.indexOf("Win") != -1) OSName = "win";
+ else if (navigator.appVersion.indexOf("Mac") != -1) OSName = "mac";
+ else if (navigator.userAgent.indexOf("Android") != -1) OSName = "android";
+ return OSName;
+}
+
+function getBrowser() {
+ var browserName = "unknown";
+ if (navigator.userAgent.indexOf("Firefox") != -1) browserName = "firefox";
+ if (navigator.userAgent.indexOf("Chrome") != -1) browserName = "chrome";
+ if (navigator.userAgent.indexOf("Edge") != -1) browserName = "edge";
+ if (navigator.userAgent.indexOf("Version/") != -1) browserName = "safari";
+ if (navigator.userAgent.indexOf("UCBrowser") != -1) browserName = "uc";
+ return browserName;
+}
+
+function isPortrait() {
+ // ios / mobile app
+ switch (window.orientation) {
+ case 0:
+ case 180:
+ return true;
+ break;
+ }
+
+ // desktop
+ orient = screen.msOrientation || screen.mozOrientation || (screen.orientation || {}).type;
+ if (orient == "portrait-primary") {
+ return true;
+ }
+
+ return false;
+}
diff --git a/static/js/ws.js b/static/js/ws.js
index 89d91b3c..34de43ca 100644
--- a/static/js/ws.js
+++ b/static/js/ws.js
@@ -1,7 +1,5 @@
-var pc;
var curPacketID = "";
var curSessionID = "";
-var gamelist = [];
// web socket
conn = new WebSocket(`ws://${location.host}/ws`);
@@ -28,30 +26,28 @@ conn.onmessage = e => {
switch (d["id"]) {
case "gamelist":
- files = JSON.parse(d["data"])
+ files = JSON.parse(d["data"]);
// parse files list to gamelist
- gamelist = []
+
+ gameList = [];
files.forEach(file => {
var file = file
var name = file.substr(0, file.indexOf('.'));
- // var image = name + '.png'
- gamelist.push({file: file, name: name})
- })
-
- // Update Game Options
- gamelist.forEach(game => {
- ee = document.createElement("option");
- ee.value = game.file;
- ee.innerHTML = game.name;
- gameOp.append(ee);
+ gameList.push({file: file, name: name});
});
- log("Received game list", gamelist)
+ log("Received game list");
+
+ // change screen to menu
+ showMenuScreen();
+
break;
+
case "sdp":
log("Got remote sdp");
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(d["data"]))));
//conn.send(JSON.stringify({"id": "sdpdon", "packet_id": d["packet_id"]}));
break;
+
case "requestOffer":
curPacketID = d["packet_id"];
log("Received request offer ", curPacketID)
@@ -71,8 +67,7 @@ conn.onmessage = e => {
break;
case "start":
log("Got start");
- roomID.value = ""
- currentRoomID.innerText = d["room_id"]
+ $("#room-txt").val(d["room_id"]);
break;
case "save":
log(`Got save response: ${d["data"]}`);
@@ -211,16 +206,14 @@ function startGame() {
log("Starting game screen");
screenState = "game";
- conn.send(JSON.stringify({"id": "start", "data": gamelist[gameIdx].file, "room_id": roomID.value, "player_index": parseInt(playerIndex.value, 10)}));
+ // conn.send(JSON.stringify({"id": "start", "data": gameList[gameIdx].file, "room_id": $("#room-txt").val(), "player_index": parseInt(playerIndex.value, 10)}));
+ conn.send(JSON.stringify({"id": "start", "data": gameList[gameIdx].file, "room_id": $("#room-txt").val(), "player_index": 0}));
// clear menu screen
stopInputTimer();
- document.getElementById('div').innerHTML = "";
- if (!DEBUG) {
- $("#menu-screen").fadeOut(400, function() {
- $("#game-screen").show();
- });
- }
+ $("#menu-screen").fadeOut(DEBUG?0:400, function() {
+ $("#game-screen").show();
+ });
// end clear
startInputTimer();
}