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 (
"image/color"
"strconv"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/examples/common"
)
type Board struct {
@ -42,6 +40,15 @@ func (b *Board) tileAt(x, y int) *Tile {
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 {
moved := false
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) {
x := b.size*tileSize + (b.size+1)*tileMargin
y := x
@ -101,11 +93,7 @@ func (b *Board) Draw(screen *ebiten.Image) error {
}
for j := 0; j < b.size; j++ {
for i := 0; i < b.size; i++ {
t := b.tileAt(i, j)
v := 0
if t != nil {
v = t.value
}
op := &ebiten.DrawImageOptions{}
x := i*tileSize + (i+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 {
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

View File

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

View File

@ -16,35 +16,47 @@ package twenty48
import (
"errors"
"image/color"
"math/rand"
"sort"
"strconv"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/examples/common"
)
type Tile struct {
type TileData struct {
value int
x int
y int
}
type Tile struct {
current TileData
next TileData
}
func NewTile(value int, x, y int) *Tile {
return &Tile{
value: value,
x: x,
y: y,
current: TileData{
value: value,
x: x,
y: y,
},
}
}
func (t *Tile) Value() int {
return t.value
return t.current.value
}
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 {
for t := range tiles {
if t.x == x && t.y == y {
if t.current.x == x && t.current.y == y {
return t
}
}
@ -90,7 +102,7 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) (map[*Tile]struct{},
moved = true
continue
}
if t.value != tt.value {
if t.current.value != tt.current.value {
break
}
if !merged[tt] {
@ -101,12 +113,12 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) (map[*Tile]struct{},
break
}
if tt := tileAt(tiles, ii, jj); tt != t && tt != nil {
t.value += tt.value
t.current.value += tt.current.value
merged[t] = true
delete(nextTiles, tt)
}
t.x = ii
t.y = jj
t.current.x = ii
t.current.y = jj
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 {
cells := make([]bool, size*size)
for t := range tiles {
i := t.x + t.y*size
i := t.current.x + t.current.y*size
cells[i] = true
}
availableCells := []int{}
@ -140,3 +152,43 @@ func addRandomTile(tiles map[*Tile]struct{}, size int) error {
tiles[t] = struct{}{}
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
}