You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
tetris/block.go

190 lines
3.7 KiB

package main
import (
"image/color"
)
// Block represents a single block in the game
type Block struct {
X, Y int
Type BlockType
}
// BlockType represents different types of tetrominos
type BlockType int
const (
IBlock BlockType = iota
JBlock
LBlock
OBlock
SBlock
TBlock
ZBlock
)
// Tetromino represents a complete tetris piece
type Tetromino struct {
Blocks []Block
BlockType BlockType
X, Y int
}
// Colors for different block types
var BlockColors = map[BlockType]color.Color{
IBlock: color.RGBA{0, 255, 255, 255}, // Cyan
JBlock: color.RGBA{0, 0, 255, 255}, // Blue
LBlock: color.RGBA{255, 165, 0, 255}, // Orange
OBlock: color.RGBA{255, 255, 0, 255}, // Yellow
SBlock: color.RGBA{0, 255, 0, 255}, // Green
TBlock: color.RGBA{128, 0, 128, 255}, // Purple
ZBlock: color.RGBA{255, 0, 0, 255}, // Red
}
// TetrominoShapes defines the shape of each tetromino type
var TetrominoShapes = map[BlockType][][]bool{
IBlock: {
{false, false, false, false},
{false, false, false, false},
{true, true, true, true},
{false, false, false, false},
},
JBlock: {
{true, false, false},
{true, true, true},
{false, false, false},
},
LBlock: {
{false, false, true},
{true, true, true},
{false, false, false},
},
OBlock: {
{true, true},
{true, true},
},
SBlock: {
{false, true, true},
{true, true, false},
{false, false, false},
},
TBlock: {
{false, true, false},
{true, true, true},
{false, false, false},
},
ZBlock: {
{true, true, false},
{false, true, true},
{false, false, false},
},
}
// Rotation offsets for I piece wall kicks
var IKicks = [][2]int{
{0, 0},
{-2, 0},
{1, 0},
{-2, -1},
{1, 2},
}
// Rotation offsets for other pieces wall kicks
var NormalKicks = [][2]int{
{0, 0},
{-1, 0},
{1, 0},
{0, -1},
}
// NewTetromino creates a new tetromino of the specified type
func NewTetromino(blockType BlockType, x, y int) *Tetromino {
shape := TetrominoShapes[blockType]
blocks := make([]Block, 0)
for i := 0; i < len(shape); i++ {
for j := 0; j < len(shape[i]); j++ {
if shape[i][j] {
blocks = append(blocks, Block{
X: j,
Y: i,
Type: blockType,
})
}
}
}
// Adjust initial position for I piece
if blockType == IBlock {
y-- // Start one row higher
}
return &Tetromino{
Blocks: blocks,
BlockType: blockType,
X: x,
Y: y,
}
}
// Move moves the tetromino by the specified delta
func (t *Tetromino) Move(dx, dy int) {
t.X += dx
t.Y += dy
}
// Rotate rotates the tetromino clockwise
func (t *Tetromino) Rotate() {
if t.BlockType == OBlock {
return // O block doesn't need rotation
}
// Get the size of the shape matrix
size := 3
if t.BlockType == IBlock {
size = 4
}
// Create a temporary matrix for rotation
matrix := make([][]bool, size)
for i := range matrix {
matrix[i] = make([]bool, size)
}
// Fill the matrix with current block positions
for _, block := range t.Blocks {
if block.Y >= 0 && block.Y < size && block.X >= 0 && block.X < size {
matrix[block.Y][block.X] = true
}
}
// Create a new rotated shape
newBlocks := make([]Block, 0)
// Perform rotation
for y := 0; y < size; y++ {
for x := 0; x < size; x++ {
if matrix[y][x] {
// Rotate coordinates 90 degrees clockwise
newX := size - 1 - y
newY := x
newBlocks = append(newBlocks, Block{
X: newX,
Y: newY,
Type: t.BlockType,
})
}
}
}
t.Blocks = newBlocks
}
// GetAbsolutePositions returns the absolute positions of all blocks in the tetromino
func (t *Tetromino) GetAbsolutePositions() [][2]int {
positions := make([][2]int, len(t.Blocks))
for i, block := range t.Blocks {
positions[i] = [2]int{t.X + block.X, t.Y + block.Y}
}
return positions
}