Refactoring

This commit is contained in:
Hajime Hoshi 2013-06-27 01:46:13 +09:00
parent 9dd6fff9ab
commit ef6d643438
4 changed files with 63 additions and 56 deletions

View File

@ -2,8 +2,6 @@ package ebiten
import ( import (
"github.com/hajimehoshi/go.ebiten/graphics" "github.com/hajimehoshi/go.ebiten/graphics"
"runtime"
"time"
) )
type TapInfo struct { type TapInfo struct {
@ -21,7 +19,7 @@ type Game interface {
} }
type UI interface { type UI interface {
Run(device graphics.Device) Run()
} }
type InputState struct { type InputState struct {
@ -29,35 +27,3 @@ type InputState struct {
X int X int
Y 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()
}

View File

@ -27,6 +27,7 @@ import (
"github.com/hajimehoshi/go.ebiten/graphics/opengl" "github.com/hajimehoshi/go.ebiten/graphics/opengl"
"os" "os"
"runtime" "runtime"
"time"
"unsafe" "unsafe"
) )
@ -45,16 +46,18 @@ type GlutInputEvent struct {
type GlutUI struct { type GlutUI struct {
screenScale int screenScale int
device graphics.Device
glutInputEventCh chan GlutInputEvent glutInputEventCh chan GlutInputEvent
updating chan chan func()
} }
var currentUI *GlutUI var currentUI *GlutUI
//export display //export display
func display() { func display() {
// TODO: Use channels? ch := make(chan func())
currentUI.device.Update() currentUI.updating <- ch
f := <-ch
f()
C.glutSwapBuffers() C.glutSwapBuffers()
} }
@ -81,10 +84,11 @@ func idle() {
C.glutPostRedisplay() C.glutPostRedisplay()
} }
func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI{ func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI {
ui := &GlutUI{ ui := &GlutUI{
screenScale: screenScale, screenScale: screenScale,
glutInputEventCh: make(chan GlutInputEvent, 10), glutInputEventCh: make(chan GlutInputEvent, 10),
updating: make(chan chan func()),
} }
cargs := []*C.char{} cargs := []*C.char{}
@ -113,8 +117,7 @@ func NewGlutUI(screenWidth, screenHeight, screenScale int) *GlutUI{
return ui return ui
} }
func (ui *GlutUI) Run(device graphics.Device) { func (ui *GlutUI) Run() {
ui.device = device
C.glutMainLoop() C.glutMainLoop()
} }
@ -126,24 +129,24 @@ func main() {
gameName = os.Args[1] gameName = os.Args[1]
} }
var gm ebiten.Game var game ebiten.Game
switch gameName { switch gameName {
case "blank": case "blank":
gm = blank.New() game = blank.New()
case "monochrome": case "monochrome":
gm = monochrome.New() game = monochrome.New()
case "rects": case "rects":
gm = rects.New() game = rects.New()
case "rotating": case "rotating":
gm = rotating.New() game = rotating.New()
case "sprites": case "sprites":
gm = sprites.New() game = sprites.New()
default: default:
gm = rotating.New() game = rotating.New()
} }
screenScale := 2 screenScale := 2
currentUI = NewGlutUI(gm.ScreenWidth(), gm.ScreenHeight(), screenScale) currentUI = NewGlutUI(game.ScreenWidth(), game.ScreenHeight(), screenScale)
input := make(chan ebiten.InputState) input := make(chan ebiten.InputState)
go func() { go func() {
@ -170,8 +173,38 @@ func main() {
}() }()
graphicsDevice := opengl.NewDevice( graphicsDevice := opengl.NewDevice(
gm.ScreenWidth(), gm.ScreenHeight(), screenScale) game.ScreenWidth(), game.ScreenHeight(), screenScale,
currentUI.updating)
gm.Init(graphicsDevice.TextureFactory()) game.Init(graphicsDevice.TextureFactory())
ebiten.Run(gm, currentUI, screenScale, graphicsDevice, input) 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)
} }

View File

@ -11,7 +11,6 @@ type Drawable interface {
} }
type Device interface { type Device interface {
Update()
TextureFactory() TextureFactory TextureFactory() TextureFactory
Drawing() <-chan chan Drawable Drawing() <-chan chan Drawable
} }

View File

@ -17,10 +17,10 @@ type Device struct {
graphicsContext *GraphicsContext graphicsContext *GraphicsContext
offscreenTexture graphics.Texture offscreenTexture graphics.Texture
deviceUpdate chan chan graphics.Drawable 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) graphicsContext := newGraphicsContext(screenWidth, screenHeight, screenScale)
device := &Device{ device := &Device{
@ -29,9 +29,18 @@ func NewDevice(screenWidth, screenHeight, screenScale int) *Device {
screenScale: screenScale, screenScale: screenScale,
deviceUpdate: make(chan chan graphics.Drawable), deviceUpdate: make(chan chan graphics.Drawable),
graphicsContext: graphicsContext, graphicsContext: graphicsContext,
updating: updating,
} }
device.offscreenTexture = device.offscreenTexture =
device.graphicsContext.NewTexture(screenWidth, screenHeight) device.graphicsContext.NewTexture(screenWidth, screenHeight)
go func() {
for {
ch := <-device.updating
ch <- device.Update
}
}()
return device return device
} }