diff --git a/package.json b/package.json index 7aaa5dc..b6a642b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "vite": "^5.3.1" }, "dependencies": { + "nipplejs": "^0.10.2", "sanitize.css": "^13.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index daeb4bc..28d7297 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + nipplejs: + specifier: ^0.10.2 + version: 0.10.2 sanitize.css: specifier: ^13.0.0 version: 13.0.0 @@ -254,6 +257,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nipplejs@0.10.2: + resolution: {integrity: sha512-XGxFY8C2DOtobf1fK+MXINTzkkXJLjZDDpfQhOUZf4TSytbc9s4bmA0lB9eKKM8iDivdr9NQkO7DpIQfsST+9g==} + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -453,6 +459,8 @@ snapshots: nanoid@3.3.7: {} + nipplejs@0.10.2: {} + picocolors@1.0.1: {} postcss@8.4.39: diff --git a/src/index.html b/src/index.html index f0c3c7e..01d073e 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,68 @@ Virtual Gamepad -
+
+
+
+ + +
+
+
+

Virtual Gamepad

+
+

Settings

+

+ + +

+

+ + ms +

+

+ + +

+
+
+

References

+

+ Joystick: send POST to /joystick?p=aaff (aa: + 00~FF angle, ff: 00~FF force) at intervals. +

+

Buttons: send POST to /a, /b.

+

+ More details: + TwoSquirrels/virtual-gamepad - GitHub +

+
+
diff --git a/src/main.js b/src/main.js index 44f3461..edf7fcd 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,32 @@ +import nipplejs from "nipplejs"; import "sanitize.css"; import "./style.css"; -document.querySelector("#app").innerHTML = ` -
-

Virtual Gamepad

-
-`; +let host = "http://localhost"; +let interval = 200; +let showButtons = true; + +document.querySelector("#settings-host").oninput = (event) => { + console.log(`Modify host ${host} -> ${event.target.value}`); + host = event.target.value; +}; + +document.querySelector("#settings-interval").oninput = (event) => { + console.log(`Modify interval ${interval} -> ${event.target.value}`); + interval = event.target.value; +}; + +document.querySelector("#settings-buttons").oninput = (event) => { + console.log(`Modify showButtons ${showButtons} -> ${event.target.checked}`); + showButtons = event.target.checked; + if (showButtons) + document.querySelector("#buttons-zone").classList.remove("erase"); + else document.querySelector("#buttons-zone").classList.add("erase"); +}; + +const joystickManager = nipplejs.create({ + zone: document.querySelector("#joystick-zone"), + color: "#55CCFF", + size: 200, + mode: "dynamic", +}); diff --git a/src/style.css b/src/style.css index e69de29..7e88e2b 100644 --- a/src/style.css +++ b/src/style.css @@ -0,0 +1,83 @@ +:root { + width: 0; + color: #ffffffcc; +} + +.erase { + position: absolute; + display: none; + width: 0; + height: 0; + margin: 0; + padding: 0; + visibility: hidden; + opacity: 0; +} + +main { + position: absolute; + display: flex; + top: 0; + left: 0; + height: 100dvh; + width: 100dvw; + z-index: -1; + background-color: navy; +} + +#joystick-zone { + flex: 8; + height: 100%; + background-color: #ffaaaa33; +} + +#buttons-zone { + display: flex; + flex: 5; + height: 100%; + flex-direction: column; +} + +#buttons-zone > button { + display: block; + flex: 1; + width: 100%; + font-size: 25dvmin; + opacity: 0.5; +} + +#buttons-zone > button:hover { + opacity: 0.75; +} + +article { + margin: 0.5em; + padding: 0.5em; + max-height: 50dvh; + width: 50dvw; + overflow: scroll; + font-size: max(0.75rem, 2dvmin); + background-color: #55555555; +} + +article * { + margin: 0; +} + +article h1 { + margin: 0.2em 0.1em; +} + +article h2 { + margin: 0.1em 0; +} + +article input[type="checkbox"] { + height: 1.5em; + width: 1.5em; +} + +article code { + padding: 0.25em; + background: #333355; +}