docs: Use playground pages
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,8 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
{{with .Example}}
|
{{with .Example}}
|
||||||
<h2>Ebiten example - {{.Name}}</h2>
|
<h2>Ebiten example - {{.Name}}</h2>
|
||||||
<iframe src="{{.Name}}.content.html" width="{{.Width}}" height="{{.Height}}"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/{{.Name}}">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">{{.Source}}</code></pre></div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = '{{.Example.Name}}.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
111
_docs/gen.go
@ -19,7 +19,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -38,28 +37,6 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
examplesDir = filepath.Join("public", "examples")
|
examplesDir = filepath.Join("public", "examples")
|
||||||
)
|
|
||||||
|
|
||||||
func execute(command string, args ...string) error {
|
|
||||||
cmd := exec.Command(command, args...)
|
|
||||||
stderr, err := cmd.StderrPipe()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
msg, err := ioutil.ReadAll(stderr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
return fmt.Errorf("%v: %s", err, string(msg))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
copyright = ""
|
copyright = ""
|
||||||
stableVersion = ""
|
stableVersion = ""
|
||||||
devVersion = ""
|
devVersion = ""
|
||||||
@ -158,33 +135,6 @@ func (e *example) Height() int {
|
|||||||
return e.ScreenHeight
|
return e.ScreenHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *example) Source() string {
|
|
||||||
const (
|
|
||||||
commentFor2048 = `// Please read examples/2048/main.go and examples/2048/2048/*.go`
|
|
||||||
commentForBlocks = `// Please read examples/blocks/main.go and examples/blocks/blocks/*.go
|
|
||||||
// NOTE: If Gamepad API is available in your browswer, you can use gamepads. Try it out!`
|
|
||||||
)
|
|
||||||
if e.Name == "2048" {
|
|
||||||
return commentFor2048
|
|
||||||
}
|
|
||||||
if e.Name == "blocks" {
|
|
||||||
return commentForBlocks
|
|
||||||
}
|
|
||||||
|
|
||||||
path := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "hajimehoshi", "ebiten", "examples", e.Name, "main.go")
|
|
||||||
b, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
str := regexp.MustCompile("(?s)^.*?\n\n").ReplaceAllString(string(b), "")
|
|
||||||
str = strings.Replace(str, "\t", " ", -1)
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func versions() string {
|
|
||||||
return fmt.Sprintf("v%s (dev: v%s)", stableVersion, devVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
gamesExamples = []example{
|
gamesExamples = []example{
|
||||||
{Name: "2048", ThumbWidth: 210, ThumbHeight: 300},
|
{Name: "2048", ThumbWidth: 210, ThumbHeight: 300},
|
||||||
@ -239,17 +189,6 @@ func clear() error {
|
|||||||
if m {
|
if m {
|
||||||
return os.Remove(path)
|
return os.Remove(path)
|
||||||
}
|
}
|
||||||
// Remove example resources that are copied.
|
|
||||||
m, err = regexp.MatchString("^public/examples/_resources/images$", path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if m {
|
|
||||||
if err := os.RemoveAll(path); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -298,50 +237,6 @@ func createExamplesDir() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func outputExampleResources() error {
|
|
||||||
// TODO: Using cp command might not be portable.
|
|
||||||
// Use io.Copy instead.
|
|
||||||
if err := execute("cp", "-R", filepath.Join("..", "examples", "_resources"), filepath.Join(examplesDir, "_resources")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func outputExampleContent(e *example) error {
|
|
||||||
f, err := os.Create(filepath.Join(examplesDir, e.Name+".content.html"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
funcs := template.FuncMap{
|
|
||||||
"comment": comment,
|
|
||||||
"safeHTML": safeHTML,
|
|
||||||
}
|
|
||||||
const templatePath = "examplecontent.tmpl.html"
|
|
||||||
name := filepath.Base(templatePath)
|
|
||||||
t, err := template.New(name).Funcs(funcs).ParseFiles(templatePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"Copyright": copyright,
|
|
||||||
"Example": e,
|
|
||||||
}
|
|
||||||
if err := t.Funcs(funcs).Execute(f, data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
out := filepath.Join(examplesDir, e.Name+".js")
|
|
||||||
path := "github.com/hajimehoshi/ebiten/examples/" + e.Name
|
|
||||||
if err := execute("gopherjs", "build", "--tags", "example", "-m", "-o", out, path); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func outputExample(e *example) error {
|
func outputExample(e *example) error {
|
||||||
f, err := os.Create(filepath.Join(examplesDir, e.Name+".html"))
|
f, err := os.Create(filepath.Join(examplesDir, e.Name+".html"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -378,9 +273,6 @@ func main() {
|
|||||||
if err := createExamplesDir(); err != nil {
|
if err := createExamplesDir(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := outputExampleResources(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
examples := []example{}
|
examples := []example{}
|
||||||
examples = append(examples, graphicsExamples...)
|
examples = append(examples, graphicsExamples...)
|
||||||
@ -394,9 +286,6 @@ func main() {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := outputExampleContent(&e); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := outputExample(&e); err != nil {
|
if err := outputExample(&e); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,3 @@
|
|||||||
package docs
|
package docs
|
||||||
|
|
||||||
//go:generate go run gen.go
|
//go:generate go run gen.go
|
||||||
//go:generate cp -r ../examples/_resources ./public/examples/
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a></li>
|
||||||
<!--li class="nav-item"><a class="nav-link" href=".">Playground (jsgo.io) (Coming Soon)</a></li-->
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -45,7 +44,7 @@
|
|||||||
<dt class="col-2 text-right">Mobiles</dt>
|
<dt class="col-2 text-right">Mobiles</dt>
|
||||||
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Android">Android</a>, <a href="https://github.com/hajimehoshi/ebiten/wiki/iOS">iOS</a></dd>
|
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Android">Android</a>, <a href="https://github.com/hajimehoshi/ebiten/wiki/iOS">iOS</a></dd>
|
||||||
<dt class="col-2 text-right">Web browsers</dt>
|
<dt class="col-2 text-right">Web browsers</dt>
|
||||||
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Web-Browsers">Chrome, Firefox, Safari and Edge</a> (powered by <a href="https://github.com/gopherjs/gopherjs">GopherJS</a>), <a href=".">jsgo.io Playground by Dave Brophy (Coming Soon)</a></dd>
|
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Web-Browsers">Chrome, Firefox, Safari and Edge</a> (powered by <a href="https://github.com/gopherjs/gopherjs">GopherJS</a>)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p><small>Note: Gamepads and keyboard are not available on Android/iOS.</small></p>
|
<p><small>Note: Gamepads and keyboard are not available on Android/iOS.</small></p>
|
||||||
|
|
||||||
@ -64,7 +63,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{{range .GamesExamples -}}
|
{{range .GamesExamples -}}
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/{{.Name}}.html"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/{{.Name}}"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
</div>
|
</div>
|
||||||
@ -72,7 +71,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{{range .GraphicsExamples -}}
|
{{range .GraphicsExamples -}}
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/{{.Name}}.html"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/{{.Name}}"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
</div>
|
</div>
|
||||||
@ -80,7 +79,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{{range .InputExamples -}}
|
{{range .InputExamples -}}
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/{{.Name}}.html"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/{{.Name}}"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
</div>
|
</div>
|
||||||
@ -88,7 +87,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
{{range .AudioExamples -}}
|
{{range .AudioExamples -}}
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/{{.Name}}.html"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/{{.Name}}"><img src="images/examples/{{.Name}}.png" width="{{.ThumbWidth}}" height="{{.ThumbHeight}}" alt="Ebiten example: {{.Name}}" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = '2048.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,8 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - 2048</h2>
|
<h2>Ebiten example - 2048</h2>
|
||||||
<iframe src="2048.content.html" width="420" height="600"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/2048">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// Please read examples/2048/main.go and examples/2048/2048/*.go</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
# License
|
|
||||||
|
|
||||||
## classic.mp3
|
|
||||||
|
|
||||||
```
|
|
||||||
https://musopen.org/music/466/johann-sebastian-bach/air-on-the-g-string-from-orchestral-suite-no-3-bwv-1068/
|
|
||||||
|
|
||||||
Air on the G String (from Orchestral Suite no. 3, BWV 1068)
|
|
||||||
Public Domain
|
|
||||||
```
|
|
||||||
|
|
||||||
## jab.wav
|
|
||||||
|
|
||||||
```
|
|
||||||
http://soundbible.com/995-Jab.html
|
|
||||||
|
|
||||||
Recorded by Mike Koenig
|
|
||||||
Attribution 3.0: https://creativecommons.org/licenses/by/3.0/
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## ragtime.ogg
|
|
||||||
|
|
||||||
```
|
|
||||||
https://soundcloud.com/jacaranda-trilhas-sonoras/james-scott-01-frog-legs-rag
|
|
||||||
|
|
||||||
Title: Frog Legs Rag (1906, piano roll)
|
|
||||||
Artist: James Scott
|
|
||||||
Album: Frog Legs: Ragtime Era Favorites
|
|
||||||
|
|
||||||
Attribution-NonCommercial-ShareAlike: http://creativecommons.org/licenses/by-nc-sa/3.0/
|
|
||||||
```
|
|
@ -1,48 +0,0 @@
|
|||||||
# License
|
|
||||||
|
|
||||||
## arcade_n.ttf
|
|
||||||
|
|
||||||
```
|
|
||||||
=============================================================
|
|
||||||
P.Font Series No. : 1013
|
|
||||||
Type : TrueType
|
|
||||||
Family Name : Arcade
|
|
||||||
Style Name : Arcade Normal
|
|
||||||
Arcade Interlaced
|
|
||||||
Arcade Rounded
|
|
||||||
Author : Yuji Adachi
|
|
||||||
Description : Copyright (C)1997-2003 Yuji Adachi
|
|
||||||
Support URL : http://www.9031.com/
|
|
||||||
=============================================================
|
|
||||||
|
|
||||||
Attention
|
|
||||||
|
|
||||||
印刷物、WEBページ等での御使用は自由ですが、このフォントを、
|
|
||||||
作者の許可なく販売したり、営利目的の製品に添付することは禁じます。
|
|
||||||
また、このフォントのデザインは予告なく変更することがあります。
|
|
||||||
|
|
||||||
|
|
||||||
足立 裕司
|
|
||||||
yuji@9031.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## mplus-1p-regular.ttf
|
|
||||||
|
|
||||||
```
|
|
||||||
M+ FONTS Copyright (C) 2002-2015 M+ FONTS PROJECT
|
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
LICENSE_E
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
These fonts are free software.
|
|
||||||
Unlimited permission is granted to use, copy, and distribute them, with
|
|
||||||
or without modification, either commercially or noncommercially.
|
|
||||||
THESE FONTS ARE PROVIDED "AS IS" WITHOUT WARRANTY.
|
|
||||||
|
|
||||||
|
|
||||||
http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/
|
|
||||||
```
|
|
Before Width: | Height: | Size: 138 B |
Before Width: | Height: | Size: 165 B |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 3.6 KiB |
@ -1,61 +0,0 @@
|
|||||||
# License
|
|
||||||
|
|
||||||
## ebiten.png
|
|
||||||
|
|
||||||
```
|
|
||||||
http://www.sozai-page.com/02_sozai/b/b04/b04_002/b04_002.html
|
|
||||||
```
|
|
||||||
|
|
||||||
## fiveyears.jpg
|
|
||||||
|
|
||||||
```
|
|
||||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
|
|
||||||
The design is licensed under the Creative Commons 3.0 Attributions license.
|
|
||||||
Read this article for more details: https://blog.golang.org/gopher
|
|
||||||
```
|
|
||||||
|
|
||||||
## gophers.jpg
|
|
||||||
|
|
||||||
```
|
|
||||||
http://blog.golang.org/go-programming-language-turns-two
|
|
||||||
|
|
||||||
Photograph by Chris Nokleberg
|
|
||||||
the Creative Commons Attribution 3.0 License
|
|
||||||
```
|
|
||||||
|
|
||||||
## tile.png
|
|
||||||
|
|
||||||
```
|
|
||||||
http://opengameart.org/node/8016
|
|
||||||
|
|
||||||
CC0 1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## tiles.png
|
|
||||||
|
|
||||||
```
|
|
||||||
https://opengameart.org/content/orthographic-outdoor-tiles
|
|
||||||
|
|
||||||
CC0 1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## platformer/right.png platformer/left.png platformer/mainchar.png
|
|
||||||
|
|
||||||
```
|
|
||||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
|
|
||||||
The design is licensed under the Creative Commons 3.0 Attributions license.
|
|
||||||
Read this article for more details: https://blog.golang.org/gopher
|
|
||||||
```
|
|
||||||
|
|
||||||
## platformer/background.png
|
|
||||||
|
|
||||||
```
|
|
||||||
https://corvussg.itch.io/2d-game-backgrounds
|
|
||||||
```
|
|
||||||
|
|
||||||
## Other image files
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyright 2014 Hajime Hoshi
|
|
||||||
the Creative Commons Attribution 3.0 License
|
|
||||||
```
|
|
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 599 B |
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'airship.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,267 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - airship</h2>
|
<h2>Ebiten example - airship</h2>
|
||||||
<iframe src="airship.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/airship">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
maxAngle = 256
|
|
||||||
maxLean = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
skyColor = color.RGBA{0x66, 0xcc, 0xff, 0xff}
|
|
||||||
thePlayer = &player{
|
|
||||||
x16: 16 * 100,
|
|
||||||
y16: 16 * 200,
|
|
||||||
angle: maxAngle * 3 / 4,
|
|
||||||
}
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
repeatedGophersImage *ebiten.Image
|
|
||||||
groundImage *ebiten.Image
|
|
||||||
perspectiveGroundImage *ebiten.Image
|
|
||||||
fogImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
groundImage, _ = ebiten.NewImage(screenWidth*2, screenHeight*2/3+50, ebiten.FilterDefault)
|
|
||||||
perspectiveGroundImage, _ = ebiten.NewImage(screenWidth*2, screenHeight, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
const repeat = 5
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
repeatedGophersImage, _ = ebiten.NewImage(w*repeat, h*repeat, ebiten.FilterDefault)
|
|
||||||
for j := 0; j < repeat; j++ {
|
|
||||||
for i := 0; i < repeat; i++ {
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(w*i), float64(h*j))
|
|
||||||
repeatedGophersImage.DrawImage(gophersImage, op)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fogHeight = 8
|
|
||||||
w, _ = perspectiveGroundImage.Size()
|
|
||||||
fogRGBA := image.NewRGBA(image.Rect(0, 0, w, fogHeight))
|
|
||||||
for j := 0; j < fogHeight; j++ {
|
|
||||||
a := uint32(float64(fogHeight-1-j) * 0xff / (fogHeight - 1))
|
|
||||||
clr := skyColor
|
|
||||||
r, g, b, oa := uint32(clr.R), uint32(clr.G), uint32(clr.B), uint32(clr.A)
|
|
||||||
clr.R = uint8(r * a / oa)
|
|
||||||
clr.G = uint8(g * a / oa)
|
|
||||||
clr.B = uint8(b * a / oa)
|
|
||||||
clr.A = uint8(a)
|
|
||||||
for i := 0; i < w; i++ {
|
|
||||||
fogRGBA.SetRGBA(i, j, clr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fogImage, _ = ebiten.NewImageFromImage(fogRGBA, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
// player represents the current airship's position.
|
|
||||||
type player struct {
|
|
||||||
// x16, y16 represents the position in XY plane in fixed float format.
|
|
||||||
// The fractional part has 16 bits of precision.
|
|
||||||
x16 int
|
|
||||||
y16 int
|
|
||||||
|
|
||||||
// angle represents the player's angle in XY plane.
|
|
||||||
// angle takes an integer value in [0, maxAngle).
|
|
||||||
angle int
|
|
||||||
|
|
||||||
// lean represents the player's leaning.
|
|
||||||
// lean takes an integer value in [-maxLean, maxLean].
|
|
||||||
lean int
|
|
||||||
}
|
|
||||||
|
|
||||||
func round(x float64) float64 {
|
|
||||||
return math.Floor(x + 0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MoveForward moves the player p forward.
|
|
||||||
func (p *player) MoveForward() {
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
mx := w * 16
|
|
||||||
my := h * 16
|
|
||||||
s, c := math.Sincos(float64(p.angle) * 2 * math.Pi / maxAngle)
|
|
||||||
p.x16 += int(round(16*c) * 2)
|
|
||||||
p.y16 += int(round(16*s) * 2)
|
|
||||||
for mx <= p.x16 {
|
|
||||||
p.x16 -= mx
|
|
||||||
}
|
|
||||||
for my <= p.y16 {
|
|
||||||
p.y16 -= my
|
|
||||||
}
|
|
||||||
for p.x16 < 0 {
|
|
||||||
p.x16 += mx
|
|
||||||
}
|
|
||||||
for p.y16 < 0 {
|
|
||||||
p.y16 += my
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RotateRight rotates the player p in the right direction.
|
|
||||||
func (p *player) RotateRight() {
|
|
||||||
p.angle++
|
|
||||||
if maxAngle <= p.angle {
|
|
||||||
p.angle -= maxAngle
|
|
||||||
}
|
|
||||||
p.lean++
|
|
||||||
if maxLean < p.lean {
|
|
||||||
p.lean = maxLean
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RotateLeft rotates the player p in the left direction.
|
|
||||||
func (p *player) RotateLeft() {
|
|
||||||
p.angle--
|
|
||||||
if p.angle < 0 {
|
|
||||||
p.angle += maxAngle
|
|
||||||
}
|
|
||||||
p.lean--
|
|
||||||
if p.lean < -maxLean {
|
|
||||||
p.lean = -maxLean
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stabilize tries to move the player in the stable position (lean).
|
|
||||||
func (p *player) Stabilize() {
|
|
||||||
if 0 < p.lean {
|
|
||||||
p.lean--
|
|
||||||
}
|
|
||||||
if p.lean < 0 {
|
|
||||||
p.lean++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position returns the player p's position.
|
|
||||||
func (p *player) Position() (int, int) {
|
|
||||||
return p.x16, p.y16
|
|
||||||
}
|
|
||||||
|
|
||||||
// Angle returns the player p's angle.
|
|
||||||
func (p *player) Angle() int {
|
|
||||||
return p.angle
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateGroundImage updates the ground image according to the current player's position.
|
|
||||||
func updateGroundImage(ground *ebiten.Image) {
|
|
||||||
ground.Clear()
|
|
||||||
|
|
||||||
x16, y16 := thePlayer.Position()
|
|
||||||
a := thePlayer.Angle()
|
|
||||||
gw, gh := ground.Size()
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(-x16)/16, float64(-y16)/16)
|
|
||||||
op.GeoM.Translate(float64(-w*2), float64(-h*2))
|
|
||||||
op.GeoM.Rotate(float64(-a)*2*math.Pi/maxAngle + math.Pi*3.0/2.0)
|
|
||||||
op.GeoM.Translate(float64(gw)/2, float64(gh)-32)
|
|
||||||
ground.DrawImage(repeatedGophersImage, op)
|
|
||||||
}
|
|
||||||
|
|
||||||
// drawGroundImage draws the ground image to the given screen image.
|
|
||||||
func drawGroundImage(screen *ebiten.Image, ground *ebiten.Image) {
|
|
||||||
perspectiveGroundImage.Clear()
|
|
||||||
gw, _ := ground.Size()
|
|
||||||
pw, ph := perspectiveGroundImage.Size()
|
|
||||||
for j := 0; j < ph; j++ {
|
|
||||||
// z is in [2, -1]
|
|
||||||
rate := float64(j) / float64(ph)
|
|
||||||
z := (1-rate)*2 + rate*-1
|
|
||||||
if z <= 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(-float64(pw)/2, 0)
|
|
||||||
op.GeoM.Scale(1/z, 8) // 8 is an arbitrary number not to make empty lines.
|
|
||||||
op.GeoM.Translate(float64(pw)/2, float64(j)/z)
|
|
||||||
|
|
||||||
src := image.Rect(0, j, gw, j+1)
|
|
||||||
op.SourceRect = &src
|
|
||||||
perspectiveGroundImage.DrawImage(ground, op)
|
|
||||||
}
|
|
||||||
|
|
||||||
perspectiveGroundImage.DrawImage(fogImage, nil)
|
|
||||||
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(-float64(pw)/2, 0)
|
|
||||||
op.GeoM.Rotate(-1 * float64(thePlayer.lean) / maxLean * math.Pi / 8)
|
|
||||||
op.GeoM.Translate(float64(screenWidth)/2, screenHeight/3)
|
|
||||||
screen.DrawImage(perspectiveGroundImage, op)
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Manipulate the player by the input.
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeySpace) {
|
|
||||||
thePlayer.MoveForward()
|
|
||||||
}
|
|
||||||
rotated := false
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyRight) {
|
|
||||||
thePlayer.RotateRight()
|
|
||||||
rotated = true
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
|
||||||
thePlayer.RotateLeft()
|
|
||||||
rotated = true
|
|
||||||
}
|
|
||||||
if !rotated {
|
|
||||||
thePlayer.Stabilize()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the ground image.
|
|
||||||
screen.Fill(skyColor)
|
|
||||||
updateGroundImage(groundImage)
|
|
||||||
drawGroundImage(screen, groundImage)
|
|
||||||
|
|
||||||
// Draw the message.
|
|
||||||
tutrial := "Space: Move forward\nLeft/Right: Rotate"
|
|
||||||
msg := fmt.Sprintf("FPS: %0.2f\n%s", ebiten.CurrentFPS(), tutrial)
|
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Air Ship (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'alphablending.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,83 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - alphablending</h2>
|
<h2>Ebiten example - alphablending</h2>
|
||||||
<iframe src="alphablending.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/alphablending">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
count int
|
|
||||||
ebitenImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
count++
|
|
||||||
count %= ebiten.FPS * 10
|
|
||||||
diff := float64(count) * 0.2
|
|
||||||
switch {
|
|
||||||
case 480 < count:
|
|
||||||
diff = 0
|
|
||||||
case 240 < count:
|
|
||||||
diff = float64(480-count) * 0.2
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.Fill(color.NRGBA{0x00, 0x00, 0x80, 0xff})
|
|
||||||
|
|
||||||
// Draw 100 Ebitens
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.ColorM.Scale(1.0, 1.0, 1.0, 0.5)
|
|
||||||
for i := 0; i < 10*10; i++ {
|
|
||||||
op.GeoM.Reset()
|
|
||||||
x := float64(i%10)*diff + 15
|
|
||||||
y := float64(i/10)*diff + 20
|
|
||||||
op.GeoM.Translate(x, y)
|
|
||||||
screen.DrawImage(ebitenImage, op)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Ebiten_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Alpha Blending (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'audio.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,248 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - audio</h2>
|
<h2>Ebiten example - audio</h2>
|
||||||
<iframe src="audio.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/audio">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
// This is an example to implement an audio player.
|
|
||||||
// See examples/wav for a simpler example to play a sound file.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image/color"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/audio"
|
|
||||||
"github.com/hajimehoshi/ebiten/audio/mp3"
|
|
||||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
raudio "github.com/hajimehoshi/ebiten/examples/resources/audio"
|
|
||||||
"github.com/hajimehoshi/ebiten/inpututil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
|
|
||||||
// This sample rate doesn't match with wav/mp3's sample rate,
|
|
||||||
// but decoders adjust them.
|
|
||||||
sampleRate = 48000
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
playerBarColor = color.RGBA{0x80, 0x80, 0x80, 0xff}
|
|
||||||
playerCurrentColor = color.RGBA{0xff, 0xff, 0xff, 0xff}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Player represents the current audio state.
|
|
||||||
type Player struct {
|
|
||||||
audioContext *audio.Context
|
|
||||||
audioPlayer *audio.Player
|
|
||||||
current time.Duration
|
|
||||||
total time.Duration
|
|
||||||
seBytes []byte
|
|
||||||
seCh chan []byte
|
|
||||||
volume128 int
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerBarRect() (x, y, w, h int) {
|
|
||||||
w, h = 300, 4
|
|
||||||
x = (screenWidth - w) / 2
|
|
||||||
y = screenHeight - h - 16
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPlayer(audioContext *audio.Context) (*Player, error) {
|
|
||||||
const bytesPerSample = 4 // TODO: This should be defined in audio package
|
|
||||||
s, err := mp3.Decode(audioContext, audio.BytesReadSeekCloser(raudio.Classic_mp3))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, err := audio.NewPlayer(audioContext, s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
player := &Player{
|
|
||||||
audioContext: audioContext,
|
|
||||||
audioPlayer: p,
|
|
||||||
total: time.Second * time.Duration(s.Length()) / bytesPerSample / sampleRate,
|
|
||||||
volume128: 128,
|
|
||||||
seCh: make(chan []byte),
|
|
||||||
}
|
|
||||||
if player.total == 0 {
|
|
||||||
player.total = 1
|
|
||||||
}
|
|
||||||
player.audioPlayer.Play()
|
|
||||||
go func() {
|
|
||||||
s, err := wav.Decode(audioContext, audio.BytesReadSeekCloser(raudio.Jab_wav))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b, err := ioutil.ReadAll(s)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
player.seCh <- b
|
|
||||||
}()
|
|
||||||
return player, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) update() error {
|
|
||||||
select {
|
|
||||||
case p.seBytes = <-p.seCh:
|
|
||||||
close(p.seCh)
|
|
||||||
p.seCh = nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.audioPlayer.IsPlaying() {
|
|
||||||
p.current = p.audioPlayer.Current()
|
|
||||||
}
|
|
||||||
p.seekBarIfNeeded()
|
|
||||||
p.switchPlayStateIfNeeded()
|
|
||||||
p.playSEIfNeeded()
|
|
||||||
p.updateVolumeIfNeeded()
|
|
||||||
|
|
||||||
if inpututil.IsKeyJustPressed(ebiten.KeyB) {
|
|
||||||
b := ebiten.IsRunnableInBackground()
|
|
||||||
ebiten.SetRunnableInBackground(!b)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) playSEIfNeeded() {
|
|
||||||
if p.seBytes == nil {
|
|
||||||
// Bytes for the SE is not loaded yet.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !inpututil.IsKeyJustPressed(ebiten.KeyP) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sePlayer, _ := audio.NewPlayerFromBytes(p.audioContext, p.seBytes)
|
|
||||||
sePlayer.Play()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) updateVolumeIfNeeded() {
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyZ) {
|
|
||||||
p.volume128--
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyX) {
|
|
||||||
p.volume128++
|
|
||||||
}
|
|
||||||
if p.volume128 < 0 {
|
|
||||||
p.volume128 = 0
|
|
||||||
}
|
|
||||||
if 128 < p.volume128 {
|
|
||||||
p.volume128 = 128
|
|
||||||
}
|
|
||||||
p.audioPlayer.SetVolume(float64(p.volume128) / 128)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) switchPlayStateIfNeeded() {
|
|
||||||
if !inpututil.IsKeyJustPressed(ebiten.KeyS) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.audioPlayer.IsPlaying() {
|
|
||||||
p.audioPlayer.Pause()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.audioPlayer.Play()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) seekBarIfNeeded() {
|
|
||||||
if !inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the next seeking position from the current cursor position.
|
|
||||||
x, y := ebiten.CursorPosition()
|
|
||||||
bx, by, bw, bh := playerBarRect()
|
|
||||||
const padding = 4
|
|
||||||
if y < by-padding || by+bh+padding <= y {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if x < bx || bx+bw <= x {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pos := time.Duration(x-bx) * p.total / time.Duration(bw)
|
|
||||||
p.current = pos
|
|
||||||
p.audioPlayer.Seek(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) close() error {
|
|
||||||
return p.audioPlayer.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Player) draw(screen *ebiten.Image) {
|
|
||||||
// Draw the bar.
|
|
||||||
x, y, w, h := playerBarRect()
|
|
||||||
ebitenutil.DrawRect(screen, float64(x), float64(y), float64(w), float64(h), playerBarColor)
|
|
||||||
|
|
||||||
// Draw the cursor on the bar.
|
|
||||||
c := p.current
|
|
||||||
cw, ch := 4, 10
|
|
||||||
cx := int(time.Duration(w)*c/p.total) + x - cw/2
|
|
||||||
cy := y - (ch-h)/2
|
|
||||||
ebitenutil.DrawRect(screen, float64(cx), float64(cy), float64(cw), float64(ch), playerCurrentColor)
|
|
||||||
|
|
||||||
// Compose the curren time text.
|
|
||||||
m := (c / time.Minute) % 100
|
|
||||||
s := (c / time.Second) % 60
|
|
||||||
currentTimeStr := fmt.Sprintf("%02d:%02d", m, s)
|
|
||||||
|
|
||||||
// Draw the debug message.
|
|
||||||
msg := fmt.Sprintf(`FPS: %0.2f
|
|
||||||
Press S to toggle Play/Pause
|
|
||||||
Press P to play SE
|
|
||||||
Press Z or X to change volume of the music
|
|
||||||
Press B to switch the run-in-background state
|
|
||||||
Current Time: %s`, ebiten.CurrentFPS(), currentTimeStr)
|
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
musicPlayer *Player
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if err := musicPlayer.update(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
musicPlayer.draw(screen)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
audioContext, err := audio.NewContext(sampleRate)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
musicPlayer, err = NewPlayer(audioContext)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Audio (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := musicPlayer.close(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'blocks.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,9 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - blocks</h2>
|
<h2>Ebiten example - blocks</h2>
|
||||||
<iframe src="blocks.content.html" width="512" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/blocks">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// Please read examples/blocks/main.go and examples/blocks/blocks/*.go
|
|
||||||
// NOTE: If Gamepad API is available in your browswer, you can use gamepads. Try it out!</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'filter.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,79 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - filter</h2>
|
<h2>Ebiten example - filter</h2>
|
||||||
<iframe src="filter.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/filter">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 640
|
|
||||||
screenHeight = 480
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ebitenImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ebitenutil.DebugPrint(screen, "Nearest Filter (default) VS Linear Filter")
|
|
||||||
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Scale(4, 4)
|
|
||||||
op.GeoM.Translate(64, 64)
|
|
||||||
// By default, nearest filter is used.
|
|
||||||
screen.DrawImage(ebitenImage, op)
|
|
||||||
|
|
||||||
op = &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Scale(4, 4)
|
|
||||||
op.GeoM.Translate(64, 64+240)
|
|
||||||
// Specify linear filter.
|
|
||||||
op.Filter = ebiten.FilterLinear
|
|
||||||
screen.DrawImage(ebitenImage, op)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Ebiten_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specifying filter on NewImage[FromImage] is just for backward compatibility.
|
|
||||||
// Now specifying filter at DrawImageOptions is recommended.
|
|
||||||
// Specify FilterDefault here, that means to prefer filter specified at DrawImageOptions.
|
|
||||||
ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Filter (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'flood.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,99 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - flood</h2>
|
<h2>Ebiten example - flood</h2>
|
||||||
<iframe src="flood.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/flood">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
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() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Ebiten_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
ebitenImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Flood fill with solid colors (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'font.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,154 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - font</h2>
|
<h2>Ebiten example - font</h2>
|
||||||
<iframe src="font.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/font">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image/color"
|
|
||||||
"log"
|
|
||||||
"math/rand"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/golang/freetype/truetype"
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/fonts"
|
|
||||||
"github.com/hajimehoshi/ebiten/text"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 640
|
|
||||||
screenHeight = 480
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sampleText = `The quick brown fox jumps over the lazy dog.`
|
|
||||||
mplusNormalFont font.Face
|
|
||||||
mplusBigFont font.Face
|
|
||||||
counter = 0
|
|
||||||
kanjiText = []rune{}
|
|
||||||
kanjiTextColor color.RGBA
|
|
||||||
)
|
|
||||||
|
|
||||||
var jaKanjis = []rune{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// table is the list of Japanese Kanji characters in a part of JIS X 0208.
|
|
||||||
const table = `
|
|
||||||
亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭
|
|
||||||
院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応
|
|
||||||
押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改
|
|
||||||
魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱
|
|
||||||
粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄
|
|
||||||
機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京
|
|
||||||
供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈
|
|
||||||
掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲
|
|
||||||
検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向
|
|
||||||
后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込
|
|
||||||
此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷
|
|
||||||
察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時
|
|
||||||
次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周
|
|
||||||
宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償
|
|
||||||
勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾
|
|
||||||
拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾
|
|
||||||
澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線
|
|
||||||
繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎
|
|
||||||
臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只
|
|
||||||
叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵
|
|
||||||
帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓
|
|
||||||
邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到
|
|
||||||
董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入
|
|
||||||
如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦
|
|
||||||
函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美
|
|
||||||
鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服
|
|
||||||
福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋
|
|
||||||
法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満
|
|
||||||
漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒
|
|
||||||
諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃
|
|
||||||
痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯
|
|
||||||
蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕
|
|
||||||
`
|
|
||||||
for _, c := range table {
|
|
||||||
if c == '\n' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
jaKanjis = append(jaKanjis, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
tt, err := truetype.Parse(fonts.MPlus1pRegular_ttf)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
const dpi = 72
|
|
||||||
mplusNormalFont = truetype.NewFace(tt, &truetype.Options{
|
|
||||||
Size: 24,
|
|
||||||
DPI: dpi,
|
|
||||||
Hinting: font.HintingFull,
|
|
||||||
})
|
|
||||||
mplusBigFont = truetype.NewFace(tt, &truetype.Options{
|
|
||||||
Size: 48,
|
|
||||||
DPI: dpi,
|
|
||||||
Hinting: font.HintingFull,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Change the text color for each second.
|
|
||||||
if counter%ebiten.FPS == 0 {
|
|
||||||
kanjiText = []rune{}
|
|
||||||
for j := 0; j < 4; j++ {
|
|
||||||
for i := 0; i < 8; i++ {
|
|
||||||
kanjiText = append(kanjiText, jaKanjis[rand.Intn(len(jaKanjis))])
|
|
||||||
}
|
|
||||||
kanjiText = append(kanjiText, '\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
kanjiTextColor.R = 0x80 + uint8(rand.Intn(0x7f))
|
|
||||||
kanjiTextColor.G = 0x80 + uint8(rand.Intn(0x7f))
|
|
||||||
kanjiTextColor.B = 0x80 + uint8(rand.Intn(0x7f))
|
|
||||||
kanjiTextColor.A = 0xff
|
|
||||||
}
|
|
||||||
counter++
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const x = 20
|
|
||||||
|
|
||||||
// Draw info
|
|
||||||
msg := fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS())
|
|
||||||
text.Draw(screen, msg, mplusNormalFont, x, 40, color.White)
|
|
||||||
|
|
||||||
// Draw the sample text
|
|
||||||
text.Draw(screen, sampleText, mplusNormalFont, x, 80, color.White)
|
|
||||||
|
|
||||||
// Draw Kanji text lines
|
|
||||||
for i, line := range strings.Split(string(kanjiText), "\n") {
|
|
||||||
text.Draw(screen, line, mplusBigFont, x, 160+54*i, kanjiTextColor)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Font (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'gamepad.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,80 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - gamepad</h2>
|
<h2>Ebiten example - gamepad</h2>
|
||||||
<iframe src="gamepad.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/gamepad">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/inpututil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 640
|
|
||||||
screenHeight = 480
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
ids := ebiten.GamepadIDs()
|
|
||||||
axes := map[int][]string{}
|
|
||||||
pressedButtons := map[int][]string{}
|
|
||||||
|
|
||||||
for _, id := range ids {
|
|
||||||
maxAxis := ebiten.GamepadAxisNum(id)
|
|
||||||
for a := 0; a < maxAxis; a++ {
|
|
||||||
v := ebiten.GamepadAxis(id, a)
|
|
||||||
axes[id] = append(axes[id], fmt.Sprintf("%d:%0.2f", a, v))
|
|
||||||
}
|
|
||||||
maxButton := ebiten.GamepadButton(ebiten.GamepadButtonNum(id))
|
|
||||||
for b := ebiten.GamepadButton(id); b < maxButton; b++ {
|
|
||||||
if ebiten.IsGamepadButtonPressed(id, b) {
|
|
||||||
pressedButtons[id] = append(pressedButtons[id], strconv.Itoa(int(b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log some events.
|
|
||||||
if inpututil.IsGamepadButtonJustPressed(id, b) {
|
|
||||||
log.Printf("Button Just Pressed: id(%d), button(%d)", id, b)
|
|
||||||
}
|
|
||||||
if inpututil.IsGamepadButtonJustReleased(id, b) {
|
|
||||||
log.Printf("Button Just Released: id(%d), button(%d)", id, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the current gamepad status.
|
|
||||||
str := ""
|
|
||||||
if len(ids) > 0 {
|
|
||||||
for _, id := range ids {
|
|
||||||
str += fmt.Sprintf("Gamepad (ID: %d):\n", id)
|
|
||||||
str += fmt.Sprintf(" Axes: %s\n", strings.Join(axes[id], ", "))
|
|
||||||
str += fmt.Sprintf(" Buttons: %s\n", strings.Join(pressedButtons[id], ", "))
|
|
||||||
str += "\n"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
str = "Please connect your gamepad."
|
|
||||||
}
|
|
||||||
ebitenutil.DebugPrint(screen, str)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Gamepad (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'highdpi.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,100 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - highdpi</h2>
|
<h2>Ebiten example - highdpi</h2>
|
||||||
<iframe src="highdpi.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/highdpi">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
count int
|
|
||||||
highDPIImage *ebiten.Image
|
|
||||||
highDPIImageCh = make(chan *ebiten.Image)
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Licensed under Public Domain
|
|
||||||
// https://commons.wikimedia.org/wiki/File:As08-16-2593.jpg
|
|
||||||
const url = "https://upload.wikimedia.org/wikipedia/commons/1/1f/As08-16-2593.jpg"
|
|
||||||
|
|
||||||
// Load the image asynchronously.
|
|
||||||
go func() {
|
|
||||||
img, err := ebitenutil.NewImageFromURL(url)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
highDPIImageCh <- img
|
|
||||||
close(highDPIImageCh)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if highDPIImage == nil {
|
|
||||||
// Use select and 'default' clause for non-blocking receiving.
|
|
||||||
select {
|
|
||||||
case img := <-highDPIImageCh:
|
|
||||||
highDPIImage = img
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if highDPIImage == nil {
|
|
||||||
ebitenutil.DebugPrint(screen, "Loading the image...")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
scale := ebiten.DeviceScaleFactor()
|
|
||||||
sw, sh := screen.Size()
|
|
||||||
|
|
||||||
w, h := highDPIImage.Size()
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
|
|
||||||
// Move the images's center to the upper left corner.
|
|
||||||
op.GeoM.Translate(float64(-w)/2, float64(-h)/2)
|
|
||||||
|
|
||||||
// The image is just too big. Adjust the scale.
|
|
||||||
op.GeoM.Scale(0.25, 0.25)
|
|
||||||
|
|
||||||
// Scale the image by the device ratio so that the rendering result can be same
|
|
||||||
// on various (diffrent-DPI) environments.
|
|
||||||
op.GeoM.Scale(scale, scale)
|
|
||||||
|
|
||||||
// Move the image's center to the screen's center.
|
|
||||||
op.GeoM.Translate(float64(sw)/2, float64(sh)/2)
|
|
||||||
|
|
||||||
op.Filter = ebiten.FilterLinear
|
|
||||||
screen.DrawImage(highDPIImage, op)
|
|
||||||
|
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("Device Scale Ratio: %0.2f", scale))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
const (
|
|
||||||
screenWidth = 640
|
|
||||||
screenHeight = 480
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pass the invert of scale so that Ebiten's auto scaling by device scale is disabled.
|
|
||||||
s := ebiten.DeviceScaleFactor()
|
|
||||||
if err := ebiten.Run(update, int(screenWidth*s), int(screenHeight*s), 1/s, "High DPI (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'hsv.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,142 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - hsv</h2>
|
<h2>Ebiten example - hsv</h2>
|
||||||
<iframe src="hsv.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/hsv">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
hue128 = 0
|
|
||||||
saturation128 = 128
|
|
||||||
value128 = 128
|
|
||||||
|
|
||||||
inverted = false
|
|
||||||
|
|
||||||
prevPressedI = false
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
// clamp clamps v to the range [min, max].
|
|
||||||
func clamp(v, min, max int) int {
|
|
||||||
if min > max {
|
|
||||||
panic("min must <= max")
|
|
||||||
}
|
|
||||||
if v < min {
|
|
||||||
return min
|
|
||||||
}
|
|
||||||
if max < v {
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Adjust HSV values along with the user's input.
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyQ) {
|
|
||||||
hue128--
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyW) {
|
|
||||||
hue128++
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyA) {
|
|
||||||
saturation128--
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyS) {
|
|
||||||
saturation128++
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyZ) {
|
|
||||||
value128--
|
|
||||||
}
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyX) {
|
|
||||||
value128++
|
|
||||||
}
|
|
||||||
|
|
||||||
hue128 = clamp(hue128, -256, 256)
|
|
||||||
saturation128 = clamp(saturation128, 0, 256)
|
|
||||||
value128 = clamp(value128, 0, 256)
|
|
||||||
|
|
||||||
pressedI := ebiten.IsKeyPressed(ebiten.KeyI)
|
|
||||||
if pressedI && !prevPressedI {
|
|
||||||
inverted = !inverted
|
|
||||||
}
|
|
||||||
prevPressedI = pressedI
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Center the image on the screen.
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(screenWidth-w)/2, float64(screenHeight-h)/2)
|
|
||||||
|
|
||||||
// Change HSV.
|
|
||||||
hue := float64(hue128) * 2 * math.Pi / 128
|
|
||||||
saturation := float64(saturation128) / 128
|
|
||||||
value := float64(value128) / 128
|
|
||||||
op.ColorM.ChangeHSV(hue, saturation, value)
|
|
||||||
|
|
||||||
// Invert the color.
|
|
||||||
if inverted {
|
|
||||||
op.ColorM.Scale(-1, -1, -1, 1)
|
|
||||||
op.ColorM.Translate(1, 1, 1, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
|
|
||||||
// Draw the text of the current status.
|
|
||||||
msgInverted := "false"
|
|
||||||
if inverted {
|
|
||||||
msgInverted = "true"
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf(`Hue: %0.2f [Q][W]
|
|
||||||
Saturation: %0.2f [A][S]
|
|
||||||
Value: %0.2f [Z][X]
|
|
||||||
Inverted: %s [I]`, hue, saturation, value, msgInverted)
|
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "HSV (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'hue.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,72 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - hue</h2>
|
<h2>Ebiten example - hue</h2>
|
||||||
<iframe src="hue.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/hue">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
count int
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
count++
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Center the image on the screen.
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(screenWidth-w)/2, float64(screenHeight-h)/2)
|
|
||||||
|
|
||||||
// Rotate the hue.
|
|
||||||
op.ColorM.RotateHue(float64(count%360) * 2 * math.Pi / 360)
|
|
||||||
|
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Hue (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'infinitescroll.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,105 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - infinitescroll</h2>
|
<h2>Ebiten example - infinitescroll</h2>
|
||||||
<iframe src="infinitescroll.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/infinitescroll">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
bgImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Tile_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
bgImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
theViewport = &viewport{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type viewport struct {
|
|
||||||
x16 int
|
|
||||||
y16 int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *viewport) Move() {
|
|
||||||
w, h := bgImage.Size()
|
|
||||||
maxX16 := w * 16
|
|
||||||
maxY16 := h * 16
|
|
||||||
|
|
||||||
p.x16 += w / 32
|
|
||||||
p.y16 += h / 32
|
|
||||||
p.x16 %= maxX16
|
|
||||||
p.y16 %= maxY16
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *viewport) Position() (int, int) {
|
|
||||||
return p.x16, p.y16
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
theViewport.Move()
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
x16, y16 := theViewport.Position()
|
|
||||||
offsetX, offsetY := float64(-x16)/16, float64(-y16)/16
|
|
||||||
|
|
||||||
// Draw bgImage on the screen repeatedly.
|
|
||||||
const repeat = 3
|
|
||||||
w, h := bgImage.Size()
|
|
||||||
for j := 0; j < repeat; j++ {
|
|
||||||
for i := 0; i < repeat; i++ {
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(w*i), float64(h*j))
|
|
||||||
op.GeoM.Translate(offsetX, offsetY)
|
|
||||||
screen.DrawImage(bgImage, op)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Infinite Scroll (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'keyboard.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,131 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - keyboard</h2>
|
<h2>Ebiten example - keyboard</h2>
|
||||||
<iframe src="keyboard.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/keyboard">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/keyboard/keyboard"
|
|
||||||
rkeyabord "github.com/hajimehoshi/ebiten/examples/resources/images/keyboard"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var keyboardImage *ebiten.Image
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(rkeyabord.Keyboard_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboardImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
var keyNames = map[ebiten.Key]string{
|
|
||||||
ebiten.KeyBackspace: "BS",
|
|
||||||
ebiten.KeyComma: ",",
|
|
||||||
ebiten.KeyEnter: "Enter",
|
|
||||||
ebiten.KeyEscape: "Esc",
|
|
||||||
ebiten.KeyPeriod: ".",
|
|
||||||
ebiten.KeySpace: "Space",
|
|
||||||
ebiten.KeyTab: "Tab",
|
|
||||||
ebiten.KeyMinus: "-",
|
|
||||||
ebiten.KeyEqual: "=",
|
|
||||||
ebiten.KeyBackslash: "\\",
|
|
||||||
ebiten.KeyGraveAccent: "`",
|
|
||||||
ebiten.KeyLeftBracket: "[",
|
|
||||||
ebiten.KeyRightBracket: "]",
|
|
||||||
ebiten.KeySemicolon: ";",
|
|
||||||
ebiten.KeyApostrophe: "'",
|
|
||||||
ebiten.KeySlash: "/",
|
|
||||||
|
|
||||||
// Arrows
|
|
||||||
ebiten.KeyDown: "Down",
|
|
||||||
ebiten.KeyLeft: "Left",
|
|
||||||
ebiten.KeyRight: "Right",
|
|
||||||
ebiten.KeyUp: "Up",
|
|
||||||
|
|
||||||
// Mods
|
|
||||||
ebiten.KeyShift: "Shift",
|
|
||||||
ebiten.KeyControl: "Ctrl",
|
|
||||||
ebiten.KeyAlt: "Alt",
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Collect pressed keys' names.
|
|
||||||
pressed := []string{}
|
|
||||||
for i := 0; i <= 9; i++ {
|
|
||||||
if ebiten.IsKeyPressed(ebiten.Key(i) + ebiten.Key0) {
|
|
||||||
pressed = append(pressed, string(i+'0'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for c := 'A'; c <= 'Z'; c++ {
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyA + ebiten.Key(c-'A')) {
|
|
||||||
pressed = append(pressed, string(c))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 1; i <= 12; i++ {
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyF1 + ebiten.Key(i-1)) {
|
|
||||||
pressed = append(pressed, "F"+strconv.Itoa(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for key, name := range keyNames {
|
|
||||||
if ebiten.IsKeyPressed(key) {
|
|
||||||
pressed = append(pressed, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
offsetX = 24
|
|
||||||
offsetY = 40
|
|
||||||
)
|
|
||||||
|
|
||||||
// Draw the base (grayed) keyboard image.
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(offsetX, offsetY)
|
|
||||||
op.ColorM.Scale(0.5, 0.5, 0.5, 1)
|
|
||||||
screen.DrawImage(keyboardImage, op)
|
|
||||||
|
|
||||||
// Draw the highlighted keys.
|
|
||||||
op = &ebiten.DrawImageOptions{}
|
|
||||||
for _, p := range pressed {
|
|
||||||
op.GeoM.Reset()
|
|
||||||
r, ok := keyboard.KeyRect(p)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
op.GeoM.Translate(float64(r.Min.X), float64(r.Min.Y))
|
|
||||||
op.GeoM.Translate(offsetX, offsetY)
|
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(keyboardImage, op)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Keyboard (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'life.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,177 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - life</h2>
|
<h2>Ebiten example - life</h2>
|
||||||
<iframe src="life.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/life">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
)
|
|
||||||
|
|
||||||
// World represents the game state.
|
|
||||||
type World struct {
|
|
||||||
area [][]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newArea(width, height int) [][]bool {
|
|
||||||
a := make([][]bool, height)
|
|
||||||
for i := 0; i < height; i++ {
|
|
||||||
a[i] = make([]bool, width)
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWorld creates a new world.
|
|
||||||
func NewWorld(width, height int, maxInitLiveCells int) *World {
|
|
||||||
w := &World{
|
|
||||||
area: newArea(width, height),
|
|
||||||
}
|
|
||||||
w.init(maxInitLiveCells)
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
}
|
|
||||||
|
|
||||||
// init inits world with a random state.
|
|
||||||
func (w *World) init(maxLiveCells int) {
|
|
||||||
height := len(w.area)
|
|
||||||
width := len(w.area[0])
|
|
||||||
for i := 0; i < maxLiveCells; i++ {
|
|
||||||
x := rand.Intn(width)
|
|
||||||
y := rand.Intn(height)
|
|
||||||
w.area[y][x] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update game state by one tick.
|
|
||||||
func (w *World) Update() {
|
|
||||||
height := len(w.area)
|
|
||||||
width := len(w.area[0])
|
|
||||||
next := newArea(width, height)
|
|
||||||
for y := 0; y < height; y++ {
|
|
||||||
for x := 0; x < width; x++ {
|
|
||||||
pop := neighbourCount(w.area, x, y)
|
|
||||||
switch {
|
|
||||||
case pop < 2:
|
|
||||||
// rule 1. Any live cell with fewer than two live neighbours
|
|
||||||
// dies, as if caused by under-population.
|
|
||||||
next[y][x] = false
|
|
||||||
|
|
||||||
case (pop == 2 || pop == 3) && w.area[y][x]:
|
|
||||||
// rule 2. Any live cell with two or three live neighbours
|
|
||||||
// lives on to the next generation.
|
|
||||||
next[y][x] = true
|
|
||||||
|
|
||||||
case pop > 3:
|
|
||||||
// rule 3. Any live cell with more than three live neighbours
|
|
||||||
// dies, as if by over-population.
|
|
||||||
next[y][x] = false
|
|
||||||
|
|
||||||
case pop == 3:
|
|
||||||
// rule 4. Any dead cell with exactly three live neighbours
|
|
||||||
// becomes a live cell, as if by reproduction.
|
|
||||||
next[y][x] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.area = next
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw paints current game state.
|
|
||||||
func (w *World) Draw(pix []byte) {
|
|
||||||
height := len(w.area)
|
|
||||||
width := len(w.area[0])
|
|
||||||
for y := 0; y < height; y++ {
|
|
||||||
for x := 0; x < width; x++ {
|
|
||||||
idx := 4*y*width + 4*x
|
|
||||||
if w.area[y][x] {
|
|
||||||
pix[idx] = 0xff
|
|
||||||
pix[idx+1] = 0xff
|
|
||||||
pix[idx+2] = 0xff
|
|
||||||
pix[idx+3] = 0xff
|
|
||||||
} else {
|
|
||||||
pix[idx] = 0
|
|
||||||
pix[idx+1] = 0
|
|
||||||
pix[idx+2] = 0
|
|
||||||
pix[idx+3] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func min(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// neighbourCount calculates the Moore neighborhood of (x, y).
|
|
||||||
func neighbourCount(a [][]bool, x, y int) int {
|
|
||||||
w := len(a[0])
|
|
||||||
h := len(a)
|
|
||||||
minI := max(x-1, 0)
|
|
||||||
minJ := max(y-1, 0)
|
|
||||||
maxI := min(x+1, w-1)
|
|
||||||
maxJ := min(y+1, h-1)
|
|
||||||
|
|
||||||
c := 0
|
|
||||||
for j := minJ; j <= maxJ; j++ {
|
|
||||||
for i := minI; i <= maxI; i++ {
|
|
||||||
if i == x && j == y {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a[j][i] {
|
|
||||||
c++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
world = NewWorld(screenWidth, screenHeight, int((screenWidth*screenHeight)/10))
|
|
||||||
pixels = make([]byte, screenWidth*screenHeight*4)
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
world.Update()
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
world.Draw(pixels)
|
|
||||||
screen.ReplacePixels(pixels)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Game of Life (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'mandelbrot.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,91 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - mandelbrot</h2>
|
<h2>Ebiten example - mandelbrot</h2>
|
||||||
<iframe src="mandelbrot.content.html" width="640" height="640"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/mandelbrot">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
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.FilterDefault)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'masking.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,152 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - masking</h2>
|
<h2>Ebiten example - masking</h2>
|
||||||
<iframe src="masking.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/masking">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
bgImage *ebiten.Image
|
|
||||||
fgImage *ebiten.Image
|
|
||||||
maskedFgImage *ebiten.Image
|
|
||||||
spotLightImage *ebiten.Image
|
|
||||||
spotLightX = 0
|
|
||||||
spotLightY = 0
|
|
||||||
spotLightVX = 1
|
|
||||||
spotLightVY = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
bgImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
img, _, err = image.Decode(bytes.NewReader(images.FiveYears_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fgImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
maskedFgImage, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
// Initialize the spot light image.
|
|
||||||
const r = 64
|
|
||||||
alphas := image.Point{r * 2, r * 2}
|
|
||||||
a := image.NewAlpha(image.Rectangle{image.ZP, alphas})
|
|
||||||
for j := 0; j < alphas.Y; j++ {
|
|
||||||
for i := 0; i < alphas.X; i++ {
|
|
||||||
// d is the distance between (i, j) and the (circle) center.
|
|
||||||
d := math.Sqrt(float64((i-r)*(i-r) + (j-r)*(j-r)))
|
|
||||||
// Alphas around the center are 0 and values outside of the circle are 0xff.
|
|
||||||
b := uint8(max(0, min(0xff, int(3*d*0xff/r)-2*0xff)))
|
|
||||||
a.SetAlpha(i, j, color.Alpha{b})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spotLightImage, _ = ebiten.NewImageFromImage(a, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
spotLightX += spotLightVX
|
|
||||||
spotLightY += spotLightVY
|
|
||||||
if spotLightX < 0 {
|
|
||||||
spotLightX = -spotLightX
|
|
||||||
spotLightVX = -spotLightVX
|
|
||||||
}
|
|
||||||
if spotLightY < 0 {
|
|
||||||
spotLightY = -spotLightY
|
|
||||||
spotLightVY = -spotLightVY
|
|
||||||
}
|
|
||||||
w, h := spotLightImage.Size()
|
|
||||||
maxX, maxY := screenWidth-w, screenHeight-h
|
|
||||||
if maxX < spotLightX {
|
|
||||||
spotLightX = -spotLightX + 2*maxX
|
|
||||||
spotLightVX = -spotLightVX
|
|
||||||
}
|
|
||||||
if maxY < spotLightY {
|
|
||||||
spotLightY = -spotLightY + 2*maxY
|
|
||||||
spotLightVY = -spotLightVY
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the maskedFgImage.
|
|
||||||
maskedFgImage.Fill(color.White)
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.CompositeMode = ebiten.CompositeModeCopy
|
|
||||||
op.GeoM.Translate(float64(spotLightX), float64(spotLightY))
|
|
||||||
maskedFgImage.DrawImage(spotLightImage, op)
|
|
||||||
|
|
||||||
// Use 'source-in' composite mode so that the source image (fgImage) is used but the alpha
|
|
||||||
// is determined by the destination image (maskedFgImage).
|
|
||||||
//
|
|
||||||
// The result image is the source image with the destination alpha. In maskedFgImage, alpha
|
|
||||||
// values in the hole is 0 and alpha values in other places are 0xff. As a result, the
|
|
||||||
// maskedFgImage draws the source image with a hole that shape is spotLightImage. Note that
|
|
||||||
// RGB values in the destination image are ignored.
|
|
||||||
//
|
|
||||||
// See also https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin.
|
|
||||||
op = &ebiten.DrawImageOptions{}
|
|
||||||
op.CompositeMode = ebiten.CompositeModeSourceIn
|
|
||||||
maskedFgImage.DrawImage(fgImage, op)
|
|
||||||
|
|
||||||
screen.Fill(color.RGBA{0x00, 0x00, 0x80, 0xff})
|
|
||||||
screen.DrawImage(bgImage, &ebiten.DrawImageOptions{})
|
|
||||||
screen.DrawImage(maskedFgImage, &ebiten.DrawImageOptions{})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func min(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Masking (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'mosaic.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,76 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - mosaic</h2>
|
<h2>Ebiten example - mosaic</h2>
|
||||||
<iframe src="mosaic.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/mosaic">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
const mosaicRatio = 16
|
|
||||||
|
|
||||||
var (
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
gophersRenderTarget *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shrink the image once.
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Scale(1.0/mosaicRatio, 1.0/mosaicRatio)
|
|
||||||
gophersRenderTarget.DrawImage(gophersImage, op)
|
|
||||||
|
|
||||||
// Enlarge the shrunk image.
|
|
||||||
// The filter is the nearest filter, so the result will be mosaic.
|
|
||||||
op = &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Scale(mosaicRatio, mosaicRatio)
|
|
||||||
screen.DrawImage(gophersRenderTarget, op)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
gophersRenderTarget, _ = ebiten.NewImage(w/mosaicRatio, h/mosaicRatio, ebiten.FilterDefault)
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Mosaic (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'noise.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,71 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - noise</h2>
|
<h2>Ebiten example - noise</h2>
|
||||||
<iframe src="noise.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/noise">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
noiseImage *image.RGBA
|
|
||||||
)
|
|
||||||
|
|
||||||
type rand struct {
|
|
||||||
x, y, z, w uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rand) next() uint32 {
|
|
||||||
// math/rand is too slow to keep 60 FPS on web browsers.
|
|
||||||
// Use Xorshift instead: http://en.wikipedia.org/wiki/Xorshift
|
|
||||||
t := r.x ^ (r.x << 11)
|
|
||||||
r.x, r.y, r.z = r.y, r.z, r.w
|
|
||||||
r.w = (r.w ^ (r.w >> 19)) ^ (t ^ (t >> 8))
|
|
||||||
return r.w
|
|
||||||
}
|
|
||||||
|
|
||||||
var theRand = &rand{12345678, 4185243, 776511, 45411}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Generate the noise with random RGB values.
|
|
||||||
const l = screenWidth * screenHeight
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
x := theRand.next()
|
|
||||||
noiseImage.Pix[4*i] = uint8(x >> 24)
|
|
||||||
noiseImage.Pix[4*i+1] = uint8(x >> 16)
|
|
||||||
noiseImage.Pix[4*i+2] = uint8(x >> 8)
|
|
||||||
noiseImage.Pix[4*i+3] = 0xff
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.ReplacePixels(noiseImage.Pix)
|
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %f", ebiten.CurrentFPS()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
noiseImage = image.NewRGBA(image.Rect(0, 0, screenWidth, screenHeight))
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Noise (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'paint.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,107 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - paint</h2>
|
<h2>Ebiten example - paint</h2>
|
||||||
<iframe src="paint.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/paint">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
count int
|
|
||||||
brushImage *ebiten.Image
|
|
||||||
canvasImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
const (
|
|
||||||
a0 = 0x40
|
|
||||||
a1 = 0xc0
|
|
||||||
a2 = 0xff
|
|
||||||
)
|
|
||||||
pixels := []uint8{
|
|
||||||
a0, a1, a1, a0,
|
|
||||||
a1, a2, a2, a1,
|
|
||||||
a1, a2, a2, a1,
|
|
||||||
a0, a1, a1, a0,
|
|
||||||
}
|
|
||||||
brushImage, _ = ebiten.NewImageFromImage(&image.Alpha{
|
|
||||||
Pix: pixels,
|
|
||||||
Stride: 4,
|
|
||||||
Rect: image.Rect(0, 0, 4, 4),
|
|
||||||
}, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
canvasImage, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterDefault)
|
|
||||||
canvasImage.Fill(color.White)
|
|
||||||
}
|
|
||||||
|
|
||||||
// paint draws the brush on the given canvas image at the position (x, y).
|
|
||||||
func paint(canvas *ebiten.Image, x, y int) {
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64(x), float64(y))
|
|
||||||
// Scale the color and rotate the hue so that colors vary on each frame.
|
|
||||||
op.ColorM.Scale(1.0, 0.50, 0.125, 1.0)
|
|
||||||
theta := 2.0 * math.Pi * float64(count%ebiten.FPS) / ebiten.FPS
|
|
||||||
op.ColorM.RotateHue(theta)
|
|
||||||
canvas.DrawImage(brushImage, op)
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
drawn := false
|
|
||||||
|
|
||||||
// Paint the brush by mouse dragging
|
|
||||||
mx, my := ebiten.CursorPosition()
|
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
|
||||||
paint(canvasImage, mx, my)
|
|
||||||
drawn = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paint the brush by touches
|
|
||||||
for _, t := range ebiten.Touches() {
|
|
||||||
x, y := t.Position()
|
|
||||||
paint(canvasImage, x, y)
|
|
||||||
drawn = true
|
|
||||||
}
|
|
||||||
if drawn {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.DrawImage(canvasImage, nil)
|
|
||||||
|
|
||||||
msg := fmt.Sprintf("(%d, %d)", mx, my)
|
|
||||||
for _, t := range ebiten.Touches() {
|
|
||||||
x, y := t.Position()
|
|
||||||
msg += fmt.Sprintf("\n(%d, %d) touch %d", x, y, t.ID())
|
|
||||||
}
|
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Paint (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'perspective.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,81 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - perspective</h2>
|
<h2>Ebiten example - perspective</h2>
|
||||||
<iframe src="perspective.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/perspective">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the image into horizontal lines and draw them with different scales.
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
for i := 0; i < h; i++ {
|
|
||||||
op.GeoM.Reset()
|
|
||||||
|
|
||||||
// Move the image's center to the upper-left corner.
|
|
||||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
|
||||||
|
|
||||||
// Scale each lines and adjust the position.
|
|
||||||
lineW := w + i*3/4
|
|
||||||
x := -float64(lineW) / float64(w) / 2
|
|
||||||
op.GeoM.Scale(float64(lineW)/float64(w), 1)
|
|
||||||
op.GeoM.Translate(x, float64(i))
|
|
||||||
|
|
||||||
// Move the image's center to the screen's center.
|
|
||||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
|
||||||
|
|
||||||
r := image.Rect(0, i, w, i+1)
|
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Perspective (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'piano.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,233 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - piano</h2>
|
<h2>Ebiten example - piano</h2>
|
||||||
<iframe src="piano.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/piano">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image/color"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/golang/freetype/truetype"
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/audio"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/fonts"
|
|
||||||
"github.com/hajimehoshi/ebiten/inpututil"
|
|
||||||
"github.com/hajimehoshi/ebiten/text"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
arcadeFont font.Face
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
tt, err := truetype.Parse(fonts.ArcadeN_ttf)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
arcadeFontSize = 8
|
|
||||||
dpi = 72
|
|
||||||
)
|
|
||||||
arcadeFont = truetype.NewFace(tt, &truetype.Options{
|
|
||||||
Size: arcadeFontSize,
|
|
||||||
DPI: dpi,
|
|
||||||
Hinting: font.HintingFull,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
sampleRate = 44100
|
|
||||||
baseFreq = 220
|
|
||||||
)
|
|
||||||
|
|
||||||
var audioContext *audio.Context
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
audioContext, err = audio.NewContext(sampleRate)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pianoAt returns an i-th sample of piano with the given frequency.
|
|
||||||
func pianoAt(i int, freq float64) float64 {
|
|
||||||
// Create piano-like waves with multiple sin waves.
|
|
||||||
amp := []float64{1.0, 0.8, 0.6, 0.4, 0.2}
|
|
||||||
x := []float64{4.0, 2.0, 1.0, 0.5, 0.25}
|
|
||||||
v := 0.0
|
|
||||||
for j := 0; j < len(amp); j++ {
|
|
||||||
// Decay
|
|
||||||
a := amp[j] * math.Exp(-5*float64(i)*freq/baseFreq/(x[j]*sampleRate))
|
|
||||||
v += a * math.Sin(2.0*math.Pi*float64(i)*freq*float64(j+1)/sampleRate)
|
|
||||||
}
|
|
||||||
return v / 5.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// toBytes returns the 2ch little endian 16bit byte sequence with the given left/right sequence.
|
|
||||||
func toBytes(l, r []int16) []byte {
|
|
||||||
if len(l) != len(r) {
|
|
||||||
panic("len(l) must equal to len(r)")
|
|
||||||
}
|
|
||||||
b := make([]byte, len(l)*4)
|
|
||||||
for i := range l {
|
|
||||||
b[4*i] = byte(l[i])
|
|
||||||
b[4*i+1] = byte(l[i] >> 8)
|
|
||||||
b[4*i+2] = byte(r[i])
|
|
||||||
b[4*i+3] = byte(r[i] >> 8)
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
pianoNoteSamples = map[int][]byte{}
|
|
||||||
pianoNoteSamplesInited = false
|
|
||||||
pianoNoteSamplesInitCh = make(chan struct{})
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Initialize piano data.
|
|
||||||
// This takes a little long time (especially on browsers),
|
|
||||||
// so run this asynchronously and notice the progress.
|
|
||||||
go func() {
|
|
||||||
// Create a reference data and use this for other frequency.
|
|
||||||
const refFreq = 110
|
|
||||||
length := 4 * sampleRate * baseFreq / refFreq
|
|
||||||
refData := make([]int16, length)
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
refData[i] = int16(pianoAt(i, refFreq) * math.MaxInt16)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range keys {
|
|
||||||
freq := baseFreq * math.Exp2(float64(i-1)/12.0)
|
|
||||||
|
|
||||||
// Clculate the wave data for the freq.
|
|
||||||
length := 4 * sampleRate * baseFreq / int(freq)
|
|
||||||
l := make([]int16, length)
|
|
||||||
r := make([]int16, length)
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
idx := int(float64(i) * freq / refFreq)
|
|
||||||
if len(refData) <= idx {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
l[i] = refData[idx]
|
|
||||||
}
|
|
||||||
copy(r, l)
|
|
||||||
n := toBytes(l, r)
|
|
||||||
pianoNoteSamples[int(freq)] = n
|
|
||||||
}
|
|
||||||
close(pianoNoteSamplesInitCh)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// playNote plays piano sound with the given frequency.
|
|
||||||
func playNote(freq float64) {
|
|
||||||
f := int(freq)
|
|
||||||
p, _ := audio.NewPlayerFromBytes(audioContext, pianoNoteSamples[f])
|
|
||||||
p.Play()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
pianoImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
pianoImage, _ = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
const (
|
|
||||||
keyWidth = 24
|
|
||||||
y = 48
|
|
||||||
)
|
|
||||||
|
|
||||||
whiteKeys := []string{"A", "S", "D", "F", "G", "H", "J", "K", "L"}
|
|
||||||
for i, k := range whiteKeys {
|
|
||||||
x := i*keyWidth + 36
|
|
||||||
height := 112
|
|
||||||
ebitenutil.DrawRect(pianoImage, float64(x), float64(y), float64(keyWidth-1), float64(height), color.White)
|
|
||||||
text.Draw(pianoImage, k, arcadeFont, x+8, y+height-8, color.Black)
|
|
||||||
}
|
|
||||||
|
|
||||||
blackKeys := []string{"Q", "W", "", "R", "T", "", "U", "I", "O"}
|
|
||||||
for i, k := range blackKeys {
|
|
||||||
if k == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
x := i*keyWidth + 24
|
|
||||||
height := 64
|
|
||||||
ebitenutil.DrawRect(pianoImage, float64(x), float64(y), float64(keyWidth-1), float64(height), color.Black)
|
|
||||||
text.Draw(pianoImage, k, arcadeFont, x+8, y+height-8, color.White)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
keys = []ebiten.Key{
|
|
||||||
ebiten.KeyQ,
|
|
||||||
ebiten.KeyA,
|
|
||||||
ebiten.KeyW,
|
|
||||||
ebiten.KeyS,
|
|
||||||
ebiten.KeyD,
|
|
||||||
ebiten.KeyR,
|
|
||||||
ebiten.KeyF,
|
|
||||||
ebiten.KeyT,
|
|
||||||
ebiten.KeyG,
|
|
||||||
ebiten.KeyH,
|
|
||||||
ebiten.KeyU,
|
|
||||||
ebiten.KeyJ,
|
|
||||||
ebiten.KeyI,
|
|
||||||
ebiten.KeyK,
|
|
||||||
ebiten.KeyO,
|
|
||||||
ebiten.KeyL,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// The piano data is still being initialized.
|
|
||||||
// Get the progress if available.
|
|
||||||
if !pianoNoteSamplesInited {
|
|
||||||
select {
|
|
||||||
case <-pianoNoteSamplesInitCh:
|
|
||||||
pianoNoteSamplesInited = true
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pianoNoteSamplesInited {
|
|
||||||
for i, key := range keys {
|
|
||||||
if !inpututil.IsKeyJustPressed(key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
playNote(baseFreq * math.Exp2(float64(i-1)/12.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.Fill(color.RGBA{0x80, 0x80, 0xc0, 0xff})
|
|
||||||
screen.DrawImage(pianoImage, nil)
|
|
||||||
|
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Piano (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'rotate.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,76 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - rotate</h2>
|
<h2>Ebiten example - rotate</h2>
|
||||||
<iframe src="rotate.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/rotate">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"image"
|
|
||||||
_ "image/jpeg"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
count = 0
|
|
||||||
gophersImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
count++
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w, h := gophersImage.Size()
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
|
|
||||||
// Move the image's center to the screen's upper-left corner.
|
|
||||||
// This is a prepartion for rotating. When geometry matrices are applied,
|
|
||||||
// the origin point is the upper-left corner.
|
|
||||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
|
||||||
|
|
||||||
// Rotate the image. As a result, the anchor point of this rotate is
|
|
||||||
// the center of the image.
|
|
||||||
op.GeoM.Rotate(float64(count%360) * 2 * math.Pi / 360)
|
|
||||||
|
|
||||||
// Move the image to the screen's center.
|
|
||||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
gophersImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Rotate (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'sinewave.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,99 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - sinewave</h2>
|
<h2>Ebiten example - sinewave</h2>
|
||||||
<iframe src="sinewave.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/sinewave">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'sprites.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,179 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - sprites</h2>
|
<h2>Ebiten example - sprites</h2>
|
||||||
<iframe src="sprites.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/sprites">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 320
|
|
||||||
screenHeight = 240
|
|
||||||
maxAngle = 256
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ebitenImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
type Sprite struct {
|
|
||||||
imageWidth int
|
|
||||||
imageHeight int
|
|
||||||
x int
|
|
||||||
y int
|
|
||||||
vx int
|
|
||||||
vy int
|
|
||||||
angle int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sprite) Update() {
|
|
||||||
s.x += s.vx
|
|
||||||
s.y += s.vy
|
|
||||||
if s.x < 0 {
|
|
||||||
s.x = -s.x
|
|
||||||
s.vx = -s.vx
|
|
||||||
} else if screenWidth <= s.x+s.imageWidth {
|
|
||||||
s.x = 2*(screenWidth-s.imageWidth) - s.x
|
|
||||||
s.vx = -s.vx
|
|
||||||
}
|
|
||||||
if s.y < 0 {
|
|
||||||
s.y = -s.y
|
|
||||||
s.vy = -s.vy
|
|
||||||
} else if screenHeight <= s.y+s.imageHeight {
|
|
||||||
s.y = 2*(screenHeight-s.imageHeight) - s.y
|
|
||||||
s.vy = -s.vy
|
|
||||||
}
|
|
||||||
s.angle++
|
|
||||||
s.angle %= maxAngle
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sprites struct {
|
|
||||||
sprites []*Sprite
|
|
||||||
num int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sprites) Update() {
|
|
||||||
for _, sprite := range s.sprites {
|
|
||||||
sprite.Update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
MinSprites = 0
|
|
||||||
MaxSprites = 50000
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sprites = &Sprites{make([]*Sprite, MaxSprites), 500}
|
|
||||||
op = &ebiten.DrawImageOptions{}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Ebiten_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
origEbitenImage, _ := ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
|
|
||||||
w, h := origEbitenImage.Size()
|
|
||||||
ebitenImage, _ = ebiten.NewImage(w, h, ebiten.FilterNearest)
|
|
||||||
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.ColorM.Scale(1, 1, 1, 0.5)
|
|
||||||
ebitenImage.DrawImage(origEbitenImage, op)
|
|
||||||
|
|
||||||
for i := range sprites.sprites {
|
|
||||||
w, h := ebitenImage.Size()
|
|
||||||
x, y := rand.Intn(screenWidth-w), rand.Intn(screenHeight-h)
|
|
||||||
vx, vy := 2*rand.Intn(2)-1, 2*rand.Intn(2)-1
|
|
||||||
a := rand.Intn(maxAngle)
|
|
||||||
sprites.sprites[i] = &Sprite{
|
|
||||||
imageWidth: w,
|
|
||||||
imageHeight: h,
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
vx: vx,
|
|
||||||
vy: vy,
|
|
||||||
angle: a,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
// Decrease the nubmer of the sprites.
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
|
||||||
sprites.num -= 20
|
|
||||||
if sprites.num < MinSprites {
|
|
||||||
sprites.num = MinSprites
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increase the nubmer of the sprites.
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyRight) {
|
|
||||||
sprites.num += 20
|
|
||||||
if MaxSprites < sprites.num {
|
|
||||||
sprites.num = MaxSprites
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sprites.Update()
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw each sprite.
|
|
||||||
// DrawImage can be called many many times, but in the implementation,
|
|
||||||
// the actual draw call to GPU is very few since these calls satisfy
|
|
||||||
// some conditions e.g. all the rendering sources and targets are same.
|
|
||||||
// For more detail, see:
|
|
||||||
// https://godoc.org/github.com/hajimehoshi/ebiten#Image.DrawImage
|
|
||||||
w, h := ebitenImage.Size()
|
|
||||||
for i := 0; i < sprites.num; i++ {
|
|
||||||
s := sprites.sprites[i]
|
|
||||||
op.GeoM.Reset()
|
|
||||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
|
||||||
op.GeoM.Rotate(2 * math.Pi * float64(s.angle) / maxAngle)
|
|
||||||
op.GeoM.Translate(float64(w)/2, float64(h)/2)
|
|
||||||
op.GeoM.Translate(float64(s.x), float64(s.y))
|
|
||||||
screen.DrawImage(ebitenImage, op)
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf(`FPS: %0.2f
|
|
||||||
Num of sprites: %d
|
|
||||||
Press <- or -> to change the number of sprites`, ebiten.CurrentFPS(), sprites.num)
|
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Sprites (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'tiles.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,131 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - tiles</h2>
|
<h2>Ebiten example - tiles</h2>
|
||||||
<iframe src="tiles.content.html" width="480" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/tiles">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
"github.com/hajimehoshi/ebiten/examples/resources/images"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
screenWidth = 240
|
|
||||||
screenHeight = 240
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
tileSize = 16
|
|
||||||
tileXNum = 25
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
tilesImage *ebiten.Image
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Decode image from a byte slice instead of a file so that
|
|
||||||
// this example works in any working directory.
|
|
||||||
// If you want to use a file, there are some options:
|
|
||||||
// 1) Use os.Open and pass the file to the image decoder.
|
|
||||||
// This is a very regular way, but doesn't work on browsers.
|
|
||||||
// 2) Use ebitenutil.OpenFile and pass the file to the image decoder.
|
|
||||||
// This works even on browsers.
|
|
||||||
// 3) Use ebitenutil.NewImageFromFile to create an ebiten.Image directly from a file.
|
|
||||||
// This also works on browsers.
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(images.Tiles_png))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
tilesImage, _ = ebiten.NewImageFromImage(img, ebiten.FilterDefault)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
layers = [][]int{
|
|
||||||
{
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 218, 243, 243, 243, 243, 243, 243, 243, 243, 243, 218, 243, 244, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 244, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 219, 243, 243, 243, 219, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
243, 218, 243, 243, 243, 243, 243, 243, 243, 243, 243, 244, 243, 243, 243,
|
|
||||||
243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 51, 52, 53, 54, 55, 56, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 76, 77, 78, 79, 80, 81, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 101, 102, 103, 104, 105, 106, 0, 0, 0, 0,
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 126, 127, 128, 129, 130, 131, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 303, 303, 245, 242, 303, 303, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 245, 242, 0, 0, 0, 0, 0, 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw each tile with each DrawImage call.
|
|
||||||
// As the source images of all DrawImage calls are always same,
|
|
||||||
// this rendering is done very effectively.
|
|
||||||
// For more detail, see https://godoc.org/github.com/hajimehoshi/ebiten#Image.DrawImage
|
|
||||||
const xNum = screenWidth / tileSize
|
|
||||||
for _, l := range layers {
|
|
||||||
for i, t := range l {
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
op.GeoM.Translate(float64((i%xNum)*tileSize), float64((i/xNum)*tileSize))
|
|
||||||
|
|
||||||
sx := (t % tileXNum) * tileSize
|
|
||||||
sy := (t / tileXNum) * tileSize
|
|
||||||
r := image.Rect(sx, sy, sx+tileSize, sy+tileSize)
|
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(tilesImage, op)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS()))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Tiles (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
function isProduction() {
|
|
||||||
var l = window.top.location;
|
|
||||||
if (l.hash === '#_production') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (l.hostname === 'localhost' || l.hostname === '127.0.0.1') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var s = document.createElement('script');
|
|
||||||
var src = 'typewriter.js';
|
|
||||||
if (isProduction()) {
|
|
||||||
src = 'https://hajimehoshi.github.io/ebiten.pagestorage/latest/' + src;
|
|
||||||
}
|
|
||||||
s.src = src;
|
|
||||||
s.onload = function() {
|
|
||||||
var notice = document.getElementById('notice');
|
|
||||||
notice.parentNode.removeChild(notice);
|
|
||||||
};
|
|
||||||
document.body.appendChild(s);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<title>(Example)</title>
|
|
||||||
<p id="notice" style="color: white;">Now Loading...</p>
|
|
@ -18,7 +18,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -26,72 +25,7 @@
|
|||||||
<main><div class="container">
|
<main><div class="container">
|
||||||
|
|
||||||
<h2>Ebiten example - typewriter</h2>
|
<h2>Ebiten example - typewriter</h2>
|
||||||
<iframe src="typewriter.content.html" width="640" height="480"></iframe>
|
<p><a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/typewriter">Go Playground page</a></p>
|
||||||
<div class="card"><pre class="card-body"><code class="language-go">// +build example jsgo
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
text = "Type on the keyboard:\n"
|
|
||||||
counter = 0
|
|
||||||
bsPrevPressed = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func update(screen *ebiten.Image) 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.
|
|
||||||
text += string(ebiten.InputChars())
|
|
||||||
|
|
||||||
// Adjust the string to be at most 10 lines.
|
|
||||||
ss := strings.Split(text, "\n")
|
|
||||||
if len(ss) > 10 {
|
|
||||||
text = strings.Join(ss[len(ss)-10:], "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the enter key is pressed, add a line break.
|
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyEnter) && !strings.HasSuffix(text, "\n") {
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the backspace key is pressed, remove one character.
|
|
||||||
bsPressed := ebiten.IsKeyPressed(ebiten.KeyBackspace)
|
|
||||||
if !bsPrevPressed && bsPressed {
|
|
||||||
if len(text) >= 1 {
|
|
||||||
text = text[:len(text)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bsPrevPressed = bsPressed
|
|
||||||
|
|
||||||
counter++
|
|
||||||
|
|
||||||
if ebiten.IsRunningSlowly() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blink the cursor.
|
|
||||||
t := text
|
|
||||||
if counter%60 < 30 {
|
|
||||||
t += "_"
|
|
||||||
}
|
|
||||||
ebitenutil.DebugPrint(screen, t)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := ebiten.Run(update, 320, 240, 2.0, "Typewriter (Ebiten Demo)"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre></div>
|
|
||||||
|
|
||||||
</div></main>
|
</div></main>
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a></li>
|
<li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div></nav>
|
</div></nav>
|
||||||
@ -45,7 +44,7 @@
|
|||||||
<dt class="col-2 text-right">Mobiles</dt>
|
<dt class="col-2 text-right">Mobiles</dt>
|
||||||
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Android">Android</a>, <a href="https://github.com/hajimehoshi/ebiten/wiki/iOS">iOS</a></dd>
|
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Android">Android</a>, <a href="https://github.com/hajimehoshi/ebiten/wiki/iOS">iOS</a></dd>
|
||||||
<dt class="col-2 text-right">Web browsers</dt>
|
<dt class="col-2 text-right">Web browsers</dt>
|
||||||
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Web-Browsers">Chrome, Firefox, Safari and Edge</a> (powered by <a href="https://github.com/gopherjs/gopherjs">GopherJS</a>), <a href=".">jsgo.io Playground by Dave Brophy (Coming Soon)</a></dd>
|
<dd class="col-10"><a href="https://github.com/hajimehoshi/ebiten/wiki/Web-Browsers">Chrome, Firefox, Safari and Edge</a> (powered by <a href="https://github.com/gopherjs/gopherjs">GopherJS</a>)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p><small>Note: Gamepads and keyboard are not available on Android/iOS.</small></p>
|
<p><small>Note: Gamepads and keyboard are not available on Android/iOS.</small></p>
|
||||||
|
|
||||||
@ -63,71 +62,71 @@
|
|||||||
<h3>Games</h3>
|
<h3>Games</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/2048.html"><img src="images/examples/2048.png" width="210" height="300" alt="Ebiten example: 2048" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/2048"><img src="images/examples/2048.png" width="210" height="300" alt="Ebiten example: 2048" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/blocks.html"><img src="images/examples/blocks.png" width="256" height="240" alt="Ebiten example: blocks" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/blocks"><img src="images/examples/blocks.png" width="256" height="240" alt="Ebiten example: blocks" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3>Graphics</h3>
|
<h3>Graphics</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/airship.html"><img src="images/examples/airship.png" width="320" height="240" alt="Ebiten example: airship" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/airship"><img src="images/examples/airship.png" width="320" height="240" alt="Ebiten example: airship" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/alphablending.html"><img src="images/examples/alphablending.png" width="320" height="240" alt="Ebiten example: alphablending" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/alphablending"><img src="images/examples/alphablending.png" width="320" height="240" alt="Ebiten example: alphablending" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/filter.html"><img src="images/examples/filter.png" width="320" height="240" alt="Ebiten example: filter" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/filter"><img src="images/examples/filter.png" width="320" height="240" alt="Ebiten example: filter" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/flood.html"><img src="images/examples/flood.png" width="320" height="240" alt="Ebiten example: flood" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/flood"><img src="images/examples/flood.png" width="320" height="240" alt="Ebiten example: flood" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/font.html"><img src="images/examples/font.png" width="320" height="240" alt="Ebiten example: font" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/font"><img src="images/examples/font.png" width="320" height="240" alt="Ebiten example: font" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/highdpi.html"><img src="images/examples/highdpi.png" width="320" height="240" alt="Ebiten example: highdpi" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/highdpi"><img src="images/examples/highdpi.png" width="320" height="240" alt="Ebiten example: highdpi" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/hsv.html"><img src="images/examples/hsv.png" width="320" height="240" alt="Ebiten example: hsv" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/hsv"><img src="images/examples/hsv.png" width="320" height="240" alt="Ebiten example: hsv" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/hue.html"><img src="images/examples/hue.png" width="320" height="240" alt="Ebiten example: hue" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/hue"><img src="images/examples/hue.png" width="320" height="240" alt="Ebiten example: hue" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/infinitescroll.html"><img src="images/examples/infinitescroll.png" width="320" height="240" alt="Ebiten example: infinitescroll" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/infinitescroll"><img src="images/examples/infinitescroll.png" width="320" height="240" alt="Ebiten example: infinitescroll" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/life.html"><img src="images/examples/life.png" width="320" height="240" alt="Ebiten example: life" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/life"><img src="images/examples/life.png" width="320" height="240" alt="Ebiten example: life" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/mandelbrot.html"><img src="images/examples/mandelbrot.png" width="320" height="320" alt="Ebiten example: mandelbrot" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/mandelbrot"><img src="images/examples/mandelbrot.png" width="320" height="320" alt="Ebiten example: mandelbrot" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/masking.html"><img src="images/examples/masking.png" width="320" height="240" alt="Ebiten example: masking" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/masking"><img src="images/examples/masking.png" width="320" height="240" alt="Ebiten example: masking" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/mosaic.html"><img src="images/examples/mosaic.png" width="320" height="240" alt="Ebiten example: mosaic" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/mosaic"><img src="images/examples/mosaic.png" width="320" height="240" alt="Ebiten example: mosaic" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/noise.html"><img src="images/examples/noise.png" width="320" height="240" alt="Ebiten example: noise" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/noise"><img src="images/examples/noise.png" width="320" height="240" alt="Ebiten example: noise" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/paint.html"><img src="images/examples/paint.png" width="320" height="240" alt="Ebiten example: paint" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/paint"><img src="images/examples/paint.png" width="320" height="240" alt="Ebiten example: paint" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/perspective.html"><img src="images/examples/perspective.png" width="320" height="240" alt="Ebiten example: perspective" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/perspective"><img src="images/examples/perspective.png" width="320" height="240" alt="Ebiten example: perspective" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/rotate.html"><img src="images/examples/rotate.png" width="320" height="240" alt="Ebiten example: rotate" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/rotate"><img src="images/examples/rotate.png" width="320" height="240" alt="Ebiten example: rotate" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/sprites.html"><img src="images/examples/sprites.png" width="320" height="240" alt="Ebiten example: sprites" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/sprites"><img src="images/examples/sprites.png" width="320" height="240" alt="Ebiten example: sprites" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/tiles.html"><img src="images/examples/tiles.png" width="240" height="240" alt="Ebiten example: tiles" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/tiles"><img src="images/examples/tiles.png" width="240" height="240" alt="Ebiten example: tiles" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3>Input</h3>
|
<h3>Input</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/gamepad.html"><img src="images/examples/gamepad.png" width="320" height="240" alt="Ebiten example: gamepad" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/gamepad"><img src="images/examples/gamepad.png" width="320" height="240" alt="Ebiten example: gamepad" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/keyboard.html"><img src="images/examples/keyboard.png" width="320" height="240" alt="Ebiten example: keyboard" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/keyboard"><img src="images/examples/keyboard.png" width="320" height="240" alt="Ebiten example: keyboard" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/typewriter.html"><img src="images/examples/typewriter.png" width="320" height="240" alt="Ebiten example: typewriter" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/typewriter"><img src="images/examples/typewriter.png" width="320" height="240" alt="Ebiten example: typewriter" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3>Audio</h3>
|
<h3>Audio</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<a href="examples/audio.html"><img src="images/examples/audio.png" width="320" height="240" alt="Ebiten example: audio" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/audio"><img src="images/examples/audio.png" width="320" height="240" alt="Ebiten example: audio" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/piano.html"><img src="images/examples/piano.png" width="320" height="240" alt="Ebiten example: piano" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/piano"><img src="images/examples/piano.png" width="320" height="240" alt="Ebiten example: piano" class="img-thumbnail"></a>
|
||||||
</div><div class="col-3">
|
</div><div class="col-3">
|
||||||
<a href="examples/sinewave.html"><img src="images/examples/sinewave.png" width="320" height="240" alt="Ebiten example: sinewave" class="img-thumbnail"></a>
|
<a href="https://play.jsgo.io/github.com/hajimehoshi/ebiten/examples/examples/sinewave"><img src="images/examples/sinewave.png" width="320" height="240" alt="Ebiten example: sinewave" class="img-thumbnail"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|