Remove jQuery (#299)
* Remove jQuery * Remove browser (vendor) prefixes for some CSS properties * Use simple device orientation test * Realign D-pad pointers * Make GameBoy text unselectable * Cleanup console.log * Keep 90% size on mobile browsers due to gh-ribbon overlap * Remove legacy `unselectable="on"` attributes * Align UI buttons * Remove not used UI elements * Change Options button * Don't show player change message when not in a game * Add click/touch handler for circle-pad
243
web/css/main.css
vendored
|
|
@ -1,3 +1,9 @@
|
|||
html {
|
||||
/* force full size for Firefox */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-image: url('/static/img/background.jpg');
|
||||
background-repeat: repeat;
|
||||
|
|
@ -76,7 +82,7 @@ body {
|
|||
}
|
||||
|
||||
.dpad-empty {
|
||||
background-image: url('/static/img/ui/bt MOVE EMPTY.png') !important;
|
||||
background-image: url('/static/img/ui/bt MOVE EMPTY.png') !important;
|
||||
}
|
||||
|
||||
#guide-txt {
|
||||
|
|
@ -86,6 +92,8 @@ body {
|
|||
left: 30px;
|
||||
width: 1000px;
|
||||
position: absolute;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#circle-pad {
|
||||
|
|
@ -97,14 +105,16 @@ body {
|
|||
top: 15px;
|
||||
left: 15px;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
opacity: 0.5;
|
||||
background-image: url('/static/img/ui/bong.png');
|
||||
}
|
||||
|
||||
|
||||
.bong-full {
|
||||
opacity: 1.0 !important;
|
||||
background-image: url('/static/img/ui/bong full.png') !important;
|
||||
opacity: 1.0 !important;
|
||||
background-image: url('/static/img/ui/bong full.png') !important;
|
||||
}
|
||||
|
||||
.dpad {
|
||||
|
|
@ -318,6 +328,20 @@ body {
|
|||
background-image: url('/static/img/ui/bt Y.png');
|
||||
}
|
||||
|
||||
#btn-settings {
|
||||
width: 65px;
|
||||
height: 21px;
|
||||
|
||||
top: 9%;
|
||||
left: 55px;
|
||||
|
||||
padding: 0;
|
||||
|
||||
transform: translateY(-50%);
|
||||
background-image: url('/static/img/ui/bt OPTIONS.png');
|
||||
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
#lights-holder {
|
||||
display: block;
|
||||
|
|
@ -390,12 +414,12 @@ body {
|
|||
|
||||
|
||||
.pressed {
|
||||
filter: brightness(50%);
|
||||
filter: brightness(50%);
|
||||
}
|
||||
|
||||
.dpad-pressed {
|
||||
background-color: #333 !important;
|
||||
opacity: 0.75;
|
||||
background-color: #333 !important;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
#bottom-screen {
|
||||
|
|
@ -458,7 +482,6 @@ body {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto'; /*a name to be used later*/
|
||||
src: url('/static/fonts/Roboto-Regular.ttf'); /*URL to font*/
|
||||
|
|
@ -514,34 +537,64 @@ body {
|
|||
|
||||
|
||||
@-moz-keyframes horizontally {
|
||||
0% { transform: translateX(0%); }
|
||||
25% { transform: translateX(-20%); }
|
||||
50% { transform: translateX(0%); }
|
||||
75% { transform: translateX(20%); }
|
||||
100% { transform: translateX(0%); }
|
||||
}
|
||||
@-webkit-keyframes horizontally {
|
||||
0% { transform: translateX(0%); }
|
||||
25% { transform: translateX(-20%); }
|
||||
50% { transform: translateX(0%); }
|
||||
75% { transform: translateX(20%); }
|
||||
100% { transform: translateX(0%); }
|
||||
}
|
||||
@keyframes horizontally {
|
||||
0% { transform: translateX(0%); }
|
||||
25% { transform: translateX(-20%); }
|
||||
50% { transform: translateX(0%); }
|
||||
75% { transform: translateX(20%); }
|
||||
100% { transform: translateX(0%); }
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
25% {
|
||||
transform: translateX(-20%);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
75% {
|
||||
transform: translateX(20%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes horizontally {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
25% {
|
||||
transform: translateX(-20%);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
75% {
|
||||
transform: translateX(20%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes horizontally {
|
||||
0% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
25% {
|
||||
transform: translateX(-20%);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
75% {
|
||||
transform: translateX(20%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
}
|
||||
|
||||
#noti-box {
|
||||
display: none;
|
||||
padding: 5px 10px 0 10px;
|
||||
height: 20px;
|
||||
background-color: #ddd;
|
||||
opacity: 0.8;
|
||||
position: absolute;
|
||||
|
||||
border: 5px #000;
|
||||
|
|
@ -566,60 +619,62 @@ body {
|
|||
top: 90px;
|
||||
left: 20px;
|
||||
width: 100px;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* The slider itself */
|
||||
.slider {
|
||||
-webkit-appearance: none; /* Override default CSS styles */
|
||||
appearance: none;
|
||||
width: 100%; /* Full-width */
|
||||
height: 25px; /* Specified height */
|
||||
outline: none; /* Remove outline */
|
||||
/*opacity: 0.7; [> Set transparency (for mouse-over effects on hover) <]*/
|
||||
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
|
||||
transition: opacity .2s;
|
||||
-webkit-appearance: none; /* Override default CSS styles */
|
||||
appearance: none;
|
||||
width: 100%; /* Full-width */
|
||||
height: 25px; /* Specified height */
|
||||
outline: none; /* Remove outline */
|
||||
/*opacity: 0.7; [> Set transparency (for mouse-over effects on hover) <]*/
|
||||
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
|
||||
transition: opacity .2s;
|
||||
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/FramePlayerIndex.png');
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/FramePlayerIndex.png');
|
||||
}
|
||||
|
||||
/* Mouse-over effects */
|
||||
.slider:hover {
|
||||
opacity: 1; /* Fully shown on mouse-over */
|
||||
opacity: 1; /* Fully shown on mouse-over */
|
||||
}
|
||||
|
||||
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none; /* Override default look */
|
||||
appearance: none;
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
-webkit-appearance: none; /* Override default look */
|
||||
appearance: none;
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/bt PlayerIndex.png');
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/bt PlayerIndex.png');
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
appearance: none;
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
appearance: none;
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
|
||||
border: 0px;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/bt PlayerIndex.png');
|
||||
border: 0px;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-image: url('/static/img/ui/bt PlayerIndex.png');
|
||||
}
|
||||
|
||||
* {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
#stats-overlay {
|
||||
position: absolute;
|
||||
|
|
@ -653,7 +708,7 @@ body {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#stats-overlay>div>div {
|
||||
#stats-overlay > div > div {
|
||||
display: inline-block;
|
||||
font-weight: 500;
|
||||
width: 4em;
|
||||
|
|
@ -675,53 +730,53 @@ body {
|
|||
}
|
||||
|
||||
.dpad-toggle-label {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 35px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 35px;
|
||||
height: 20px;
|
||||
|
||||
top: 44px;
|
||||
left: 85px;
|
||||
top: 44px;
|
||||
left: 85px;
|
||||
}
|
||||
|
||||
.dpad-toggle-label input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.dpad-toggle-slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #515151;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 20px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #515151;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.dpad-toggle-slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: #5f5f5f;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: #5f5f5f;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
input:checked + .dpad-toggle-slider {
|
||||
background-color: #515151;
|
||||
background-color: #515151;
|
||||
}
|
||||
|
||||
input:checked + .dpad-toggle-slider:before {
|
||||
-webkit-transform: translateX(15px);
|
||||
-ms-transform: translateX(15px);
|
||||
transform: translateX(15px);
|
||||
-webkit-transform: translateX(15px);
|
||||
-ms-transform: translateX(15px);
|
||||
transform: translateX(15px);
|
||||
}
|
||||
|
|
|
|||
5
web/css/ui.css
vendored
|
|
@ -3,11 +3,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
#btn-settings {
|
||||
top: 14px;
|
||||
left: 70px;
|
||||
}
|
||||
|
||||
.modal-window {
|
||||
position: fixed;
|
||||
|
||||
|
|
|
|||
BIN
web/img/darkui/Help.png
vendored
|
Before Width: | Height: | Size: 4.4 KiB |
BIN
web/img/darkui/PLAYER INDEX.png
vendored
|
Before Width: | Height: | Size: 1,006 B |
BIN
web/img/darkui/Pgsdgddgdsgd.png
vendored
|
Before Width: | Height: | Size: 1 KiB |
BIN
web/img/darkui/Ui4.jpg
vendored
|
Before Width: | Height: | Size: 71 KiB |
BIN
web/img/darkui/bg.png
vendored
|
Before Width: | Height: | Size: 366 KiB |
BIN
web/img/darkui/bong copy.png
vendored
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
web/img/darkui/bong.png
vendored
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
web/img/darkui/bt A copy.png
vendored
|
Before Width: | Height: | Size: 4.8 KiB |
BIN
web/img/darkui/bt A.png
vendored
|
Before Width: | Height: | Size: 4.8 KiB |
BIN
web/img/darkui/bt B copy.png
vendored
|
Before Width: | Height: | Size: 4.7 KiB |
BIN
web/img/darkui/bt B.png
vendored
|
Before Width: | Height: | Size: 4.7 KiB |
BIN
web/img/darkui/bt LOAD copy.png
vendored
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
web/img/darkui/bt LOAD.png
vendored
|
Before Width: | Height: | Size: 3 KiB |
BIN
web/img/darkui/bt MOVE copy.png
vendored
|
Before Width: | Height: | Size: 15 KiB |
BIN
web/img/darkui/bt MOVE.png
vendored
|
Before Width: | Height: | Size: 15 KiB |
BIN
web/img/darkui/bt PlayIndex copy.png
vendored
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
web/img/darkui/bt PlayIndex.png
vendored
|
Before Width: | Height: | Size: 1.8 KiB |
BIN
web/img/darkui/bt QUIT copy.png
vendored
|
Before Width: | Height: | Size: 2.1 KiB |
BIN
web/img/darkui/bt QUIT.png
vendored
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
web/img/darkui/bt SAVE copy.png
vendored
|
Before Width: | Height: | Size: 3.1 KiB |
BIN
web/img/darkui/bt SAVE.png
vendored
|
Before Width: | Height: | Size: 3.5 KiB |
BIN
web/img/darkui/bt SELECT copy.png
vendored
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
web/img/darkui/bt SELECT.png
vendored
|
Before Width: | Height: | Size: 2.4 KiB |
BIN
web/img/darkui/bt SHARE copy.png
vendored
|
Before Width: | Height: | Size: 2.7 KiB |
BIN
web/img/darkui/bt SHARE.png
vendored
|
Before Width: | Height: | Size: 2.6 KiB |
BIN
web/img/darkui/bt START copy.png
vendored
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
web/img/darkui/bt START.png
vendored
|
Before Width: | Height: | Size: 2.4 KiB |
BIN
web/img/darkui/bt X copy.png
vendored
|
Before Width: | Height: | Size: 4.8 KiB |
BIN
web/img/darkui/bt X.png
vendored
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
web/img/darkui/bt Y copy.png
vendored
|
Before Width: | Height: | Size: 4.6 KiB |
BIN
web/img/darkui/bt Y.png
vendored
|
Before Width: | Height: | Size: 4.7 KiB |
BIN
web/img/darkui/frame.png
vendored
|
Before Width: | Height: | Size: 3 KiB |
BIN
web/img/darkui/framePlayIndex.png
vendored
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
web/img/darkui/frameTEXT.png
vendored
|
Before Width: | Height: | Size: 864 B |
BIN
web/img/darkui/hept copy.png
vendored
|
Before Width: | Height: | Size: 4.5 KiB |
BIN
web/img/ui/Help-2.png
vendored
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
web/img/ui/PLAYER INDEX.png
vendored
|
Before Width: | Height: | Size: 1,006 B |
BIN
web/img/ui/Pgsdgddgdsgd.png
vendored
|
Before Width: | Height: | Size: 1 KiB |
BIN
web/img/ui/Ui.jpg
vendored
|
Before Width: | Height: | Size: 115 KiB |
BIN
web/img/ui/bong-2.png
vendored
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
web/img/ui/bt A-2.png
vendored
|
Before Width: | Height: | Size: 5 KiB |
BIN
web/img/ui/bt B-2.png
vendored
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
web/img/ui/bt B.png
vendored
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
web/img/ui/bt LOAD-2.png
vendored
|
Before Width: | Height: | Size: 3.4 KiB |
BIN
web/img/ui/bt MOVE-2.png
vendored
|
Before Width: | Height: | Size: 15 KiB |
BIN
web/img/ui/bt MOVE.png
vendored
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
BIN
web/img/ui/bt OPTIONS.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
web/img/ui/bt PlayerIndex-2.png
vendored
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
web/img/ui/bt QUIT-2.png
vendored
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
web/img/ui/bt SAVE-2.png
vendored
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
web/img/ui/bt SELECT-2.png
vendored
|
Before Width: | Height: | Size: 2.7 KiB |
BIN
web/img/ui/bt SHARE-2.png
vendored
|
Before Width: | Height: | Size: 3 KiB |
BIN
web/img/ui/bt START-2.png
vendored
|
Before Width: | Height: | Size: 2.8 KiB |
BIN
web/img/ui/bt X-2.png
vendored
|
Before Width: | Height: | Size: 5.1 KiB |
BIN
web/img/ui/bt X.png
vendored
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 5 KiB |
BIN
web/img/ui/bt Y-2.png
vendored
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
web/img/ui/bt Y.png
vendored
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
39
web/index.html
vendored
|
|
@ -49,45 +49,43 @@
|
|||
<div id="guide-txt"><b>Arrows</b>(move),<b>ZXCVAS</b>(game ABXYLR),<b>1/2</b>(1st/2nd player),<b>Shift/Enter/K/L</b>(select/start/save/load),<b>F</b>(fullscreen),<b>share</b>(copy
|
||||
sharelink to clipboard)
|
||||
</div>
|
||||
<div id="btn-load" unselectable="on" class="btn big unselectable" value="load"></div>
|
||||
<div id="btn-save" unselectable="on" class="btn big unselectable" value="save"></div>
|
||||
<div id="btn-join" unselectable="on" class="btn big unselectable" value="join"></div>
|
||||
<div id="btn-load" class="btn big unselectable" value="load"></div>
|
||||
<div id="btn-save" class="btn big unselectable" value="save"></div>
|
||||
<div id="btn-join" class="btn big unselectable" value="join"></div>
|
||||
<div id="slider-playeridx" class="slidecontainer">
|
||||
player choice
|
||||
<input type="range" min="1" max="4" value="1" class="slider" id="playeridx" onkeydown="event.preventDefault()">
|
||||
</div>
|
||||
|
||||
<div id="btn-quit" unselectable="on" class="btn big unselectable" value="quit"></div>
|
||||
<div id="btn-select" unselectable="on" class="btn big unselectable" value="select"></div>
|
||||
<div id="btn-start" unselectable="on" class="btn big unselectable" value="start"></div>
|
||||
<div id="btn-quit" class="btn big unselectable" value="quit"></div>
|
||||
<div id="btn-select" class="btn big unselectable" value="select"></div>
|
||||
<div id="btn-start" class="btn big unselectable" value="start"></div>
|
||||
|
||||
|
||||
<div id="color-button-holder">
|
||||
<div id="btn-a" unselectable="on" class="btn unselectable" value="a"></div>
|
||||
<div id="btn-b" unselectable="on" class="btn unselectable" value="b"></div>
|
||||
<div id="btn-x" unselectable="on" class="btn unselectable" value="x"></div>
|
||||
<div id="btn-y" unselectable="on" class="btn unselectable" value="y"></div>
|
||||
<div id="btn-a" class="btn unselectable" value="a"></div>
|
||||
<div id="btn-b" class="btn unselectable" value="b"></div>
|
||||
<div id="btn-x" class="btn unselectable" value="x"></div>
|
||||
<div id="btn-y" class="btn unselectable" value="y"></div>
|
||||
</div>
|
||||
|
||||
<div id="btn-settings" class="btn unselectable" value="settings"></div>
|
||||
|
||||
<!-- TODO: remove -->
|
||||
<input id="room-txt" type="text" placeholder="room id..." unselectable="on" class=" unselectable" disabled>
|
||||
<input id="room-txt" type="text" placeholder="room id..." class=" unselectable" disabled>
|
||||
|
||||
<label class="dpad-toggle-label" title="D-pad toggle">
|
||||
<input type="checkbox" id="dpad-toggle" checked>
|
||||
<span class="dpad-toggle-slider"></span>
|
||||
</label>
|
||||
|
||||
<div id="noti-box" unselectable="on" class="unselectable">Oh my god</div>
|
||||
<div id="noti-box" class="unselectable">Oh my god</div>
|
||||
|
||||
<div id="help-overlay">
|
||||
<div id="help-overlay-background"></div>
|
||||
<div id="help-overlay-detail"></div>
|
||||
</div>
|
||||
<div id="btn-help" unselectable="on" class="btn unselectable" value="help"></div>
|
||||
|
||||
<div id="btn-settings" class="btn btn2 unselectable" value="settings">
|
||||
Settings
|
||||
</div>
|
||||
<div id="btn-help" class="btn unselectable" value="help"></div>
|
||||
</div>
|
||||
|
||||
<div id="app-settings" class="modal-window">
|
||||
|
|
@ -98,7 +96,7 @@
|
|||
<span title="Reset" id="settings__controls__reset" class="semi-button">⟲</span>
|
||||
<span title="Close" id="settings__controls__close" class="semi-button">X</span>
|
||||
</div>
|
||||
<h1>Settings</h1>
|
||||
<h1>Options</h1>
|
||||
<div id="settings-data"></div>
|
||||
<div>
|
||||
* -- applied after application restart
|
||||
|
|
@ -111,11 +109,10 @@
|
|||
src="https://github.blog/wp-content/uploads/2008/12/forkme_right_gray_6d6d6d.png?resize=149%2C149"
|
||||
class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1"></a>
|
||||
|
||||
<script src="/static/js/lib/jquery-3.4.1.min.js"></script>
|
||||
|
||||
<script src="/static/js/gui/gui.js?v=1"></script>
|
||||
<script src="/static/js/log.js?v=5"></script>
|
||||
<script src="/static/js/utils.js?v1"></script>
|
||||
<script src="/static/js/gui/message.js?v=1"></script>
|
||||
<script src="/static/js/log.js?v=5"></script>
|
||||
<script src="/static/js/event/event.js?v=5"></script>
|
||||
<script src="/static/js/input/keys.js?v=3"></script>
|
||||
<script src="/static/js/settings/opts.js?v=1"></script>
|
||||
|
|
|
|||
76
web/js/controller.js
vendored
|
|
@ -19,15 +19,14 @@
|
|||
})();
|
||||
let prevDir = DIR.IDLE;
|
||||
|
||||
const menuScreen = $('#menu-screen');
|
||||
const helpOverlay = $('#help-overlay');
|
||||
const popupBox = $('#noti-box');
|
||||
const menuScreen = document.getElementById('menu-screen');
|
||||
const helpOverlay = document.getElementById('help-overlay');
|
||||
const playerIndex = document.getElementById('playeridx');
|
||||
|
||||
// keymap
|
||||
const keyButtons = {};
|
||||
Object.keys(KEY).forEach(button => {
|
||||
keyButtons[KEY[button]] = $(`#btn-${KEY[button]}`);
|
||||
keyButtons[KEY[button]] = document.getElementById(`btn-${KEY[button]}`);
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -61,7 +60,7 @@
|
|||
};
|
||||
|
||||
const onGameRoomAvailable = () => {
|
||||
popup('Now you can share you game!');
|
||||
message.show('Now you can share you game!');
|
||||
};
|
||||
|
||||
const onConnectionReady = () => {
|
||||
|
|
@ -74,7 +73,7 @@
|
|||
};
|
||||
|
||||
const onLatencyCheck = (data) => {
|
||||
popup('Connecting to fastest server...');
|
||||
message.show('Connecting to fastest server...');
|
||||
const timeoutMs = 1111;
|
||||
// deduplicate
|
||||
const addresses = [...new Set(data.addresses || [])];
|
||||
|
|
@ -102,13 +101,13 @@
|
|||
if (isGameScreen) {
|
||||
stream.toggle(!show);
|
||||
} else {
|
||||
menuScreen.toggle(!show);
|
||||
gui.toggle(menuScreen, !show);
|
||||
}
|
||||
|
||||
keyButtons[KEY.SAVE].toggle(show || isGameScreen);
|
||||
keyButtons[KEY.LOAD].toggle(show || isGameScreen);
|
||||
gui.toggle(keyButtons[KEY.SAVE], show || isGameScreen);
|
||||
gui.toggle(keyButtons[KEY.LOAD], show || isGameScreen);
|
||||
|
||||
helpOverlay.toggle(show);
|
||||
gui.toggle(helpOverlay, show);
|
||||
|
||||
this.shown = show;
|
||||
|
||||
|
|
@ -120,23 +119,23 @@
|
|||
log.debug('[control] loading menu screen');
|
||||
|
||||
stream.toggle(false);
|
||||
keyButtons[KEY.SAVE].hide();
|
||||
keyButtons[KEY.LOAD].hide();
|
||||
gui.hide(keyButtons[KEY.SAVE]);
|
||||
gui.hide(keyButtons[KEY.LOAD]);
|
||||
|
||||
gameList.show();
|
||||
menuScreen.show();
|
||||
gui.show(menuScreen);
|
||||
|
||||
setState(app.state.menu);
|
||||
};
|
||||
|
||||
const startGame = () => {
|
||||
if (!rtcp.isConnected()) {
|
||||
popup('Game cannot load. Please refresh');
|
||||
message.show('Game cannot load. Please refresh');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rtcp.isInputReady()) {
|
||||
popup('Game is not ready yet. Please wait');
|
||||
message.show('Game is not ready yet. Please wait');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -155,10 +154,10 @@
|
|||
|
||||
// clear menu screen
|
||||
input.poll().disable();
|
||||
menuScreen.hide();
|
||||
gui.hide(menuScreen);
|
||||
stream.toggle(true);
|
||||
keyButtons[KEY.SAVE].show();
|
||||
keyButtons[KEY.LOAD].show();
|
||||
gui.show(keyButtons[KEY.SAVE]);
|
||||
gui.show(keyButtons[KEY.LOAD]);
|
||||
// end clear
|
||||
input.poll().enable();
|
||||
};
|
||||
|
|
@ -166,9 +165,6 @@
|
|||
const saveGame = utils.debounce(socket.saveGame, 1000);
|
||||
const loadGame = utils.debounce(socket.loadGame, 1000);
|
||||
|
||||
const _popup = (message) => popupBox.html(message).fadeIn().fadeOut();
|
||||
const popup = utils.throttle(_popup, 1000);
|
||||
|
||||
const _dpadArrowKeys = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT];
|
||||
|
||||
// pre-state key press handler
|
||||
|
|
@ -176,9 +172,9 @@
|
|||
const button = keyButtons[data.key];
|
||||
|
||||
if (_dpadArrowKeys.includes(data.key)) {
|
||||
button.addClass('dpad-pressed');
|
||||
button.classList.add('dpad-pressed');
|
||||
} else {
|
||||
if (button) button.addClass('pressed');
|
||||
if (button) button.classList.add('pressed');
|
||||
}
|
||||
|
||||
if (state !== app.state.settings) {
|
||||
|
|
@ -192,12 +188,10 @@
|
|||
const onKeyRelease = data => {
|
||||
const button = keyButtons[data.key];
|
||||
|
||||
if (!button) return;
|
||||
|
||||
if (_dpadArrowKeys.includes(data.key)) {
|
||||
button.removeClass('dpad-pressed');
|
||||
button.classList.remove('dpad-pressed');
|
||||
} else {
|
||||
if (button) button.removeClass('pressed');
|
||||
if (button) button.classList.remove('pressed');
|
||||
}
|
||||
|
||||
if (state !== app.state.settings) {
|
||||
|
|
@ -314,13 +308,13 @@
|
|||
startGame();
|
||||
break;
|
||||
case KEY.QUIT:
|
||||
popup('You are already in menu screen!');
|
||||
message.show('You are already in menu screen!');
|
||||
break;
|
||||
case KEY.LOAD:
|
||||
popup('Loading the game.');
|
||||
message.show('Loading the game.');
|
||||
break;
|
||||
case KEY.SAVE:
|
||||
popup('Saving the game.');
|
||||
message.show('Saving the game.');
|
||||
break;
|
||||
case KEY.STATS:
|
||||
event.pub(STATS_TOGGLE);
|
||||
|
|
@ -351,7 +345,7 @@
|
|||
// save when click share
|
||||
saveGame();
|
||||
room.copyToClipboard();
|
||||
popup('Shared link copied to the clipboard!');
|
||||
message.show('Shared link copied to the clipboard!');
|
||||
break;
|
||||
case KEY.SAVE:
|
||||
saveGame();
|
||||
|
|
@ -390,7 +384,7 @@
|
|||
socket.quitGame(room.getId());
|
||||
room.reset();
|
||||
|
||||
popup('Quit!');
|
||||
message.show('Quit!');
|
||||
|
||||
window.location = window.location.pathname;
|
||||
break;
|
||||
|
|
@ -410,9 +404,11 @@
|
|||
|
||||
// subscriptions
|
||||
event.sub(GAME_ROOM_AVAILABLE, onGameRoomAvailable, 2);
|
||||
event.sub(GAME_SAVED, () => popup('Saved'));
|
||||
event.sub(GAME_LOADED, () => popup('Loaded'));
|
||||
event.sub(GAME_PLAYER_IDX, idx => popup(+idx + 1));
|
||||
event.sub(GAME_SAVED, () => message.show('Saved'));
|
||||
event.sub(GAME_LOADED, () => message.show('Loaded'));
|
||||
event.sub(GAME_PLAYER_IDX, idx => {
|
||||
if (!isNaN(+idx)) message.show(+idx + 1);
|
||||
});
|
||||
|
||||
event.sub(MEDIA_STREAM_INITIALIZED, (data) => {
|
||||
rtcp.start(data.stunturn);
|
||||
|
|
@ -428,16 +424,16 @@
|
|||
socket.abort();
|
||||
});
|
||||
event.sub(LATENCY_CHECK_REQUESTED, onLatencyCheck);
|
||||
event.sub(GAMEPAD_CONNECTED, () => popup('Gamepad connected'));
|
||||
event.sub(GAMEPAD_DISCONNECTED, () => popup('Gamepad disconnected'));
|
||||
event.sub(GAMEPAD_CONNECTED, () => message.show('Gamepad connected'));
|
||||
event.sub(GAMEPAD_DISCONNECTED, () => message.show('Gamepad disconnected'));
|
||||
// touch stuff
|
||||
event.sub(MENU_HANDLER_ATTACHED, (data) => {
|
||||
menuScreen.on(data.event, data.handler);
|
||||
menuScreen.addEventListener(data.event, data.handler);
|
||||
});
|
||||
event.sub(KEY_PRESSED, onKeyPress);
|
||||
event.sub(KEY_RELEASED, onKeyRelease);
|
||||
event.sub(KEY_STATE_UPDATED, data => rtcp.input(data));
|
||||
event.sub(SETTINGS_CHANGED, () => popup('Settings have been updated'));
|
||||
event.sub(SETTINGS_CHANGED, () => message.show('Settings have been updated'));
|
||||
event.sub(SETTINGS_CLOSED, () => {
|
||||
state.keyRelease(KEY.SETTINGS);
|
||||
});
|
||||
|
|
@ -446,4 +442,4 @@
|
|||
|
||||
// initial app state
|
||||
setState(app.state.eden);
|
||||
})($, document, event, env, gameList, input, KEY, log, room, settings, socket, stats, stream, utils);
|
||||
})(document, event, env, gameList, input, KEY, log, message, room, settings, socket, stats, stream, utils);
|
||||
|
|
|
|||
68
web/js/env.js
vendored
|
|
@ -1,57 +1,41 @@
|
|||
const env = (() => {
|
||||
// UI
|
||||
const doc = $(document);
|
||||
const gameBoy = $('#gamebody');
|
||||
const ghRibbon = $('#ribbon');
|
||||
const page = document.getElementsByTagName('html')[0];
|
||||
const gameBoy = document.getElementById('gamebody');
|
||||
const ghRibbon = document.getElementById('ribbon');
|
||||
|
||||
let isLayoutSwitched = false;
|
||||
|
||||
// Window rerender / rotate screen if needed
|
||||
const fixScreenLayout = () => {
|
||||
let targetWidth = Math.round(doc.width() * 0.9 / 2) * 2,
|
||||
targetHeight = Math.round(doc.height() * 0.9 / 2) * 2;
|
||||
let pw = getWidth(page),
|
||||
ph = getHeight(page),
|
||||
targetWidth = Math.round(pw * 0.9 / 2) * 2,
|
||||
targetHeight = Math.round(ph * 0.9 / 2) * 2;
|
||||
|
||||
// mobile == full screen
|
||||
if (env.getOs() === 'android') {
|
||||
targetWidth = doc.width();
|
||||
targetHeight = doc.height();
|
||||
}
|
||||
|
||||
// Should have maximum box for desktop?
|
||||
// targetWidth = 800; targetHeight = 600; // test on desktop
|
||||
// save page rotation
|
||||
isLayoutSwitched = isPortrait();
|
||||
|
||||
rescaleGameBoy(targetWidth, targetHeight);
|
||||
|
||||
let st = isLayoutSwitched ? 'rotate(90deg)' : '';
|
||||
ghRibbon.css({
|
||||
'bottom': isLayoutSwitched ? 0 : '',
|
||||
'top': isLayoutSwitched ? '' : 0,
|
||||
'transform': st,
|
||||
'-webkit-transform': st,
|
||||
'-moz-transform': st
|
||||
})
|
||||
ghRibbon.style['bottom'] = isLayoutSwitched ? 0 : '';
|
||||
ghRibbon.style['top'] = isLayoutSwitched ? '' : 0;
|
||||
ghRibbon.style['transform'] = isLayoutSwitched ? 'rotate(90deg)' : '';
|
||||
};
|
||||
|
||||
const rescaleGameBoy = (targetWidth, targetHeight) => {
|
||||
const transformations = ['translate(-50%, -50%)'];
|
||||
|
||||
// rotate portrait layout
|
||||
isLayoutSwitched = isPortrait();
|
||||
if (isLayoutSwitched) {
|
||||
transformations.push('rotate(90deg)');
|
||||
[targetWidth, targetHeight] = [targetHeight, targetWidth]
|
||||
}
|
||||
|
||||
// scale, fit to target size
|
||||
const scale = Math.min(targetWidth / gameBoy.width(), targetHeight / gameBoy.height());
|
||||
const scale = Math.min(targetWidth / getWidth(gameBoy), targetHeight / getHeight(gameBoy));
|
||||
transformations.push(`scale(${scale})`);
|
||||
|
||||
const transform = transformations.join(' ');
|
||||
gameBoy.css({
|
||||
'transform': transform,
|
||||
'-webkit-transform': transform,
|
||||
'-moz-transform': transform
|
||||
});
|
||||
gameBoy.style['transform'] = transformations.join(' ');
|
||||
}
|
||||
|
||||
const getOS = () => {
|
||||
|
|
@ -74,19 +58,7 @@ const env = (() => {
|
|||
return browserName;
|
||||
};
|
||||
|
||||
// !to use more sophisticated approach / lib
|
||||
const isPortrait = () => {
|
||||
// ios / mobile app
|
||||
switch (window.orientation) {
|
||||
case 0:
|
||||
case 180:
|
||||
return true;
|
||||
}
|
||||
|
||||
// desktop
|
||||
const orientation = screen.msOrientation || screen.mozOrientation || (screen.orientation || {}).type;
|
||||
return orientation === 'portrait-primary';
|
||||
};
|
||||
const isPortrait = () => getWidth(page) < getHeight(page);
|
||||
|
||||
const toggleFullscreen = (enable, element) => {
|
||||
const el = enable ? element : document;
|
||||
|
|
@ -114,6 +86,14 @@ const env = (() => {
|
|||
}
|
||||
};
|
||||
|
||||
function getHeight(el) {
|
||||
return parseFloat(getComputedStyle(el, null).height.replace("px", ""));
|
||||
}
|
||||
|
||||
function getWidth(el) {
|
||||
return parseFloat(getComputedStyle(el, null).width.replace("px", ""));
|
||||
}
|
||||
|
||||
window.addEventListener('resize', fixScreenLayout);
|
||||
window.addEventListener('orientationchange', fixScreenLayout);
|
||||
document.addEventListener('DOMContentLoaded', () => fixScreenLayout(), false);
|
||||
|
|
@ -130,4 +110,4 @@ const env = (() => {
|
|||
isLayoutSwitched: isLayoutSwitched
|
||||
})
|
||||
}
|
||||
})($, document, log, navigator, screen, window);
|
||||
})(document, log, navigator, screen, window);
|
||||
|
|
|
|||
39
web/js/gameList.js
vendored
|
|
@ -9,8 +9,8 @@ const gameList = (() => {
|
|||
let gamePickTimer = null;
|
||||
|
||||
// UI
|
||||
const listBox = $('#menu-container');
|
||||
const menuItemChoice = $('#menu-item-choice');
|
||||
const listBox = document.getElementById('menu-container');
|
||||
const menuItemChoice = document.getElementById('menu-item-choice');
|
||||
|
||||
const MENU_TOP_POSITION = 102;
|
||||
let menuTop = MENU_TOP_POSITION;
|
||||
|
|
@ -22,22 +22,17 @@ const gameList = (() => {
|
|||
const render = () => {
|
||||
log.debug('[games] load game menu');
|
||||
|
||||
listBox.html(games
|
||||
.map(game => `<div class="menu-item unselectable" unselectable="on"><div><span>${game}</span></div></div>`)
|
||||
.join('')
|
||||
);
|
||||
listBox.innerHTML = games
|
||||
.map(game => `<div class="menu-item unselectable"><div><span>${game}</span></div></div>`)
|
||||
.join('');
|
||||
};
|
||||
|
||||
const show = () => {
|
||||
render();
|
||||
menuItemChoice.show();
|
||||
menuItemChoice.style.display = "block";
|
||||
pickGame();
|
||||
};
|
||||
|
||||
const hide = () => {
|
||||
menuItemChoice.hide();
|
||||
};
|
||||
|
||||
const pickGame = (index) => {
|
||||
let idx = undefined !== index ? index : gameIndex;
|
||||
|
||||
|
|
@ -47,16 +42,17 @@ const gameList = (() => {
|
|||
if (idx >= games.length) idx = 0;
|
||||
|
||||
// transition menu box
|
||||
listBox.css('transition', 'top 0.2s');
|
||||
listBox.css('-moz-transition', 'top 0.2s');
|
||||
listBox.css('-webkit-transition', 'top 0.2s');
|
||||
listBox.style['transition'] = 'top 0.2s';
|
||||
|
||||
menuTop = MENU_TOP_POSITION - idx * 36;
|
||||
listBox.css('top', `${menuTop}px`);
|
||||
listBox.style['top'] = `${menuTop}px`;
|
||||
|
||||
// overflow marquee
|
||||
$('.menu-item .pick').removeClass('pick');
|
||||
$(`.menu-item:eq(${idx}) span`).addClass('pick');
|
||||
let pick = document.querySelectorAll('.menu-item .pick')[0];
|
||||
if (pick) {
|
||||
pick.classList.remove('pick');
|
||||
}
|
||||
document.querySelectorAll(`.menu-item span`)[idx].classList.add('pick');
|
||||
|
||||
gameIndex = idx;
|
||||
};
|
||||
|
|
@ -80,10 +76,8 @@ const gameList = (() => {
|
|||
};
|
||||
|
||||
const onMenuPressed = (newPosition) => {
|
||||
listBox.css('transition', '');
|
||||
listBox.css('-moz-transition', '');
|
||||
listBox.css('-webkit-transition', '');
|
||||
listBox.css('top', `${menuTop - newPosition}px`);
|
||||
listBox.style['transition'] = '';
|
||||
listBox.style['top'] = `${menuTop - newPosition}px`;
|
||||
};
|
||||
|
||||
const onMenuReleased = (position) => {
|
||||
|
|
@ -100,8 +94,7 @@ const gameList = (() => {
|
|||
stopGamePickerTimer: stopGamePickerTimer,
|
||||
pickGame: pickGame,
|
||||
show: show,
|
||||
hide: hide,
|
||||
set: setGames,
|
||||
getCurrentGame: () => games[gameIndex]
|
||||
}
|
||||
})($, event, log);
|
||||
})(document, event, log);
|
||||
|
|
|
|||
61
web/js/gui/gui.js
vendored
|
|
@ -56,9 +56,70 @@ const gui = (() => {
|
|||
return el;
|
||||
}
|
||||
|
||||
const show = (el) => {
|
||||
el.style.display = 'block';
|
||||
}
|
||||
|
||||
const hide = (el) => {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
|
||||
const toggle = (el, what) => {
|
||||
if (what) {
|
||||
show(el)
|
||||
} else {
|
||||
hide(el)
|
||||
}
|
||||
}
|
||||
|
||||
const fadeIn = async (el, speed = .1) => {
|
||||
el.style.opacity = '0';
|
||||
el.style.display = 'block';
|
||||
return new Promise((done) => (function fade() {
|
||||
let val = parseFloat(el.style.opacity);
|
||||
const proceed = ((val += 0.1) <= 1);
|
||||
if (proceed) {
|
||||
el.style.opacity = '' + val;
|
||||
requestAnimationFrame(fade);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
||||
|
||||
const fadeOut = async (el, speed = .1) => {
|
||||
el.style.opacity = '1';
|
||||
return new Promise((done) => (function fade() {
|
||||
if ((el.style.opacity -= speed) < 0) {
|
||||
el.style.display = "none";
|
||||
done();
|
||||
} else {
|
||||
requestAnimationFrame(fade);
|
||||
}
|
||||
})()
|
||||
)
|
||||
}
|
||||
|
||||
const sleep = async (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
const fadeInOut = async (el, wait = 1000, speed = .1) => {
|
||||
await fadeIn(el, speed)
|
||||
await sleep(wait);
|
||||
await fadeOut(el, speed)
|
||||
}
|
||||
|
||||
return {
|
||||
anim: {
|
||||
fadeIn,
|
||||
fadeOut,
|
||||
fadeInOut,
|
||||
},
|
||||
create: _create,
|
||||
select,
|
||||
binding,
|
||||
show,
|
||||
hide,
|
||||
toggle,
|
||||
}
|
||||
})(document);
|
||||
|
|
|
|||
46
web/js/gui/message.js
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* App UI message module.
|
||||
*
|
||||
* @version 1
|
||||
*/
|
||||
const message = (() => {
|
||||
const popupBox = document.getElementById('noti-box');
|
||||
|
||||
// fifo queue
|
||||
let queue = [];
|
||||
const queueMaxSize = 5;
|
||||
|
||||
let isScreenFree = true;
|
||||
|
||||
const _popup = () => {
|
||||
// recursion edge case:
|
||||
// no messages in the queue or one on the screen
|
||||
if (!(queue.length > 0 && isScreenFree)) {
|
||||
return;
|
||||
}
|
||||
|
||||
isScreenFree = false;
|
||||
popupBox.innerText = queue.shift();
|
||||
gui.anim.fadeInOut(popupBox, 1000, .05).finally(() => {
|
||||
isScreenFree = true;
|
||||
_popup();
|
||||
})
|
||||
}
|
||||
|
||||
const _storeMessage = (text) => {
|
||||
if (queue.length <= queueMaxSize) {
|
||||
queue.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
const _proceed = (text) => {
|
||||
_storeMessage(text);
|
||||
_popup();
|
||||
}
|
||||
|
||||
const show = utils.throttle(_proceed, 1000);
|
||||
|
||||
return Object.freeze({
|
||||
show: show
|
||||
})
|
||||
})(document, gui, utils);
|
||||
139
web/js/input/touch.js
vendored
|
|
@ -16,37 +16,36 @@ const touch = (() => {
|
|||
|
||||
let vpadTouchIdx = null;
|
||||
let vpadTouchDrag = null;
|
||||
let vpadHolder = $("#circle-pad-holder");
|
||||
let vpadCircle = $("#circle-pad");
|
||||
let vpadHolder = document.getElementById('circle-pad-holder');
|
||||
let vpadCircle = document.getElementById('circle-pad');
|
||||
|
||||
const window_ = $(window);
|
||||
const buttons = $(".btn");
|
||||
const playerSlider = $("#playeridx")
|
||||
const dpad = $(".dpad");
|
||||
const buttons = Array.from(document.getElementsByClassName('btn'));
|
||||
const playerSlider = document.getElementById('playeridx');
|
||||
const dpad = Array.from(document.getElementsByClassName('dpad'));
|
||||
|
||||
const dpadToggle = document.getElementById('dpad-toggle')
|
||||
dpadToggle.addEventListener('change', (e) => {
|
||||
event.pub(DPAD_TOGGLE, {checked: e.target.checked});
|
||||
event.pub(DPAD_TOGGLE, {checked: e.target.checked});
|
||||
});
|
||||
|
||||
let dpadMode = true;
|
||||
const deadZone = 0.1;
|
||||
|
||||
function onDpadToggle(checked) {
|
||||
if (dpadMode === checked) {
|
||||
return //error?
|
||||
}
|
||||
if (dpadMode) {
|
||||
dpadMode = false;
|
||||
vpadHolder.addClass('dpad-empty');
|
||||
vpadCircle.addClass('bong-full');
|
||||
// reset dpad keys pressed before moving to analog stick mode
|
||||
resetVpadState()
|
||||
} else {
|
||||
dpadMode = true;
|
||||
vpadHolder.removeClass('dpad-empty');
|
||||
vpadCircle.removeClass('bong-full');
|
||||
}
|
||||
if (dpadMode === checked) {
|
||||
return //error?
|
||||
}
|
||||
if (dpadMode) {
|
||||
dpadMode = false;
|
||||
vpadHolder.classList.add('dpad-empty');
|
||||
vpadCircle.classList.add('bong-full');
|
||||
// reset dpad keys pressed before moving to analog stick mode
|
||||
resetVpadState()
|
||||
} else {
|
||||
dpadMode = true;
|
||||
vpadHolder.classList.remove('dpad-empty');
|
||||
vpadCircle.classList.remove('bong-full');
|
||||
}
|
||||
}
|
||||
|
||||
function resetVpadState() {
|
||||
|
|
@ -63,7 +62,8 @@ const touch = (() => {
|
|||
|
||||
vpadTouchDrag = null;
|
||||
vpadTouchIdx = null;
|
||||
dpad.removeClass('pressed');
|
||||
|
||||
dpad.forEach(arrow => arrow.classList.remove('pressed'));
|
||||
}
|
||||
|
||||
function checkVpadState(axis, state) {
|
||||
|
|
@ -82,9 +82,7 @@ const touch = (() => {
|
|||
}
|
||||
|
||||
function handleVpadJoystickDown(event) {
|
||||
vpadCircle.css('transition', '0s');
|
||||
vpadCircle.css('-moz-transition', '0s');
|
||||
vpadCircle.css('-webkit-transition', '0s');
|
||||
vpadCircle.style['transition'] = '0s';
|
||||
|
||||
if (event.changedTouches) {
|
||||
resetVpadState();
|
||||
|
|
@ -99,12 +97,8 @@ const touch = (() => {
|
|||
function handleVpadJoystickUp() {
|
||||
if (vpadTouchDrag === null) return;
|
||||
|
||||
vpadCircle.css('transition', '.2s');
|
||||
vpadCircle.css('-moz-transition', '.2s');
|
||||
vpadCircle.css('-webkit-transition', '.2s');
|
||||
vpadCircle.css('transform', 'translate3d(0px, 0px, 0px)');
|
||||
vpadCircle.css('-moz-transform', 'translate3d(0px, 0px, 0px)');
|
||||
vpadCircle.css('-webkit-transform', 'translate3d(0px, 0px, 0px)');
|
||||
vpadCircle.style['transition'] = '.2s';
|
||||
vpadCircle.style['transform'] = 'translate3d(0px, 0px, 0px)';
|
||||
|
||||
resetVpadState();
|
||||
}
|
||||
|
|
@ -137,10 +131,7 @@ const touch = (() => {
|
|||
yNew = -tmp;
|
||||
}
|
||||
|
||||
let style = `translate(${xNew}px, ${yNew}px)`;
|
||||
vpadCircle.css('transform', style);
|
||||
vpadCircle.css('-webkit-transform', style);
|
||||
vpadCircle.css('-moz-transform', style);
|
||||
vpadCircle.style['transform'] = `translate(${xNew}px, ${yNew}px)`;
|
||||
|
||||
let xRatio = xNew / MAX_DIFF;
|
||||
let yRatio = yNew / MAX_DIFF;
|
||||
|
|
@ -156,33 +147,29 @@ const touch = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Right side - Control buttons
|
||||
*/
|
||||
// right side - control buttons
|
||||
const _handleButton = (key, state) => checkVpadState(key, state)
|
||||
|
||||
function handleButtonDown() {
|
||||
checkVpadState($(this).attr('value'), true);
|
||||
// add touchIdx?
|
||||
_handleButton(this.getAttribute('value'), true);
|
||||
}
|
||||
|
||||
function handleButtonUp() {
|
||||
checkVpadState($(this).attr('value'), false);
|
||||
_handleButton(this.getAttribute('value'), false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Player index slider
|
||||
*/
|
||||
function handleButtonClick() {
|
||||
_handleButton(this.getAttribute('value'), true);
|
||||
setTimeout(() => {
|
||||
_handleButton(this.getAttribute('value'), false);
|
||||
}, 30);
|
||||
}
|
||||
|
||||
function handlePlayerSlider() {
|
||||
socket.updatePlayerIndex($(this).val() - 1);
|
||||
socket.updatePlayerIndex(this.value - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Touch menu
|
||||
*/
|
||||
|
||||
// Touch menu
|
||||
let menuTouchIdx = null;
|
||||
let menuTouchDrag = null;
|
||||
let menuTouchTime = null;
|
||||
|
|
@ -240,9 +227,7 @@ const touch = (() => {
|
|||
menuTouchDrag = null;
|
||||
}
|
||||
|
||||
/*
|
||||
Common events
|
||||
*/
|
||||
// Common events
|
||||
function handleWindowMove(event) {
|
||||
event.preventDefault();
|
||||
handleVpadJoystickMove(event);
|
||||
|
|
@ -255,10 +240,11 @@ const touch = (() => {
|
|||
// check class
|
||||
|
||||
let elem = document.elementFromPoint(event.changedTouches[i].clientX, event.changedTouches[i].clientY);
|
||||
|
||||
if (elem.classList.contains('btn')) {
|
||||
$(elem).trigger('touchstart');
|
||||
elem.dispatchEvent(new Event('touchstart'));
|
||||
} else {
|
||||
buttons.trigger('touchend');
|
||||
elem.dispatchEvent(new Event('touchend'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -268,23 +254,31 @@ const touch = (() => {
|
|||
function handleWindowUp(ev) {
|
||||
handleVpadJoystickUp(ev);
|
||||
handleMenuUp(ev);
|
||||
buttons.trigger('touchend');
|
||||
buttons.forEach((btn) => {
|
||||
btn.dispatchEvent(new Event('touchend'));
|
||||
});
|
||||
}
|
||||
|
||||
// touch/mouse events for control buttons. mouseup events is binded to window.
|
||||
buttons.on('mousedown', handleButtonDown);
|
||||
buttons.on('touchstart', handleButtonDown);
|
||||
buttons.on('touchend', handleButtonUp);
|
||||
buttons.forEach((btn) => {
|
||||
btn.addEventListener('mousedown', handleButtonDown);
|
||||
btn.addEventListener('touchstart', handleButtonDown);
|
||||
btn.addEventListener('touchend', handleButtonUp);
|
||||
});
|
||||
|
||||
// touch/mouse events for dpad. mouseup events is binded to window.
|
||||
vpadHolder.on('mousedown', handleVpadJoystickDown);
|
||||
vpadHolder.on('touchstart', handleVpadJoystickDown);
|
||||
vpadHolder.on('touchend', handleVpadJoystickUp);
|
||||
vpadHolder.addEventListener('mousedown', handleVpadJoystickDown);
|
||||
vpadHolder.addEventListener('touchstart', handleVpadJoystickDown);
|
||||
vpadHolder.addEventListener('touchend', handleVpadJoystickUp);
|
||||
|
||||
dpad.forEach((arrow) => {
|
||||
arrow.addEventListener('click', handleButtonClick);
|
||||
});
|
||||
|
||||
// touch/mouse events for player slider.
|
||||
playerSlider.on('oninput', handlePlayerSlider);
|
||||
playerSlider.on('onchange', handlePlayerSlider);
|
||||
playerSlider.on('mouseup', handlePlayerSlider);
|
||||
playerSlider.addEventListener('oninput', handlePlayerSlider);
|
||||
playerSlider.addEventListener('onchange', handlePlayerSlider);
|
||||
playerSlider.addEventListener('mouseup', handlePlayerSlider);
|
||||
|
||||
// Bind events for menu
|
||||
// TODO change this flow
|
||||
|
|
@ -297,16 +291,15 @@ const touch = (() => {
|
|||
return {
|
||||
init: () => {
|
||||
// add buttons into the state 🤦
|
||||
$('.btn, .btn-big').each((_, el) => {
|
||||
vpadState[$(el).attr('value')] = false;
|
||||
Array.from(document.querySelectorAll('.btn,.btn-big')).forEach((el) => {
|
||||
vpadState[el.getAttribute('value')] = false;
|
||||
});
|
||||
|
||||
// Bind events for window
|
||||
window_.on('mousemove', handleWindowMove);
|
||||
window_[0].addEventListener('touchmove', handleWindowMove, {passive: false});
|
||||
window_.on('mouseup', handleWindowUp);
|
||||
window.addEventListener('mousemove', handleWindowMove);
|
||||
window.addEventListener('touchmove', handleWindowMove, {passive: false});
|
||||
window.addEventListener('mouseup', handleWindowUp);
|
||||
|
||||
log.info('[input] touch input has been initialized');
|
||||
}
|
||||
}
|
||||
})($, document, event, KEY, window);
|
||||
})(document, event, KEY, window);
|
||||
|
|
|
|||
2
web/js/lib/jquery-3.4.1.min.js
vendored
2
web/js/network/socket.js
vendored
|
|
@ -145,4 +145,4 @@ const socket = (() => {
|
|||
quitGame: quitGame,
|
||||
toggleMultitap: toggleMultitap,
|
||||
}
|
||||
})($, event, log);
|
||||
})(event, log);
|
||||
|
|
|
|||
12
web/js/room.js
vendored
|
|
@ -6,14 +6,14 @@ const room = (() => {
|
|||
let id = '';
|
||||
|
||||
// UI
|
||||
const roomLabel = $('#room-txt');
|
||||
const roomLabel = document.getElementById('room-txt');
|
||||
|
||||
// !to rewrite
|
||||
const parseURLForRoom = () => {
|
||||
let queryDict = {};
|
||||
let regex = /^\/?([A-Za-z]*)\/?/g;
|
||||
var zone = regex.exec(location.pathname)[1]
|
||||
var room = null
|
||||
const zone = regex.exec(location.pathname)[1];
|
||||
let room = null;
|
||||
|
||||
// get room from URL
|
||||
location.search.substr(1)
|
||||
|
|
@ -23,7 +23,7 @@ const room = (() => {
|
|||
});
|
||||
|
||||
if (typeof queryDict.id === 'string') {
|
||||
room = decodeURIComponent(queryDict.id);
|
||||
room = decodeURIComponent(queryDict.id);
|
||||
}
|
||||
|
||||
return [room, zone];
|
||||
|
|
@ -38,11 +38,11 @@ const room = (() => {
|
|||
getId: () => id,
|
||||
setId: (id_) => {
|
||||
id = id_;
|
||||
roomLabel.val(id);
|
||||
roomLabel.value = id;
|
||||
},
|
||||
reset: () => {
|
||||
id = '';
|
||||
roomLabel.val(id);
|
||||
roomLabel.value = id;
|
||||
},
|
||||
save: (roomIndex) => {
|
||||
localStorage.setItem('roomID', roomIndex);
|
||||
|
|
|
|||