mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-04 15:04:28 +01:00
Move a piece
This commit is contained in:
parent
bc7dd51adf
commit
631b226b5b
@ -13,11 +13,49 @@ func NewField() *Field {
|
|||||||
return &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) {
|
func (f *Field) Draw(context graphics.Context, geo matrix.Geometry) {
|
||||||
blocks := make([][]BlockType, len(f.blocks))
|
blocks := make([][]BlockType, len(f.blocks))
|
||||||
for i, blockLine := range f.blocks {
|
for i, blockCol := range f.blocks {
|
||||||
blocks[i] = make([]BlockType, len(blockLine))
|
blocks[i] = make([]BlockType, len(blockCol))
|
||||||
copy(blocks[i], blockLine[:])
|
copy(blocks[i], blockCol[:])
|
||||||
}
|
}
|
||||||
drawBlocks(context, blocks, geo)
|
drawBlocks(context, blocks, geo)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package blocks
|
|||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics"
|
"github.com/hajimehoshi/go-ebiten/graphics"
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
||||||
|
"github.com/hajimehoshi/go-ebiten/ui"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
@ -13,10 +14,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GameScene struct {
|
type GameScene struct {
|
||||||
field *Field
|
field *Field
|
||||||
rand *rand.Rand
|
rand *rand.Rand
|
||||||
currentPiece *Piece
|
currentPiece *Piece
|
||||||
nextPiece *Piece
|
currentPieceX int
|
||||||
|
currentPieceY int
|
||||||
|
currentPieceAngle Angle
|
||||||
|
nextPiece *Piece
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGameScene() *GameScene {
|
func NewGameScene() *GameScene {
|
||||||
@ -32,15 +36,36 @@ const fieldWidth = blockWidth * fieldBlockNumX
|
|||||||
const fieldHeight = blockHeight * fieldBlockNumY
|
const fieldHeight = blockHeight * fieldBlockNumY
|
||||||
|
|
||||||
func (s *GameScene) choosePiece() *Piece {
|
func (s *GameScene) choosePiece() *Piece {
|
||||||
// Omit BlockTypeNone.
|
//num := NormalBlockTypeNum
|
||||||
num := int(BlockTypeMax) - 1
|
//blockType := BlockType(s.rand.Intn(num) + 1)
|
||||||
blockType := BlockType(s.rand.Intn(num) + 1)
|
blockType := BlockType1
|
||||||
return Pieces[blockType]
|
return Pieces[blockType]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GameScene) Update(state *GameState) {
|
func (s *GameScene) Update(state *GameState) {
|
||||||
if s.currentPiece == nil {
|
if s.currentPiece == nil {
|
||||||
s.currentPiece = s.choosePiece()
|
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"]
|
field := drawInfo.textures["empty"]
|
||||||
geoMat := matrix.IdentityGeometry()
|
geoMat := matrix.IdentityGeometry()
|
||||||
geoMat.Scale(float64(fieldWidth) / float64(emptyWidth),
|
geoMat.Scale(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.IdentityColor()
|
colorMat := matrix.IdentityColor()
|
||||||
colorMat.Scale(color.RGBA{0, 0, 0, 0x80})
|
colorMat.Scale(color.RGBA{0, 0, 0, 0x80})
|
||||||
@ -61,6 +86,7 @@ func (s *GameScene) Draw(context graphics.Context) {
|
|||||||
s.field.Draw(context, geoMat)
|
s.field.Draw(context, geoMat)
|
||||||
|
|
||||||
if s.currentPiece != nil {
|
if s.currentPiece != nil {
|
||||||
s.currentPiece.Draw(context, geoMat)
|
s.currentPiece.Draw(context, 20, 20,
|
||||||
|
s.currentPieceX, s.currentPieceY, s.currentPieceAngle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,22 @@ func init() {
|
|||||||
texturePaths["blocks"] = "images/blocks/blocks.png"
|
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
|
type BlockType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -20,9 +36,10 @@ const (
|
|||||||
BlockType5
|
BlockType5
|
||||||
BlockType6
|
BlockType6
|
||||||
BlockType7
|
BlockType7
|
||||||
BlockTypeMax
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const NormalBlockTypeNum = 7
|
||||||
|
|
||||||
type Piece struct {
|
type Piece struct {
|
||||||
blockType BlockType
|
blockType BlockType
|
||||||
blocks [][]bool
|
blocks [][]bool
|
||||||
@ -30,67 +47,70 @@ type Piece struct {
|
|||||||
|
|
||||||
func toBlocks(ints [][]int) [][]bool {
|
func toBlocks(ints [][]int) [][]bool {
|
||||||
blocks := make([][]bool, len(ints))
|
blocks := make([][]bool, len(ints))
|
||||||
for i, line := range ints {
|
for j, row := range ints {
|
||||||
blocks[i] = make([]bool, len(line))
|
blocks[j] = make([]bool, len(row))
|
||||||
for j, v := range line {
|
}
|
||||||
blocks[i][j] = v != 0
|
// Tranpose the argument matrix.
|
||||||
|
for i, col := range ints {
|
||||||
|
for j, v := range col {
|
||||||
|
blocks[j][i] = v != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return blocks
|
return blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
var Pieces = map[BlockType]*Piece{
|
var Pieces = map[BlockType]*Piece{
|
||||||
BlockTypeNone: nil,
|
|
||||||
BlockType1: &Piece{
|
BlockType1: &Piece{
|
||||||
blockType: BlockType1,
|
blockType: BlockType1,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 1, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{0, 1, 0, 0},
|
{1, 1, 1, 1},
|
||||||
{0, 1, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{0, 1, 0, 0},
|
{0, 0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType2: &Piece{
|
BlockType2: &Piece{
|
||||||
blockType: BlockType2,
|
blockType: BlockType2,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 1, 1},
|
{1, 0, 0},
|
||||||
{0, 1, 0},
|
{1, 1, 1},
|
||||||
{0, 1, 0},
|
{0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType3: &Piece{
|
BlockType3: &Piece{
|
||||||
blockType: BlockType3,
|
blockType: BlockType3,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 1, 0},
|
{0, 1, 0},
|
||||||
{0, 1, 1},
|
{1, 1, 1},
|
||||||
{0, 1, 0},
|
{0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType4: &Piece{
|
BlockType4: &Piece{
|
||||||
blockType: BlockType4,
|
blockType: BlockType4,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 1, 0},
|
{0, 0, 1},
|
||||||
{0, 1, 0},
|
{1, 1, 1},
|
||||||
{0, 1, 1},
|
{0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType5: &Piece{
|
BlockType5: &Piece{
|
||||||
blockType: BlockType5,
|
blockType: BlockType5,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 0, 1},
|
{1, 1, 0},
|
||||||
{0, 1, 1},
|
{0, 1, 1},
|
||||||
{0, 1, 0},
|
{0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType6: &Piece{
|
BlockType6: &Piece{
|
||||||
blockType: BlockType6,
|
blockType: BlockType6,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{0, 1, 0},
|
|
||||||
{0, 1, 1},
|
{0, 1, 1},
|
||||||
{0, 0, 1},
|
{1, 1, 0},
|
||||||
|
{0, 0, 0},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
BlockType7: &Piece{
|
BlockType7: &Piece{
|
||||||
|
blockType: BlockType7,
|
||||||
blocks: toBlocks([][]int{
|
blocks: toBlocks([][]int{
|
||||||
{1, 1},
|
{1, 1},
|
||||||
{1, 1},
|
{1, 1},
|
||||||
@ -105,13 +125,13 @@ const fieldBlockNumY = 20
|
|||||||
|
|
||||||
func drawBlocks(context graphics.Context, blocks [][]BlockType, geo matrix.Geometry) {
|
func drawBlocks(context graphics.Context, blocks [][]BlockType, geo matrix.Geometry) {
|
||||||
parts := []graphics.TexturePart{}
|
parts := []graphics.TexturePart{}
|
||||||
for i, blockLine := range blocks {
|
for i, blockCol := range blocks {
|
||||||
for j, block := range blockLine {
|
for j, block := range blockCol {
|
||||||
if block == BlockTypeNone {
|
if block == BlockTypeNone {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
locationX := j * blockWidth
|
locationX := i * blockWidth
|
||||||
locationY := i * blockHeight
|
locationY := j * blockHeight
|
||||||
source := graphics.Rect{
|
source := graphics.Rect{
|
||||||
(int(block) - 1) * blockWidth, 0,
|
(int(block) - 1) * blockWidth, 0,
|
||||||
blockWidth, blockHeight}
|
blockWidth, blockHeight}
|
||||||
@ -127,15 +147,68 @@ func drawBlocks(context graphics.Context, blocks [][]BlockType, geo matrix.Geome
|
|||||||
context.DrawTextureParts(blocksTexture, parts, geo, matrix.IdentityColor())
|
context.DrawTextureParts(blocksTexture, parts, geo, matrix.IdentityColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Piece) Draw(context graphics.Context, geo matrix.Geometry) {
|
func (p *Piece) InitialPosition() (int, int) {
|
||||||
blocks := make([][]BlockType, len(p.blocks))
|
size := len(p.blocks)
|
||||||
for i, blockLine := range p.blocks {
|
x := (fieldBlockNumX - size) / 2
|
||||||
blocks[i] = make([]BlockType, len(blockLine))
|
y := 0
|
||||||
for j, v := range blockLine {
|
Loop:
|
||||||
if v {
|
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
|
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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user