diff --git a/example/blocks/game.go b/example/blocks/game.go index c6d2438f8..78eb1f98a 100644 --- a/example/blocks/game.go +++ b/example/blocks/game.go @@ -18,7 +18,6 @@ package blocks import ( "github.com/hajimehoshi/ebiten" - "sync" ) type Size struct { @@ -39,21 +38,24 @@ type GameState struct { } type Game struct { + gameContext ebiten.GameContext sceneManager *SceneManager - ebiten *Input + input *Input textures *Textures } func NewGame() *Game { game := &Game{ sceneManager: NewSceneManager(NewTitleScene()), - ebiten: NewInput(), - textures: NewTextures(), + input: NewInput(), } return game } func (game *Game) isInitialized() bool { + if game.textures == nil { + return false + } for name := range texturePaths { if !game.textures.Has(name) { return false @@ -67,32 +69,33 @@ func (game *Game) isInitialized() bool { return true } -var once sync.Once +func (game *Game) Initialize(g ebiten.GameContext) { + game.gameContext = g + game.textures = NewTextures(g) + for name, path := range texturePaths { + game.textures.RequestTexture(name, path) + } + for name, size := range renderTargetSizes { + game.textures.RequestRenderTarget(name, size) + } +} func (game *Game) Update() error { - once.Do(func() { - for name, path := range texturePaths { - game.textures.RequestTexture(name, path) - } - for name, size := range renderTargetSizes { - game.textures.RequestRenderTarget(name, size) - } - }) if !game.isInitialized() { return nil } - game.ebiten.Update() + game.input.Update(game.gameContext) game.sceneManager.Update(&GameState{ SceneManager: game.sceneManager, - Input: game.ebiten, + Input: game.input, }) return nil } -func (game *Game) Draw(context ebiten.GraphicsContext) error { +func (game *Game) Draw(g ebiten.GraphicsContext) error { if !game.isInitialized() { return nil } - game.sceneManager.Draw(context, game.textures) + game.sceneManager.Draw(g, game.textures) return nil } diff --git a/example/blocks/input.go b/example/blocks/input.go index afc80045c..2425ee4f6 100644 --- a/example/blocks/input.go +++ b/example/blocks/input.go @@ -38,9 +38,9 @@ func (i *Input) StateForKey(key ebiten.Key) int { return i.states[key] } -func (i *Input) Update() { +func (i *Input) Update(g ebiten.GameContext) { for key := range i.states { - if !ebiten.IsKeyPressed(key) { + if !g.IsKeyPressed(key) { i.states[key] = 0 continue } diff --git a/example/blocks/textures.go b/example/blocks/textures.go index 1d39fb1e5..2416832cd 100644 --- a/example/blocks/textures.go +++ b/example/blocks/textures.go @@ -35,6 +35,7 @@ type nameSize struct { } type Textures struct { + gameContext ebiten.GameContext texturePaths chan namePath renderTargetSizes chan nameSize textures map[string]ebiten.TextureID @@ -42,8 +43,9 @@ type Textures struct { sync.RWMutex } -func NewTextures() *Textures { +func NewTextures(g ebiten.GameContext) *Textures { textures := &Textures{ + gameContext: g, texturePaths: make(chan namePath), renderTargetSizes: make(chan nameSize), textures: map[string]ebiten.TextureID{}, @@ -81,7 +83,7 @@ func (t *Textures) loopMain() { if err != nil { panic(err) } - id, err := ebiten.NewTextureID(img, ebiten.FilterNearest) + id, err := t.gameContext.NewTextureID(img, ebiten.FilterNearest) if err != nil { panic(err) } @@ -93,7 +95,7 @@ func (t *Textures) loopMain() { name := s.name size := s.size go func() { - id, err := ebiten.NewRenderTargetID(size.Width, size.Height, ebiten.FilterNearest) + id, err := t.gameContext.NewRenderTargetID(size.Width, size.Height, ebiten.FilterNearest) if err != nil { panic(err) } diff --git a/gamecontext.go b/gamecontext.go index 9f4c663a4..5bcffc4b1 100644 --- a/gamecontext.go +++ b/gamecontext.go @@ -20,6 +20,12 @@ import ( "image" ) +type Game interface { + Initialize(g GameContext) + Update() error + Draw(gr GraphicsContext) error +} + type GameContext interface { IsKeyPressed(key Key) bool CursorPosition() (x, y int) @@ -27,9 +33,3 @@ type GameContext interface { NewRenderTargetID(width, height int, filter Filter) (RenderTargetID, error) NewTextureID(img image.Image, filter Filter) (TextureID, error) } - -var currentGameContext GameContext - -func SetGameContext(g GameContext) { - currentGameContext = g -} diff --git a/graphicscontext.go b/graphics.go similarity index 68% rename from graphicscontext.go rename to graphics.go index 312c78349..739548e6f 100644 --- a/graphicscontext.go +++ b/graphics.go @@ -50,7 +50,33 @@ type GraphicsContext interface { Fill(r, g, b uint8) Texture(id TextureID) Drawer RenderTarget(id RenderTargetID) Drawer - ResetOffscreen() SetOffscreen(id RenderTargetID) } + +// Filter represents the type of filter to be used when a texture or a render +// target is maginified or minified. +type Filter int + +const ( + FilterNearest Filter = iota + FilterLinear +) + +// TextureID represents an ID of a texture. +type TextureID int + +// IsNil returns true if the texture is nil. +func (i TextureID) IsNil() bool { + return i == 0 +} + +// RenderTargetID represents an ID of a render target. +// A render target is essentially same as a texture, but it is assumed that the +// all alpha of a render target is maximum. +type RenderTargetID int + +// IsNil returns true if the render target is nil. +func (i RenderTargetID) IsNil() bool { + return i == 0 +} diff --git a/input.go b/input.go index 50637c8b8..f96cd6a36 100644 --- a/input.go +++ b/input.go @@ -36,24 +36,3 @@ const ( MouseButtonMiddle MouseButtonMax ) - -func IsKeyPressed(key Key) bool { - if currentGameContext == nil { - panic("ebiten.IsKeyPressed: currentGameContext is not set") - } - return currentGameContext.IsKeyPressed(key) -} - -func CursorPosition() (x, y int) { - if currentGameContext == nil { - panic("ebiten.CurrentPosition: currentGameContext is not set") - } - return currentGameContext.CursorPosition() -} - -func IsMouseButtonPressed(button MouseButton) bool { - if currentGameContext == nil { - panic("ebiten.IsMouseButtonPressed: currentGameContext is not set") - } - return currentGameContext.IsMouseButtonPressed(button) -} diff --git a/internal/glfw/canvas.go b/internal/glfw/canvas.go index 7dac5508c..c8365dd48 100644 --- a/internal/glfw/canvas.go +++ b/internal/glfw/canvas.go @@ -32,11 +32,11 @@ type canvas struct { funcsDone chan struct{} } -func (c *canvas) draw(d GraphicsContextDrawer) (err error) { +func (c *canvas) draw(game ebiten.Game) (err error) { c.use(func() { c.graphicsContext.PreUpdate() }) - if err = d.Draw(&graphicsContext{c}); err != nil { + if err = game.Draw(&graphicsContext{c}); err != nil { return } c.use(func() { diff --git a/internal/glfw/ui.go b/internal/glfw/ui.go index 43a1cd48f..9c0ebce34 100644 --- a/internal/glfw/ui.go +++ b/internal/glfw/ui.go @@ -30,15 +30,11 @@ func init() { }) } -type GraphicsContextDrawer interface { - Draw(d ebiten.GraphicsContext) error -} - type UI struct { canvas *canvas } -func (u *UI) Start(width, height, scale int, title string) error { +func (u *UI) Start(game ebiten.Game, width, height, scale int, title string) error { if !glfw.Init() { return errors.New("glfw.Init() fails") } @@ -53,7 +49,6 @@ func (u *UI) Start(width, height, scale int, title string) error { funcs: make(chan func()), funcsDone: make(chan struct{}), } - ebiten.SetGameContext(c) c.run(width, height, scale) @@ -68,6 +63,7 @@ func (u *UI) Start(width, height, scale int, title string) error { } u.canvas = c + game.Initialize(c) return nil } @@ -81,10 +77,10 @@ func (u *UI) Terminate() { glfw.Terminate() } -func (u *UI) Draw(drawer GraphicsContextDrawer) error { - return u.canvas.draw(drawer) -} - func (u *UI) IsClosed() bool { return u.canvas.isClosed() } + +func (u *UI) DrawGame(game ebiten.Game) error { + return u.canvas.draw(game) +} diff --git a/runner/run.go b/runner/run.go index 7ebf621ee..4bb12fc3c 100644 --- a/runner/run.go +++ b/runner/run.go @@ -25,26 +25,19 @@ import ( "time" ) -type Game interface { - Update() error - Draw(context ebiten.GraphicsContext) error -} - -// Run runs the game. Basically, this function executes ui.Start() at the start, -// calls ui.DoEvent(), game.Update() and game.Draw() at a regular interval, and finally -// calls ui.Terminate(). -func Run(game Game, width, height, scale int, title string, fps int) error { +// Run runs the game. +func Run(game ebiten.Game, width, height, scale int, title string, fps int) error { ui := new(glfw.UI) - if err := ui.Start(width, height, scale, title); err != nil { + if err := ui.Start(game, width, height, scale, title); err != nil { return err } + defer ui.Terminate() frameTime := time.Duration(int64(time.Second) / int64(fps)) tick := time.Tick(frameTime) sigterm := make(chan os.Signal, 1) signal.Notify(sigterm, os.Interrupt, syscall.SIGTERM) - defer ui.Terminate() for { ui.DoEvents() if ui.IsClosed() { @@ -52,7 +45,7 @@ func Run(game Game, width, height, scale int, title string, fps int) error { } select { default: - if err := ui.Draw(game); err != nil { + if err := ui.DrawGame(game); err != nil { return err } case <-tick: diff --git a/texturefactory.go b/texturefactory.go deleted file mode 100644 index cf8f20ec0..000000000 --- a/texturefactory.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2014 Hajime Hoshi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ebiten - -import ( - "image" -) - -// Filter represents the type of filter to be used when a texture or a render -// target is maginified or minified. -type Filter int - -const ( - FilterNearest Filter = iota - FilterLinear -) - -// TextureID represents an ID of a texture. -type TextureID int - -// IsNil returns true if the texture is nil. -func (i TextureID) IsNil() bool { - return i == 0 -} - -// RenderTargetID represents an ID of a render target. -// A render target is essentially same as a texture, but it is assumed that the -// all alpha of a render target is maximum. -type RenderTargetID int - -// IsNil returns true if the render target is nil. -func (i RenderTargetID) IsNil() bool { - return i == 0 -} - -// NewRenderTargetID returns an ID of a newly created render target. -func NewRenderTargetID(width, height int, filter Filter) (RenderTargetID, error) { - if currentGameContext == nil { - panic("graphics.NewRenderTarget: currentGameContext is not set.") - } - return currentGameContext.NewRenderTargetID(width, height, filter) -} - -// NewRenderTargetID returns an ID of a newly created texture. -func NewTextureID(img image.Image, filter Filter) (TextureID, error) { - if currentGameContext == nil { - panic("graphics.NewTexture: currentGameContext is not set") - } - return currentGameContext.NewTextureID(img, filter) -}