2013-12-18 19:21:25 +01:00
|
|
|
package blocks
|
|
|
|
|
|
|
|
import (
|
2014-12-05 14:16:58 +01:00
|
|
|
"github.com/hajimehoshi/ebiten/graphics"
|
|
|
|
"github.com/hajimehoshi/ebiten/graphics/matrix"
|
2014-12-07 14:10:04 +01:00
|
|
|
"github.com/hajimehoshi/ebiten/input"
|
2013-12-18 19:21:25 +01:00
|
|
|
"image/color"
|
|
|
|
"math/rand"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
texturePaths["empty"] = "images/blocks/empty.png"
|
|
|
|
}
|
|
|
|
|
|
|
|
type GameScene struct {
|
2013-12-19 17:08:32 +01:00
|
|
|
field *Field
|
|
|
|
rand *rand.Rand
|
|
|
|
currentPiece *Piece
|
|
|
|
currentPieceX int
|
|
|
|
currentPieceY int
|
|
|
|
currentPieceAngle Angle
|
|
|
|
nextPiece *Piece
|
2013-12-19 19:03:35 +01:00
|
|
|
landingCount int
|
2013-12-18 19:21:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewGameScene() *GameScene {
|
|
|
|
return &GameScene{
|
|
|
|
field: NewField(),
|
|
|
|
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const emptyWidth = 16
|
|
|
|
const emptyHeight = 16
|
|
|
|
const fieldWidth = blockWidth * fieldBlockNumX
|
|
|
|
const fieldHeight = blockHeight * fieldBlockNumY
|
|
|
|
|
|
|
|
func (s *GameScene) choosePiece() *Piece {
|
2013-12-19 17:23:00 +01:00
|
|
|
num := NormalBlockTypeNum
|
|
|
|
blockType := BlockType(s.rand.Intn(num) + 1)
|
2013-12-18 19:21:25 +01:00
|
|
|
return Pieces[blockType]
|
|
|
|
}
|
|
|
|
|
2013-12-19 19:21:10 +01:00
|
|
|
func (s *GameScene) initCurrentPiece(piece *Piece) {
|
|
|
|
s.currentPiece = piece
|
|
|
|
x, y := s.currentPiece.InitialPosition()
|
|
|
|
s.currentPieceX = x
|
|
|
|
s.currentPieceY = y
|
|
|
|
s.currentPieceAngle = Angle0
|
|
|
|
}
|
|
|
|
|
2013-12-18 19:21:25 +01:00
|
|
|
func (s *GameScene) Update(state *GameState) {
|
2013-12-19 19:21:10 +01:00
|
|
|
const maxLandingCount = 60
|
2013-12-19 19:03:35 +01:00
|
|
|
|
2013-12-18 19:21:25 +01:00
|
|
|
if s.currentPiece == nil {
|
2013-12-19 19:21:10 +01:00
|
|
|
s.initCurrentPiece(s.choosePiece())
|
|
|
|
}
|
|
|
|
if s.nextPiece == nil {
|
|
|
|
s.nextPiece = s.choosePiece()
|
2013-12-19 17:08:32 +01:00
|
|
|
}
|
2013-12-19 19:03:35 +01:00
|
|
|
piece := s.currentPiece
|
|
|
|
x := s.currentPieceX
|
|
|
|
y := s.currentPieceY
|
|
|
|
angle := s.currentPieceAngle
|
|
|
|
moved := false
|
2014-12-07 14:10:04 +01:00
|
|
|
if state.Input.StateForKey(input.KeySpace) == 1 {
|
2013-12-19 19:03:35 +01:00
|
|
|
s.currentPieceAngle = s.field.RotatePieceRight(piece, x, y, angle)
|
2013-12-19 19:21:10 +01:00
|
|
|
moved = angle != s.currentPieceAngle
|
2013-12-19 17:08:32 +01:00
|
|
|
}
|
2014-12-07 14:10:04 +01:00
|
|
|
if l := state.Input.StateForKey(input.KeyLeft); l == 1 || (10 <= l && l%2 == 0) {
|
2013-12-19 19:03:35 +01:00
|
|
|
s.currentPieceX = s.field.MovePieceToLeft(piece, x, y, angle)
|
2013-12-19 19:21:10 +01:00
|
|
|
moved = x != s.currentPieceX
|
2013-12-19 17:08:32 +01:00
|
|
|
}
|
2014-12-07 14:10:04 +01:00
|
|
|
if r := state.Input.StateForKey(input.KeyRight); r == 1 || (10 <= r && r%2 == 0) {
|
2013-12-19 19:03:35 +01:00
|
|
|
s.currentPieceX = s.field.MovePieceToRight(piece, x, y, angle)
|
2013-12-19 19:21:10 +01:00
|
|
|
moved = y != s.currentPieceX
|
2013-12-18 19:21:25 +01:00
|
|
|
}
|
2014-12-07 14:10:04 +01:00
|
|
|
if d := state.Input.StateForKey(input.KeyDown); (d-1)%2 == 0 {
|
2013-12-19 19:03:35 +01:00
|
|
|
s.currentPieceY = s.field.DropPiece(piece, x, y, angle)
|
2013-12-19 19:21:10 +01:00
|
|
|
moved = y != s.currentPieceY
|
2013-12-19 19:03:35 +01:00
|
|
|
}
|
|
|
|
if moved {
|
|
|
|
s.landingCount = 0
|
|
|
|
} else if !s.field.PieceDroppable(piece, x, y, angle) {
|
2014-12-07 14:10:04 +01:00
|
|
|
if 0 < state.Input.StateForKey(input.KeyDown) {
|
2013-12-19 19:21:10 +01:00
|
|
|
s.landingCount += 10
|
|
|
|
} else {
|
|
|
|
s.landingCount++
|
|
|
|
}
|
2013-12-19 19:03:35 +01:00
|
|
|
if maxLandingCount <= s.landingCount {
|
2013-12-19 19:21:10 +01:00
|
|
|
s.field.AbsorbPiece(piece, x, y, angle)
|
|
|
|
s.initCurrentPiece(s.nextPiece)
|
|
|
|
s.nextPiece = nil
|
2013-12-19 19:03:35 +01:00
|
|
|
s.landingCount = 0
|
|
|
|
}
|
2013-12-19 17:23:00 +01:00
|
|
|
}
|
2013-12-18 19:21:25 +01:00
|
|
|
}
|
|
|
|
|
2014-12-06 17:09:59 +01:00
|
|
|
func (s *GameScene) Draw(context graphics.Context, textures *Textures) {
|
2013-12-18 19:21:25 +01:00
|
|
|
context.Fill(0xff, 0xff, 0xff)
|
|
|
|
|
2014-05-03 08:25:41 +02:00
|
|
|
field := textures.GetTexture("empty")
|
2014-12-06 15:03:17 +01:00
|
|
|
geoMat := matrix.GeometryI()
|
2014-05-03 06:58:18 +02:00
|
|
|
geoMat.Scale(
|
|
|
|
float64(fieldWidth)/float64(emptyWidth),
|
2013-12-19 17:08:32 +01:00
|
|
|
float64(fieldHeight)/float64(emptyHeight))
|
2013-12-18 19:21:25 +01:00
|
|
|
geoMat.Translate(20, 20) // magic number?
|
2014-12-06 15:03:17 +01:00
|
|
|
colorMat := matrix.ColorI()
|
2013-12-18 19:21:25 +01:00
|
|
|
colorMat.Scale(color.RGBA{0, 0, 0, 0x80})
|
2014-12-06 17:09:59 +01:00
|
|
|
graphics.DrawWhole(context.Texture(field), emptyWidth, emptyHeight, geoMat, colorMat)
|
2013-12-18 19:21:25 +01:00
|
|
|
|
2014-12-06 15:03:17 +01:00
|
|
|
geoMat = matrix.GeometryI()
|
2013-12-18 19:21:25 +01:00
|
|
|
geoMat.Translate(20, 20)
|
2014-05-03 08:25:41 +02:00
|
|
|
s.field.Draw(context, textures, geoMat)
|
2013-12-18 19:21:25 +01:00
|
|
|
|
|
|
|
if s.currentPiece != nil {
|
2014-12-06 17:09:59 +01:00
|
|
|
s.currentPiece.Draw(context, textures, 20, 20, s.currentPieceX, s.currentPieceY, s.currentPieceAngle)
|
2013-12-18 19:21:25 +01:00
|
|
|
}
|
|
|
|
}
|