ebiten: Remove the argument from Update

Fixes #1260
This commit is contained in:
Hajime Hoshi 2020-10-04 17:42:54 +09:00
parent 81f336ac46
commit 8f00c8fbf5
67 changed files with 95 additions and 116 deletions

2
doc.go
View File

@ -21,7 +21,7 @@
//
// // Update proceeds the game state.
// // Update is called every tick (1/60 [s] by default).
// func (g *Game) Update(screen *ebiten.Image) error {
// func (g *Game) Update() error {
// // Write your game's logical update.
// return nil
// }

View File

@ -57,7 +57,7 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeigh
}
// Update updates the current game state.
func (g *Game) Update(*ebiten.Image) error {
func (g *Game) Update() error {
g.input.Update()
if err := g.board.Update(g.input); err != nil {
return err

View File

@ -38,7 +38,7 @@ var (
type Game struct{}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -104,7 +104,7 @@ func drawRect(screen *ebiten.Image, img *ebiten.Image, x, y, width, height float
type Game struct{}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -241,7 +241,7 @@ func NewGame() *Game {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Manipulate the player by the input.
if ebiten.IsKeyPressed(ebiten.KeySpace) {
g.player.MoveForward()

View File

@ -40,7 +40,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
g.count %= ebiten.MaxTPS() * 10
return nil

View File

@ -45,7 +45,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
return nil
}

View File

@ -284,7 +284,7 @@ func NewGame() (*Game, error) {
}, nil
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
select {
case p := <-g.musicPlayerCh:
g.musicPlayer = p

View File

@ -51,7 +51,7 @@ type Game struct {
player *audio.Player
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.player != nil {
return nil
}

View File

@ -94,7 +94,7 @@ func lerp(a, b, t float64) float64 {
return a*(1-t) + b*t
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.initAudio()
g.count++
r := float64(g.count) * ((1.0 / 60.0) * 2 * math.Pi) * 0.1 // full cycle every 10 seconds

View File

@ -32,7 +32,7 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeigh
return ScreenWidth, ScreenHeight
}
func (g *Game) Update(*ebiten.Image) error {
func (g *Game) Update() error {
if g.sceneManager == nil {
g.sceneManager = &SceneManager{}
g.sceneManager.GoTo(&TitleScene{})

View File

@ -37,7 +37,7 @@ var (
type Game struct{}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -133,7 +133,7 @@ type Game struct {
camera Camera
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if ebiten.IsKeyPressed(ebiten.KeyA) || ebiten.IsKeyPressed(ebiten.KeyLeft) {
g.camera.Position[0] -= 1
}

View File

@ -90,7 +90,7 @@ func NewGame() *Game {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.space.Step(1.0 / float64(ebiten.MaxTPS()))
return nil
}

View File

@ -78,7 +78,7 @@ func (g *Game) loseAndRestoreContext(context js.Value) {
}()
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
doc := js.Global().Get("document")
canvas := doc.Call("getElementsByTagName", "canvas").Index(0)

View File

@ -125,7 +125,7 @@ func (g *Game) renderFire() {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.updateFirePixels()
return nil
}

View File

@ -266,7 +266,7 @@ func (g *Game) updateStroke(stroke *Stroke) {
stroke.SetDraggingObject(nil)
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
s := NewStroke(&MouseStrokeSource{})
s.SetDraggingObject(g.spriteAt(s.Position()))

View File

@ -39,7 +39,7 @@ var (
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -203,7 +203,7 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
switch g.mode {
case ModeTitle:
if jump() {

View File

@ -49,7 +49,7 @@ var (
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -124,7 +124,7 @@ type Game struct {
kanjiTextColor color.RGBA
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Change the text color for each second.
if g.counter%ebiten.MaxTPS() == 0 {
g.kanjiText = nil

View File

@ -79,7 +79,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
if ebiten.IsKeyPressed(ebiten.KeyQ) {

View File

@ -39,7 +39,7 @@ type Game struct {
pressedButtons map[int][]string
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.gamepadIDs == nil {
g.gamepadIDs = map[int]struct{}{}
}

View File

@ -49,7 +49,7 @@ type Game struct {
highDPIImage *ebiten.Image
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// TODO: DeviceScaleFactor() might return different values for different monitors.
// Add a mode to adjust the screen size along with the current device scale (#705).
// Now this example uses the device scale initialized at the beginning of this application.

View File

@ -68,7 +68,7 @@ func NewGame() *Game {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Adjust HSV values along with the user's input.
if ebiten.IsKeyPressed(ebiten.KeyQ) {
g.hue128--

View File

@ -40,7 +40,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
return nil
}

View File

@ -78,7 +78,7 @@ type Game struct {
viewport viewport
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.viewport.Move()
return nil
}

View File

@ -49,7 +49,7 @@ type Game struct {
pressed []ebiten.Key
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.pressed = nil
for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ {
if ebiten.IsKeyPressed(k) {

View File

@ -160,7 +160,7 @@ type Game struct {
pixels []byte
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.world.Update()
return nil
}

View File

@ -81,7 +81,7 @@ func init() {
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -87,7 +87,7 @@ func (m *mascot) Layout(outsideWidth, outsideHeight int) (int, int) {
return width, height
}
func (m *mascot) Update(screen *ebiten.Image) error {
func (m *mascot) Update() error {
m.count++
sw, sh := ebiten.ScreenSizeInFullscreen()

View File

@ -96,7 +96,7 @@ func NewGame() *Game {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.spotLightVX == 0 {
g.spotLightVX = 1
}

View File

@ -48,7 +48,7 @@ type Game struct {
counter int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.counter++
if g.counter == 480 {
g.counter = 0

View File

@ -66,7 +66,7 @@ func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func (g *game) Update(screen *ebiten.Image) error {
func (g *game) Update() error {
fullscreen := ebiten.IsFullscreen()
if inpututil.IsKeyJustPressed(ebiten.KeyS) {

View File

@ -58,7 +58,7 @@ func init() {
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -49,7 +49,7 @@ type Game struct {
noiseImage *image.RGBA
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Generate the noise with random RGB values.
const l = screenWidth * screenHeight
for i := 0; i < l; i++ {

View File

@ -63,7 +63,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
drawn := false
// Paint the brush by mouse dragging

View File

@ -141,7 +141,7 @@ type Game struct {
sprites *list.List
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.sprites == nil {
g.sprites = list.New()
}

View File

@ -137,7 +137,7 @@ type Game struct {
currentNote rune
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Play notes for each half second.
if g.frames%30 == 0 && audioContext.IsReady() {
g.currentNote = playNote(g.scoreIndex)

View File

@ -37,7 +37,7 @@ var (
type Game struct{}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -207,7 +207,7 @@ var (
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// The piano data is still being initialized.
// Get the progress if available.
if !pianoNoteSamplesInited {

View File

@ -124,7 +124,7 @@ type Game struct {
gopher *char
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.gopher == nil {
g.gopher = &char{x: 50 * unit, y: groundY * unit}
}

View File

@ -98,7 +98,7 @@ type Game struct {
prevNgon int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {
g.ngon--
if g.ngon < 1 {

View File

@ -221,7 +221,7 @@ type Game struct {
objects []object
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
return errors.New("game ended by player")
}

View File

@ -40,7 +40,7 @@ type Game struct {
count int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
return nil
}

View File

@ -45,7 +45,7 @@ func init() {
type Game struct {
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
w, h := offscreen.Size()
x := rand.Intn(w)
y := rand.Intn(h)

View File

@ -96,7 +96,7 @@ type Game struct {
time int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.time++
if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
g.idx++

View File

@ -154,7 +154,7 @@ func rect(x, y, w, h float32, clr color.RGBA) ([]ebiten.Vertex, []uint16) {
}, []uint16{0, 1, 2, 1, 2, 3}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.count++
g.count %= 240
return nil

View File

@ -97,7 +97,7 @@ type Game struct {
player *audio.Player
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if g.player == nil {
// Pass the (infinite) stream to audio.NewPlayer.
// After calling Play, the stream never ends as long as the player object lives.

View File

@ -102,7 +102,7 @@ func (g *Game) reset() {
g.moveDirection = dirNone
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if inpututil.IsKeyJustPressed(ebiten.KeyLeft) || inpututil.IsKeyJustPressed(ebiten.KeyA) {
if g.moveDirection != dirRight {
g.moveDirection = dirLeft

View File

@ -163,7 +163,7 @@ func rightTouched() bool {
return false
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if !g.inited {
g.init()
}

View File

@ -145,7 +145,7 @@ func (g *Game) init() {
var regularTermination = errors.New("regular termination")
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if !g.inited {
g.init()
}

View File

@ -289,7 +289,7 @@ func init() {
type Game struct{}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
reset := false
if inpututil.IsKeyJustPressed(ebiten.KeyB) {

View File

@ -79,7 +79,7 @@ type Game struct {
kanjiTextColor color.RGBA
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -63,7 +63,7 @@ type Game struct {
layers [][]int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
return nil
}

View File

@ -51,7 +51,7 @@ type Game struct {
counter int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
// Add a string from InputChars, that returns string input by users.
// Note that InputChars result changes every frame, so you need to call this
// every frame.

View File

@ -490,7 +490,7 @@ func init() {
})
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.button1.Update()
g.button2.Update()
g.checkBox.Update()

View File

@ -175,7 +175,7 @@ type Game struct {
counter int
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
g.counter++
return nil
}

View File

@ -74,7 +74,7 @@ func init() {
}
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
if ebiten.IsKeyPressed(ebiten.KeyP) && !g.audioPlayer.IsPlaying() {
// As audioPlayer has one stream and remembers the playing position,
// rewinding is needed before playing when reusing audioPlayer.

View File

@ -42,7 +42,7 @@ type Game struct {
y float64
}
func (g *Game) Update(screen *ebiten.Image) error {
func (g *Game) Update() error {
dx, dy := ebiten.Wheel()
g.x += dx
g.y += dy

View File

@ -97,7 +97,7 @@ func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
return g.width, g.height
}
func (g *game) Update(screen *ebiten.Image) error {
func (g *game) Update() error {
var (
screenWidth int
screenHeight int

View File

@ -84,7 +84,7 @@ func dumpInternalImages() error {
}
type imageDumper struct {
f func(screen *Image) error
g Game
keyState map[Key]int
@ -95,15 +95,21 @@ type imageDumper struct {
hasDumpInternalImagesKey bool
dumpInternalImagesKey Key
toDumpInternalImages bool
err error
}
func (i *imageDumper) update(screen *Image) error {
func (i *imageDumper) update() error {
if i.err != nil {
return i.err
}
const (
envScreenshotKey = "EBITEN_SCREENSHOT_KEY"
envInternalImagesKey = "EBITEN_INTERNAL_IMAGES_KEY"
)
if err := i.f(screen); err != nil {
if err := i.g.Update(); err != nil {
return err
}
@ -153,9 +159,7 @@ func (i *imageDumper) update(screen *Image) error {
i.keyState[key] = 0
}
}
// TODO: As the screen will be available only from Draw, move this to a drawing function.
return i.dump(screen)
return nil
}
func (i *imageDumper) dump(screen *Image) error {

View File

@ -17,11 +17,11 @@
package ebiten
type imageDumper struct {
f func(screen *Image) error
g Game
}
func (i *imageDumper) update(screen *Image) error {
return i.f(screen)
func (i *imageDumper) update() error {
return i.g.Update()
}
func (i *imageDumper) dump(screen *Image) error {

View File

@ -42,7 +42,7 @@ type game struct {
code int
}
func (g *game) Update(*ebiten.Image) error {
func (g *game) Update() error {
select {
case f := <-mainCh:
f()

View File

@ -30,7 +30,7 @@ type game struct {
code int
}
func (g *game) Update(*ebiten.Image) error {
func (g *game) Update() error {
g.code = g.m.Run()
return regularTermination
}

55
run.go
View File

@ -25,20 +25,14 @@ import (
type Game interface {
// Update updates a game by one tick. The given argument represents a screen image.
//
// Basically Update updates the game logic. Whether Update also draws the screen or not depends on the
// existence of Draw implementation.
//
// The Draw function's definition is:
//
// Draw(screen *Image)
//
// Update updates only the game logic and Draw draws the screen.
// In this case, the argument screen's updated content by Update is not adopted for the actual game screen,
// and the screen's updated content by Draw is adopted instead.
//
// In the first frame, it is ensured that Update is called at least once before Draw. You can use Update
// to initialize the game state. After the first frame, Update might not be called or might be called once
// to initialize the game state.
//
// After the first frame, Update might not be called or might be called once
// or more for one frame. The frequency is determined by the current TPS (tick-per-second).
Update(screen *Image) error
Update() error
// Draw draws the game screen by one frame.
//
@ -102,32 +96,20 @@ func IsScreenClearedEveryFrame() bool {
return atomic.LoadInt32(&isScreenClearedEveryFrame) != 0
}
type imageDumperGame struct {
type imageDumperGameWithDraw struct {
game Game
d *imageDumper
err error
}
func (i *imageDumperGame) Update(screen *Image) error {
if i.d == nil {
i.d = &imageDumper{f: i.game.Update}
}
return i.d.update(screen)
}
func (i *imageDumperGame) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
return i.game.Layout(outsideWidth, outsideHeight)
}
type imageDumperGameWithDraw struct {
imageDumperGame
err error
}
func (i *imageDumperGameWithDraw) Update(screen *Image) error {
func (i *imageDumperGameWithDraw) Update() error {
if i.err != nil {
return i.err
}
return i.imageDumperGame.Update(screen)
if i.d == nil {
i.d = &imageDumper{g: i.game}
}
return i.d.update()
}
func (i *imageDumperGameWithDraw) Draw(screen *Image) {
@ -136,14 +118,13 @@ func (i *imageDumperGameWithDraw) Draw(screen *Image) {
}
i.game.Draw(screen)
// Call dump explicitly. IsDrawingSkipped always returns true when Draw is defined.
if i.d == nil {
i.d = &imageDumper{f: i.game.Update}
}
i.err = i.d.dump(screen)
}
func (i *imageDumperGameWithDraw) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
return i.game.Layout(outsideWidth, outsideHeight)
}
// RunGame starts the main loop and runs the game.
// game's Update function is called every tick to update the game logic.
// game's Draw function is, if it exists, called every frame to draw the screen.
@ -188,7 +169,7 @@ func (i *imageDumperGameWithDraw) Draw(screen *Image) {
func RunGame(game Game) error {
fixWindowPosition(WindowSize())
return runGame(&imageDumperGameWithDraw{
imageDumperGame: imageDumperGame{game: game},
game: game,
}, 0)
}
@ -211,7 +192,7 @@ func runGame(game Game, scale float64) error {
func RunGameWithoutMainLoop(game Game) {
fixWindowPosition(WindowSize())
game = &imageDumperGameWithDraw{
imageDumperGame: imageDumperGame{game: game},
game: game,
}
theUIContext.set(game, 0)
uiDriver().RunWithoutMainLoop(theUIContext)

View File

@ -194,13 +194,7 @@ func (c *uiContext) update() error {
if err := hooks.RunBeforeUpdateHooks(); err != nil {
return err
}
// Multiple successive Clear call should be integrated into one graphics command, then
// calling Clear on every Update should not affect the performance.
if IsScreenClearedEveryFrame() {
c.offscreen.Clear()
}
if err := c.game.Update(c.offscreen); err != nil {
if err := c.game.Update(); err != nil {
return err
}
uiDriver().ResetForFrame()