From fb4751e8cda24e3f42836dfc2a76b61e5ddacc8b Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 11 May 2014 21:24:37 +0900 Subject: [PATCH] Remove ui.GameWindow; Add ui.Canvas --- example/blocks/game.go | 12 +--- example/blocks/input.go | 19 +++--- example/main.go | 20 +++--- ui/cocoa/game_window.go | 137 ++++++++++++++++++++-------------------- ui/cocoa/ui.go | 2 +- ui/ui.go | 33 ++++------ 6 files changed, 102 insertions(+), 121 deletions(-) diff --git a/example/blocks/game.go b/example/blocks/game.go index 06b1b6b24..10f1911e5 100644 --- a/example/blocks/game.go +++ b/example/blocks/game.go @@ -52,14 +52,6 @@ func NewGame(textures Textures) *Game { return game } -func (game *Game) HandleEvent(e interface{}) { - switch e := e.(type) { - case ui.KeyStateUpdatedEvent: - game.input.UpdateKeys(e.Keys) - case ui.MouseStateUpdatedEvent: - } -} - func (game *Game) isInitialized() bool { for name, _ := range texturePaths { if !game.textures.Has(name) { @@ -74,11 +66,11 @@ func (game *Game) isInitialized() bool { return true } -func (game *Game) Update() { +func (game *Game) Update(state ui.CanvasState) { if !game.isInitialized() { return } - game.input.Update() + game.input.Update(state.Keys) game.sceneManager.Update(&GameState{ SceneManager: game.sceneManager, Input: game.input, diff --git a/example/blocks/input.go b/example/blocks/input.go index 62fb74ac0..5b4b4054e 100644 --- a/example/blocks/input.go +++ b/example/blocks/input.go @@ -5,8 +5,7 @@ import ( ) type Input struct { - states map[ui.Key]int - lastPressedKeys map[ui.Key]struct{} + states map[ui.Key]int } func NewInput() *Input { @@ -23,19 +22,17 @@ func (i *Input) StateForKey(key ui.Key) int { return i.states[key] } -func (i *Input) Update() { +func (i *Input) Update(keys []ui.Key) { + pressedKeys := map[ui.Key]struct{}{} + for _, key := range keys { + pressedKeys[key] = struct{}{} + } + for key, _ := range i.states { - if _, ok := i.lastPressedKeys[key]; !ok { + if _, ok := pressedKeys[key]; !ok { i.states[key] = 0 continue } i.states[key] += 1 } } - -func (i *Input) UpdateKeys(keys []ui.Key) { - i.lastPressedKeys = map[ui.Key]struct{}{} - for _, key := range keys { - i.lastPressedKeys[key] = struct{}{} - } -} diff --git a/example/main.go b/example/main.go index efb626065..8c3cff379 100644 --- a/example/main.go +++ b/example/main.go @@ -13,8 +13,7 @@ import ( ) type Game interface { - HandleEvent(e interface{}) - Update() + Update(state ui.CanvasState) Draw(c graphics.Context) } @@ -31,9 +30,8 @@ func main() { const title = "Ebiten Demo" u := cocoa.UI() - window := u.CreateGameWindow(screenWidth, screenHeight, screenScale, title) + canvas := u.CreateCanvas(screenWidth, screenHeight, screenScale, title) - windowEvents := window.Events() textureFactory := cocoa.TextureFactory() var game Game = blocks.NewGame(NewTextures(textureFactory)) tick := time.Tick(frameTime) @@ -47,16 +45,18 @@ func main() { u.DoEvents() select { default: - window.Draw(func(context graphics.Context) { - game.Draw(context) - }) + canvas.Draw(game.Draw) case <-tick: - game.Update() - case e := <-windowEvents: + state := canvas.State() + game.Update(state) + if state.IsClosed { + return + } + /*case e := <-windowEvents: game.HandleEvent(e) if _, ok := e.(ui.WindowClosedEvent); ok { return - } + }*/ case <-sigterm: return } diff --git a/ui/cocoa/game_window.go b/ui/cocoa/game_window.go index 612e5a3b3..8b499f92c 100644 --- a/ui/cocoa/game_window.go +++ b/ui/cocoa/game_window.go @@ -21,35 +21,41 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics/opengl" "github.com/hajimehoshi/go-ebiten/ui" "runtime" + "sync" "time" "unsafe" ) type GameWindow struct { - screenWidth int - screenHeight int - screenScale int - title string - native *C.EbitenGameWindow - pressedKeys map[ui.Key]struct{} - funcs chan func(*opengl.Context) - funcsDone chan struct{} - closed chan struct{} - events chan interface{} + state ui.CanvasState + title string + native *C.EbitenGameWindow + pressedKeys map[ui.Key]struct{} + funcs chan func(*opengl.Context) + funcsDone chan struct{} + closed chan struct{} + sync.RWMutex } var windows = map[*C.EbitenGameWindow]*GameWindow{} func newGameWindow(width, height, scale int, title string) *GameWindow { + state := ui.CanvasState{ + Width: width, + Height: height, + Scale: scale, + Keys: []ui.Key{}, + MouseX: -1, + MouseY: -1, + IsClosed: false, + } return &GameWindow{ - screenWidth: width, - screenHeight: height, - screenScale: scale, - title: title, - pressedKeys: map[ui.Key]struct{}{}, - funcs: make(chan func(*opengl.Context)), - funcsDone: make(chan struct{}), - closed: make(chan struct{}), + state: state, + title: title, + pressedKeys: map[ui.Key]struct{}{}, + funcs: make(chan func(*opengl.Context)), + funcsDone: make(chan struct{}), + closed: make(chan struct{}), } } @@ -61,8 +67,9 @@ func (w *GameWindow) run(sharedGLContext *C.NSOpenGLContext) { go func() { runtime.LockOSThread() glContext := C.CreateGLContext(sharedGLContext) - w.native = C.CreateGameWindow(C.size_t(w.screenWidth*w.screenScale), - C.size_t(w.screenHeight*w.screenScale), + w.native = C.CreateGameWindow( + C.size_t(w.state.Width*w.state.Scale), + C.size_t(w.state.Height*w.state.Scale), cTitle, glContext) windows[w.native] = w @@ -70,7 +77,7 @@ func (w *GameWindow) run(sharedGLContext *C.NSOpenGLContext) { C.UseGLContext(glContext) context := opengl.NewContext( - w.screenWidth, w.screenHeight, w.screenScale) + w.state.Width, w.state.Height, w.state.Scale) C.UnuseGLContext() defer func() { @@ -117,39 +124,10 @@ func (w *GameWindow) useGLContext(f func(*opengl.Context)) { <-w.funcsDone } -func (w *GameWindow) Events() <-chan interface{} { - if w.events != nil { - return w.events - } - w.events = make(chan interface{}) - return w.events -} - -func (w *GameWindow) notify(e interface{}) { - if w.events == nil { - return - } - go func() { - w.events <- e - }() -} - -// Now this function is not used anywhere. -//export ebiten_WindowSizeUpdated -func ebiten_WindowSizeUpdated(nativeWindow C.EbitenGameWindowPtr, width, height int) { - w := windows[nativeWindow] - e := ui.WindowSizeUpdatedEvent{width, height} - w.notify(e) -} - -func (w *GameWindow) keyStateUpdatedEvent() ui.KeyStateUpdatedEvent { - keys := []ui.Key{} - for key, _ := range w.pressedKeys { - keys = append(keys, key) - } - return ui.KeyStateUpdatedEvent{ - Keys: keys, - } +func (w *GameWindow) State() ui.CanvasState { + w.RLock() + defer w.RUnlock() + return w.state } var cocoaKeyCodeToKey = map[int]ui.Key{ @@ -168,7 +146,15 @@ func ebiten_KeyDown(nativeWindow C.EbitenGameWindowPtr, keyCode int) { } w := windows[nativeWindow] w.pressedKeys[key] = struct{}{} - w.notify(w.keyStateUpdatedEvent()) + + keys := []ui.Key{} + for key, _ := range w.pressedKeys { + keys = append(keys, key) + } + + w.Lock() + defer w.Unlock() + w.state.Keys = keys } //export ebiten_KeyUp @@ -179,7 +165,15 @@ func ebiten_KeyUp(nativeWindow C.EbitenGameWindowPtr, keyCode int) { } w := windows[nativeWindow] delete(w.pressedKeys, key) - w.notify(w.keyStateUpdatedEvent()) + + keys := []ui.Key{} + for key, _ := range w.pressedKeys { + keys = append(keys, key) + } + + w.Lock() + defer w.Unlock() + w.state.Keys = keys } //export ebiten_MouseStateUpdated @@ -187,32 +181,41 @@ func ebiten_MouseStateUpdated(nativeWindow C.EbitenGameWindowPtr, inputType C.In w := windows[nativeWindow] if inputType == C.InputTypeMouseUp { - e := ui.MouseStateUpdatedEvent{-1, -1} - w.notify(e) + w.Lock() + defer w.Unlock() + w.state.MouseX = -1 + w.state.MouseY = -1 return } x, y := int(cx), int(cy) - x /= w.screenScale - y /= w.screenScale + x /= w.state.Scale + y /= w.state.Scale if x < 0 { x = 0 - } else if w.screenWidth <= x { - x = w.screenWidth - 1 + } else if w.state.Width <= x { + x = w.state.Width - 1 } if y < 0 { y = 0 - } else if w.screenHeight <= y { - y = w.screenHeight - 1 + } else if w.state.Height <= y { + y = w.state.Height - 1 } - e := ui.MouseStateUpdatedEvent{x, y} - w.notify(e) + + w.Lock() + defer w.Unlock() + w.state.MouseX = x + w.state.MouseY = y } //export ebiten_WindowClosed func ebiten_WindowClosed(nativeWindow C.EbitenGameWindowPtr) { w := windows[nativeWindow] close(w.closed) - w.notify(ui.WindowClosedEvent{}) + + w.Lock() + defer w.Unlock() + w.state.IsClosed = true + delete(windows, nativeWindow) } diff --git a/ui/cocoa/ui.go b/ui/cocoa/ui.go index 2196d73d7..f226833d5 100644 --- a/ui/cocoa/ui.go +++ b/ui/cocoa/ui.go @@ -38,7 +38,7 @@ func TextureFactory() graphics.TextureFactory { return getCurrentUI().sharedContext } -func (u *cocoaUI) CreateGameWindow(width, height, scale int, title string) ui.GameWindow { +func (u *cocoaUI) CreateCanvas(width, height, scale int, title string) ui.Canvas { return u.sharedContext.createGameWindow(width, height, scale, title) } diff --git a/ui/ui.go b/ui/ui.go index 5ecc2d274..805135b1d 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -15,35 +15,24 @@ const ( KeyMax ) -type WindowSizeUpdatedEvent struct { - Width int - Height int -} - -type KeyStateUpdatedEvent struct { - Keys []Key -} - -type MouseStateUpdatedEvent struct { - X int - Y int -} - -type WindowClosedEvent struct { -} - type UI interface { - CreateGameWindow(screenWidth, screenHeight, screenScale int, title string) GameWindow + CreateCanvas(widht, height, scale int, title string) Canvas Start() DoEvents() Terminate() } -type Window interface { - Events() <-chan interface{} +type CanvasState struct { + Width int + Height int + Scale int + Keys []Key + MouseX int + MouseY int + IsClosed bool } -type GameWindow interface { +type Canvas interface { Draw(func(graphics.Context)) - Window + State() CanvasState }