- From: Norren <notifications@github.com>
- Date: Thu, 16 Nov 2023 04:26:24 -0800
- To: w3c/gamepad <gamepad@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3c/gamepad/issues/37/1814344040@github.com>
Having just stumbled across this in a late night hunt for the answers to this question along with other gamepad API questions for my own ElectronJS powered game, I would like to provide the long overdue context in long format, I see all this in the thread above but since @marcoscaceres wants evidence, I will restate it in the form of my real world problem. My apologies if being a little sleep deprived has made it into a bit of a ramble, but I feel the meandering explanation helps build the case, as it demonstrates a borderline layperson's approach to confronting the problem: (And perhaps if I have overlooked something obvious, the thing I have overlooked will be as or more informative to you as my plea itself.) Presently, to render a WebGL powered 3D Engine to a Canvas, the most performant way to do this is to pass control of the Canvas element to a WebWorker via Offscreen Canvas. A RequestAnimationFrame() loop on the DOM drops animation frames inconsistently due to... blocking? (Yes, I think the term is Blocking) from a number of main DOM thread related background and foreground tasks while Offscreen Canvas has an entire thread to itself. Gamers always notice these frame drops when they happen as it usually negatively impacts their gaming experience, so we are ***forced*** to use Offscreen Canvas to not lose customers. So thanks to Offscreen Canvas, the entire 3D Engine lives in a Web Worker along with the RequestAnimationFrame() loop that it uses to draw every frame, which naturally has to coexist with the actual game logic loop for basic important things like updating entity positions, checking for collision, etc. During this the game logic loop is expected to take input from the player... not play a potentially laggy game of telephone with the DOM 60 times a second in the hopes of eventually getting input from the player. For the same reason, input polling in the DOM is bad, because the DOM may defer JS events for some number of milliseconds while it resolves whatever blocking event is going on. Which gets us to the unreliable tool we have for handling that input polling. Presently, the main thread has to take input from the player in an event (key/mouse) or redundant RequestAnimationFrame() loop (gamepad), and shoot that input over to the WebWorker as a message or write it to a SharedArrayBuffer. Neither is ideal as Messaging will arrive an unknown number of milliseconds later (necessitating rollback code for times when DOM blocking events cause the messages to arrive a few frames late) and SharedArrayBuffers apparently require something called Atomics to mitigate the race conditions caused when you have two separate threads pounding away at the same byte at 60 FPS or more, high refresh rate monitors allowing. Players notice when buttons "stick" or lag. Sometimes my Keyup events do not actually make it into the SharedArrayBuffer, and I have been putting off learning this new confusing Atomics thing as I am not a programmer, my background is in illustration and desktop IT support. I suspect I can get compensate for this without learning Atomics, but I find it ridiculous I have to jump through so many hoops, every one adds lag, and brings its own quirks, glitches, and unintended behavior. Any reasonable developer using a compiled language would expect to be able to run some equivalent of `if(keyboard.keys(KeyRotateRight).pressed || gamepad.buttons[ButtonRotateRight].pressed)` tests, letting them have that data available on the very frame that the button is pressed, ready for the game loop, *right there in the game loop* where it is required. In summary, being unable to test for input exactly at the point that input is required is *inexcusable*. The traditional Event based model works for interacting with DOM elements because adding a pointer event to the specific DOM element it controlled was *exactly this*, a test for input at the point the input is required. Now there is another location, the worker thread, that requires a test for input, and it should not have to play a game of telephone with another thread to get it! You have your context for why this is needed now. Better 7 years later than never, but I do not want to be waiting another 7 years for a feature I needed to use earlier tonight. :) -- Reply to this email directly or view it on GitHub: https://github.com/w3c/gamepad/issues/37#issuecomment-1814344040 You are receiving this because you are subscribed to this thread. Message ID: <w3c/gamepad/issues/37/1814344040@github.com>
Received on Thursday, 16 November 2023 12:26:30 UTC