examples: Use RunGame

Updates #1111
This commit is contained in:
Hajime Hoshi 2020-04-12 19:12:57 +09:00
parent 7b77164710
commit 6529629d29
6 changed files with 123 additions and 78 deletions

View File

@ -39,14 +39,17 @@ const (
) )
var ( var (
count = 0
gophersImage *ebiten.Image gophersImage *ebiten.Image
extraImages []*ebiten.Image extraImages []*ebiten.Image
lost = false
) )
func loseAndRestoreContext(context js.Value) { type Game struct {
if lost { count int
lost bool
}
func (g *Game) loseAndRestoreContext(context js.Value) {
if g.lost {
return return
} }
@ -61,7 +64,7 @@ func loseAndRestoreContext(context js.Value) {
ext.Call("loseContext") ext.Call("loseContext")
fmt.Println("Lost the context!") fmt.Println("Lost the context!")
fmt.Println("The context is automatically restored after 3 seconds.") fmt.Println("The context is automatically restored after 3 seconds.")
lost = true g.lost = true
// If and only if the context is lost by loseContext, you need to call restoreContext. Note that in usual // If and only if the context is lost by loseContext, you need to call restoreContext. Note that in usual
// case of context lost, you cannot call restoreContext but the context should be restored automatically. // case of context lost, you cannot call restoreContext but the context should be restored automatically.
@ -71,11 +74,11 @@ func loseAndRestoreContext(context js.Value) {
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
ext.Call("restoreContext") ext.Call("restoreContext")
fmt.Println("Restored the context!") fmt.Println("Restored the context!")
lost = false g.lost = false
}() }()
} }
func update(screen *ebiten.Image) error { func (g *Game) Update(screen *ebiten.Image) error {
if inpututil.IsKeyJustPressed(ebiten.KeySpace) { if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
doc := js.Global().Get("document") doc := js.Global().Get("document")
canvas := doc.Call("getElementsByTagName", "canvas").Index(0) canvas := doc.Call("getElementsByTagName", "canvas").Index(0)
@ -86,26 +89,29 @@ func update(screen *ebiten.Image) error {
context = canvas.Call("getContext", "experimental-webgl") context = canvas.Call("getContext", "experimental-webgl")
} }
} }
loseAndRestoreContext(context) g.loseAndRestoreContext(context)
return nil return nil
} }
count++ g.count++
if ebiten.IsDrawingSkipped() {
return nil return nil
} }
func (g *Game) Draw(screen *ebiten.Image) {
w, h := gophersImage.Size() w, h := gophersImage.Size()
op := &ebiten.DrawImageOptions{} op := &ebiten.DrawImageOptions{}
// For the details, see examples/rotate. // For the details, see examples/rotate.
op.GeoM.Translate(-float64(w)/2, -float64(h)/2) op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
op.GeoM.Rotate(float64(count%360) * 2 * math.Pi / 360) op.GeoM.Rotate(float64(g.count%360) * 2 * math.Pi / 360)
op.GeoM.Translate(screenWidth/2, screenHeight/2) op.GeoM.Translate(screenWidth/2, screenHeight/2)
screen.DrawImage(gophersImage, op) screen.DrawImage(gophersImage, op)
ebitenutil.DebugPrint(screen, "Press Space to force to lose/restore the GL context!\n(Browser only)") ebitenutil.DebugPrint(screen, "Press Space to force to lose/restore the GL context!\n(Browser only)")
}
return nil func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
@ -130,7 +136,9 @@ func main() {
extraImages = append(extraImages, eimg) extraImages = append(extraImages, eimg)
} }
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Context Lost (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth*2, screenHeight*2)
ebiten.SetWindowTitle("Context Lost (Ebiten Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -33,7 +33,6 @@ const (
var ( var (
pixels = make([]byte, screenSize*4) pixels = make([]byte, screenSize*4)
firePixels = make([]byte, screenSize)
firePalette = []color.RGBA{ firePalette = []color.RGBA{
{R: 7, G: 7, B: 7, A: 255}, // 0 {R: 7, G: 7, B: 7, A: 255}, // 0
{R: 31, G: 7, B: 7, A: 255}, // 1 {R: 31, G: 7, B: 7, A: 255}, // 1
@ -75,29 +74,37 @@ var (
} }
) )
func init() { type Game struct {
firePixels []byte
}
func NewGame() *Game {
firePixels := make([]byte, screenSize)
for i := screenSize - screenWidth; i < screenSize; i++ { for i := screenSize - screenWidth; i < screenSize; i++ {
firePixels[i] = 36 firePixels[i] = 36
} }
return &Game{
firePixels: firePixels,
}
} }
func updateFirePixels() { func (g *Game) updateFirePixels() {
for i := 0; i < screenWidth; i++ { for i := 0; i < screenWidth; i++ {
for j := 0; j < screenHeight; j++ { for j := 0; j < screenHeight; j++ {
idx := i + (screenWidth * j) idx := i + (screenWidth * j)
updateFireIntensityPerPixel(idx) g.updateFireIntensityPerPixel(idx)
} }
} }
} }
func updateFireIntensityPerPixel(currentPixelIndex int) { func (g *Game) updateFireIntensityPerPixel(currentPixelIndex int) {
below := currentPixelIndex + screenWidth below := currentPixelIndex + screenWidth
if below >= screenSize { if below >= screenSize {
return return
} }
d := rand.Intn(3) d := rand.Intn(3)
newI := int(firePixels[below]) - d newI := int(g.firePixels[below]) - d
if newI < 0 { if newI < 0 {
newI = 0 newI = 0
} }
@ -105,11 +112,11 @@ func updateFireIntensityPerPixel(currentPixelIndex int) {
if currentPixelIndex-d < 0 { if currentPixelIndex-d < 0 {
return return
} }
firePixels[currentPixelIndex-d] = byte(newI) g.firePixels[currentPixelIndex-d] = byte(newI)
} }
func renderFire() { func (g *Game) renderFire() {
for i, v := range firePixels { for i, v := range g.firePixels {
p := firePalette[v] p := firePalette[v]
pixels[i*4] = p.R pixels[i*4] = p.R
pixels[i*4+1] = p.G pixels[i*4+1] = p.G
@ -118,22 +125,26 @@ func renderFire() {
} }
} }
func update(screen *ebiten.Image) error { func (g *Game) Update(screen *ebiten.Image) error {
updateFirePixels() g.updateFirePixels()
if ebiten.IsDrawingSkipped() {
return nil return nil
} }
renderFire() func (g *Game) Draw(screen *ebiten.Image) {
g.renderFire()
screen.ReplacePixels(pixels) screen.ReplacePixels(pixels)
return nil }
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
if err := ebiten.Run(update, screenWidth, screenHeight, 6, "Doom Fire (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth*6, screenHeight*6)
ebiten.SetWindowTitle("Doom Fire (Ebiten Demo)")
if err := ebiten.RunGame(NewGame()); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -187,7 +187,7 @@ type Game struct {
sprites []*Sprite sprites []*Sprite
} }
var theGame *Game var ebitenImage *ebiten.Image
func init() { func init() {
// Decode image from a byte slice instead of a file so that // Decode image from a byte slice instead of a file so that
@ -203,8 +203,10 @@ func init() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
ebitenImage, _ := ebiten.NewImageFromImage(img, ebiten.FilterDefault) ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
}
func NewGame() *Game {
// Initialize the sprites. // Initialize the sprites.
sprites := []*Sprite{} sprites := []*Sprite{}
w, h := ebitenImage.Size() w, h := ebitenImage.Size()
@ -218,7 +220,7 @@ func init() {
} }
// Initialize the game. // Initialize the game.
theGame = &Game{ return &Game{
strokes: map[*Stroke]struct{}{}, strokes: map[*Stroke]struct{}{},
sprites: sprites, sprites: sprites,
} }
@ -264,7 +266,7 @@ func (g *Game) updateStroke(stroke *Stroke) {
stroke.SetDraggingObject(nil) stroke.SetDraggingObject(nil)
} }
func (g *Game) update(screen *ebiten.Image) error { func (g *Game) Update(screen *ebiten.Image) error {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
s := NewStroke(&MouseStrokeSource{}) s := NewStroke(&MouseStrokeSource{})
s.SetDraggingObject(g.spriteAt(s.Position())) s.SetDraggingObject(g.spriteAt(s.Position()))
@ -282,11 +284,10 @@ func (g *Game) update(screen *ebiten.Image) error {
delete(g.strokes, s) delete(g.strokes, s)
} }
} }
if ebiten.IsDrawingSkipped() {
return nil return nil
} }
func (g *Game) Draw(screen *ebiten.Image) {
draggingSprites := map[*Sprite]struct{}{} draggingSprites := map[*Sprite]struct{}{}
for s := range g.strokes { for s := range g.strokes {
if sprite := s.DraggingObject().(*Sprite); sprite != nil { if sprite := s.DraggingObject().(*Sprite); sprite != nil {
@ -308,12 +309,16 @@ func (g *Game) update(screen *ebiten.Image) error {
} }
ebitenutil.DebugPrint(screen, "Drag & Drop the sprites!") ebitenutil.DebugPrint(screen, "Drag & Drop the sprites!")
}
return nil func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
if err := ebiten.Run(theGame.update, screenWidth, screenHeight, 2, "Drag & Drop (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth*2, screenHeight*2)
ebiten.SetWindowTitle("Drag & Drop (Ebiten Demo)")
if err := ebiten.RunGame(NewGame()); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -36,11 +36,14 @@ var (
ebitenImage *ebiten.Image ebitenImage *ebiten.Image
) )
func update(screen *ebiten.Image) error { type Game struct {
if ebiten.IsDrawingSkipped() { }
return nil
}
func (g *Game) Update(screen *ebiten.Image) error {
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
ebitenutil.DebugPrint(screen, "Nearest Filter (default) VS Linear Filter") ebitenutil.DebugPrint(screen, "Nearest Filter (default) VS Linear Filter")
op := &ebiten.DrawImageOptions{} op := &ebiten.DrawImageOptions{}
@ -55,8 +58,10 @@ func update(screen *ebiten.Image) error {
// Specify linear filter. // Specify linear filter.
op.Filter = ebiten.FilterLinear op.Filter = ebiten.FilterLinear
screen.DrawImage(ebitenImage, op) screen.DrawImage(ebitenImage, op)
}
return nil func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
@ -79,7 +84,9 @@ func main() {
// Specify FilterDefault here, that means to prefer filter specified at DrawImageOptions. // Specify FilterDefault here, that means to prefer filter specified at DrawImageOptions.
ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault) ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Filter (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Filter (Ebiten Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -46,11 +46,14 @@ var (
} }
) )
func update(screen *ebiten.Image) error { type Game struct {
if ebiten.IsDrawingSkipped() { }
return nil
}
func (g *Game) Update(screen *ebiten.Image) error {
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
const ( const (
ox = 10 ox = 10
oy = 10 oy = 10
@ -80,7 +83,10 @@ func update(screen *ebiten.Image) error {
op.ColorM.Translate(r, g, b, 0) op.ColorM.Translate(r, g, b, 0)
screen.DrawImage(ebitenImage, op) screen.DrawImage(ebitenImage, op)
} }
return nil }
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
@ -99,7 +105,9 @@ func main() {
} }
ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault) ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Flood fill with solid colors (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth*2, screenHeight*2)
ebiten.SetWindowTitle("Flood fill with solid colors (Ebiten Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -41,11 +41,7 @@ var (
sampleText = `The quick brown fox jumps over the lazy dog.` sampleText = `The quick brown fox jumps over the lazy dog.`
mplusNormalFont font.Face mplusNormalFont font.Face
mplusBigFont font.Face mplusBigFont font.Face
counter = 0
kanjiText = []rune{}
kanjiTextColor color.RGBA
) )
var jaKanjis = []rune{} var jaKanjis = []rune{}
func init() { func init() {
@ -115,28 +111,33 @@ func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
func update(screen *ebiten.Image) error { type Game struct {
counter int
kanjiText []rune
kanjiTextColor color.RGBA
}
func (g *Game) Update(screen *ebiten.Image) error {
// Change the text color for each second. // Change the text color for each second.
if counter%ebiten.MaxTPS() == 0 { if g.counter%ebiten.MaxTPS() == 0 {
kanjiText = []rune{} g.kanjiText = nil
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
kanjiText = append(kanjiText, jaKanjis[rand.Intn(len(jaKanjis))]) g.kanjiText = append(g.kanjiText, jaKanjis[rand.Intn(len(jaKanjis))])
} }
kanjiText = append(kanjiText, '\n') g.kanjiText = append(g.kanjiText, '\n')
} }
kanjiTextColor.R = 0x80 + uint8(rand.Intn(0x7f)) g.kanjiTextColor.R = 0x80 + uint8(rand.Intn(0x7f))
kanjiTextColor.G = 0x80 + uint8(rand.Intn(0x7f)) g.kanjiTextColor.G = 0x80 + uint8(rand.Intn(0x7f))
kanjiTextColor.B = 0x80 + uint8(rand.Intn(0x7f)) g.kanjiTextColor.B = 0x80 + uint8(rand.Intn(0x7f))
kanjiTextColor.A = 0xff g.kanjiTextColor.A = 0xff
} }
counter++ g.counter++
if ebiten.IsDrawingSkipped() {
return nil return nil
} }
func (g *Game) Draw(screen *ebiten.Image) {
const x = 20 const x = 20
// Draw info // Draw info
@ -147,14 +148,19 @@ func update(screen *ebiten.Image) error {
text.Draw(screen, sampleText, mplusNormalFont, x, 80, color.White) text.Draw(screen, sampleText, mplusNormalFont, x, 80, color.White)
// Draw Kanji text lines // Draw Kanji text lines
for i, line := range strings.Split(string(kanjiText), "\n") { for i, line := range strings.Split(string(g.kanjiText), "\n") {
text.Draw(screen, line, mplusBigFont, x, 160+54*i, kanjiTextColor) text.Draw(screen, line, mplusBigFont, x, 160+54*i, g.kanjiTextColor)
} }
return nil }
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
} }
func main() { func main() {
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Font (Ebiten Demo)"); err != nil { ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Font (Ebiten Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }