diff --git a/ebiten.go b/ebiten.go index 6389834a3..3e178f3f7 100644 --- a/ebiten.go +++ b/ebiten.go @@ -4,19 +4,33 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics" ) -type Game interface { - InitTextures(tf graphics.TextureFactory) - Update(context GameContext) - Draw(canvas graphics.Canvas) -} - +// TODO: Remove this type GameContext interface { ScreenWidth() int ScreenHeight() int - InputState() InputState } -type InputState struct { +type ScreenSizeUpdatedEvent struct { + Width int + Height int +} + +type InputStateUpdatedEvent struct { X int Y int } + +type UIEvents interface { + ScreenSizeUpdated() <-chan ScreenSizeUpdatedEvent +} + +type UI interface { + PollEvents() + InitTextures(func(graphics.TextureFactory)) + Draw(func(graphics.Canvas)) + + InputStateUpdated() <-chan InputStateUpdatedEvent + + // TODO: Remove this + Update(func(GameContext)) +} diff --git a/example/game/input/input.go b/example/game/input/input.go index 3a6731762..b9e232c48 100644 --- a/example/game/input/input.go +++ b/example/game/input/input.go @@ -11,11 +11,21 @@ import ( type Input struct { textTextureId graphics.TextureId - inputState ebiten.InputState + inputStateCh chan ebiten.InputStateUpdatedEvent + x int + y int } func New() *Input { - return &Input{} + return &Input{ + inputStateCh: make(chan ebiten.InputStateUpdatedEvent, 1), + x: -1, + y: -1, + } +} + +func (game *Input) InputStateUpdated() chan<- ebiten.InputStateUpdatedEvent { + return game.inputStateCh } func (game *Input) InitTextures(tf graphics.TextureFactory) { @@ -35,14 +45,22 @@ func (game *Input) InitTextures(tf graphics.TextureFactory) { } func (game *Input) Update(context ebiten.GameContext) { - game.inputState = context.InputState() +events: + for { + select { + case e := <-game.inputStateCh: + game.x, game.y = e.X, e.Y + default: + break events + } + } } func (game *Input) Draw(g graphics.Canvas) { g.Fill(128, 128, 255) str := fmt.Sprintf(`Input State: X: %d - Y: %d`, game.inputState.X, game.inputState.Y) + Y: %d`, game.x, game.y) game.drawText(g, str, 5, 5) } diff --git a/example/main.go b/example/main.go index 1be989713..8f131d089 100644 --- a/example/main.go +++ b/example/main.go @@ -17,6 +17,12 @@ import ( "time" ) +type Game interface { + InitTextures(tf graphics.TextureFactory) + Update(context ebiten.GameContext) + Draw(canvas graphics.Canvas) +} + func main() { runtime.GOMAXPROCS(runtime.NumCPU()) @@ -25,7 +31,7 @@ func main() { gameName = os.Args[1] } - var game ebiten.Game + var game Game switch gameName { case "blank": game = blank.New() @@ -50,7 +56,8 @@ func main() { const screenScale = 2 const fps = 60 const title = "Ebiten Demo" - ui := cocoa.New(screenWidth, screenHeight, screenScale, title) + + var ui ebiten.UI = cocoa.New(screenWidth, screenHeight, screenScale, title) ui.InitTextures(game.InitTextures) lock := sync.Mutex{} @@ -66,8 +73,24 @@ func main() { }) } }() + + inputStateUpdated := ui.InputStateUpdated() for { ui.PollEvents() + events: + for { + select { + case e := <-inputStateUpdated: + type InputStateUpdatedHandler interface { + InputStateUpdated() chan<- ebiten.InputStateUpdatedEvent + } + if game2, ok := game.(InputStateUpdatedHandler); ok { + game2.InputStateUpdated() <- e + } + default: + break events + } + } ui.Draw(func(c graphics.Canvas) { lock.Lock() defer lock.Unlock() diff --git a/ui/cocoa/cocoa.go b/ui/cocoa/cocoa.go index d05c0db44..73d3d8fb4 100644 --- a/ui/cocoa/cocoa.go +++ b/ui/cocoa/cocoa.go @@ -20,7 +20,6 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics/opengl" "runtime" - "sync" "unsafe" ) @@ -31,7 +30,6 @@ func init() { type GameContext struct { screenWidth int screenHeight int - inputState ebiten.InputState } func (context *GameContext) ScreenWidth() int { @@ -42,18 +40,15 @@ func (context *GameContext) ScreenHeight() int { return context.screenHeight } -func (context *GameContext) InputState() ebiten.InputState { - return context.inputState -} - type UI struct { - screenWidth int - screenHeight int - screenScale int - graphicsDevice *opengl.Device - gameContext *GameContext - gameContextLock sync.Mutex - window unsafe.Pointer + screenWidth int + screenHeight int + screenScale int + graphicsDevice *opengl.Device + gameContext *GameContext + window unsafe.Pointer + inputStateUpdatedChs chan chan ebiten.InputStateUpdatedEvent + inputStateUpdatedNotified chan ebiten.InputStateUpdatedEvent } var currentUI *UI @@ -69,9 +64,9 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { gameContext: &GameContext{ screenWidth: screenWidth, screenHeight: screenHeight, - inputState: ebiten.InputState{-1, -1}, }, - gameContextLock: sync.Mutex{}, + inputStateUpdatedChs: make(chan chan ebiten.InputStateUpdatedEvent), + inputStateUpdatedNotified: make(chan ebiten.InputStateUpdatedEvent), } cTitle := C.CString(title) @@ -91,9 +86,26 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { cTitle, context) currentUI = ui + + go ui.chLoop() + return ui } +func (ui *UI) chLoop() { + inputStateUpdated := []chan ebiten.InputStateUpdatedEvent{} + for { + select { + case ch := <-ui.inputStateUpdatedChs: + inputStateUpdated = append(inputStateUpdated, ch) + case e := <-ui.inputStateUpdatedNotified: + for _, ch := range inputStateUpdated { + ch <- e + } + } + } +} + func (ui *UI) PollEvents() { C.PollEvents() } @@ -105,8 +117,6 @@ func (ui *UI) InitTextures(f func(graphics.TextureFactory)) { } func (ui *UI) Update(f func(ebiten.GameContext)) { - ui.gameContextLock.Lock() - defer ui.gameContextLock.Unlock() f(ui.gameContext) } @@ -116,15 +126,27 @@ func (ui *UI) Draw(f func(graphics.Canvas)) { C.EndDrawing(ui.window) } +func (ui *UI) InputStateUpdated() <-chan ebiten.InputStateUpdatedEvent { + ch := make(chan ebiten.InputStateUpdatedEvent) + go func() { + ui.inputStateUpdatedChs <- ch + }() + return ch +} + +func (ui *UI) notifyInputStateUpdated(e ebiten.InputStateUpdatedEvent) { + go func() { + ui.inputStateUpdatedNotified <- e + }() +} + //export ebiten_InputUpdated func ebiten_InputUpdated(inputType C.InputType, cx, cy C.int) { ui := currentUI - ui.gameContextLock.Lock() - defer ui.gameContextLock.Unlock() - if inputType == C.InputTypeMouseUp { - ui.gameContext.inputState = ebiten.InputState{-1, -1} + e := ebiten.InputStateUpdatedEvent{-1, -1} + ui.notifyInputStateUpdated(e) return } @@ -141,5 +163,6 @@ func ebiten_InputUpdated(inputType C.InputType, cx, cy C.int) { } else if ui.screenHeight <= y { y = ui.screenHeight - 1 } - ui.gameContext.inputState = ebiten.InputState{x, y} + e := ebiten.InputStateUpdatedEvent{x, y} + ui.notifyInputStateUpdated(e) } diff --git a/ui/ui.go b/ui/ui.go deleted file mode 100644 index 5b1faa293..000000000 --- a/ui/ui.go +++ /dev/null @@ -1 +0,0 @@ -package ui