Move a piece

This commit is contained in:
Hajime Hoshi 2013-12-20 01:08:32 +09:00
parent bc7dd51adf
commit 631b226b5b
3 changed files with 183 additions and 46 deletions

View File

@ -13,11 +13,49 @@ func NewField() *Field {
return &Field{}
}
func (f *Field) IsBlocked(x, y int) bool {
if x < 0 || fieldBlockNumX <= x {
return true
}
if y < 0 {
return false
}
if fieldBlockNumX <= y {
return true
}
return f.blocks[x][y] != BlockTypeNone
}
func (f *Field) collides(piece *Piece, x, y int, angle Angle) bool {
return piece.collides(f, x, y, angle)
}
func (f *Field) MovePieceToLeft(piece *Piece, x, y int, angle Angle) int {
if f.collides(piece, x-1, y, angle) {
return x
}
return x - 1
}
func (f *Field) MovePieceToRight(piece *Piece, x, y int, angle Angle) int {
if f.collides(piece, x+1, y, angle) {
return x
}
return x + 1
}
func (f *Field) RotatePieceRight(piece *Piece, x, y int, angle Angle) Angle {
if f.collides(piece, x, y, angle.RotateRight()) {
return angle
}
return angle.RotateRight()
}
func (f *Field) Draw(context graphics.Context, geo matrix.Geometry) {
blocks := make([][]BlockType, len(f.blocks))
for i, blockLine := range f.blocks {
blocks[i] = make([]BlockType, len(blockLine))
copy(blocks[i], blockLine[:])
for i, blockCol := range f.blocks {
blocks[i] = make([]BlockType, len(blockCol))
copy(blocks[i], blockCol[:])
}
drawBlocks(context, blocks, geo)
}

View File

@ -3,6 +3,7 @@ package blocks
import (
"github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
"github.com/hajimehoshi/go-ebiten/ui"
"image/color"
"math/rand"
"time"
@ -13,10 +14,13 @@ func init() {
}
type GameScene struct {
field *Field
rand *rand.Rand
currentPiece *Piece
nextPiece *Piece
field *Field
rand *rand.Rand
currentPiece *Piece
currentPieceX int
currentPieceY int
currentPieceAngle Angle
nextPiece *Piece
}
func NewGameScene() *GameScene {
@ -32,15 +36,36 @@ const fieldWidth = blockWidth * fieldBlockNumX
const fieldHeight = blockHeight * fieldBlockNumY
func (s *GameScene) choosePiece() *Piece {
// Omit BlockTypeNone.
num := int(BlockTypeMax) - 1
blockType := BlockType(s.rand.Intn(num) + 1)
//num := NormalBlockTypeNum
//blockType := BlockType(s.rand.Intn(num) + 1)
blockType := BlockType1
return Pieces[blockType]
}
func (s *GameScene) Update(state *GameState) {
if s.currentPiece == nil {
s.currentPiece = s.choosePiece()
x, y := s.currentPiece.InitialPosition()
s.currentPieceX = x
s.currentPieceY = y
s.currentPieceAngle = Angle0
}
if state.Input.StateForKey(ui.KeySpace) == 1 {
s.currentPieceAngle = s.field.RotatePieceRight(
s.currentPiece, s.currentPieceX, s.currentPieceY,
s.currentPieceAngle)
}
l := state.Input.StateForKey(ui.KeyLeft)
if l == 1 || (10 <= l && l % 2 == 0) {
s.currentPieceX = s.field.MovePieceToLeft(
s.currentPiece, s.currentPieceX, s.currentPieceY,
s.currentPieceAngle)
}
r := state.Input.StateForKey(ui.KeyRight)
if r == 1 || (10 <= r && r % 2 == 0) {
s.currentPieceX = s.field.MovePieceToRight(
s.currentPiece, s.currentPieceX, s.currentPieceY,
s.currentPieceAngle)
}
}
@ -49,8 +74,8 @@ func (s *GameScene) Draw(context graphics.Context) {
field := drawInfo.textures["empty"]
geoMat := matrix.IdentityGeometry()
geoMat.Scale(float64(fieldWidth) / float64(emptyWidth),
float64(fieldHeight) / float64(emptyHeight))
geoMat.Scale(float64(fieldWidth)/float64(emptyWidth),
float64(fieldHeight)/float64(emptyHeight))
geoMat.Translate(20, 20) // magic number?
colorMat := matrix.IdentityColor()
colorMat.Scale(color.RGBA{0, 0, 0, 0x80})
@ -61,6 +86,7 @@ func (s *GameScene) Draw(context graphics.Context) {
s.field.Draw(context, geoMat)
if s.currentPiece != nil {
s.currentPiece.Draw(context, geoMat)
s.currentPiece.Draw(context, 20, 20,
s.currentPieceX, s.currentPieceY, s.currentPieceAngle)
}
}

View File

@ -9,6 +9,22 @@ func init() {
texturePaths["blocks"] = "images/blocks/blocks.png"
}
type Angle int
const (
Angle0 Angle = iota
Angle90
Angle180
Angle270
)
func (a Angle) RotateRight() Angle {
if a == Angle270 {
return Angle0
}
return a + 1
}
type BlockType int
const (
@ -20,9 +36,10 @@ const (
BlockType5
BlockType6
BlockType7
BlockTypeMax
)
const NormalBlockTypeNum = 7
type Piece struct {
blockType BlockType
blocks [][]bool
@ -30,67 +47,70 @@ type Piece struct {
func toBlocks(ints [][]int) [][]bool {
blocks := make([][]bool, len(ints))
for i, line := range ints {
blocks[i] = make([]bool, len(line))
for j, v := range line {
blocks[i][j] = v != 0
for j, row := range ints {
blocks[j] = make([]bool, len(row))
}
// Tranpose the argument matrix.
for i, col := range ints {
for j, v := range col {
blocks[j][i] = v != 0
}
}
return blocks
}
var Pieces = map[BlockType]*Piece{
BlockTypeNone: nil,
BlockType1: &Piece{
blockType: BlockType1,
blocks: toBlocks([][]int{
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
}),
},
BlockType2: &Piece{
blockType: BlockType2,
blocks: toBlocks([][]int{
{0, 1, 1},
{0, 1, 0},
{0, 1, 0},
{1, 0, 0},
{1, 1, 1},
{0, 0, 0},
}),
},
BlockType3: &Piece{
blockType: BlockType3,
blocks: toBlocks([][]int{
{0, 1, 0},
{0, 1, 1},
{0, 1, 0},
{1, 1, 1},
{0, 0, 0},
}),
},
BlockType4: &Piece{
blockType: BlockType4,
blocks: toBlocks([][]int{
{0, 1, 0},
{0, 1, 0},
{0, 1, 1},
{0, 0, 1},
{1, 1, 1},
{0, 0, 0},
}),
},
BlockType5: &Piece{
blockType: BlockType5,
blocks: toBlocks([][]int{
{0, 0, 1},
{1, 1, 0},
{0, 1, 1},
{0, 1, 0},
{0, 0, 0},
}),
},
BlockType6: &Piece{
blockType: BlockType6,
blocks: toBlocks([][]int{
{0, 1, 0},
{0, 1, 1},
{0, 0, 1},
{1, 1, 0},
{0, 0, 0},
}),
},
BlockType7: &Piece{
blockType: BlockType7,
blocks: toBlocks([][]int{
{1, 1},
{1, 1},
@ -105,13 +125,13 @@ const fieldBlockNumY = 20
func drawBlocks(context graphics.Context, blocks [][]BlockType, geo matrix.Geometry) {
parts := []graphics.TexturePart{}
for i, blockLine := range blocks {
for j, block := range blockLine {
for i, blockCol := range blocks {
for j, block := range blockCol {
if block == BlockTypeNone {
continue
}
locationX := j * blockWidth
locationY := i * blockHeight
locationX := i * blockWidth
locationY := j * blockHeight
source := graphics.Rect{
(int(block) - 1) * blockWidth, 0,
blockWidth, blockHeight}
@ -127,15 +147,68 @@ func drawBlocks(context graphics.Context, blocks [][]BlockType, geo matrix.Geome
context.DrawTextureParts(blocksTexture, parts, geo, matrix.IdentityColor())
}
func (p *Piece) Draw(context graphics.Context, geo matrix.Geometry) {
blocks := make([][]BlockType, len(p.blocks))
for i, blockLine := range p.blocks {
blocks[i] = make([]BlockType, len(blockLine))
for j, v := range blockLine {
if v {
func (p *Piece) InitialPosition() (int, int) {
size := len(p.blocks)
x := (fieldBlockNumX - size) / 2
y := 0
Loop:
for j := 0; j < size; j++ {
for i := 0; i < size; i++ {
if p.blocks[i][j] {
break Loop
}
}
y--
}
return x, y
}
func (p *Piece) isBlocked(i, j int, angle Angle) bool {
size := len(p.blocks)
i2, j2 := i, j
switch angle {
case Angle0:
case Angle90:
i2 = j
j2 = size-1-i
case Angle180:
i2 = size-1-i
j2 = size-1-j
case Angle270:
i2 = size-1-j
j2 = i
}
return p.blocks[i2][j2]
}
func (p *Piece) collides(field *Field, x, y int, angle Angle) bool {
size := len(p.blocks)
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
if field.IsBlocked(x+i, y+j) && p.isBlocked(i, j, angle) {
return true
}
}
}
return false
}
func (p *Piece) Draw(context graphics.Context, fieldX, fieldY int, pieceX, pieceY int, angle Angle) {
size := len(p.blocks)
blocks := make([][]BlockType, size)
for i, _ := range p.blocks {
blocks[i] = make([]BlockType, size)
for j, _ := range blocks[i] {
if p.isBlocked(i, j, angle) {
blocks[i][j] = p.blockType
}
}
}
drawBlocks(context, blocks, geo)
geoMat := matrix.IdentityGeometry()
x := fieldX + pieceX * blockWidth
y := fieldY + pieceY * blockHeight
geoMat.Translate(float64(x), float64(y))
drawBlocks(context, blocks, geoMat)
}