markcornwell / spacewar

Javascript implementation of 1962 game Spacewar! originally developed for the PDP-1
MIT License
0 stars 0 forks source link

Touch burn / rotation buttons require rapid tapping #32

Closed J-Puls closed 4 years ago

J-Puls commented 4 years ago

Touch controls behave differently from keyboard controls. While a physical key is held down, multiple "keydown" events fire in rapid succession. While holding a touch button, only one "ontouchstart" event is fired, thus requiring the button to be tapped rapidly for the same result. Consider implementing a "burn-duration" parameter that cancels once "ontouchend" fires. This could also eliminate the lag in rotation after the initial keydown event, smoothing the animation

markcornwell commented 4 years ago

Agree the keyboard and touch controls should act and feel the same to the player. You observation about multiple keydown events firing in rapid succession is important. I would like to get away from any reliance on the keyboard sending events to autorepeat keystrokes. So changes are needed.

Let me focus in on the desired behavior as opposed to the "as built" behavior. Then a bit about a strategy for getting there.

Desired Behavior:

Proposed approach

Track the state of key, is it up or down, and drive behavior to the change in state, not arrival of new keydown events. The arrival of a keydown event when the key state is recorded as already down should be ignored. So, in the case of a burn, the burn starts at the keydown event for say KeyI and the burn ends at the keyup event for KeyI. That way the keyboard ought to be acting the same as the touch controls.

I don't know if this stream of repeated keypress events also has keyrelease events generated as well. Can experiment to find out. But if we we get lucky and there are no keyrelease events being synthesized implementing this new strategy should be straightforward.

Make sense?

J-Puls commented 4 years ago

Yep, makes sense. Tracking key state sounds like the way to go for sure.

In addition to this, I just noticed the reliance on continuous keydown events also introduces the issue that in a multiplayer game, both players will not be able to perform complex maneuvers at the same time if more than 3 keys are pressed (n-key rollover issue, I assume). For instance, if both ships are burning, and one is rotating, rotating the second ship will cancel the rotation of the first.

markcornwell commented 4 years ago

I agree.

Just did a quick experiment and confirmed that while you get a stream of repeated keydown events, they don't synthesize the corresponding keyup events. You can believe a keyup is a key release. That is good news.

Need to take some time to watch a movie with my wife, this evening. Otherwise I'd be right on it.

My thinking is that in spacewar.js use commandKeyDown and commandKeyUp to set flags (e.g. ship1.rotateRight = true, or ship1.burn = true) and not call the rotate or burn functions directly. Instead we call them from within the animate() function, perhaps as a separate inner loop devoted to controls.

I think if the mobile controls follow the same strategy (just setting flags) an let the animate loop execute the operations we will get the behavior we are after.

markcornwell commented 4 years ago

I went ahead and tagged this as a bug. It represents a gap between the desired behavior (as specified above) and the actual behavior. It should get priority over new features and enhancements.

markcornwell commented 4 years ago

Implemented the changes as outlined above. Tested on iPad and the need for tapping rotate and burn is eliminated. Still repeating the missile fire, but this is progress enough to close out this issue. Will file a separate issue for repeated missile fire. iPad play will be much enhanced when we get the AI for player 2 working; or get remote multiplayer functioning.

J-Puls commented 4 years ago

Just tested this on my devices, controls work much smoother now. Excellent.