example/2048: Pop tiles when appearing

This commit is contained in:
Hajime Hoshi 2016-07-31 20:56:46 +09:00
parent 1df77c196c
commit e5ece83e78

View File

@ -32,10 +32,11 @@ type TileData struct {
} }
type Tile struct { type Tile struct {
current TileData current TileData
next TileData next TileData
moveCount int movingCount int
popCount int startPoppingCount int
poppingCount int
} }
func NewTile(value int, x, y int) *Tile { func NewTile(value int, x, y int) *Tile {
@ -45,6 +46,7 @@ func NewTile(value int, x, y int) *Tile {
x: x, x: x,
y: y, y: y,
}, },
startPoppingCount: maxPoppingCount,
} }
} }
@ -65,11 +67,11 @@ func (t *Tile) NextPos() (int, int) {
} }
func (t *Tile) IsMoving() bool { func (t *Tile) IsMoving() bool {
return 0 < t.moveCount return 0 < t.movingCount
} }
func (t *Tile) isPopping() bool { func (t *Tile) isPopping() bool {
return 0 < t.popCount return 0 < t.poppingCount
} }
func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile { func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile {
@ -89,7 +91,7 @@ func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile {
func nextTileAt(tiles map[*Tile]struct{}, x, y int) *Tile { func nextTileAt(tiles map[*Tile]struct{}, x, y int) *Tile {
var result *Tile var result *Tile
for t := range tiles { for t := range tiles {
if 0 < t.moveCount { if 0 < t.movingCount {
if t.next.x != x || t.next.y != y || t.next.value == 0 { if t.next.x != x || t.next.y != y || t.next.value == 0 {
continue continue
} }
@ -157,7 +159,7 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) bool {
if t.current.value != tt.current.value { if t.current.value != tt.current.value {
break break
} }
if 0 < tt.moveCount && tt.current.value != tt.next.value { if 0 < tt.movingCount && tt.current.value != tt.next.value {
// already merged // already merged
break break
} }
@ -173,20 +175,20 @@ func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) bool {
tt.next.value = 0 tt.next.value = 0
tt.next.x = ii tt.next.x = ii
tt.next.y = jj tt.next.y = jj
tt.moveCount = maxMovingCount tt.movingCount = maxMovingCount
} }
next.x = ii next.x = ii
next.y = jj next.y = jj
if t.current != next { if t.current != next {
t.next = next t.next = next
t.moveCount = maxMovingCount t.movingCount = maxMovingCount
} }
} }
} }
if !moved { if !moved {
for t := range tiles { for t := range tiles {
t.next = TileData{} t.next = TileData{}
t.moveCount = 0 t.movingCount = 0
} }
} }
return moved return moved
@ -225,17 +227,19 @@ func addRandomTile(tiles map[*Tile]struct{}, size int) error {
func (t *Tile) Update() error { func (t *Tile) Update() error {
switch { switch {
case 0 < t.moveCount: case 0 < t.movingCount:
t.moveCount-- t.movingCount--
if t.moveCount == 0 { if t.movingCount == 0 {
if t.current.value != t.next.value && 0 < t.next.value { if t.current.value != t.next.value && 0 < t.next.value {
t.popCount = maxPoppingCount t.poppingCount = maxPoppingCount
} }
t.current = t.next t.current = t.next
t.next = TileData{} t.next = TileData{}
} }
case 0 < t.popCount: case 0 < t.startPoppingCount:
t.popCount-- t.startPoppingCount--
case 0 < t.poppingCount:
t.poppingCount--
} }
return nil return nil
} }
@ -295,20 +299,26 @@ func (t *Tile) Draw(boardImage *ebiten.Image) error {
y := j*tileSize + (j+1)*tileMargin y := j*tileSize + (j+1)*tileMargin
nx := ni*tileSize + (ni+1)*tileMargin nx := ni*tileSize + (ni+1)*tileMargin
ny := nj*tileSize + (nj+1)*tileMargin ny := nj*tileSize + (nj+1)*tileMargin
if 0 < t.moveCount { switch {
rate := 1 - float64(t.moveCount)/maxMovingCount case 0 < t.movingCount:
rate := 1 - float64(t.movingCount)/maxMovingCount
x = mean(x, nx, rate) x = mean(x, nx, rate)
y = mean(y, ny, rate) y = mean(y, ny, rate)
} case 0 < t.startPoppingCount:
if 0 < t.popCount { rate := 1 - float64(t.startPoppingCount)/float64(maxPoppingCount)
scale := meanF(0.0, 1.0, rate)
op.GeoM.Translate(float64(-tileSize/2), float64(-tileSize/2))
op.GeoM.Scale(scale, scale)
op.GeoM.Translate(float64(tileSize/2), float64(tileSize/2))
case 0 < t.poppingCount:
const maxScale = 1.2 const maxScale = 1.2
rate := 0.0 rate := 0.0
if maxPoppingCount*2/3 <= t.popCount { if maxPoppingCount*2/3 <= t.poppingCount {
// 0 to 1 // 0 to 1
rate = 1 - float64(t.popCount-2*maxPoppingCount/3)/float64(maxPoppingCount/3) rate = 1 - float64(t.poppingCount-2*maxPoppingCount/3)/float64(maxPoppingCount/3)
} else { } else {
// 1 to 0 // 1 to 0
rate = float64(t.popCount) / float64(maxPoppingCount*2/3) rate = float64(t.poppingCount) / float64(maxPoppingCount*2/3)
} }
scale := meanF(1.0, maxScale, rate) scale := meanF(1.0, maxScale, rate)
op.GeoM.Translate(float64(-tileSize/2), float64(-tileSize/2)) op.GeoM.Translate(float64(-tileSize/2), float64(-tileSize/2))