79
README.md
|
@ -2,6 +2,16 @@
|
||||||
|
|
||||||
Golang Tetris for console window with optional AI
|
Golang Tetris for console window with optional AI
|
||||||
|
|
||||||
|
## Features include
|
||||||
|
|
||||||
|
- AI (use i key to toggle)
|
||||||
|
- Lock delay
|
||||||
|
- Next piece
|
||||||
|
- Ghost piece
|
||||||
|
- Top scores
|
||||||
|
- Board choices
|
||||||
|
- Edit boards
|
||||||
|
|
||||||
## Compile
|
## Compile
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -13,21 +23,6 @@ go install github.com/MichaelS11/go-tetris
|
||||||
|
|
||||||
Then run the binary created, go-tetris or go-tetris.exe
|
Then run the binary created, go-tetris or go-tetris.exe
|
||||||
|
|
||||||
## Keys during game
|
|
||||||
|
|
||||||
| Key | Action |
|
|
||||||
| --- | --- |
|
|
||||||
| ← | left move |
|
|
||||||
| z | left rotate |
|
|
||||||
| x | right rotate |
|
|
||||||
| → | right move |
|
|
||||||
| ↓ | soft drop |
|
|
||||||
| ↑ | hard drop |
|
|
||||||
| spacebar | hard drop |
|
|
||||||
| p | pause |
|
|
||||||
| q | quit |
|
|
||||||
| i | toggle AI |
|
|
||||||
|
|
||||||
## Keys start screen
|
## Keys start screen
|
||||||
|
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
|
@ -35,26 +30,58 @@ Then run the binary created, go-tetris or go-tetris.exe
|
||||||
| ← | previous board |
|
| ← | previous board |
|
||||||
| → | next board |
|
| → | next board |
|
||||||
| spacebar | start game |
|
| spacebar | start game |
|
||||||
|
| ctrl e | edit board |
|
||||||
| q | quit |
|
| q | quit |
|
||||||
|
|
||||||
## Features include
|
## Keys during game
|
||||||
|
|
||||||
- AI (use i key to toggle)
|
| Key | Action |
|
||||||
- Lock delay
|
| --- | --- |
|
||||||
- Next piece
|
| ← | left move |
|
||||||
- Ghost piece
|
| → | right move |
|
||||||
- Top scores
|
| ↓ | soft drop |
|
||||||
- Board choices
|
| ↑ | hard drop |
|
||||||
|
| spacebar | hard drop |
|
||||||
|
| z | left rotate |
|
||||||
|
| x | right rotate |
|
||||||
|
| p | pause |
|
||||||
|
| q | quit |
|
||||||
|
| i | toggle AI |
|
||||||
|
|
||||||
|
## Keys edit mode
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
| --- | --- |
|
||||||
|
| ← | move cursor left |
|
||||||
|
| → | move cursor right |
|
||||||
|
| ↓ | move cursor down |
|
||||||
|
| ↑ | move cursor up |
|
||||||
|
| z | rotate left |
|
||||||
|
| x | rotate right |
|
||||||
|
| c | cyan block - I |
|
||||||
|
| b | blue block - J |
|
||||||
|
| w | white block - L |
|
||||||
|
| e | yellow block - O |
|
||||||
|
| g | green block - S |
|
||||||
|
| a | magenta block - T |
|
||||||
|
| r | red block - Z |
|
||||||
|
| f | free block |
|
||||||
|
| ctrl b | change board size |
|
||||||
|
| ctrl s | save board |
|
||||||
|
| ctrl n | save board as new |
|
||||||
|
| ctrl k | delete board |
|
||||||
|
| ctrl o | empty board |
|
||||||
|
| ctrl q | quit edit mode |
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot1.png "Go Tetris")
|
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/tetris.png "Go Tetris")
|
||||||
|
|
||||||
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot2.png "Golang Tetris")
|
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/heart.png "Golang Tetris Heart")
|
||||||
|
|
||||||
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot3.png "Golang Tetris Heart")
|
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/editmode.png "Edit Mode Peace Symbol")
|
||||||
|
|
||||||
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot4.png "Tetris High Scores")
|
![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/highscores.png "Tetris High Scores")
|
||||||
|
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
|
|
89
board.go
|
@ -13,24 +13,73 @@ func NewBoard() {
|
||||||
board.Clear()
|
board.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears the board
|
// ChangeBoardSize changes board size
|
||||||
|
func ChangeBoardSize(width int, height int) {
|
||||||
|
if board.width == width && board.height == height {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newBoard := &Board{width: width, height: height, boardsIndex: board.boardsIndex}
|
||||||
|
newBoard.colors = make([][]termbox.Attribute, width)
|
||||||
|
for i := 0; i < width; i++ {
|
||||||
|
newBoard.colors[i] = make([]termbox.Attribute, height)
|
||||||
|
for j := 0; j < height; j++ {
|
||||||
|
if i < board.width && j < board.height {
|
||||||
|
newBoard.colors[i][j] = board.colors[i][j]
|
||||||
|
} else {
|
||||||
|
newBoard.colors[i][j] = blankColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newBoard.rotation = make([][]int, width)
|
||||||
|
for i := 0; i < width; i++ {
|
||||||
|
newBoard.rotation[i] = make([]int, height)
|
||||||
|
for j := 0; j < height; j++ {
|
||||||
|
if i < board.width && j < board.height {
|
||||||
|
newBoard.rotation[i][j] = board.rotation[i][j]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
board = newBoard
|
||||||
|
board.previewMino = NewMino()
|
||||||
|
board.currentMino = NewMino()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the board to orginal state
|
||||||
func (board *Board) Clear() {
|
func (board *Board) Clear() {
|
||||||
board.width = len(boards[board.boardsIndex].colors)
|
board.width = len(boards[board.boardsIndex].colors)
|
||||||
board.height = len(boards[board.boardsIndex].colors[0])
|
board.height = len(boards[board.boardsIndex].colors[0])
|
||||||
board.colors = make([][]termbox.Attribute, len(boards[board.boardsIndex].colors))
|
board.colors = make([][]termbox.Attribute, board.width)
|
||||||
for i := 0; i < len(boards[board.boardsIndex].colors); i++ {
|
for i := 0; i < board.width; i++ {
|
||||||
board.colors[i] = make([]termbox.Attribute, len(boards[board.boardsIndex].colors[i]))
|
board.colors[i] = make([]termbox.Attribute, board.height)
|
||||||
copy(board.colors[i], boards[board.boardsIndex].colors[i])
|
copy(board.colors[i], boards[board.boardsIndex].colors[i])
|
||||||
}
|
}
|
||||||
board.rotation = make([][]int, len(boards[board.boardsIndex].rotation))
|
board.rotation = make([][]int, board.width)
|
||||||
for i := 0; i < len(boards[board.boardsIndex].rotation); i++ {
|
for i := 0; i < board.width; i++ {
|
||||||
board.rotation[i] = make([]int, len(boards[board.boardsIndex].rotation[i]))
|
board.rotation[i] = make([]int, board.height)
|
||||||
copy(board.rotation[i], boards[board.boardsIndex].rotation[i])
|
copy(board.rotation[i], boards[board.boardsIndex].rotation[i])
|
||||||
}
|
}
|
||||||
board.previewMino = NewMino()
|
board.previewMino = NewMino()
|
||||||
board.currentMino = NewMino()
|
board.currentMino = NewMino()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmptyBoard removes all blocks/colors from the board
|
||||||
|
func (board *Board) EmptyBoard() {
|
||||||
|
for i := 0; i < board.width; i++ {
|
||||||
|
for j := 0; j < board.height; j++ {
|
||||||
|
board.colors[i][j] = blankColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < board.width; i++ {
|
||||||
|
for j := 0; j < board.height; j++ {
|
||||||
|
board.rotation[i][j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PreviousBoard switches to previous board
|
// PreviousBoard switches to previous board
|
||||||
func (board *Board) PreviousBoard() {
|
func (board *Board) PreviousBoard() {
|
||||||
board.boardsIndex--
|
board.boardsIndex--
|
||||||
|
@ -247,9 +296,30 @@ func (board *Board) deleteLine(line int) {
|
||||||
// SetColor sets the color and rotation of board location
|
// SetColor sets the color and rotation of board location
|
||||||
func (board *Board) SetColor(x int, y int, color termbox.Attribute, rotation int) {
|
func (board *Board) SetColor(x int, y int, color termbox.Attribute, rotation int) {
|
||||||
board.colors[x][y] = color
|
board.colors[x][y] = color
|
||||||
|
if rotation < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
board.rotation[x][y] = rotation
|
board.rotation[x][y] = rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RotateLeft rotates cell left
|
||||||
|
func (board *Board) RotateLeft(x int, y int) {
|
||||||
|
if board.rotation[x][y] == 0 {
|
||||||
|
board.rotation[x][y] = 3
|
||||||
|
return
|
||||||
|
}
|
||||||
|
board.rotation[x][y]--
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateRight rotates cell right
|
||||||
|
func (board *Board) RotateRight(x int, y int) {
|
||||||
|
if board.rotation[x][y] == 3 {
|
||||||
|
board.rotation[x][y] = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
board.rotation[x][y]++
|
||||||
|
}
|
||||||
|
|
||||||
// ValidBlockLocation checks if block location is vaild
|
// ValidBlockLocation checks if block location is vaild
|
||||||
func (board *Board) ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool {
|
func (board *Board) ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool {
|
||||||
if x < 0 || x >= board.width || y >= board.height {
|
if x < 0 || x >= board.width || y >= board.height {
|
||||||
|
@ -311,6 +381,11 @@ func (board *Board) DrawDropMino() {
|
||||||
mino.DrawMino(MinoDrop)
|
mino.DrawMino(MinoDrop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawCursor draws the edit cursor
|
||||||
|
func (board *Board) DrawCursor(x int, y int) {
|
||||||
|
view.DrawCursor(x, y, board.colors[x][y])
|
||||||
|
}
|
||||||
|
|
||||||
// printDebugBoard is for printing board in text for debuging
|
// printDebugBoard is for printing board in text for debuging
|
||||||
func (board *Board) printDebugBoard() {
|
func (board *Board) printDebugBoard() {
|
||||||
for j := 0; j < board.height; j++ {
|
for j := 0; j < board.height; j++ {
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewEdit creates a new edit mode
|
||||||
|
func NewEdit() {
|
||||||
|
edit = &Edit{moved: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnabledEditMode enable edit mode
|
||||||
|
func (edit *Edit) EnabledEditMode() {
|
||||||
|
if edit.y > board.height-1 {
|
||||||
|
edit.y = board.height - 1
|
||||||
|
}
|
||||||
|
if edit.x > board.width-1 {
|
||||||
|
edit.x = board.width - 1
|
||||||
|
}
|
||||||
|
edit.moved = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableEditMode disable edit mode
|
||||||
|
func (edit *Edit) DisableEditMode() {
|
||||||
|
err := saveUserBoards()
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("error saving user boards:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoardSizeMode changed to board size edit mode
|
||||||
|
func (edit *Edit) BoardSizeMode() {
|
||||||
|
edit.width = board.width
|
||||||
|
edit.height = board.height
|
||||||
|
edit.boardSize = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoardWidthIncrement board width increment
|
||||||
|
func (edit *Edit) BoardWidthIncrement() {
|
||||||
|
if edit.width > 39 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.width++
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoardWidthDecrement board width decrement
|
||||||
|
func (edit *Edit) BoardWidthDecrement() {
|
||||||
|
if edit.width < 9 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.width--
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoardHeightIncrement board height increment
|
||||||
|
func (edit *Edit) BoardHeightIncrement() {
|
||||||
|
if edit.height > 39 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.height++
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoardHeightDecrement board height decrement
|
||||||
|
func (edit *Edit) BoardHeightDecrement() {
|
||||||
|
if edit.height < 9 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.height--
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeBoardSize create new board
|
||||||
|
func (edit *Edit) ChangeBoardSize() {
|
||||||
|
ChangeBoardSize(edit.width, edit.height)
|
||||||
|
edit.boardSize = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyBoard removes all blocks/colors from the board
|
||||||
|
func (edit *Edit) EmptyBoard() {
|
||||||
|
board.EmptyBoard()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CursorUp move cursor up
|
||||||
|
func (edit *Edit) CursorUp() {
|
||||||
|
if !edit.moved {
|
||||||
|
edit.moved = true
|
||||||
|
}
|
||||||
|
if edit.y < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.y--
|
||||||
|
}
|
||||||
|
|
||||||
|
// CursorDown move cursor down
|
||||||
|
func (edit *Edit) CursorDown() {
|
||||||
|
if !edit.moved {
|
||||||
|
edit.moved = true
|
||||||
|
}
|
||||||
|
if edit.y == board.height-1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.y++
|
||||||
|
}
|
||||||
|
|
||||||
|
// CursorRight move cursor right
|
||||||
|
func (edit *Edit) CursorRight() {
|
||||||
|
if !edit.moved {
|
||||||
|
edit.moved = true
|
||||||
|
}
|
||||||
|
if edit.x == board.width-1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.x++
|
||||||
|
}
|
||||||
|
|
||||||
|
// CursorLeft move cursor left
|
||||||
|
func (edit *Edit) CursorLeft() {
|
||||||
|
if !edit.moved {
|
||||||
|
edit.moved = true
|
||||||
|
}
|
||||||
|
if edit.x < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
edit.x--
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColor sets the board color
|
||||||
|
func (edit *Edit) SetColor(color termbox.Attribute) {
|
||||||
|
if edit.moved {
|
||||||
|
edit.moved = false
|
||||||
|
}
|
||||||
|
if edit.saved {
|
||||||
|
edit.saved = false
|
||||||
|
}
|
||||||
|
board.SetColor(edit.x, edit.y, color, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateLeft rotates cell left
|
||||||
|
func (edit *Edit) RotateLeft() {
|
||||||
|
if edit.moved {
|
||||||
|
edit.moved = false
|
||||||
|
}
|
||||||
|
if edit.saved {
|
||||||
|
edit.saved = false
|
||||||
|
}
|
||||||
|
board.RotateLeft(edit.x, edit.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateRight rotates cell right
|
||||||
|
func (edit *Edit) RotateRight() {
|
||||||
|
if edit.moved {
|
||||||
|
edit.moved = false
|
||||||
|
}
|
||||||
|
if edit.saved {
|
||||||
|
edit.saved = false
|
||||||
|
}
|
||||||
|
board.RotateRight(edit.x, edit.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawCursor draws the cursor location when cursor moves
|
||||||
|
func (edit *Edit) DrawCursor() {
|
||||||
|
if !edit.moved {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
board.DrawCursor(edit.x, edit.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveBoard save board
|
||||||
|
func (edit *Edit) SaveBoard() {
|
||||||
|
if board.boardsIndex < numInternalBoards {
|
||||||
|
edit.SaveBoardNew()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
boards[board.boardsIndex].colors = board.colors
|
||||||
|
boards[board.boardsIndex].rotation = board.rotation
|
||||||
|
if !edit.saved {
|
||||||
|
edit.saved = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveBoardNew save board as new board
|
||||||
|
func (edit *Edit) SaveBoardNew() {
|
||||||
|
aBoards := Boards{name: time.Now().Format("Jan 2 3:4:5")}
|
||||||
|
aBoards.colors = make([][]termbox.Attribute, len(board.colors))
|
||||||
|
for i := 0; i < len(board.colors); i++ {
|
||||||
|
aBoards.colors[i] = append(aBoards.colors[i], board.colors[i]...)
|
||||||
|
}
|
||||||
|
aBoards.rotation = make([][]int, len(board.rotation))
|
||||||
|
for i := 0; i < len(board.rotation); i++ {
|
||||||
|
aBoards.rotation[i] = append(aBoards.rotation[i], board.rotation[i]...)
|
||||||
|
}
|
||||||
|
boards = append(boards, aBoards)
|
||||||
|
board.boardsIndex = len(boards) - 1
|
||||||
|
if !edit.saved {
|
||||||
|
edit.saved = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBoard deletes a board
|
||||||
|
func (edit *Edit) DeleteBoard() {
|
||||||
|
if board.boardsIndex < numInternalBoards {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
boards = append(boards[:board.boardsIndex], boards[board.boardsIndex+1:]...)
|
||||||
|
board.boardsIndex--
|
||||||
|
board.Clear()
|
||||||
|
}
|
18
engine.go
|
@ -48,7 +48,7 @@ loop:
|
||||||
engine.tick()
|
engine.tick()
|
||||||
case <-engine.aiTimer.C:
|
case <-engine.aiTimer.C:
|
||||||
engine.ai.ProcessQueue()
|
engine.ai.ProcessQueue()
|
||||||
engine.aiTimer.Reset(engine.tickTime / 6)
|
engine.aiTimer.Reset(engine.tickTime / aiTickDivider)
|
||||||
case <-engine.chanStop:
|
case <-engine.chanStop:
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ func (engine *Engine) Pause() {
|
||||||
func (engine *Engine) UnPause() {
|
func (engine *Engine) UnPause() {
|
||||||
engine.timer.Reset(engine.tickTime)
|
engine.timer.Reset(engine.tickTime)
|
||||||
if engine.aiEnabled {
|
if engine.aiEnabled {
|
||||||
engine.aiTimer.Reset(engine.tickTime / 6)
|
engine.aiTimer.Reset(engine.tickTime / aiTickDivider)
|
||||||
}
|
}
|
||||||
engine.paused = false
|
engine.paused = false
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ loop:
|
||||||
func (engine *Engine) EnabledAi() {
|
func (engine *Engine) EnabledAi() {
|
||||||
engine.aiEnabled = true
|
engine.aiEnabled = true
|
||||||
go engine.ai.GetBestQueue()
|
go engine.ai.GetBestQueue()
|
||||||
engine.aiTimer.Reset(engine.tickTime / 6)
|
engine.aiTimer.Reset(engine.tickTime / aiTickDivider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableAi disables the AI
|
// DisableAi disables the AI
|
||||||
|
@ -259,3 +259,15 @@ func (engine *Engine) DisableAi() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnabledEditMode enables edit mode
|
||||||
|
func (engine *Engine) EnabledEditMode() {
|
||||||
|
edit.EnabledEditMode()
|
||||||
|
engine.editMode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableEditMode disables edit mode
|
||||||
|
func (engine *Engine) DisableEditMode() {
|
||||||
|
edit.DisableEditMode()
|
||||||
|
engine.editMode = false
|
||||||
|
}
|
||||||
|
|
43
globals.go
|
@ -8,10 +8,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blankColor = termbox.ColorBlack
|
blankColor = termbox.ColorBlack
|
||||||
boardXOffset = 4
|
boardXOffset = 4
|
||||||
boardYOffset = 2
|
boardYOffset = 2
|
||||||
rankingFileName = "/tetris.db"
|
aiTickDivider = 8
|
||||||
|
rankingFileName = "/go-tetris.db"
|
||||||
|
settingsFileName = "/go-tetris.json"
|
||||||
|
|
||||||
// MinoPreview is for the preview mino
|
// MinoPreview is for the preview mino
|
||||||
MinoPreview MinoType = iota
|
MinoPreview MinoType = iota
|
||||||
|
@ -57,12 +59,20 @@ type (
|
||||||
dropDistance int
|
dropDistance int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boards holds all the premade boards
|
// Boards holds all the boards
|
||||||
Boards struct {
|
Boards struct {
|
||||||
|
name string
|
||||||
colors [][]termbox.Attribute
|
colors [][]termbox.Attribute
|
||||||
rotation [][]int
|
rotation [][]int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoardsJSON is for JSON format of boards
|
||||||
|
BoardsJSON struct {
|
||||||
|
Name string
|
||||||
|
Mino [][]string
|
||||||
|
Rotation [][]int
|
||||||
|
}
|
||||||
|
|
||||||
// KeyInput is the key input engine
|
// KeyInput is the key input engine
|
||||||
KeyInput struct {
|
KeyInput struct {
|
||||||
stopped bool
|
stopped bool
|
||||||
|
@ -103,16 +113,35 @@ type (
|
||||||
ai *Ai
|
ai *Ai
|
||||||
aiEnabled bool
|
aiEnabled bool
|
||||||
aiTimer *time.Timer
|
aiTimer *time.Timer
|
||||||
|
editMode bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit is the board edit mode
|
||||||
|
Edit struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
moved bool
|
||||||
|
boardSize bool
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
saved bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings is the JSON load/save file
|
||||||
|
Settings struct {
|
||||||
|
Boards []BoardsJSON
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
boards []Boards
|
|
||||||
|
|
||||||
baseDir string
|
baseDir string
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
minos *Minos
|
minos *Minos
|
||||||
board *Board
|
board *Board
|
||||||
view *View
|
view *View
|
||||||
engine *Engine
|
engine *Engine
|
||||||
|
edit *Edit
|
||||||
|
|
||||||
|
boards []Boards
|
||||||
|
numInternalBoards int
|
||||||
)
|
)
|
||||||
|
|
93
keyInput.go
|
@ -40,7 +40,7 @@ loop:
|
||||||
|
|
||||||
// ProcessEvent process the key input event
|
// ProcessEvent process the key input event
|
||||||
func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||||
if event.Key == termbox.KeyCtrlI {
|
if event.Key == termbox.KeyCtrlL {
|
||||||
// Ctrl l (lower case L) to log stack trace
|
// Ctrl l (lower case L) to log stack trace
|
||||||
buffer := make([]byte, 1<<16)
|
buffer := make([]byte, 1<<16)
|
||||||
length := runtime.Stack(buffer, true)
|
length := runtime.Stack(buffer, true)
|
||||||
|
@ -49,6 +49,73 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if engine.editMode {
|
||||||
|
if edit.boardSize {
|
||||||
|
switch event.Ch {
|
||||||
|
case 0:
|
||||||
|
switch event.Key {
|
||||||
|
case termbox.KeyArrowUp:
|
||||||
|
edit.BoardHeightIncrement()
|
||||||
|
case termbox.KeyArrowDown:
|
||||||
|
edit.BoardHeightDecrement()
|
||||||
|
case termbox.KeyArrowLeft:
|
||||||
|
edit.BoardWidthDecrement()
|
||||||
|
case termbox.KeyArrowRight:
|
||||||
|
edit.BoardWidthIncrement()
|
||||||
|
}
|
||||||
|
case 'q':
|
||||||
|
edit.ChangeBoardSize()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch event.Ch {
|
||||||
|
case 0:
|
||||||
|
switch event.Key {
|
||||||
|
case termbox.KeyArrowUp:
|
||||||
|
edit.CursorUp()
|
||||||
|
case termbox.KeyArrowDown:
|
||||||
|
edit.CursorDown()
|
||||||
|
case termbox.KeyArrowLeft:
|
||||||
|
edit.CursorLeft()
|
||||||
|
case termbox.KeyArrowRight:
|
||||||
|
edit.CursorRight()
|
||||||
|
case termbox.KeyCtrlB:
|
||||||
|
edit.BoardSizeMode()
|
||||||
|
case termbox.KeyCtrlS:
|
||||||
|
edit.SaveBoard()
|
||||||
|
case termbox.KeyCtrlN:
|
||||||
|
edit.SaveBoardNew()
|
||||||
|
case termbox.KeyCtrlK:
|
||||||
|
edit.DeleteBoard()
|
||||||
|
case termbox.KeyCtrlO:
|
||||||
|
edit.EmptyBoard()
|
||||||
|
case termbox.KeyCtrlQ, termbox.KeyCtrlC:
|
||||||
|
engine.DisableEditMode()
|
||||||
|
}
|
||||||
|
case 'c':
|
||||||
|
edit.SetColor(termbox.ColorCyan)
|
||||||
|
case 'b':
|
||||||
|
edit.SetColor(termbox.ColorBlue)
|
||||||
|
case 'w':
|
||||||
|
edit.SetColor(termbox.ColorWhite)
|
||||||
|
case 'e':
|
||||||
|
edit.SetColor(termbox.ColorYellow)
|
||||||
|
case 'g':
|
||||||
|
edit.SetColor(termbox.ColorGreen)
|
||||||
|
case 'a':
|
||||||
|
edit.SetColor(termbox.ColorMagenta)
|
||||||
|
case 'r':
|
||||||
|
edit.SetColor(termbox.ColorRed)
|
||||||
|
case 'f':
|
||||||
|
edit.SetColor(blankColor)
|
||||||
|
case 'z':
|
||||||
|
edit.RotateLeft()
|
||||||
|
case 'x':
|
||||||
|
edit.RotateRight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if event.Ch == 'q' || event.Key == termbox.KeyCtrlC {
|
if event.Ch == 'q' || event.Key == termbox.KeyCtrlC {
|
||||||
if !keyInput.stopped {
|
if !keyInput.stopped {
|
||||||
keyInput.stopped = true
|
keyInput.stopped = true
|
||||||
|
@ -67,6 +134,8 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||||
board.PreviousBoard()
|
board.PreviousBoard()
|
||||||
case termbox.KeyArrowRight:
|
case termbox.KeyArrowRight:
|
||||||
board.NextBoard()
|
board.NextBoard()
|
||||||
|
case termbox.KeyCtrlE:
|
||||||
|
engine.EnabledEditMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -89,7 +158,8 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.Ch == 0 {
|
switch event.Ch {
|
||||||
|
case 0:
|
||||||
switch event.Key {
|
switch event.Key {
|
||||||
case termbox.KeySpace:
|
case termbox.KeySpace:
|
||||||
board.MinoDrop()
|
board.MinoDrop()
|
||||||
|
@ -102,17 +172,14 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||||
case termbox.KeyArrowRight:
|
case termbox.KeyArrowRight:
|
||||||
board.MinoMoveRight()
|
board.MinoMoveRight()
|
||||||
}
|
}
|
||||||
} else {
|
case 'z':
|
||||||
switch event.Ch {
|
board.MinoRotateLeft()
|
||||||
case 'z':
|
case 'x':
|
||||||
board.MinoRotateLeft()
|
board.MinoRotateRight()
|
||||||
case 'x':
|
case 'p':
|
||||||
board.MinoRotateRight()
|
engine.Pause()
|
||||||
case 'p':
|
case 'i':
|
||||||
engine.Pause()
|
engine.EnabledAi()
|
||||||
case 'i':
|
|
||||||
engine.EnabledAi()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@ func setupForTesting() {
|
||||||
|
|
||||||
rand.Seed(1)
|
rand.Seed(1)
|
||||||
|
|
||||||
|
err := loadBoards()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error loading boards:", err)
|
||||||
|
}
|
||||||
|
|
||||||
NewMinos()
|
NewMinos()
|
||||||
NewBoard()
|
NewBoard()
|
||||||
NewEngine()
|
NewEngine()
|
||||||
|
|
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.0 KiB |
14
tetris.go
|
@ -13,20 +13,30 @@ func main() {
|
||||||
logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.LUTC|log.Llongfile)
|
logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.LUTC|log.Llongfile)
|
||||||
logFile, err := os.OpenFile(baseDir+"/go-tetris.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
logFile, err := os.OpenFile(baseDir+"/go-tetris.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error opening logFile:", err)
|
logger.Fatal("error opening log file:", err)
|
||||||
}
|
}
|
||||||
defer logFile.Close()
|
defer logFile.Close()
|
||||||
logger.SetOutput(logFile)
|
logger.SetOutput(logFile)
|
||||||
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
err = loadBoards()
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("error loading internal boards:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = loadUserBoards()
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("error loading user boards:", err)
|
||||||
|
}
|
||||||
|
|
||||||
NewMinos()
|
NewMinos()
|
||||||
NewBoard()
|
NewBoard()
|
||||||
NewView()
|
NewView()
|
||||||
NewEngine()
|
NewEngine()
|
||||||
|
NewEdit()
|
||||||
|
|
||||||
engine.Run()
|
engine.Run()
|
||||||
|
|
||||||
view.Stop()
|
view.Stop()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
205
view.go
|
@ -32,29 +32,53 @@ func (view *View) Stop() {
|
||||||
func (view *View) RefreshScreen() {
|
func (view *View) RefreshScreen() {
|
||||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||||
|
|
||||||
view.drawBackground()
|
view.drawBoardBoarder()
|
||||||
|
|
||||||
|
if engine.editMode {
|
||||||
|
if edit.boardSize {
|
||||||
|
board.DrawBoard()
|
||||||
|
view.drawEditTextsBoardSize()
|
||||||
|
} else {
|
||||||
|
board.DrawBoard()
|
||||||
|
edit.DrawCursor()
|
||||||
|
view.drawEditTexts()
|
||||||
|
}
|
||||||
|
termbox.Flush()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
view.drawPreviewBoarder()
|
||||||
view.drawTexts()
|
view.drawTexts()
|
||||||
|
|
||||||
if engine.previewBoard {
|
if engine.previewBoard {
|
||||||
board.DrawBoard()
|
board.DrawBoard()
|
||||||
view.drawGameOver()
|
view.drawGameOver()
|
||||||
} else if engine.gameOver {
|
termbox.Flush()
|
||||||
view.drawGameOver()
|
return
|
||||||
view.drawRankingScores()
|
|
||||||
} else if engine.paused {
|
|
||||||
view.drawPaused()
|
|
||||||
} else {
|
|
||||||
board.DrawBoard()
|
|
||||||
board.DrawPreviewMino()
|
|
||||||
board.DrawDropMino()
|
|
||||||
board.DrawCurrentMino()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if engine.gameOver {
|
||||||
|
view.drawGameOver()
|
||||||
|
view.drawRankingScores()
|
||||||
|
termbox.Flush()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if engine.paused {
|
||||||
|
view.drawPaused()
|
||||||
|
termbox.Flush()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
board.DrawBoard()
|
||||||
|
board.DrawPreviewMino()
|
||||||
|
board.DrawDropMino()
|
||||||
|
board.DrawCurrentMino()
|
||||||
termbox.Flush()
|
termbox.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawBackground draws the background
|
// drawBoard draws the board boarder
|
||||||
func (view *View) drawBackground() {
|
func (view *View) drawBoardBoarder() {
|
||||||
// playing board
|
// playing board
|
||||||
xOffset := boardXOffset
|
xOffset := boardXOffset
|
||||||
yOffset := boardYOffset
|
yOffset := boardYOffset
|
||||||
|
@ -70,12 +94,14 @@ func (view *View) drawBackground() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// piece preview
|
// drawPreviewBoarder draws the preview boarder
|
||||||
xOffset = boardXOffset + board.width*2 + 8
|
func (view *View) drawPreviewBoarder() {
|
||||||
yOffset = boardYOffset
|
xOffset := boardXOffset + board.width*2 + 8
|
||||||
xEnd = xOffset + 14
|
yOffset := boardYOffset
|
||||||
yEnd = yOffset + 6
|
xEnd := xOffset + 14
|
||||||
|
yEnd := yOffset + 6
|
||||||
for x := xOffset; x < xEnd; x++ {
|
for x := xOffset; x < xEnd; x++ {
|
||||||
for y := yOffset; y < yEnd; y++ {
|
for y := yOffset; y < yEnd; y++ {
|
||||||
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 ||
|
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 ||
|
||||||
|
@ -112,10 +138,6 @@ func (view *View) drawTexts() {
|
||||||
// ascii arrow characters add extra two spaces
|
// ascii arrow characters add extra two spaces
|
||||||
view.drawText(xOffset, yOffset, "← - left", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "← - left", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
yOffset++
|
yOffset++
|
||||||
view.drawText(xOffset, yOffset, "z - rotate left", termbox.ColorWhite, termbox.ColorBlack)
|
|
||||||
yOffset++
|
|
||||||
view.drawText(xOffset, yOffset, "x - rotate right", termbox.ColorWhite, termbox.ColorBlack)
|
|
||||||
yOffset++
|
|
||||||
view.drawText(xOffset, yOffset, "→ - right", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "→ - right", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
yOffset++
|
yOffset++
|
||||||
view.drawText(xOffset, yOffset, "↓ - soft drop", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "↓ - soft drop", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
@ -124,21 +146,116 @@ func (view *View) drawTexts() {
|
||||||
yOffset++
|
yOffset++
|
||||||
view.drawText(xOffset, yOffset, "sbar - hard drop", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "sbar - hard drop", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
yOffset++
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "z - rotate left", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "x - rotate right", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
view.drawText(xOffset, yOffset, "p - pause", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "p - pause", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
yOffset++
|
yOffset++
|
||||||
view.drawText(xOffset, yOffset, "q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
view.drawText(xOffset, yOffset, "q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drawEditTexts draws the edit text
|
||||||
|
func (view *View) drawEditTexts() {
|
||||||
|
xOffset := boardXOffset + board.width*2 + 8
|
||||||
|
yOffset := boardYOffset
|
||||||
|
|
||||||
|
view.drawText(xOffset, yOffset, "Name:", termbox.ColorWhite, termbox.ColorBlue)
|
||||||
|
view.drawText(xOffset+7, yOffset, boards[board.boardsIndex].name, termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "Saved:", termbox.ColorWhite, termbox.ColorBlue)
|
||||||
|
if edit.saved {
|
||||||
|
view.drawText(xOffset+7, yOffset, "yes", termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
} else {
|
||||||
|
view.drawText(xOffset+7, yOffset, "no", termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
}
|
||||||
|
|
||||||
|
yOffset += 2
|
||||||
|
|
||||||
|
// ascii arrow characters add extra two spaces
|
||||||
|
view.drawText(xOffset, yOffset, "← - left", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "→ - right", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "↓ - down", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "↑ - up", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "z - rotate left", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "x - rotate right", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "c - cyan", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "b - blue", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "w - white", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "e - yellow", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "g - green", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "a - magenta", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "r - red", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "f - free", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl b - change board size", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl s - save board", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl n - save board as new", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl k - delete board", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl o - empty board", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "ctrl q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// drawEditTextsBoardSize draws the edit text for board size mode
|
||||||
|
func (view *View) drawEditTextsBoardSize() {
|
||||||
|
xOffset := boardXOffset + board.width*2 + 8
|
||||||
|
yOffset := boardYOffset
|
||||||
|
|
||||||
|
view.drawText(xOffset, yOffset, "Name:", termbox.ColorWhite, termbox.ColorBlue)
|
||||||
|
view.drawText(xOffset+7, yOffset, boards[board.boardsIndex].name, termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
|
||||||
|
yOffset += 2
|
||||||
|
|
||||||
|
view.drawText(xOffset, yOffset, "Size:", termbox.ColorWhite, termbox.ColorBlue)
|
||||||
|
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%2d X %2d", edit.width, edit.height), termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
|
||||||
|
yOffset += 2
|
||||||
|
|
||||||
|
// ascii arrow characters add extra two spaces
|
||||||
|
view.drawText(xOffset, yOffset, "← - board width decrement", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "→ - board width increment", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "↓ - board height decrement", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "↑ - board height increment", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
yOffset++
|
||||||
|
view.drawText(xOffset, yOffset, "q - done", termbox.ColorWhite, termbox.ColorBlack)
|
||||||
|
}
|
||||||
|
|
||||||
// DrawPreviewMinoBlock draws the preview mino
|
// DrawPreviewMinoBlock draws the preview mino
|
||||||
func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, rotation int, length int) {
|
func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, rotation int, length int) {
|
||||||
var char1 rune
|
char1 := ' '
|
||||||
var char2 rune
|
char2 := ' '
|
||||||
if rotation < 2 {
|
switch rotation {
|
||||||
char1 = '▓'
|
case 0:
|
||||||
char2 = ' '
|
char1 = '▄'
|
||||||
} else {
|
char2 = '▄'
|
||||||
char1 = ' '
|
case 1:
|
||||||
char2 = '▓'
|
char1 = '█'
|
||||||
|
case 2:
|
||||||
|
char1 = '▀'
|
||||||
|
char2 = '▀'
|
||||||
|
case 3:
|
||||||
|
char2 = '█'
|
||||||
}
|
}
|
||||||
xOffset := 2*x + 2*board.width + boardXOffset + 11 + (4 - length)
|
xOffset := 2*x + 2*board.width + boardXOffset + 11 + (4 - length)
|
||||||
termbox.SetCell(xOffset, y+boardYOffset+2, char1, color, color^termbox.AttrBold)
|
termbox.SetCell(xOffset, y+boardYOffset+2, char1, color, color^termbox.AttrBold)
|
||||||
|
@ -147,14 +264,19 @@ func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, ro
|
||||||
|
|
||||||
// DrawBlock draws a block
|
// DrawBlock draws a block
|
||||||
func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int) {
|
func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int) {
|
||||||
var char1 rune
|
char1 := ' '
|
||||||
var char2 rune
|
char2 := ' '
|
||||||
if rotation < 2 {
|
switch rotation {
|
||||||
char1 = '▓'
|
case 0:
|
||||||
char2 = ' '
|
char1 = '▄'
|
||||||
} else {
|
char2 = '▄'
|
||||||
char1 = ' '
|
case 1:
|
||||||
char2 = '▓'
|
char1 = '█'
|
||||||
|
case 2:
|
||||||
|
char1 = '▀'
|
||||||
|
char2 = '▀'
|
||||||
|
case 3:
|
||||||
|
char2 = '█'
|
||||||
}
|
}
|
||||||
if color == blankColor {
|
if color == blankColor {
|
||||||
// blankColor means drop Mino
|
// blankColor means drop Mino
|
||||||
|
@ -304,3 +426,10 @@ func (view *View) colorizeLine(y int, color termbox.Attribute) {
|
||||||
termbox.SetCell(x*2+boardXOffset+3, y+boardYOffset+1, ' ', termbox.ColorDefault, color)
|
termbox.SetCell(x*2+boardXOffset+3, y+boardYOffset+1, ' ', termbox.ColorDefault, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawCursor draws current cursor location
|
||||||
|
func (view *View) DrawCursor(x int, y int, color termbox.Attribute) {
|
||||||
|
termbox.SetCell(x*2+boardXOffset+2, y+boardYOffset+1, '◄', color^termbox.AttrBold, termbox.ColorBlack^termbox.AttrBold)
|
||||||
|
termbox.SetCell(x*2+boardXOffset+3, y+boardYOffset+1, '►', color^termbox.AttrBold, termbox.ColorBlack^termbox.AttrBold)
|
||||||
|
termbox.Flush()
|
||||||
|
}
|
||||||
|
|