Added edit mode

Added peace symbol
This commit is contained in:
MichaelS11 2019-01-09 18:30:45 -08:00
parent edbeeee440
commit ab5692a2da
18 changed files with 1363 additions and 1173 deletions

View File

@ -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

View File

@ -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++ {

1783
boards.go

File diff suppressed because it is too large Load Diff

207
edit.go Normal file
View File

@ -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()
}

View File

@ -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
}

View File

@ -11,7 +11,9 @@ 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
) )

View File

@ -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,8 +172,6 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
case termbox.KeyArrowRight: case termbox.KeyArrowRight:
board.MinoMoveRight() board.MinoMoveRight()
} }
} else {
switch event.Ch {
case 'z': case 'z':
board.MinoRotateLeft() board.MinoRotateLeft()
case 'x': case 'x':
@ -113,6 +181,5 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
case 'i': case 'i':
engine.EnabledAi() engine.EnabledAi()
} }
}
} }

View File

@ -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()

BIN
screenshots/editmode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screenshots/heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
screenshots/highscores.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

BIN
screenshots/tetris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -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()
} }

195
view.go
View File

@ -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()
return
}
if engine.gameOver {
view.drawGameOver() view.drawGameOver()
view.drawRankingScores() view.drawRankingScores()
} else if engine.paused { termbox.Flush()
return
}
if engine.paused {
view.drawPaused() view.drawPaused()
} else { termbox.Flush()
return
}
board.DrawBoard() board.DrawBoard()
board.DrawPreviewMino() board.DrawPreviewMino()
board.DrawDropMino() board.DrawDropMino()
board.DrawCurrentMino() 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()
}