hajimehoshi / ebiten

Ebitengine - A dead simple 2D game engine for Go
https://ebitengine.org
Apache License 2.0
11.06k stars 662 forks source link

ebiten: organize global functions for input, window, and monitor #1852

Open hajimehoshi opened 3 years ago

hajimehoshi commented 3 years ago

What about

func DefaultInput() *Input

type Input struct {} // Or FrozenInputStateForTick?
func (i *Input) Keyboard() *Keyboard
func (i *Input) Mouse() *Mouse
func (i *Input) Touches() iter.Seq[*Touch]
func (i *Input) Gamepads() iter.Seq[*Gamepad]
func (i *Input) UpdateStandardGamepadLayoutMappings(mappings string) (bool, error)

type Keyboard struct{}
func (k *Keyboard) IsKeyPressed(key Key) bool
func (k *Keyboard) InputChars() iter.Seq[rune]

type Mouse struct{}
func (m *Mouse) IsButtonPressed(mouseButton MouseButton) bool
func (m *Mouse) CursorPosition() (int, int)
func (m *Mouse) Wheel() (int, int)

type Touch struct{}
func (t *Touch) ID() int
func (t *Touch) Position() (int, int)
func (t *Touch) PositionInPreviousTick() (int, int) // This is necessary to get the position just after releasing

type Gamepad struct{}
func (g *Gamepad) ID() int
func (g *Gamepad) AxisCount() int
func (g *Gamepad) AxisValue(id int) int
func (g *Gamepad) ButtonCount() int
func (g *Gamepad) IsButtonPressed(id GamepadButton) bool
func (g *Gamepad) Name() string
func (g *Gamepad) SDLID() string
func (g *Gamepad) IsStandardLayoutAvailable() bool
func (g *Gamepad) StandardAxisValue(axis StandardGamepadAxis) float64
func (g *Gamepad) IsStandardButtonPressed(button StandardGamepadButton) bool
func (g *Gamepad) StandardButtonValue(button StandardGamepadButton) float64

?

Probably the controversial point is whether Input, Keyboard, Mouse, Touch and Gamepad are interfaces or structs. If they are interfaces, it is pretty hard or impossible to add a new function to them, otherwise it would break backward compatibility.

EDIT: Added iter.Seq

hajimehoshi commented 3 years ago

This will be a preparation for HandleInput (#1704)

EDIT: Or, HandleInput might have to take an event argument like what key is pressed. Hmm

hajimehoshi commented 1 year ago

This doesn't resolve an issue when a user invokes input functions in Draw instead of Update (#2462). I think we have to restrict the input API only for Update.

hajimehoshi commented 1 year ago

If we don't have to consider backward compatibility,

hajimehoshi commented 1 year ago

I think this should be done in the last 2.x after v3.0.0-alpha is tagged. Or, the API would be unnecessarily complex.

tinne26 commented 1 year ago

What about exp/input? I feel like this is not trivial to get right with a single minor version or two. For these complicated features, it may be helpful to have a less stable surface where you can iterate and figure out exactly what's working well and what not. Saying this because I saw the exp/textinput issue, and I think that was a great idea. It's an uncommon pattern, but only because very few projects are big and complex enough to deserve such exp packages. For Ebitengine, though, it may work very well (e.g. this input issue, figuring out text/v2, maybe something with shaders, etc).

hajimehoshi commented 1 year ago

My concern is that existing APIs are marked as 'deprecated' and then pkg.go.dev for Ebitengine would be confusing. exp/textinput was a completely new feature so this didn't have such an issue.

hajimehoshi commented 1 year ago

We discussion at Discord about #1704, and realized that global input functions are not available at HandleInput suggested at #1704. It's because the global APIs return a frozen input state for a tick. In order to avoid the confusions, we should give a good name like:

func FrozenInputStateForTick() *ebiten.InputState

if we keep global functions.