examples/2048: Add Tile.Draw

This commit is contained in:
Hajime Hoshi 2016-07-30 17:54:05 +09:00
parent ba8138f69b
commit 3ce0572a81
3 changed files with 80 additions and 49 deletions

View File

@ -16,10 +16,8 @@ package twenty48
import ( import (
"image/color" "image/color"
"strconv"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/examples/common"
) )
type Board struct { type Board struct {
@ -42,6 +40,15 @@ func (b *Board) tileAt(x, y int) *Tile {
return tileAt(b.tiles, x, y) return tileAt(b.tiles, x, y)
} }
func (b *Board) Update(input *Input) error {
if dir, ok := input.Dir(); ok {
if err := b.Move(dir); err != nil {
return err
}
}
return nil
}
func (b *Board) Move(dir Dir) error { func (b *Board) Move(dir Dir) error {
moved := false moved := false
b.tiles, moved = MoveTiles(b.tiles, b.size, dir) b.tiles, moved = MoveTiles(b.tiles, b.size, dir)
@ -74,21 +81,6 @@ func init() {
} }
} }
func colorToScale(clr color.Color) (float64, float64, float64, float64) {
r, g, b, a := clr.RGBA()
rf := float64(r) / 0xffff
gf := float64(g) / 0xffff
bf := float64(b) / 0xffff
af := float64(a) / 0xffff
// Convert to non-premultiplied alpha components.
if 0 < af {
rf /= af
gf /= af
bf /= af
}
return rf, gf, bf, af
}
func (b *Board) Size() (int, int) { func (b *Board) Size() (int, int) {
x := b.size*tileSize + (b.size+1)*tileMargin x := b.size*tileSize + (b.size+1)*tileMargin
y := x y := x
@ -101,11 +93,7 @@ func (b *Board) Draw(screen *ebiten.Image) error {
} }
for j := 0; j < b.size; j++ { for j := 0; j < b.size; j++ {
for i := 0; i < b.size; i++ { for i := 0; i < b.size; i++ {
t := b.tileAt(i, j)
v := 0 v := 0
if t != nil {
v = t.value
}
op := &ebiten.DrawImageOptions{} op := &ebiten.DrawImageOptions{}
x := i*tileSize + (i+1)*tileMargin x := i*tileSize + (i+1)*tileMargin
y := j*tileSize + (j+1)*tileMargin y := j*tileSize + (j+1)*tileMargin
@ -115,18 +103,11 @@ func (b *Board) Draw(screen *ebiten.Image) error {
if err := screen.DrawImage(tileImage, op); err != nil { if err := screen.DrawImage(tileImage, op); err != nil {
return err return err
} }
if t != nil {
str := strconv.Itoa(t.value)
scale := 2
if 2 < len(str) {
scale = 1
} }
w := common.ArcadeFont.TextWidth(str) * scale
h := common.ArcadeFont.TextHeight(str) * scale
x := x + (tileSize-w)/2
y := y + (tileSize-h)/2
common.ArcadeFont.DrawText(screen, str, x, y, scale, tileColor(t.value))
} }
for t := range b.tiles {
if err := t.Draw(screen); err != nil {
return err
} }
} }
return nil return nil

View File

@ -48,11 +48,9 @@ func (g *Game) Update() error {
if err := g.input.Update(); err != nil { if err := g.input.Update(); err != nil {
return err return err
} }
if dir, ok := g.input.Dir(); ok { if err := g.board.Update(g.input); err != nil {
if err := g.board.Move(dir); err != nil {
return err return err
} }
}
return nil return nil
} }

View File

@ -16,35 +16,47 @@ package twenty48
import ( import (
"errors" "errors"
"image/color"
"math/rand" "math/rand"
"sort" "sort"
"strconv"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/examples/common"
) )
type Tile struct { type TileData struct {
value int value int
x int x int
y int y int
} }
type Tile struct {
current TileData
next TileData
}
func NewTile(value int, x, y int) *Tile { func NewTile(value int, x, y int) *Tile {
return &Tile{ return &Tile{
current: TileData{
value: value, value: value,
x: x, x: x,
y: y, y: y,
},
} }
} }
func (t *Tile) Value() int { func (t *Tile) Value() int {
return t.value return t.current.value
} }
func (t *Tile) Pos() (int, int) { func (t *Tile) Pos() (int, int) {
return t.x, t.y return t.current.x, t.current.y
} }
func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile { func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile {
for t := range tiles { for t := range tiles {
if t.x == x && t.y == y { if t.current.x == x && t.current.y == y {
return t return t
} }
} }
@ -90,7 +102,7 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) (map[*Tile]struct{},
moved = true moved = true
continue continue
} }
if t.value != tt.value { if t.current.value != tt.current.value {
break break
} }
if !merged[tt] { if !merged[tt] {
@ -101,12 +113,12 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) (map[*Tile]struct{},
break break
} }
if tt := tileAt(tiles, ii, jj); tt != t && tt != nil { if tt := tileAt(tiles, ii, jj); tt != t && tt != nil {
t.value += tt.value t.current.value += tt.current.value
merged[t] = true merged[t] = true
delete(nextTiles, tt) delete(nextTiles, tt)
} }
t.x = ii t.current.x = ii
t.y = jj t.current.y = jj
nextTiles[t] = struct{}{} nextTiles[t] = struct{}{}
} }
} }
@ -116,7 +128,7 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) (map[*Tile]struct{},
func addRandomTile(tiles map[*Tile]struct{}, size int) error { func addRandomTile(tiles map[*Tile]struct{}, size int) error {
cells := make([]bool, size*size) cells := make([]bool, size*size)
for t := range tiles { for t := range tiles {
i := t.x + t.y*size i := t.current.x + t.current.y*size
cells[i] = true cells[i] = true
} }
availableCells := []int{} availableCells := []int{}
@ -140,3 +152,43 @@ func addRandomTile(tiles map[*Tile]struct{}, size int) error {
tiles[t] = struct{}{} tiles[t] = struct{}{}
return nil return nil
} }
func colorToScale(clr color.Color) (float64, float64, float64, float64) {
r, g, b, a := clr.RGBA()
rf := float64(r) / 0xffff
gf := float64(g) / 0xffff
bf := float64(b) / 0xffff
af := float64(a) / 0xffff
// Convert to non-premultiplied alpha components.
if 0 < af {
rf /= af
gf /= af
bf /= af
}
return rf, gf, bf, af
}
func (t *Tile) Draw(boardImage *ebiten.Image) error {
i, j := t.current.x, t.current.y
op := &ebiten.DrawImageOptions{}
x := i*tileSize + (i+1)*tileMargin
y := j*tileSize + (j+1)*tileMargin
v := t.current.value
op.GeoM.Translate(float64(x), float64(y))
r, g, b, a := colorToScale(tileBackgroundColor(v))
op.ColorM.Scale(r, g, b, a)
if err := boardImage.DrawImage(tileImage, op); err != nil {
return err
}
str := strconv.Itoa(v)
scale := 2
if 2 < len(str) {
scale = 1
}
w := common.ArcadeFont.TextWidth(str) * scale
h := common.ArcadeFont.TextHeight(str) * scale
x = x + (tileSize-w)/2
y = y + (tileSize-h)/2
common.ArcadeFont.DrawText(boardImage, str, x, y, scale, tileColor(v))
return nil
}