diff --git a/ebiten.go b/ebiten.go index 3a5b38187..e1166bbf2 100644 --- a/ebiten.go +++ b/ebiten.go @@ -2,8 +2,6 @@ package ebiten import ( "github.com/hajimehoshi/go.ebiten/graphics" - "runtime" - "time" ) type TapInfo struct { @@ -21,7 +19,7 @@ type Game interface { } type UI interface { - Run(device graphics.Device) + Run() } type InputState struct { @@ -29,35 +27,3 @@ type InputState struct { X int Y int } - -func mainLoop(game Game, input <-chan InputState, draw <-chan chan graphics.Drawable) { - frameTime := time.Duration(int64(time.Second) / int64(game.Fps())) - update := time.Tick(frameTime) - for { - select { - case <-update: - inputState := <-input - game.Update(inputState) - case gameDraw := <-draw: - gameDraw <- game - // TODO: wait! - } - } -} - -func Run(game Game, ui UI, - screenScale int, - graphicsDevice graphics.Device, - input <-chan InputState) { - - draw := graphicsDevice.Drawing() - - go mainLoop(game, input, draw) - - // UI should be executed on the main thread. - ui.Run(graphicsDevice) -} - -func init() { - runtime.LockOSThread() -} diff --git a/example/glut/main.go b/example/glut/main.go index dd87f4b3d..0733c18b6 100644 --- a/example/glut/main.go +++ b/example/glut/main.go @@ -27,6 +27,7 @@ import ( "github.com/hajimehoshi/go.ebiten/graphics/opengl" "os" "runtime" + "time" "unsafe" ) @@ -45,16 +46,18 @@ type GlutInputEvent struct { type GlutUI struct { screenScale int - device graphics.Device glutInputEventCh chan GlutInputEvent + updating chan chan func() } var currentUI *GlutUI //export display func display() { - // TODO: Use channels? - currentUI.device.Update() + ch := make(chan func()) + currentUI.updating <- ch + f := <-ch + f() C.glutSwapBuffers() } @@ -81,10 +84,11 @@ func idle() { C.glutPostRedisplay() } -func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI{ +func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI { ui := &GlutUI{ - screenScale: screenScale, + screenScale: screenScale, glutInputEventCh: make(chan GlutInputEvent, 10), + updating: make(chan chan func()), } cargs := []*C.char{} @@ -113,8 +117,7 @@ func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI{ return ui } -func (ui *GlutUI) Run(device graphics.Device) { - ui.device = device +func (ui *GlutUI) Run() { C.glutMainLoop() } @@ -126,24 +129,24 @@ func main() { gameName = os.Args[1] } - var gm ebiten.Game + var game ebiten.Game switch gameName { case "blank": - gm = blank.New() + game = blank.New() case "monochrome": - gm = monochrome.New() + game = monochrome.New() case "rects": - gm = rects.New() + game = rects.New() case "rotating": - gm = rotating.New() + game = rotating.New() case "sprites": - gm = sprites.New() + game = sprites.New() default: - gm = rotating.New() + game = rotating.New() } screenScale := 2 - currentUI = NewGlutUI(gm.ScreenWidth(), gm.ScreenHeight(), screenScale) + currentUI = NewGlutUI(game.ScreenWidth(), game.ScreenHeight(), screenScale) input := make(chan ebiten.InputState) go func() { @@ -170,8 +173,38 @@ func main() { }() graphicsDevice := opengl.NewDevice( - gm.ScreenWidth(), gm.ScreenHeight(), screenScale) + game.ScreenWidth(), game.ScreenHeight(), screenScale, + currentUI.updating) - gm.Init(graphicsDevice.TextureFactory()) - ebiten.Run(gm, currentUI, screenScale, graphicsDevice, input) + game.Init(graphicsDevice.TextureFactory()) + draw := graphicsDevice.Drawing() + + go func() { + frameTime := time.Duration(int64(time.Second) / int64(game.Fps())) + update := time.Tick(frameTime) + for { + select { + case <-update: + inputState := <-input + game.Update(inputState) + case gameDraw := <-draw: + ch := make(chan interface{}) + s := &SyncDrawable{game, ch} + gameDraw <- s + <-ch + } + } + }() + + currentUI.Run() +} + +type SyncDrawable struct { + drawable graphics.Drawable + ch chan interface{} +} + +func (s *SyncDrawable) Draw(g graphics.GraphicsContext, offscreen graphics.Texture) { + s.drawable.Draw(g, offscreen) + close(s.ch) } diff --git a/graphics/graphics.go b/graphics/graphics.go index f1e4361b0..2ebb355a8 100644 --- a/graphics/graphics.go +++ b/graphics/graphics.go @@ -11,7 +11,6 @@ type Drawable interface { } type Device interface { - Update() TextureFactory() TextureFactory Drawing() <-chan chan Drawable } diff --git a/graphics/opengl/device.go b/graphics/opengl/device.go index 3fea29f4a..14050f1a4 100644 --- a/graphics/opengl/device.go +++ b/graphics/opengl/device.go @@ -17,10 +17,10 @@ type Device struct { graphicsContext *GraphicsContext offscreenTexture graphics.Texture deviceUpdate chan chan graphics.Drawable + updating chan chan func() } -func NewDevice(screenWidth, screenHeight, screenScale int) *Device { - +func NewDevice(screenWidth, screenHeight, screenScale int, updating chan chan func()) *Device { graphicsContext := newGraphicsContext(screenWidth, screenHeight, screenScale) device := &Device{ @@ -29,9 +29,18 @@ func NewDevice(screenWidth, screenHeight, screenScale int) *Device { screenScale: screenScale, deviceUpdate: make(chan chan graphics.Drawable), graphicsContext: graphicsContext, + updating: updating, } device.offscreenTexture = device.graphicsContext.NewTexture(screenWidth, screenHeight) + + go func() { + for { + ch := <-device.updating + ch <- device.Update + } + }() + return device }