Unify packages to ebiten (#19)

This commit is contained in:
Hajime Hoshi 2014-12-09 22:09:22 +09:00
parent 7311369a07
commit 164b320170
39 changed files with 378 additions and 399 deletions

View File

@ -1,4 +1,4 @@
package matrix package ebiten
type affine interface { type affine interface {
dim() int dim() int
@ -6,11 +6,11 @@ type affine interface {
setElement(i, j int, element float64) setElement(i, j int, element float64)
} }
func isIdentity(matrix affine) bool { func isIdentity(ebiten affine) bool {
dim := matrix.dim() dim := ebiten.dim()
for i := 0; i < dim-1; i++ { for i := 0; i < dim-1; i++ {
for j := 0; j < dim; j++ { for j := 0; j < dim; j++ {
element := matrix.element(i, j) element := ebiten.element(i, j)
if i == j && element != 1 { if i == j && element != 1 {
return false return false
} else if i != j && element != 0 { } else if i != j && element != 0 {

85
colormatrix.go Normal file
View File

@ -0,0 +1,85 @@
package ebiten
import (
"image/color"
"math"
)
const ColorMatrixDim = 5
type ColorMatrix struct {
Elements [ColorMatrixDim - 1][ColorMatrixDim]float64
}
func ColorMatrixI() ColorMatrix {
return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{
{1, 0, 0, 0, 0},
{0, 1, 0, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 0, 1, 0},
},
}
}
func (c *ColorMatrix) dim() int {
return ColorMatrixDim
}
func (c *ColorMatrix) Concat(other ColorMatrix) {
result := ColorMatrix{}
mul(&other, c, &result)
*c = result
}
func (c *ColorMatrix) IsIdentity() bool {
return isIdentity(c)
}
func (c *ColorMatrix) element(i, j int) float64 {
return c.Elements[i][j]
}
func (c *ColorMatrix) setElement(i, j int, element float64) {
c.Elements[i][j] = element
}
func Monochrome() ColorMatrix {
const r float64 = 6968.0 / 32768.0
const g float64 = 23434.0 / 32768.0
const b float64 = 2366.0 / 32768.0
return ColorMatrix{
[ColorMatrixDim - 1][ColorMatrixDim]float64{
{r, g, b, 0, 0},
{r, g, b, 0, 0},
{r, g, b, 0, 0},
{0, 0, 0, 1, 0},
},
}
}
func rgba(clr color.Color) (float64, float64, float64, float64) {
r, g, b, a := clr.RGBA()
rf := float64(r) / float64(math.MaxUint16)
gf := float64(g) / float64(math.MaxUint16)
bf := float64(b) / float64(math.MaxUint16)
af := float64(a) / float64(math.MaxUint16)
return rf, gf, bf, af
}
func (c *ColorMatrix) Scale(clr color.Color) {
rf, gf, bf, af := rgba(clr)
for i, e := range []float64{rf, gf, bf, af} {
for j := 0; j < 4; j++ {
c.Elements[i][j] *= e
}
}
}
func (c *ColorMatrix) Translate(clr color.Color) {
rf, gf, bf, af := rgba(clr)
c.Elements[0][4] = rf
c.Elements[1][4] = gf
c.Elements[2][4] = bf
c.Elements[3][4] = af
}

View File

@ -1,4 +1,4 @@
package matrix_test package ebiten_test
import ( import (
. "." . "."
@ -6,8 +6,8 @@ import (
) )
func TestColorIdentity(t *testing.T) { func TestColorIdentity(t *testing.T) {
matrix := ColorI() ebiten := ColorMatrixI()
got := matrix.IsIdentity() got := ebiten.IsIdentity()
want := true want := true
if want != got { if want != got {
t.Errorf("matrix.IsIdentity() = %t, want %t", got, want) t.Errorf("matrix.IsIdentity() = %t, want %t", got, want)

View File

@ -2,9 +2,9 @@ package main
import ( import (
"flag" "flag"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/example/blocks" "github.com/hajimehoshi/ebiten/example/blocks"
"github.com/hajimehoshi/ebiten/ui" "github.com/hajimehoshi/ebiten/glfw"
"github.com/hajimehoshi/ebiten/ui/glfw"
"log" "log"
"os" "os"
"runtime" "runtime"
@ -30,7 +30,7 @@ func main() {
u := new(glfw.UI) u := new(glfw.UI)
game := blocks.NewGame() game := blocks.NewGame()
if err := ui.Run(u, game, blocks.ScreenWidth, blocks.ScreenHeight, 2, "Blocks (Ebiten Demo)", 60); err != nil { if err := ebiten.Run(u, game, blocks.ScreenWidth, blocks.ScreenHeight, 2, "Blocks (Ebiten Demo)", 60); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -1,8 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
) )
type Field struct { type Field struct {
@ -97,7 +96,7 @@ func (f *Field) flushLine(j int) bool {
return true return true
} }
func (f *Field) Draw(context graphics.Context, textures *Textures, geo matrix.Geometry) { func (f *Field) Draw(context ebiten.GraphicsContext, textures *Textures, geo ebiten.GeometryMatrix) {
blocks := make([][]BlockType, len(f.blocks)) blocks := make([][]BlockType, len(f.blocks))
for i, blockCol := range f.blocks { for i, blockCol := range f.blocks {
blocks[i] = make([]BlockType, len(blockCol)) blocks[i] = make([]BlockType, len(blockCol))

View File

@ -1,8 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"image/color" "image/color"
) )
@ -17,9 +16,9 @@ func textWidth(str string) int {
return charWidth * len(str) return charWidth * len(str)
} }
func drawText(context graphics.Context, textures *Textures, str string, x, y, scale int, clr color.Color) { func drawText(context ebiten.GraphicsContext, textures *Textures, str string, x, y, scale int, clr color.Color) {
fontTextureId := textures.GetTexture("font") fontTextureId := textures.GetTexture("font")
parts := []graphics.TexturePart{} parts := []ebiten.TexturePart{}
locationX := 0 locationX := 0
locationY := 0 locationY := 0
@ -32,23 +31,23 @@ func drawText(context graphics.Context, textures *Textures, str string, x, y, sc
code := int(c) code := int(c)
x := (code % 16) * charWidth x := (code % 16) * charWidth
y := ((code - 32) / 16) * charHeight y := ((code - 32) / 16) * charHeight
parts = append(parts, graphics.TexturePart{ parts = append(parts, ebiten.TexturePart{
LocationX: locationX, LocationX: locationX,
LocationY: locationY, LocationY: locationY,
Source: graphics.Rect{x, y, charWidth, charHeight}, Source: ebiten.Rect{x, y, charWidth, charHeight},
}) })
locationX += charWidth locationX += charWidth
} }
geoMat := matrix.GeometryI() geoMat := ebiten.GeometryMatrixI()
geoMat.Scale(float64(scale), float64(scale)) geoMat.Scale(float64(scale), float64(scale))
geoMat.Translate(float64(x), float64(y)) geoMat.Translate(float64(x), float64(y))
clrMat := matrix.ColorI() clrMat := ebiten.ColorMatrixI()
clrMat.Scale(clr) clrMat.Scale(clr)
context.Texture(fontTextureId).Draw(parts, geoMat, clrMat) context.Texture(fontTextureId).Draw(parts, geoMat, clrMat)
} }
func drawTextWithShadow(context graphics.Context, textures *Textures, str string, x, y, scale int, clr color.Color) { func drawTextWithShadow(context ebiten.GraphicsContext, textures *Textures, str string, x, y, scale int, clr color.Color) {
drawText(context, textures, str, x+1, y+1, scale, color.RGBA{0, 0, 0, 0x80}) drawText(context, textures, str, x+1, y+1, scale, color.RGBA{0, 0, 0, 0x80})
drawText(context, textures, str, x, y, scale, clr) drawText(context, textures, str, x, y, scale, clr)
} }

View File

@ -1,7 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"sync" "sync"
) )
@ -24,14 +24,14 @@ type GameState struct {
type Game struct { type Game struct {
sceneManager *SceneManager sceneManager *SceneManager
input *Input ebiten *Input
textures *Textures textures *Textures
} }
func NewGame() *Game { func NewGame() *Game {
game := &Game{ game := &Game{
sceneManager: NewSceneManager(NewTitleScene()), sceneManager: NewSceneManager(NewTitleScene()),
input: NewInput(), ebiten: NewInput(),
textures: NewTextures(), textures: NewTextures(),
} }
return game return game
@ -65,15 +65,15 @@ func (game *Game) Update() error {
if !game.isInitialized() { if !game.isInitialized() {
return nil return nil
} }
game.input.Update() game.ebiten.Update()
game.sceneManager.Update(&GameState{ game.sceneManager.Update(&GameState{
SceneManager: game.sceneManager, SceneManager: game.sceneManager,
Input: game.input, Input: game.ebiten,
}) })
return nil return nil
} }
func (game *Game) Draw(context graphics.Context) error { func (game *Game) Draw(context ebiten.GraphicsContext) error {
if !game.isInitialized() { if !game.isInitialized() {
return nil return nil
} }

View File

@ -1,9 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"github.com/hajimehoshi/ebiten/input"
"image/color" "image/color"
"math/rand" "math/rand"
"time" "time"
@ -64,26 +62,26 @@ func (s *GameScene) Update(state *GameState) {
y := s.currentPieceY y := s.currentPieceY
angle := s.currentPieceAngle angle := s.currentPieceAngle
moved := false moved := false
if state.Input.StateForKey(input.KeySpace) == 1 { if state.Input.StateForKey(ebiten.KeySpace) == 1 {
s.currentPieceAngle = s.field.RotatePieceRight(piece, x, y, angle) s.currentPieceAngle = s.field.RotatePieceRight(piece, x, y, angle)
moved = angle != s.currentPieceAngle moved = angle != s.currentPieceAngle
} }
if l := state.Input.StateForKey(input.KeyLeft); l == 1 || (10 <= l && l%2 == 0) { if l := state.Input.StateForKey(ebiten.KeyLeft); l == 1 || (10 <= l && l%2 == 0) {
s.currentPieceX = s.field.MovePieceToLeft(piece, x, y, angle) s.currentPieceX = s.field.MovePieceToLeft(piece, x, y, angle)
moved = x != s.currentPieceX moved = x != s.currentPieceX
} }
if r := state.Input.StateForKey(input.KeyRight); r == 1 || (10 <= r && r%2 == 0) { if r := state.Input.StateForKey(ebiten.KeyRight); r == 1 || (10 <= r && r%2 == 0) {
s.currentPieceX = s.field.MovePieceToRight(piece, x, y, angle) s.currentPieceX = s.field.MovePieceToRight(piece, x, y, angle)
moved = y != s.currentPieceX moved = y != s.currentPieceX
} }
if d := state.Input.StateForKey(input.KeyDown); (d-1)%2 == 0 { if d := state.Input.StateForKey(ebiten.KeyDown); (d-1)%2 == 0 {
s.currentPieceY = s.field.DropPiece(piece, x, y, angle) s.currentPieceY = s.field.DropPiece(piece, x, y, angle)
moved = y != s.currentPieceY moved = y != s.currentPieceY
} }
if moved { if moved {
s.landingCount = 0 s.landingCount = 0
} else if !s.field.PieceDroppable(piece, x, y, angle) { } else if !s.field.PieceDroppable(piece, x, y, angle) {
if 0 < state.Input.StateForKey(input.KeyDown) { if 0 < state.Input.StateForKey(ebiten.KeyDown) {
s.landingCount += 10 s.landingCount += 10
} else { } else {
s.landingCount++ s.landingCount++
@ -97,20 +95,20 @@ func (s *GameScene) Update(state *GameState) {
} }
} }
func (s *GameScene) Draw(context graphics.Context, textures *Textures) { func (s *GameScene) Draw(context ebiten.GraphicsContext, textures *Textures) {
context.Fill(0xff, 0xff, 0xff) context.Fill(0xff, 0xff, 0xff)
field := textures.GetTexture("empty") field := textures.GetTexture("empty")
geoMat := matrix.GeometryI() geoMat := ebiten.GeometryMatrixI()
geoMat.Scale( geoMat.Scale(
float64(fieldWidth)/float64(emptyWidth), float64(fieldWidth)/float64(emptyWidth),
float64(fieldHeight)/float64(emptyHeight)) float64(fieldHeight)/float64(emptyHeight))
geoMat.Translate(20, 20) // magic number? geoMat.Translate(20, 20) // magic number?
colorMat := matrix.ColorI() colorMat := ebiten.ColorMatrixI()
colorMat.Scale(color.RGBA{0, 0, 0, 0x80}) colorMat.Scale(color.RGBA{0, 0, 0, 0x80})
graphics.DrawWhole(context.Texture(field), emptyWidth, emptyHeight, geoMat, colorMat) ebiten.DrawWhole(context.Texture(field), emptyWidth, emptyHeight, geoMat, colorMat)
geoMat = matrix.GeometryI() geoMat = ebiten.GeometryMatrixI()
geoMat.Translate(20, 20) geoMat.Translate(20, 20)
s.field.Draw(context, textures, geoMat) s.field.Draw(context, textures, geoMat)

View File

@ -1,16 +1,16 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/input" "github.com/hajimehoshi/ebiten"
) )
type Input struct { type Input struct {
states map[input.Key]int states map[ebiten.Key]int
} }
func NewInput() *Input { func NewInput() *Input {
states := map[input.Key]int{} states := map[ebiten.Key]int{}
for key := input.Key(0); key < input.KeyMax; key++ { for key := ebiten.Key(0); key < ebiten.KeyMax; key++ {
states[key] = 0 states[key] = 0
} }
return &Input{ return &Input{
@ -18,13 +18,13 @@ func NewInput() *Input {
} }
} }
func (i *Input) StateForKey(key input.Key) int { func (i *Input) StateForKey(key ebiten.Key) int {
return i.states[key] return i.states[key]
} }
func (i *Input) Update() { func (i *Input) Update() {
for key := range i.states { for key := range i.states {
if !input.IsKeyPressed(key) { if !ebiten.IsKeyPressed(key) {
i.states[key] = 0 i.states[key] = 0
continue continue
} }

View File

@ -1,8 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
) )
func init() { func init() {
@ -123,8 +122,8 @@ const blockHeight = 10
const fieldBlockNumX = 10 const fieldBlockNumX = 10
const fieldBlockNumY = 20 const fieldBlockNumY = 20
func drawBlocks(context graphics.Context, textures *Textures, blocks [][]BlockType, geo matrix.Geometry) { func drawBlocks(context ebiten.GraphicsContext, textures *Textures, blocks [][]BlockType, geo ebiten.GeometryMatrix) {
parts := []graphics.TexturePart{} parts := []ebiten.TexturePart{}
for i, blockCol := range blocks { for i, blockCol := range blocks {
for j, block := range blockCol { for j, block := range blockCol {
if block == BlockTypeNone { if block == BlockTypeNone {
@ -132,11 +131,11 @@ func drawBlocks(context graphics.Context, textures *Textures, blocks [][]BlockTy
} }
locationX := i * blockWidth locationX := i * blockWidth
locationY := j * blockHeight locationY := j * blockHeight
source := graphics.Rect{ source := ebiten.Rect{
(int(block) - 1) * blockWidth, 0, (int(block) - 1) * blockWidth, 0,
blockWidth, blockHeight} blockWidth, blockHeight}
parts = append(parts, parts = append(parts,
graphics.TexturePart{ ebiten.TexturePart{
LocationX: locationX, LocationX: locationX,
LocationY: locationY, LocationY: locationY,
Source: source, Source: source,
@ -144,7 +143,7 @@ func drawBlocks(context graphics.Context, textures *Textures, blocks [][]BlockTy
} }
} }
blocksTexture := textures.GetTexture("blocks") blocksTexture := textures.GetTexture("blocks")
context.Texture(blocksTexture).Draw(parts, geo, matrix.ColorI()) context.Texture(blocksTexture).Draw(parts, geo, ebiten.ColorMatrixI())
} }
func (p *Piece) InitialPosition() (int, int) { func (p *Piece) InitialPosition() (int, int) {
@ -204,7 +203,7 @@ func (p *Piece) AbsorbInto(field *Field, x, y int, angle Angle) {
} }
} }
func (p *Piece) Draw(context graphics.Context, textures *Textures, fieldX, fieldY int, pieceX, pieceY int, angle Angle) { func (p *Piece) Draw(context ebiten.GraphicsContext, textures *Textures, fieldX, fieldY int, pieceX, pieceY int, angle Angle) {
size := len(p.blocks) size := len(p.blocks)
blocks := make([][]BlockType, size) blocks := make([][]BlockType, size)
for i := range p.blocks { for i := range p.blocks {
@ -216,7 +215,7 @@ func (p *Piece) Draw(context graphics.Context, textures *Textures, fieldX, field
} }
} }
geoMat := matrix.GeometryI() geoMat := ebiten.GeometryMatrixI()
x := fieldX + pieceX*blockWidth x := fieldX + pieceX*blockWidth
y := fieldY + pieceY*blockHeight y := fieldY + pieceY*blockHeight
geoMat.Translate(float64(x), float64(y)) geoMat.Translate(float64(x), float64(y))

View File

@ -1,8 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
) )
func init() { func init() {
@ -14,7 +13,7 @@ func init() {
type Scene interface { type Scene interface {
Update(state *GameState) Update(state *GameState)
Draw(context graphics.Context, textures *Textures) Draw(context ebiten.GraphicsContext, textures *Textures)
} }
const transitionMaxCount = 20 const transitionMaxCount = 20
@ -45,7 +44,7 @@ func (s *SceneManager) Update(state *GameState) {
} }
} }
func (s *SceneManager) Draw(context graphics.Context, textures *Textures) { func (s *SceneManager) Draw(context ebiten.GraphicsContext, textures *Textures) {
if s.transitionCount == -1 { if s.transitionCount == -1 {
s.current.Draw(context, textures) s.current.Draw(context, textures)
return return
@ -61,21 +60,21 @@ func (s *SceneManager) Draw(context graphics.Context, textures *Textures) {
s.next.Draw(context, textures) s.next.Draw(context, textures)
context.ResetOffscreen() context.ResetOffscreen()
color := matrix.ColorI() color := ebiten.ColorMatrixI()
graphics.DrawWhole( ebiten.DrawWhole(
context.RenderTarget(from), context.RenderTarget(from),
ScreenWidth, ScreenWidth,
ScreenHeight, ScreenHeight,
matrix.GeometryI(), ebiten.GeometryMatrixI(),
color) color)
alpha := float64(s.transitionCount) / float64(transitionMaxCount) alpha := float64(s.transitionCount) / float64(transitionMaxCount)
color.Elements[3][3] = alpha color.Elements[3][3] = alpha
graphics.DrawWhole( ebiten.DrawWhole(
context.RenderTarget(to), context.RenderTarget(to),
ScreenWidth, ScreenWidth,
ScreenHeight, ScreenHeight,
matrix.GeometryI(), ebiten.GeometryMatrixI(),
color) color)
} }

View File

@ -1,7 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"image" "image"
_ "image/png" _ "image/png"
"os" "os"
@ -21,8 +21,8 @@ type nameSize struct {
type Textures struct { type Textures struct {
texturePaths chan namePath texturePaths chan namePath
renderTargetSizes chan nameSize renderTargetSizes chan nameSize
textures map[string]graphics.TextureID textures map[string]ebiten.TextureID
renderTargets map[string]graphics.RenderTargetID renderTargets map[string]ebiten.RenderTargetID
sync.RWMutex sync.RWMutex
} }
@ -30,8 +30,8 @@ func NewTextures() *Textures {
textures := &Textures{ textures := &Textures{
texturePaths: make(chan namePath), texturePaths: make(chan namePath),
renderTargetSizes: make(chan nameSize), renderTargetSizes: make(chan nameSize),
textures: map[string]graphics.TextureID{}, textures: map[string]ebiten.TextureID{},
renderTargets: map[string]graphics.RenderTargetID{}, renderTargets: map[string]ebiten.RenderTargetID{},
} }
go func() { go func() {
for { for {
@ -65,7 +65,7 @@ func (t *Textures) loopMain() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
id, err := graphics.NewTextureID(img, graphics.FilterNearest) id, err := ebiten.NewTextureID(img, ebiten.FilterNearest)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -77,7 +77,7 @@ func (t *Textures) loopMain() {
name := s.name name := s.name
size := s.size size := s.size
go func() { go func() {
id, err := graphics.NewRenderTargetID(size.Width, size.Height, graphics.FilterNearest) id, err := ebiten.NewRenderTargetID(size.Width, size.Height, ebiten.FilterNearest)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -107,13 +107,13 @@ func (t *Textures) Has(name string) bool {
return ok return ok
} }
func (t *Textures) GetTexture(name string) graphics.TextureID { func (t *Textures) GetTexture(name string) ebiten.TextureID {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.textures[name] return t.textures[name]
} }
func (t *Textures) GetRenderTarget(name string) graphics.RenderTargetID { func (t *Textures) GetRenderTarget(name string) ebiten.RenderTargetID {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.renderTargets[name] return t.renderTargets[name]

View File

@ -1,9 +1,7 @@
package blocks package blocks
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"github.com/hajimehoshi/ebiten/input"
"image/color" "image/color"
) )
@ -21,12 +19,12 @@ func NewTitleScene() *TitleScene {
func (s *TitleScene) Update(state *GameState) { func (s *TitleScene) Update(state *GameState) {
s.count++ s.count++
if state.Input.StateForKey(input.KeySpace) == 1 { if state.Input.StateForKey(ebiten.KeySpace) == 1 {
state.SceneManager.GoTo(NewGameScene()) state.SceneManager.GoTo(NewGameScene())
} }
} }
func (s *TitleScene) Draw(context graphics.Context, textures *Textures) { func (s *TitleScene) Draw(context ebiten.GraphicsContext, textures *Textures) {
drawTitleBackground(context, textures, s.count) drawTitleBackground(context, textures, s.count)
drawLogo(context, textures, "BLOCKS") drawLogo(context, textures, "BLOCKS")
@ -36,31 +34,31 @@ func (s *TitleScene) Draw(context graphics.Context, textures *Textures) {
drawTextWithShadow(context, textures, message, x, y, 1, color.RGBA{0x80, 0, 0, 0xff}) drawTextWithShadow(context, textures, message, x, y, 1, color.RGBA{0x80, 0, 0, 0xff})
} }
func drawTitleBackground(context graphics.Context, textures *Textures, c int) { func drawTitleBackground(context ebiten.GraphicsContext, textures *Textures, c int) {
const textureWidth = 32 const textureWidth = 32
const textureHeight = 32 const textureHeight = 32
backgroundTextureId := textures.GetTexture("background") backgroundTextureId := textures.GetTexture("background")
parts := []graphics.TexturePart{} parts := []ebiten.TexturePart{}
for j := -1; j < ScreenHeight/textureHeight+1; j++ { for j := -1; j < ScreenHeight/textureHeight+1; j++ {
for i := 0; i < ScreenWidth/textureWidth+1; i++ { for i := 0; i < ScreenWidth/textureWidth+1; i++ {
parts = append(parts, graphics.TexturePart{ parts = append(parts, ebiten.TexturePart{
LocationX: i * textureWidth, LocationX: i * textureWidth,
LocationY: j * textureHeight, LocationY: j * textureHeight,
Source: graphics.Rect{0, 0, textureWidth, textureHeight}, Source: ebiten.Rect{0, 0, textureWidth, textureHeight},
}) })
} }
} }
dx := (-c / 4) % textureWidth dx := (-c / 4) % textureWidth
dy := (c / 4) % textureHeight dy := (c / 4) % textureHeight
geo := matrix.GeometryI() geo := ebiten.GeometryMatrixI()
geo.Translate(float64(dx), float64(dy)) geo.Translate(float64(dx), float64(dy))
clr := matrix.ColorI() clr := ebiten.ColorMatrixI()
context.Texture(backgroundTextureId).Draw(parts, geo, clr) context.Texture(backgroundTextureId).Draw(parts, geo, clr)
} }
func drawLogo(context graphics.Context, textures *Textures, str string) { func drawLogo(context ebiten.GraphicsContext, textures *Textures, str string) {
scale := 4 scale := 4
textWidth := textWidth(str) * scale textWidth := textWidth(str) * scale
x := (ScreenWidth - textWidth) / 2 x := (ScreenWidth - textWidth) / 2

67
geometrymatrix.go Normal file
View File

@ -0,0 +1,67 @@
package ebiten
import (
"math"
)
const GeometryDim = 3
type GeometryMatrix struct {
Elements [GeometryDim - 1][GeometryDim]float64
}
func GeometryMatrixI() GeometryMatrix {
return GeometryMatrix{
[GeometryDim - 1][GeometryDim]float64{
{1, 0, 0},
{0, 1, 0},
},
}
}
func (g *GeometryMatrix) dim() int {
return GeometryDim
}
func (g *GeometryMatrix) Concat(other GeometryMatrix) {
result := GeometryMatrix{}
mul(&other, g, &result)
*g = result
}
func (g *GeometryMatrix) IsIdentity() bool {
return isIdentity(g)
}
func (g *GeometryMatrix) element(i, j int) float64 {
return g.Elements[i][j]
}
func (g *GeometryMatrix) setElement(i, j int, element float64) {
g.Elements[i][j] = element
}
func (g *GeometryMatrix) Translate(tx, ty float64) {
g.Elements[0][2] += tx
g.Elements[1][2] += ty
}
func (g *GeometryMatrix) Scale(x, y float64) {
g.Elements[0][0] *= x
g.Elements[0][1] *= x
g.Elements[0][2] *= x
g.Elements[1][0] *= y
g.Elements[1][1] *= y
g.Elements[1][2] *= y
}
func (g *GeometryMatrix) Rotate(theta float64) {
sin, cos := math.Sincos(theta)
rotate := GeometryMatrix{
[2][3]float64{
{cos, -sin, 0},
{sin, cos, 0},
},
}
g.Concat(rotate)
}

View File

@ -1,4 +1,4 @@
package matrix_test package ebiten_test
import ( import (
. "." . "."
@ -6,8 +6,8 @@ import (
) )
func TestGeometryIdentity(t *testing.T) { func TestGeometryIdentity(t *testing.T) {
matrix := GeometryI() ebiten := GeometryMatrixI()
got := matrix.IsIdentity() got := ebiten.IsIdentity()
want := true want := true
if want != got { if want != got {
t.Errorf("matrix.IsIdentity() = %t, want %t", got, want) t.Errorf("matrix.IsIdentity() = %t, want %t", got, want)
@ -15,8 +15,8 @@ func TestGeometryIdentity(t *testing.T) {
} }
func TestGeometryConcat(t *testing.T) { func TestGeometryConcat(t *testing.T) {
matrix1 := Geometry{} matrix1 := GeometryMatrix{}
matrix2 := Geometry{} matrix2 := GeometryMatrix{}
matrix1.Elements = [2][3]float64{ matrix1.Elements = [2][3]float64{
{2, 0, 0}, {2, 0, 0},
{0, 2, 0}, {0, 2, 0},

View File

@ -2,23 +2,22 @@ package glfw
import ( import (
glfw "github.com/go-gl/glfw3" glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/opengl" "github.com/hajimehoshi/ebiten/opengl"
"github.com/hajimehoshi/ebiten/ui"
"image" "image"
"runtime" "runtime"
) )
type canvas struct { type canvas struct {
window *glfw.Window window *glfw.Window
context *opengl.Context context *opengl.GraphicsContext
keyboard keyboard keyboard keyboard
mouse mouse mouse mouse
funcs chan func() funcs chan func()
funcsDone chan struct{} funcsDone chan struct{}
} }
func (c *canvas) Draw(d ui.Drawer) (err error) { func (c *canvas) Draw(d ebiten.Drawer2) (err error) {
c.use(func() { c.use(func() {
c.context.PreUpdate() c.context.PreUpdate()
}) })
@ -36,8 +35,8 @@ func (c *canvas) IsClosed() bool {
return c.window.ShouldClose() return c.window.ShouldClose()
} }
func (c *canvas) NewTextureID(img image.Image, filter graphics.Filter) (graphics.TextureID, error) { func (c *canvas) NewTextureID(img image.Image, filter ebiten.Filter) (ebiten.TextureID, error) {
var id graphics.TextureID var id ebiten.TextureID
var err error var err error
c.use(func() { c.use(func() {
id, err = opengl.NewTextureID(img, filter) id, err = opengl.NewTextureID(img, filter)
@ -45,8 +44,8 @@ func (c *canvas) NewTextureID(img image.Image, filter graphics.Filter) (graphics
return id, err return id, err
} }
func (c *canvas) NewRenderTargetID(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) { func (c *canvas) NewRenderTargetID(width, height int, filter ebiten.Filter) (ebiten.RenderTargetID, error) {
var id graphics.RenderTargetID var id ebiten.RenderTargetID
var err error var err error
c.use(func() { c.use(func() {
id, err = opengl.NewRenderTargetID(width, height, filter) id, err = opengl.NewRenderTargetID(width, height, filter)

View File

@ -1,15 +1,14 @@
package glfw package glfw
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
) )
type context struct { type context struct {
canvas *canvas canvas *canvas
} }
var _ graphics.Context = new(context) var _ ebiten.GraphicsContext = new(context)
func (c *context) Clear() { func (c *context) Clear() {
c.canvas.use(func() { c.canvas.use(func() {
@ -23,7 +22,7 @@ func (c *context) Fill(r, g, b uint8) {
}) })
} }
func (c *context) Texture(id graphics.TextureID) (d graphics.Drawer) { func (c *context) Texture(id ebiten.TextureID) (d ebiten.Drawer) {
c.canvas.use(func() { c.canvas.use(func() {
d = &drawer{ d = &drawer{
canvas: c.canvas, canvas: c.canvas,
@ -33,7 +32,7 @@ func (c *context) Texture(id graphics.TextureID) (d graphics.Drawer) {
return return
} }
func (c *context) RenderTarget(id graphics.RenderTargetID) (d graphics.Drawer) { func (c *context) RenderTarget(id ebiten.RenderTargetID) (d ebiten.Drawer) {
c.canvas.use(func() { c.canvas.use(func() {
d = &drawer{ d = &drawer{
canvas: c.canvas, canvas: c.canvas,
@ -49,7 +48,7 @@ func (c *context) ResetOffscreen() {
}) })
} }
func (c *context) SetOffscreen(id graphics.RenderTargetID) { func (c *context) SetOffscreen(id ebiten.RenderTargetID) {
c.canvas.use(func() { c.canvas.use(func() {
c.canvas.context.SetOffscreen(id) c.canvas.context.SetOffscreen(id)
}) })
@ -57,12 +56,12 @@ func (c *context) SetOffscreen(id graphics.RenderTargetID) {
type drawer struct { type drawer struct {
canvas *canvas canvas *canvas
innerDrawer graphics.Drawer innerDrawer ebiten.Drawer
} }
var _ graphics.Drawer = new(drawer) var _ ebiten.Drawer = new(drawer)
func (d *drawer) Draw(parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) { func (d *drawer) Draw(parts []ebiten.TexturePart, geo ebiten.GeometryMatrix, color ebiten.ColorMatrix) {
d.canvas.use(func() { d.canvas.use(func() {
d.innerDrawer.Draw(parts, geo, color) d.innerDrawer.Draw(parts, geo, color)
}) })

28
glfw/keyboard.go Normal file
View File

@ -0,0 +1,28 @@
package glfw
import (
glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten"
)
type keyboard struct {
keyPressed [ebiten.KeyMax]bool
}
func (k *keyboard) IsKeyPressed(key ebiten.Key) bool {
return k.keyPressed[key]
}
var glfwKeyCodeToKey = map[glfw.Key]ebiten.Key{
glfw.KeySpace: ebiten.KeySpace,
glfw.KeyLeft: ebiten.KeyLeft,
glfw.KeyRight: ebiten.KeyRight,
glfw.KeyUp: ebiten.KeyUp,
glfw.KeyDown: ebiten.KeyDown,
}
func (k *keyboard) update(window *glfw.Window) {
for g, u := range glfwKeyCodeToKey {
k.keyPressed[u] = window.GetKey(g) == glfw.Press
}
}

View File

@ -2,21 +2,21 @@ package glfw
import ( import (
glfw "github.com/go-gl/glfw3" glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/input" "github.com/hajimehoshi/ebiten"
"math" "math"
) )
type mouse struct { type mouse struct {
buttonPressed [input.MouseButtonMax]bool buttonPressed [ebiten.MouseButtonMax]bool
x int x int
y int y int
} }
func (m *mouse) CurrentPosition() (x, y int) { func (m *mouse) CursorPosition() (x, y int) {
return m.x, m.y return m.x, m.y
} }
func (m *mouse) IsMouseButtonPressed(button input.MouseButton) bool { func (m *mouse) IsMouseButtonPressed(button ebiten.MouseButton) bool {
return m.buttonPressed[button] return m.buttonPressed[button]
} }
@ -24,7 +24,7 @@ func (m *mouse) update(window *glfw.Window) {
x, y := window.GetCursorPosition() x, y := window.GetCursorPosition()
m.x = int(math.Floor(x)) m.x = int(math.Floor(x))
m.y = int(math.Floor(y)) m.y = int(math.Floor(y))
for i := input.MouseButtonLeft; i < input.MouseButtonMax; i++ { for i := ebiten.MouseButtonLeft; i < ebiten.MouseButtonMax; i++ {
m.buttonPressed[i] = window.GetMouseButton(glfw.MouseButton(i)) == glfw.Press m.buttonPressed[i] = window.GetMouseButton(glfw.MouseButton(i)) == glfw.Press
} }
} }

View File

@ -4,10 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
glfw "github.com/go-gl/glfw3" glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/opengl" "github.com/hajimehoshi/ebiten/opengl"
"github.com/hajimehoshi/ebiten/input"
"github.com/hajimehoshi/ebiten/ui"
) )
func init() { func init() {
@ -20,7 +18,7 @@ type UI struct {
canvas *canvas canvas *canvas
} }
func (u *UI) Start(width, height, scale int, title string) (ui.Canvas, error) { func (u *UI) Start(width, height, scale int, title string) (ebiten.Canvas, error) {
if !glfw.Init() { if !glfw.Init() {
return nil, errors.New("glfw.Init() fails") return nil, errors.New("glfw.Init() fails")
} }
@ -35,9 +33,9 @@ func (u *UI) Start(width, height, scale int, title string) (ui.Canvas, error) {
funcs: make(chan func()), funcs: make(chan func()),
funcsDone: make(chan struct{}), funcsDone: make(chan struct{}),
} }
input.SetKeyboard(&c.keyboard) ebiten.SetKeyboard(&c.keyboard)
input.SetMouse(&c.mouse) ebiten.SetMouse(&c.mouse)
graphics.SetTextureFactory(c) ebiten.SetTextureFactory(c)
c.run(width, height, scale) c.run(width, height, scale)

View File

@ -1 +0,0 @@
package matrix_test

View File

@ -1,85 +0,0 @@
package matrix
import (
"image/color"
"math"
)
const ColorDim = 5
type Color struct {
Elements [ColorDim - 1][ColorDim]float64
}
func ColorI() Color {
return Color{
[ColorDim - 1][ColorDim]float64{
{1, 0, 0, 0, 0},
{0, 1, 0, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 0, 1, 0},
},
}
}
func (matrix *Color) dim() int {
return ColorDim
}
func (matrix *Color) Concat(other Color) {
result := Color{}
mul(&other, matrix, &result)
*matrix = result
}
func (matrix *Color) IsIdentity() bool {
return isIdentity(matrix)
}
func (matrix *Color) element(i, j int) float64 {
return matrix.Elements[i][j]
}
func (matrix *Color) setElement(i, j int, element float64) {
matrix.Elements[i][j] = element
}
func Monochrome() Color {
const r float64 = 6968.0 / 32768.0
const g float64 = 23434.0 / 32768.0
const b float64 = 2366.0 / 32768.0
return Color{
[ColorDim - 1][ColorDim]float64{
{r, g, b, 0, 0},
{r, g, b, 0, 0},
{r, g, b, 0, 0},
{0, 0, 0, 1, 0},
},
}
}
func rgba(clr color.Color) (float64, float64, float64, float64) {
r, g, b, a := clr.RGBA()
rf := float64(r) / float64(math.MaxUint16)
gf := float64(g) / float64(math.MaxUint16)
bf := float64(b) / float64(math.MaxUint16)
af := float64(a) / float64(math.MaxUint16)
return rf, gf, bf, af
}
func (matrix *Color) Scale(clr color.Color) {
rf, gf, bf, af := rgba(clr)
for i, e := range []float64{rf, gf, bf, af} {
for j := 0; j < 4; j++ {
matrix.Elements[i][j] *= e
}
}
}
func (matrix *Color) Translate(clr color.Color) {
rf, gf, bf, af := rgba(clr)
matrix.Elements[0][4] = rf
matrix.Elements[1][4] = gf
matrix.Elements[2][4] = bf
matrix.Elements[3][4] = af
}

View File

@ -1,67 +0,0 @@
package matrix
import (
"math"
)
const GeometryDim = 3
type Geometry struct {
Elements [GeometryDim - 1][GeometryDim]float64
}
func GeometryI() Geometry {
return Geometry{
[GeometryDim - 1][GeometryDim]float64{
{1, 0, 0},
{0, 1, 0},
},
}
}
func (matrix *Geometry) dim() int {
return GeometryDim
}
func (matrix *Geometry) Concat(other Geometry) {
result := Geometry{}
mul(&other, matrix, &result)
*matrix = result
}
func (matrix *Geometry) IsIdentity() bool {
return isIdentity(matrix)
}
func (matrix *Geometry) element(i, j int) float64 {
return matrix.Elements[i][j]
}
func (matrix *Geometry) setElement(i, j int, element float64) {
matrix.Elements[i][j] = element
}
func (matrix *Geometry) Translate(tx, ty float64) {
matrix.Elements[0][2] += tx
matrix.Elements[1][2] += ty
}
func (matrix *Geometry) Scale(x, y float64) {
matrix.Elements[0][0] *= x
matrix.Elements[0][1] *= x
matrix.Elements[0][2] *= x
matrix.Elements[1][0] *= y
matrix.Elements[1][1] *= y
matrix.Elements[1][2] *= y
}
func (matrix *Geometry) Rotate(theta float64) {
sin, cos := math.Sincos(theta)
rotate := Geometry{
[2][3]float64{
{cos, -sin, 0},
{sin, cos, 0},
},
}
matrix.Concat(rotate)
}

View File

@ -1,8 +1,4 @@
package graphics package ebiten
import (
"github.com/hajimehoshi/ebiten/graphics/matrix"
)
// A Rect represents a rectangle. // A Rect represents a rectangle.
type Rect struct { type Rect struct {
@ -21,11 +17,11 @@ type TexturePart struct {
// A Drawer is the interface that draws itself. // A Drawer is the interface that draws itself.
type Drawer interface { type Drawer interface {
Draw(parts []TexturePart, geo matrix.Geometry, color matrix.Color) Draw(parts []TexturePart, geo GeometryMatrix, color ColorMatrix)
} }
// DrawWhole draws the whole texture. // DrawWhole draws the whole texture.
func DrawWhole(drawer Drawer, width, height int, geo matrix.Geometry, color matrix.Color) { func DrawWhole(drawer Drawer, width, height int, geo GeometryMatrix, color ColorMatrix) {
parts := []TexturePart{ parts := []TexturePart{
{0, 0, Rect{0, 0, width, height}}, {0, 0, Rect{0, 0, width, height}},
} }
@ -33,7 +29,7 @@ func DrawWhole(drawer Drawer, width, height int, geo matrix.Geometry, color matr
} }
// A Context is the interface that means a context of rendering. // A Context is the interface that means a context of rendering.
type Context interface { type GraphicsContext interface {
Clear() Clear()
Fill(r, g, b uint8) Fill(r, g, b uint8)
Texture(id TextureID) Drawer Texture(id TextureID) Drawer

View File

@ -1,4 +1,4 @@
package input package ebiten
type Key int type Key int

View File

@ -1,4 +1,4 @@
package input package ebiten
type MouseButton int type MouseButton int
@ -12,7 +12,7 @@ const (
var currentMouse Mouse var currentMouse Mouse
type Mouse interface { type Mouse interface {
CurrentPosition() (x, y int) CursorPosition() (x, y int)
IsMouseButtonPressed(mouseButton MouseButton) bool IsMouseButtonPressed(mouseButton MouseButton) bool
} }
@ -20,11 +20,11 @@ func SetMouse(mouse Mouse) {
currentMouse = mouse currentMouse = mouse
} }
func CurrentPosition() (x, y int) { func CursorPosition() (x, y int) {
if currentMouse == nil { if currentMouse == nil {
panic("input.CurrentPosition: currentMouse is not set") panic("input.CurrentPosition: currentMouse is not set")
} }
return currentMouse.CurrentPosition() return currentMouse.CursorPosition()
} }
func IsMouseButtonPressed(button MouseButton) bool { func IsMouseButtonPressed(button MouseButton) bool {

View File

@ -2,16 +2,15 @@ package opengl
import ( import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
) )
func Initialize(screenWidth, screenHeight, screenScale int) (*Context, error) { func Initialize(screenWidth, screenHeight, screenScale int) (*GraphicsContext, error) {
gl.Init() gl.Init()
gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.TEXTURE_2D)
gl.Enable(gl.BLEND) gl.Enable(gl.BLEND)
c := &Context{ c := &GraphicsContext{
screenWidth: screenWidth, screenWidth: screenWidth,
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
@ -25,7 +24,7 @@ func Initialize(screenWidth, screenHeight, screenScale int) (*Context, error) {
}) })
var err error var err error
c.screenId, err = idsInstance.createRenderTarget(screenWidth, screenHeight, graphics.FilterNearest) c.screenId, err = idsInstance.createRenderTarget(screenWidth, screenHeight, ebiten.FilterNearest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -35,66 +34,68 @@ func Initialize(screenWidth, screenHeight, screenScale int) (*Context, error) {
return c, nil return c, nil
} }
type Context struct { type GraphicsContext struct {
screenId graphics.RenderTargetID screenId ebiten.RenderTargetID
defaultId graphics.RenderTargetID defaultId ebiten.RenderTargetID
currentId graphics.RenderTargetID currentId ebiten.RenderTargetID
screenWidth int screenWidth int
screenHeight int screenHeight int
screenScale int screenScale int
} }
func (c *Context) dispose() { var _ ebiten.GraphicsContext = new(GraphicsContext)
func (c *GraphicsContext) dispose() {
// NOTE: Now this method is not used anywhere. // NOTE: Now this method is not used anywhere.
idsInstance.deleteRenderTarget(c.screenId) idsInstance.deleteRenderTarget(c.screenId)
} }
func (c *Context) Clear() { func (c *GraphicsContext) Clear() {
c.Fill(0, 0, 0) c.Fill(0, 0, 0)
} }
func (c *Context) Fill(r, g, b uint8) { func (c *GraphicsContext) Fill(r, g, b uint8) {
idsInstance.fillRenderTarget(c.currentId, r, g, b) idsInstance.fillRenderTarget(c.currentId, r, g, b)
} }
func (c *Context) Texture(id graphics.TextureID) graphics.Drawer { func (c *GraphicsContext) Texture(id ebiten.TextureID) ebiten.Drawer {
return &textureWithContext{id, c} return &textureWithContext{id, c}
} }
func (c *Context) RenderTarget(id graphics.RenderTargetID) graphics.Drawer { func (c *GraphicsContext) RenderTarget(id ebiten.RenderTargetID) ebiten.Drawer {
return &textureWithContext{idsInstance.toTexture(id), c} return &textureWithContext{idsInstance.toTexture(id), c}
} }
func (c *Context) ResetOffscreen() { func (c *GraphicsContext) ResetOffscreen() {
c.currentId = c.screenId c.currentId = c.screenId
} }
func (c *Context) SetOffscreen(renderTargetId graphics.RenderTargetID) { func (c *GraphicsContext) SetOffscreen(renderTargetId ebiten.RenderTargetID) {
c.currentId = renderTargetId c.currentId = renderTargetId
} }
func (c *Context) PreUpdate() { func (c *GraphicsContext) PreUpdate() {
c.ResetOffscreen() c.ResetOffscreen()
c.Clear() c.Clear()
} }
func (c *Context) PostUpdate() { func (c *GraphicsContext) PostUpdate() {
c.SetOffscreen(c.defaultId) c.SetOffscreen(c.defaultId)
c.Clear() c.Clear()
scale := float64(c.screenScale) scale := float64(c.screenScale)
geo := matrix.GeometryI() geo := ebiten.GeometryMatrixI()
geo.Scale(scale, scale) geo.Scale(scale, scale)
graphics.DrawWhole(c.RenderTarget(c.screenId), c.screenWidth, c.screenHeight, geo, matrix.ColorI()) ebiten.DrawWhole(c.RenderTarget(c.screenId), c.screenWidth, c.screenHeight, geo, ebiten.ColorMatrixI())
gl.Flush() gl.Flush()
} }
type textureWithContext struct { type textureWithContext struct {
id graphics.TextureID id ebiten.TextureID
context *Context context *GraphicsContext
} }
func (t *textureWithContext) Draw(parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) { func (t *textureWithContext) Draw(parts []ebiten.TexturePart, geo ebiten.GeometryMatrix, color ebiten.ColorMatrix) {
idsInstance.drawTexture(t.context.currentId, t.id, parts, geo, color) idsInstance.drawTexture(t.context.currentId, t.id, parts, geo, color)
} }

View File

@ -2,57 +2,56 @@ package opengl
import ( import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix" "github.com/hajimehoshi/ebiten/opengl/internal/shader"
"github.com/hajimehoshi/ebiten/graphics/opengl/internal/shader"
"image" "image"
"math" "math"
"sync" "sync"
) )
type ids struct { type ids struct {
textures map[graphics.TextureID]*texture textures map[ebiten.TextureID]*texture
renderTargets map[graphics.RenderTargetID]*renderTarget renderTargets map[ebiten.RenderTargetID]*renderTarget
renderTargetToTexture map[graphics.RenderTargetID]graphics.TextureID renderTargetToTexture map[ebiten.RenderTargetID]ebiten.TextureID
lastId int lastId int
currentRenderTargetId graphics.RenderTargetID currentRenderTargetId ebiten.RenderTargetID
sync.RWMutex sync.RWMutex
} }
var idsInstance = &ids{ var idsInstance = &ids{
textures: map[graphics.TextureID]*texture{}, textures: map[ebiten.TextureID]*texture{},
renderTargets: map[graphics.RenderTargetID]*renderTarget{}, renderTargets: map[ebiten.RenderTargetID]*renderTarget{},
renderTargetToTexture: map[graphics.RenderTargetID]graphics.TextureID{}, renderTargetToTexture: map[ebiten.RenderTargetID]ebiten.TextureID{},
currentRenderTargetId: -1, currentRenderTargetId: -1,
} }
func NewRenderTargetID(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) { func NewRenderTargetID(width, height int, filter ebiten.Filter) (ebiten.RenderTargetID, error) {
return idsInstance.createRenderTarget(width, height, filter) return idsInstance.createRenderTarget(width, height, filter)
} }
func NewTextureID(img image.Image, filter graphics.Filter) (graphics.TextureID, error) { func NewTextureID(img image.Image, filter ebiten.Filter) (ebiten.TextureID, error) {
return idsInstance.createTexture(img, filter) return idsInstance.createTexture(img, filter)
} }
func (i *ids) textureAt(id graphics.TextureID) *texture { func (i *ids) textureAt(id ebiten.TextureID) *texture {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.textures[id] return i.textures[id]
} }
func (i *ids) renderTargetAt(id graphics.RenderTargetID) *renderTarget { func (i *ids) renderTargetAt(id ebiten.RenderTargetID) *renderTarget {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.renderTargets[id] return i.renderTargets[id]
} }
func (i *ids) toTexture(id graphics.RenderTargetID) graphics.TextureID { func (i *ids) toTexture(id ebiten.RenderTargetID) ebiten.TextureID {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.renderTargetToTexture[id] return i.renderTargetToTexture[id]
} }
func (i *ids) createTexture(img image.Image, filter graphics.Filter) (graphics.TextureID, error) { func (i *ids) createTexture(img image.Image, filter ebiten.Filter) (ebiten.TextureID, error) {
texture, err := createTextureFromImage(img, filter) texture, err := createTextureFromImage(img, filter)
if err != nil { if err != nil {
return 0, err return 0, err
@ -61,12 +60,12 @@ func (i *ids) createTexture(img image.Image, filter graphics.Filter) (graphics.T
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
i.lastId++ i.lastId++
textureId := graphics.TextureID(i.lastId) textureId := ebiten.TextureID(i.lastId)
i.textures[textureId] = texture i.textures[textureId] = texture
return textureId, nil return textureId, nil
} }
func (i *ids) createRenderTarget(width, height int, filter graphics.Filter) (graphics.RenderTargetID, error) { func (i *ids) createRenderTarget(width, height int, filter ebiten.Filter) (ebiten.RenderTargetID, error) {
texture, err := createTexture(width, height, filter) texture, err := createTexture(width, height, filter)
if err != nil { if err != nil {
return 0, err return 0, err
@ -83,9 +82,9 @@ func (i *ids) createRenderTarget(width, height int, filter graphics.Filter) (gra
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
i.lastId++ i.lastId++
textureId := graphics.TextureID(i.lastId) textureId := ebiten.TextureID(i.lastId)
i.lastId++ i.lastId++
renderTargetId := graphics.RenderTargetID(i.lastId) renderTargetId := ebiten.RenderTargetID(i.lastId)
i.textures[textureId] = texture i.textures[textureId] = texture
i.renderTargets[renderTargetId] = r i.renderTargets[renderTargetId] = r
@ -95,17 +94,17 @@ func (i *ids) createRenderTarget(width, height int, filter graphics.Filter) (gra
} }
// NOTE: renderTarget can't be used as a texture. // NOTE: renderTarget can't be used as a texture.
func (i *ids) addRenderTarget(renderTarget *renderTarget) graphics.RenderTargetID { func (i *ids) addRenderTarget(renderTarget *renderTarget) ebiten.RenderTargetID {
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
i.lastId++ i.lastId++
id := graphics.RenderTargetID(i.lastId) id := ebiten.RenderTargetID(i.lastId)
i.renderTargets[id] = renderTarget i.renderTargets[id] = renderTarget
return id return id
} }
func (i *ids) deleteRenderTarget(id graphics.RenderTargetID) { func (i *ids) deleteRenderTarget(id ebiten.RenderTargetID) {
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
@ -121,14 +120,14 @@ func (i *ids) deleteRenderTarget(id graphics.RenderTargetID) {
delete(i.textures, textureId) delete(i.textures, textureId)
} }
func (i *ids) fillRenderTarget(id graphics.RenderTargetID, r, g, b uint8) { func (i *ids) fillRenderTarget(id ebiten.RenderTargetID, r, g, b uint8) {
i.setViewportIfNeeded(id) i.setViewportIfNeeded(id)
const max = float64(math.MaxUint8) const max = float64(math.MaxUint8)
gl.ClearColor(gl.GLclampf(float64(r)/max), gl.GLclampf(float64(g)/max), gl.GLclampf(float64(b)/max), 1) gl.ClearColor(gl.GLclampf(float64(r)/max), gl.GLclampf(float64(g)/max), gl.GLclampf(float64(b)/max), 1)
gl.Clear(gl.COLOR_BUFFER_BIT) gl.Clear(gl.COLOR_BUFFER_BIT)
} }
func (i *ids) drawTexture(target graphics.RenderTargetID, id graphics.TextureID, parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) { func (i *ids) drawTexture(target ebiten.RenderTargetID, id ebiten.TextureID, parts []ebiten.TexturePart, geo ebiten.GeometryMatrix, color ebiten.ColorMatrix) {
texture := i.textureAt(id) texture := i.textureAt(id)
i.setViewportIfNeeded(target) i.setViewportIfNeeded(target)
r := i.renderTargetAt(target) r := i.renderTargetAt(target)
@ -136,7 +135,7 @@ func (i *ids) drawTexture(target graphics.RenderTargetID, id graphics.TextureID,
shader.DrawTexture(texture.native, texture.width, texture.height, projectionMatrix, parts, geo, color) shader.DrawTexture(texture.native, texture.width, texture.height, projectionMatrix, parts, geo, color)
} }
func (i *ids) setViewportIfNeeded(id graphics.RenderTargetID) { func (i *ids) setViewportIfNeeded(id ebiten.RenderTargetID) {
r := i.renderTargetAt(id) r := i.renderTargetAt(id)
if i.currentRenderTargetId != id { if i.currentRenderTargetId != id {
r.setAsViewport() r.setAsViewport()

View File

@ -2,16 +2,15 @@ package shader
import ( import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/matrix"
"sync" "sync"
) )
func glMatrix(matrix [4][4]float64) [16]float32 { func glMatrix(ebiten [4][4]float64) [16]float32 {
result := [16]float32{} result := [16]float32{}
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
result[i+j*4] = float32(matrix[i][j]) result[i+j*4] = float32(ebiten[i][j])
} }
} }
return result return result
@ -19,7 +18,8 @@ func glMatrix(matrix [4][4]float64) [16]float32 {
var once sync.Once var once sync.Once
func DrawTexture(native gl.Texture, width, height int, projectionMatrix [4][4]float64, parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) { // TODO: Use VBO
func DrawTexture(native gl.Texture, width, height int, projectionMatrix [4][4]float64, parts []ebiten.TexturePart, geo ebiten.GeometryMatrix, color ebiten.ColorMatrix) {
once.Do(func() { once.Do(func() {
initialize() initialize()
}) })
@ -51,7 +51,7 @@ func DrawTexture(native gl.Texture, width, height int, projectionMatrix [4][4]fl
vertices := []float32{} vertices := []float32{}
texCoords := []float32{} texCoords := []float32{}
indicies := []uint32{} indicies := []uint32{}
// TODO: Check len(parts) and GL_MAX_ELEMENTS_INDICES // TODO: Check len(parts) and gl.MAX_ELEMENTS_INDICES?
for i, quad := range quads { for i, quad := range quads {
x1 := quad.VertexX1 x1 := quad.VertexX1
x2 := quad.VertexX2 x2 := quad.VertexX2

View File

@ -2,7 +2,7 @@ package shader
import ( import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics/matrix" "github.com/hajimehoshi/ebiten"
) )
type program struct { type program struct {
@ -65,7 +65,7 @@ func getUniformLocation(program gl.Program, name string) gl.UniformLocation {
return location return location
} }
func use(projectionMatrix [16]float32, geo matrix.Geometry, color matrix.Color) gl.Program { func use(projectionMatrix [16]float32, geo ebiten.GeometryMatrix, color ebiten.ColorMatrix) gl.Program {
// TODO: Check the performance. // TODO: Check the performance.
program := programColorMatrix program := programColorMatrix

View File

@ -1,7 +1,7 @@
package shader package shader
import ( import (
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
) )
type textureQuad struct { type textureQuad struct {
@ -38,7 +38,7 @@ func v(y int, height int) float32 {
return float32(y) / float32(AdjustSizeForTexture(height)) return float32(y) / float32(AdjustSizeForTexture(height))
} }
func textureQuads(parts []graphics.TexturePart, width, height int) []textureQuad { func textureQuads(parts []ebiten.TexturePart, width, height int) []textureQuad {
quads := []textureQuad{} quads := []textureQuad{}
for _, part := range parts { for _, part := range parts {
x1 := float32(part.LocationX) x1 := float32(part.LocationX)

View File

@ -3,7 +3,7 @@ package opengl
import ( import (
"fmt" "fmt"
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics/opengl/internal/shader" "github.com/hajimehoshi/ebiten/opengl/internal/shader"
) )
func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 { func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
@ -62,12 +62,12 @@ func (r *renderTarget) setAsViewport() {
func (r *renderTarget) projectionMatrix() [4][4]float64 { func (r *renderTarget) projectionMatrix() [4][4]float64 {
width := shader.AdjustSizeForTexture(r.width) width := shader.AdjustSizeForTexture(r.width)
height := shader.AdjustSizeForTexture(r.height) height := shader.AdjustSizeForTexture(r.height)
matrix := orthoProjectionMatrix(0, width, 0, height) ebiten := orthoProjectionMatrix(0, width, 0, height)
if r.flipY { if r.flipY {
matrix[1][1] *= -1 ebiten[1][1] *= -1
matrix[1][3] += float64(r.height) / float64(shader.AdjustSizeForTexture(r.height)) * 2 ebiten[1][3] += float64(r.height) / float64(shader.AdjustSizeForTexture(r.height)) * 2
} }
return matrix return ebiten
} }
func (r *renderTarget) dispose() { func (r *renderTarget) dispose() {

View File

@ -2,8 +2,8 @@ package opengl
import ( import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/graphics/opengl/internal/shader" "github.com/hajimehoshi/ebiten/opengl/internal/shader"
"image" "image"
"image/draw" "image/draw"
) )
@ -36,7 +36,7 @@ type texture struct {
height int height int
} }
func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter graphics.Filter) gl.Texture { func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter ebiten.Filter) gl.Texture {
nativeTexture := gl.GenTexture() nativeTexture := gl.GenTexture()
if nativeTexture < 0 { if nativeTexture < 0 {
panic("glGenTexture failed") panic("glGenTexture failed")
@ -47,9 +47,9 @@ func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter
glFilter := 0 glFilter := 0
switch filter { switch filter {
case graphics.FilterLinear: case ebiten.FilterLinear:
glFilter = gl.LINEAR glFilter = gl.LINEAR
case graphics.FilterNearest: case ebiten.FilterNearest:
glFilter = gl.NEAREST glFilter = gl.NEAREST
default: default:
panic("not reached") panic("not reached")
@ -62,14 +62,14 @@ func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, filter
return nativeTexture return nativeTexture
} }
func createTexture(width, height int, filter graphics.Filter) (*texture, error) { func createTexture(width, height int, filter ebiten.Filter) (*texture, error) {
w := shader.AdjustSizeForTexture(width) w := shader.AdjustSizeForTexture(width)
h := shader.AdjustSizeForTexture(height) h := shader.AdjustSizeForTexture(height)
native := createNativeTexture(w, h, nil, filter) native := createNativeTexture(w, h, nil, filter)
return &texture{native, width, height}, nil return &texture{native, width, height}, nil
} }
func createTextureFromImage(img image.Image, filter graphics.Filter) (*texture, error) { func createTextureFromImage(img image.Image, filter ebiten.Filter) (*texture, error) {
adjustedImage := adjustImageForTexture(img) adjustedImage := adjustImageForTexture(img)
size := adjustedImage.Bounds().Size() size := adjustedImage.Bounds().Size()
native := createNativeTexture(size.X, size.Y, adjustedImage.Pix, filter) native := createNativeTexture(size.X, size.Y, adjustedImage.Pix, filter)

View File

@ -1,7 +1,6 @@
package ui package ebiten
import ( import (
"github.com/hajimehoshi/ebiten/graphics"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
@ -10,7 +9,7 @@ import (
type Game interface { type Game interface {
Update() error Update() error
Draw(context graphics.Context) error Draw(context GraphicsContext) error
} }
func Run(u UI, game Game, width, height, scale int, title string, fps int) error { func Run(u UI, game Game, width, height, scale int, title string, fps int) error {

View File

@ -1,4 +1,4 @@
package graphics package ebiten
import ( import (
"image" "image"

View File

@ -1,8 +1,4 @@
package ui package ebiten
import (
"github.com/hajimehoshi/ebiten/graphics"
)
type UI interface { type UI interface {
Start(widht, height, scale int, title string) (Canvas, error) Start(widht, height, scale int, title string) (Canvas, error)
@ -10,11 +6,12 @@ type UI interface {
Terminate() Terminate()
} }
type Drawer interface { // FIXME: rename this
Draw(c graphics.Context) error type Drawer2 interface {
Draw(c GraphicsContext) error
} }
type Canvas interface { type Canvas interface {
Draw(drawer Drawer) error Draw(drawer Drawer2) error
IsClosed() bool IsClosed() bool
} }

View File

@ -1,28 +0,0 @@
package glfw
import (
glfw "github.com/go-gl/glfw3"
"github.com/hajimehoshi/ebiten/input"
)
type keyboard struct {
keyPressed [input.KeyMax]bool
}
func (k *keyboard) IsKeyPressed(key input.Key) bool {
return k.keyPressed[key]
}
var glfwKeyCodeToKey = map[glfw.Key]input.Key{
glfw.KeySpace: input.KeySpace,
glfw.KeyLeft: input.KeyLeft,
glfw.KeyRight: input.KeyRight,
glfw.KeyUp: input.KeyUp,
glfw.KeyDown: input.KeyDown,
}
func (k *keyboard) update(window *glfw.Window) {
for g, u := range glfwKeyCodeToKey {
k.keyPressed[u] = window.GetKey(g) == glfw.Press
}
}