diff --git a/config/config.go b/config/config.go index e4f8557..cc1e827 100644 --- a/config/config.go +++ b/config/config.go @@ -9,6 +9,7 @@ import ( "github.com/knadh/koanf" "github.com/knadh/koanf/providers/env" "github.com/knadh/koanf/providers/posflag" + input "github.com/quasilyte/ebitengine-input" flag "github.com/spf13/pflag" ) @@ -22,11 +23,26 @@ type Config struct { Loglevel string `koanf:"loglevel"` Debug bool `koanf:"debug"` // loglevel=debug Startlevel int + Keymap input.Keymap `koanf:"keymap"` // we put it here so we can eventually customize it later } func InitConfig() (*Config, error) { var kloader = koanf.New(".") + // Load default values using the confmap provider. + /* + if err := kloader.Load(confmap.Provider(map[string]interface{}{ + "keymap": input.Keymap{ + InputMoveLeft: {input.KeyGamepadLeft, input.KeyLeft, input.KeyA}, + InputMoveRight: {input.KeyGamepadRight, input.KeyRight, input.KeyD}, + InputMoveUp: {input.KeyGamepadUp, input.KeyUp, input.KeyW}, + InputMoveDown: {input.KeyGamepadDown, input.KeyDown, input.KeyS}, + }, + }, "."), nil); err != nil { + return nil, fmt.Errorf("failed to load default values into koanf: %w", err) + } + */ + flagset := flag.NewFlagSet("config", flag.ContinueOnError) flagset.BoolP("debug", "d", false, "enable debug log") @@ -72,6 +88,17 @@ func InitConfig() (*Config, error) { conf.Startlevel = level } + conf.Keymap = input.Keymap{ + MoveLeft: {input.KeyGamepadLeft, input.KeyLeft, input.KeyA}, + MoveRight: {input.KeyGamepadRight, input.KeyRight, input.KeyD}, + MoveUp: {input.KeyGamepadUp, input.KeyUp, input.KeyW}, + MoveDown: {input.KeyGamepadDown, input.KeyDown, input.KeyS}, + SwitchPlayer: {input.KeyTab}, + Abort: {input.KeyEscape}, + Activate: {input.KeyEnter, input.KeyMouseLeft}, + Any: {}, + } + return conf, nil } diff --git a/config/static.go b/config/static.go index a7e0e61..28ae3d7 100644 --- a/config/static.go +++ b/config/static.go @@ -3,6 +3,8 @@ package config import ( "image/color" "time" + + input "github.com/quasilyte/ebitengine-input" ) const ( @@ -33,3 +35,14 @@ var VERSION string // maintained by -x var FontColorFG = color.RGBA{0, 255, 128, 255} // blue //var FontColorFG = color.RGBA{117, 167, 67, 255} // green + +const ( + MoveLeft input.Action = iota + MoveRight + MoveUp + MoveDown + SwitchPlayer + Abort + Activate + Any +) diff --git a/game/game.go b/game/game.go index e53f77c..d178bfa 100644 --- a/game/game.go +++ b/game/game.go @@ -9,6 +9,7 @@ import ( "github.com/hajimehoshi/ebiten/v2" "github.com/mlange-42/arche/ecs" + input "github.com/quasilyte/ebitengine-input" ) type Game struct { @@ -20,6 +21,8 @@ type Game struct { Observer *observers.GameObserver Levels []*Level // fed in PlayScene.GenerateLevels() Config *config.Config + InputSystem input.System + Input *input.Handler } func NewGame(width, height, cellsize int, cfg *config.Config, startscene SceneName) *Game { @@ -38,6 +41,12 @@ func NewGame(width, height, cellsize int, cfg *config.Config, startscene SceneNa game.Observer = observers.NewGameObserver( &world, cfg.Startlevel, width, height, cellsize) + game.InputSystem.Init(input.SystemConfig{ + DevicesEnabled: input.AnyDevice, + }) + + game.Input = game.InputSystem.NewHandler(0, game.Config.Keymap) + game.Scenes[Welcome] = NewWelcomeScene(game) game.Scenes[Menu] = NewMenuScene(game) game.Scenes[About] = NewAboutScene(game) @@ -57,6 +66,9 @@ func (game *Game) GetCurrentScene() Scene { } func (game *Game) Update() error { + // update ebitengine-input + game.InputSystem.Update() + // handle level ends timer := game.Observer.StopTimer diff --git a/game/levels.go b/game/levels.go index b5a01fd..a880fb1 100644 --- a/game/levels.go +++ b/game/levels.go @@ -49,7 +49,8 @@ func NewLevel(game *Game, cellsize int, plan *ldtkgo.Level) *Level { systemlist = append(systemlist, systems.NewPairSystem(game.World, gridcontainer)) systemlist = append(systemlist, - systems.NewPlayerSystem(game.World, gridcontainer, game.ScreenWidth, game.ScreenHeight)) + systems.NewPlayerSystem(game.World, gridcontainer, + game.ScreenWidth, game.ScreenHeight, game.Input)) systemlist = append(systemlist, systems.NewAnimationSystem(game.World, game.Cellsize)) diff --git a/game/play_scene.go b/game/play_scene.go index 3785857..e898655 100644 --- a/game/play_scene.go +++ b/game/play_scene.go @@ -7,7 +7,6 @@ import ( "openquell/config" "github.com/hajimehoshi/ebiten/v2" - "github.com/hajimehoshi/ebiten/v2/inpututil" ) type PlayScene struct { @@ -73,10 +72,10 @@ func (scene *PlayScene) Update() error { scene.Levels[scene.CurrentLevel].Update() switch { - case inpututil.IsKeyJustPressed(ebiten.KeyEscape): + case scene.Game.Input.ActionIsJustPressed(config.Abort): scene.SetNext(Popup) - case inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft): + case scene.Game.Input.ActionIsJustPressed(config.Activate): // ok we're checking the menu button here, but drawing it in hud_system, // because systems can't switch scenes if image.Pt(ebiten.CursorPosition()).In(scene.MenuRect) { diff --git a/game/popup_scene.go b/game/popup_scene.go index 676b1c6..c45816b 100644 --- a/game/popup_scene.go +++ b/game/popup_scene.go @@ -11,7 +11,6 @@ import ( "github.com/ebitenui/ebitenui/widget" "github.com/hajimehoshi/ebiten/v2" - "github.com/hajimehoshi/ebiten/v2/inpututil" ) type PopupScene struct { @@ -53,7 +52,7 @@ func (scene *PopupScene) Clearscreen() bool { func (scene *PopupScene) Update() error { scene.Ui.Update() - if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { + if scene.Game.Input.ActionIsJustPressed(config.Abort) { scene.SetNext(Play) } diff --git a/game/select_scene.go b/game/select_scene.go index 7ba6035..cd7a599 100644 --- a/game/select_scene.go +++ b/game/select_scene.go @@ -14,7 +14,6 @@ import ( "github.com/ebitenui/ebitenui/widget" "github.com/hajimehoshi/ebiten/v2" - "github.com/hajimehoshi/ebiten/v2/inpututil" ) type SelectScene struct { @@ -56,7 +55,7 @@ func (scene *SelectScene) Clearscreen() bool { func (scene *SelectScene) Update() error { scene.Ui.Update() - if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { + if scene.Game.Input.ActionIsJustPressed(config.Abort) { scene.SetNext(Menu) } diff --git a/game/welcome_scene.go b/game/welcome_scene.go index 6a76db3..e37716f 100644 --- a/game/welcome_scene.go +++ b/game/welcome_scene.go @@ -44,7 +44,7 @@ func (scene *WelcomeScene) Clearscreen() bool { func (scene *WelcomeScene) Update() error { switch { - case ebiten.IsKeyPressed(ebiten.KeyEnter): + case scene.Game.Input.AnyKeyJustPressed(): scene.SetNext(Menu) } diff --git a/go.mod b/go.mod index e0792bb..3262603 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,8 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/quasilyte/ebitengine-input v0.9.2-0.20240402074358-f9ddd61e57f7 // indirect + github.com/quasilyte/gmath v0.0.0-20221217210116-fba37a2e15c7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/tidwall/gjson v1.9.3 // indirect github.com/tidwall/match v1.1.1 // indirect diff --git a/go.sum b/go.sum index 4b17ad9..c3a96b6 100644 --- a/go.sum +++ b/go.sum @@ -237,6 +237,12 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/quasilyte/ebitengine-input v0.9.1 h1:sN7jNDLfGn9ZY1lurD4d3oXIOmQbZwYPVpuo4DlsiG0= +github.com/quasilyte/ebitengine-input v0.9.1/go.mod h1:xYkU+JqzWzjnVMolCIar0VFRly1TtjmEHfQWAoIan+o= +github.com/quasilyte/ebitengine-input v0.9.2-0.20240402074358-f9ddd61e57f7 h1:A33dnktcYAmgrFPSofTgLUPAos/ToFU0gN2f9KZIiug= +github.com/quasilyte/ebitengine-input v0.9.2-0.20240402074358-f9ddd61e57f7/go.mod h1:xYkU+JqzWzjnVMolCIar0VFRly1TtjmEHfQWAoIan+o= +github.com/quasilyte/gmath v0.0.0-20221217210116-fba37a2e15c7 h1:mvIS9aGirkzuYmHHNWAP6sLRoA5VFaIzMoFdPmqgPdY= +github.com/quasilyte/gmath v0.0.0-20221217210116-fba37a2e15c7/go.mod h1:EbI+KMbALSVE2s0YFOQpR4uj66zBh9ter5P4CBMSuvA= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= diff --git a/systems/player_system.go b/systems/player_system.go index d4ed6d0..e927ef6 100644 --- a/systems/player_system.go +++ b/systems/player_system.go @@ -12,9 +12,9 @@ import ( "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" - "github.com/hajimehoshi/ebiten/v2/inpututil" "github.com/mlange-42/arche/ecs" "github.com/mlange-42/arche/generic" + input "github.com/quasilyte/ebitengine-input" ) type PlayerSystem struct { @@ -22,15 +22,18 @@ type PlayerSystem struct { Selector *generic.Filter4[Position, Velocity, Player, Renderable] GridContainer *grid.GridContainer Width, Height int + Input *input.Handler } -func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer, width, height int) System { +func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer, + width, height int, handler *input.Handler) System { system := &PlayerSystem{ Selector: generic.NewFilter4[Position, Velocity, Player, Renderable](), GridContainer: gridcontainer, World: world, Width: width, Height: height, + Input: handler, } return system @@ -167,7 +170,7 @@ func (system *PlayerSystem) SwitchPlayers() { render.Image = player.SwitchSprite() } else { // many players, switch when requested - if inpututil.IsKeyJustPressed(ebiten.KeyTab) { + if system.Input.ActionIsJustPressed(SwitchPlayer) { slog.Debug("switch players") if player.IsPrimary { player.IsPrimary = false @@ -192,16 +195,16 @@ func (system *PlayerSystem) CheckMovement( if !velocity.Moving() { switch { - case inpututil.IsKeyJustPressed(ebiten.KeyRight): + case system.Input.ActionIsJustPressed(MoveRight): velocity.Change(East) moved = true - case inpututil.IsKeyJustPressed(ebiten.KeyLeft): + case system.Input.ActionIsJustPressed(MoveLeft): velocity.Change(West) moved = true - case inpututil.IsKeyJustPressed(ebiten.KeyDown): + case system.Input.ActionIsPressed(MoveDown): velocity.Change(South) moved = true - case inpututil.IsKeyJustPressed(ebiten.KeyUp): + case system.Input.ActionIsJustPressed(MoveUp): velocity.Change(North) moved = true }