diff --git a/_docs/gen.go b/_docs/gen.go index 8e1e6c2bb..57a1da495 100644 --- a/_docs/gen.go +++ b/_docs/gen.go @@ -136,17 +136,25 @@ func safeHTML(text string) template.HTML { } type example struct { - Name string - ThumbWidth int - ThumbHeight int + Name string + ThumbWidth int + ThumbHeight int + ScreenWidth int + ScreenHeight int } func (e *example) Width() int { - return e.ThumbWidth * 2 + if e.ScreenWidth == 0 { + return e.ThumbWidth * 2 + } + return e.ScreenWidth } func (e *example) Height() int { - return e.ThumbHeight * 2 + if e.ScreenHeight == 0 { + return e.ThumbHeight * 2 + } + return e.ScreenHeight } func (e *example) Source() string { @@ -177,34 +185,37 @@ func versions() string { } var ( + gamesExamples = []example{ + {Name: "2048", ThumbWidth: 210, ThumbHeight: 300}, + {Name: "blocks", ThumbWidth: 256, ThumbHeight: 240}, + } graphicsExamples = []example{ - {"alphablending", 320, 240}, - {"font", 320, 240}, - {"highdpi", 320, 240}, - {"hsv", 320, 240}, - {"hue", 320, 240}, - {"infinitescroll", 320, 240}, - {"life", 320, 240}, - {"masking", 320, 240}, - {"mosaic", 320, 240}, - {"noise", 320, 240}, - {"paint", 320, 240}, - {"perspective", 320, 240}, - {"rotate", 320, 240}, - {"sprites", 320, 240}, + {Name: "alphablending", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "flood", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "font", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "highdpi", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "hsv", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "hue", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "infinitescroll", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "life", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "mandelbrot", ThumbWidth: 320, ThumbHeight: 320, ScreenWidth: 640, ScreenHeight: 640}, + {Name: "masking", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "mosaic", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "noise", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "paint", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "perspective", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "rotate", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "sprites", ThumbWidth: 320, ThumbHeight: 240}, } inputExamples = []example{ - {"gamepad", 320, 240}, - {"keyboard", 320, 240}, - {"typewriter", 320, 240}, + {Name: "gamepad", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "keyboard", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "typewriter", ThumbWidth: 320, ThumbHeight: 240}, } audioExamples = []example{ - {"audio", 320, 240}, - {"piano", 320, 240}, - } - gameExamples = []example{ - {"2048", 210, 300}, - {"blocks", 256, 240}, + {Name: "audio", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "piano", ThumbWidth: 320, ThumbHeight: 240}, + {Name: "sinewave", ThumbWidth: 320, ThumbHeight: 240}, } ) @@ -268,7 +279,7 @@ func outputMain() error { "GraphicsExamples": graphicsExamples, "InputExamples": inputExamples, "AudioExamples": audioExamples, - "GameExamples": gameExamples, + "GamesExamples": gamesExamples, } return t.Funcs(funcs).Execute(f, data) } @@ -371,7 +382,7 @@ func main() { examples = append(examples, graphicsExamples...) examples = append(examples, inputExamples...) examples = append(examples, audioExamples...) - examples = append(examples, gameExamples...) + examples = append(examples, gamesExamples...) for _, e := range examples { if err := outputExampleContent(&e); err != nil { log.Fatal(err) diff --git a/_docs/index.tmpl.html b/_docs/index.tmpl.html index 72ab4a728..17459111b 100644 --- a/_docs/index.tmpl.html +++ b/_docs/index.tmpl.html @@ -60,6 +60,14 @@

Examples

+

Games

+
+ {{range .GamesExamples -}} +
+ Ebiten example: {{.Name}} +
+ {{- end}} +

Graphics

{{range .GraphicsExamples -}} @@ -84,14 +92,6 @@
{{- end}} -

Game

-
- {{range .GameExamples -}} -
- Ebiten example: {{.Name}} -
- {{- end}} -

The Gopher photographs by Chris Nokleberg are licensed under the Creative Commons 3.0 Attributions License.

diff --git a/docs/examples/flood.content.html b/docs/examples/flood.content.html new file mode 100644 index 000000000..1d8cb38a5 --- /dev/null +++ b/docs/examples/flood.content.html @@ -0,0 +1,31 @@ + + + +(Example) +

Now Loading...

diff --git a/docs/examples/flood.html b/docs/examples/flood.html new file mode 100644 index 000000000..c136f64aa --- /dev/null +++ b/docs/examples/flood.html @@ -0,0 +1,120 @@ + + + + + + +Ebiten example - flood + + + + + + + + +
+ +

Ebiten example - flood

+ +
// +build example
+
+package main
+
+import (
+        "image/color"
+        _ "image/png"
+        "log"
+
+        "github.com/hajimehoshi/ebiten"
+        "github.com/hajimehoshi/ebiten/ebitenutil"
+)
+
+const (
+        screenWidth  = 320
+        screenHeight = 240
+)
+
+var (
+        ebitenImage *ebiten.Image
+        colors      = []color.RGBA{
+                {0xff, 0xff, 0xff, 0xff},
+                {0xff, 0xff, 0x0, 0xff},
+                {0xff, 0x0, 0xff, 0xff},
+                {0xff, 0x0, 0x0, 0xff},
+                {0x0, 0xff, 0xff, 0xff},
+                {0x0, 0xff, 0x0, 0xff},
+                {0x0, 0x0, 0xff, 0xff},
+                {0x0, 0x0, 0x0, 0xff},
+        }
+)
+
+func update(screen *ebiten.Image) error {
+        if ebiten.IsRunningSlowly() {
+                return nil
+        }
+
+        const (
+                ox = 10
+                oy = 10
+                dx = 60
+                dy = 50
+        )
+        screen.Fill(color.NRGBA{0x00, 0x40, 0x80, 0xff})
+
+        op := &ebiten.DrawImageOptions{}
+        op.GeoM.Translate(ox, oy)
+        screen.DrawImage(ebitenImage, op)
+
+        // Fill with solid colors
+        for i, c := range colors {
+                op := &ebiten.DrawImageOptions{}
+                x := i % 4
+                y := i/4 + 1
+                op.GeoM.Translate(ox+float64(dx*x), oy+float64(dy*y))
+
+                // Reset RGB (not Alpha) 0 forcibly
+                op.ColorM.Scale(0, 0, 0, 1)
+
+                // Set color
+                r := float64(c.R) / 0xff
+                g := float64(c.G) / 0xff
+                b := float64(c.B) / 0xff
+                op.ColorM.Translate(r, g, b, 0)
+                screen.DrawImage(ebitenImage, op)
+        }
+        return nil
+}
+
+func main() {
+        var err error
+        ebitenImage, _, err = ebitenutil.NewImageFromFile("_resources/images/ebiten.png", ebiten.FilterNearest)
+        if err != nil {
+                log.Fatal(err)
+        }
+        if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Flood fill with solid colors (Ebiten Demo)"); err != nil {
+                log.Fatal(err)
+        }
+}
+
+ +
+ + + + + diff --git a/docs/examples/mandelbrot.content.html b/docs/examples/mandelbrot.content.html new file mode 100644 index 000000000..e93dda207 --- /dev/null +++ b/docs/examples/mandelbrot.content.html @@ -0,0 +1,31 @@ + + + +(Example) +

Now Loading...

diff --git a/docs/examples/mandelbrot.html b/docs/examples/mandelbrot.html new file mode 100644 index 000000000..0bb14fc5c --- /dev/null +++ b/docs/examples/mandelbrot.html @@ -0,0 +1,124 @@ + + + + + + +Ebiten example - mandelbrot + + + + + + + + +
+ +

Ebiten example - mandelbrot

+ +
// +build example
+
+package main
+
+import (
+        "log"
+        "math"
+
+        "github.com/hajimehoshi/ebiten"
+)
+
+const (
+        screenWidth  = 640
+        screenHeight = 640
+        maxIt        = 128
+)
+
+var (
+        offscreen    *ebiten.Image
+        offscreenPix []byte
+        palette      [maxIt]byte
+)
+
+func init() {
+        offscreen, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterNearest)
+        offscreenPix = make([]byte, screenWidth*screenHeight*4)
+        for i := range palette {
+                palette[i] = byte(math.Sqrt(float64(i)/float64(len(palette))) * 0x80)
+        }
+}
+
+func color(it int) (r, g, b byte) {
+        if it == maxIt {
+                return 0xff, 0xff, 0xff
+        }
+        c := palette[it]
+        return c, c, c
+}
+
+func updateOffscreen(centerX, centerY, size float64) {
+        for j := 0; j < screenHeight; j++ {
+                for i := 0; i < screenHeight; i++ {
+                        x := float64(i)*size/screenWidth - size/2 + centerX
+                        y := (screenHeight-float64(j))*size/screenHeight - size/2 + centerY
+                        c := complex(x, y)
+                        z := complex(0, 0)
+                        it := 0
+                        for ; it < maxIt; it++ {
+                                z = z*z + c
+                                if real(z)*real(z)+imag(z)*imag(z) > 4 {
+                                        break
+                                }
+                        }
+                        r, g, b := color(it)
+                        p := 4 * (i + j*screenWidth)
+                        offscreenPix[p] = r
+                        offscreenPix[p+1] = g
+                        offscreenPix[p+2] = b
+                        offscreenPix[p+3] = 0xff
+                }
+        }
+        offscreen.ReplacePixels(offscreenPix)
+}
+
+func init() {
+        // Now it is not feasible to call updateOffscreen every frame due to performance.
+        updateOffscreen(-0.75, 0.25, 2)
+}
+
+func update(screen *ebiten.Image) error {
+        if ebiten.IsRunningSlowly() {
+                return nil
+        }
+
+        screen.DrawImage(offscreen, nil)
+        return nil
+}
+
+func main() {
+        if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Mandelbrot (Ebiten Demo)"); err != nil {
+                log.Fatal(err)
+        }
+}
+
+ +
+ + + + + diff --git a/docs/examples/sinewave.content.html b/docs/examples/sinewave.content.html new file mode 100644 index 000000000..c481ba41f --- /dev/null +++ b/docs/examples/sinewave.content.html @@ -0,0 +1,31 @@ + + + +(Example) +

Now Loading...

diff --git a/docs/examples/sinewave.html b/docs/examples/sinewave.html new file mode 100644 index 000000000..ba50f6f24 --- /dev/null +++ b/docs/examples/sinewave.html @@ -0,0 +1,150 @@ + + + + + + +Ebiten example - sinewave + + + + + + + + +
+ +

Ebiten example - sinewave

+ +
// +build example
+
+package main
+
+import (
+        "errors"
+        "fmt"
+        "io"
+        "log"
+        "math"
+
+        "github.com/hajimehoshi/ebiten"
+        "github.com/hajimehoshi/ebiten/audio"
+        "github.com/hajimehoshi/ebiten/ebitenutil"
+)
+
+const (
+        screenWidth  = 320
+        screenHeight = 240
+        sampleRate   = 44100
+        frequency    = 440
+)
+
+var audioContext *audio.Context
+
+func init() {
+        var err error
+        audioContext, err = audio.NewContext(sampleRate)
+        if err != nil {
+                log.Fatal(err)
+        }
+}
+
+// stream is an infinite stream of 440 Hz sine wave.
+type stream struct {
+        position int64
+}
+
+// Read is io.Reader's Read.
+//
+// Read fills the data with sine wave samples.
+func (s *stream) Read(data []byte) (int, error) {
+        if len(data)%4 != 0 {
+                return 0, errors.New("len(data) % 4 must be 0")
+        }
+        const length = sampleRate / frequency // TODO: This should be integer?
+        p := s.position / 4
+        for i := 0; i < len(data)/4; i++ {
+                const max = (1<<15 - 1) / 2
+                b := int16(math.Sin(2*math.Pi*float64(p)/length) * max)
+                data[4*i] = byte(b)
+                data[4*i+1] = byte(b >> 8)
+                data[4*i+2] = byte(b)
+                data[4*i+3] = byte(b >> 8)
+                p++
+        }
+        s.position += int64(len(data))
+        s.position %= length * 4
+        return len(data), nil
+}
+
+// Seek is io.Seeker's Seek.
+//
+// whence must be io.SeekStart or io.SeekCurrent.
+func (s *stream) Seek(offset int64, whence int) (int64, error) {
+        const length = sampleRate / frequency
+        switch whence {
+        case io.SeekStart:
+                s.position = offset
+        case io.SeekCurrent:
+                s.position += offset
+        default:
+                return 0, errors.New("whence must be io.SeekStart or io.SeekCurrent")
+        }
+        s.position %= length * 4
+        return s.position, nil
+}
+
+// Close is io.Closer's Close.
+func (s *stream) Close() error {
+        return nil
+}
+
+var player *audio.Player
+
+func update(screen *ebiten.Image) error {
+        if player == nil {
+                // Pass the (infinite) stream to audio.NewPlayer.
+                // After calling Play, the stream never ends as long as the player object lives.
+                var err error
+                player, err = audio.NewPlayer(audioContext, &stream{})
+                if err != nil {
+                        return err
+                }
+                player.Play()
+        }
+        if ebiten.IsRunningSlowly() {
+                return nil
+        }
+        msg := fmt.Sprintf("FPS: %0.2f\nThis is an example using infinite audio stream.", ebiten.CurrentFPS())
+        ebitenutil.DebugPrint(screen, msg)
+        return nil
+}
+
+func main() {
+        if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Sine Wave (Ebiten Demo)"); err != nil {
+                log.Fatal(err)
+        }
+}
+
+ +
+ + + + + diff --git a/docs/images/examples/flood.png b/docs/images/examples/flood.png new file mode 100644 index 000000000..27157e940 Binary files /dev/null and b/docs/images/examples/flood.png differ diff --git a/docs/images/examples/mandelbrot.png b/docs/images/examples/mandelbrot.png new file mode 100644 index 000000000..4bb780a80 Binary files /dev/null and b/docs/images/examples/mandelbrot.png differ diff --git a/docs/images/examples/sinewave.png b/docs/images/examples/sinewave.png new file mode 100644 index 000000000..7df50ae4e Binary files /dev/null and b/docs/images/examples/sinewave.png differ diff --git a/docs/index.html b/docs/index.html index ef53dd9ef..64e653218 100644 --- a/docs/index.html +++ b/docs/index.html @@ -60,10 +60,20 @@

Examples

+

Games

+
+
+ Ebiten example: 2048 +
+ Ebiten example: blocks +
+

Graphics

Ebiten example: alphablending +
+ Ebiten example: flood
Ebiten example: font
@@ -76,6 +86,8 @@ Ebiten example: infinitescroll
Ebiten example: life +
+ Ebiten example: mandelbrot
Ebiten example: masking
@@ -108,14 +120,8 @@ Ebiten example: audio
Ebiten example: piano -
-
-

Game

-
-
- Ebiten example: 2048
- Ebiten example: blocks + Ebiten example: sinewave