Converted to tcell for terminal
This commit is contained in:
parent
39e38c05d9
commit
ab91e02f03
18
ai.go
18
ai.go
|
@ -1,9 +1,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewAi creates a new AI
|
||||
func NewAi() *Ai {
|
||||
ai := Ai{}
|
||||
|
@ -54,15 +50,15 @@ func (ai *Ai) GetBestQueue() {
|
|||
}
|
||||
|
||||
switch currentMino.minoRotation[0][1][1] {
|
||||
case termbox.ColorCyan, termbox.ColorGreen, termbox.ColorRed:
|
||||
case colorCyan, colorGreen, colorRed:
|
||||
rotations1 = 2
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
rotations1 = 1
|
||||
}
|
||||
switch previewMino.minoRotation[0][1][1] {
|
||||
case termbox.ColorCyan, termbox.ColorGreen, termbox.ColorRed:
|
||||
case colorCyan, colorGreen, colorRed:
|
||||
rotations2 = 2
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
rotations2 = 1
|
||||
}
|
||||
|
||||
|
@ -190,7 +186,7 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int
|
|||
for j = 0; j < board.height; j++ {
|
||||
board.fullLinesY[j] = true
|
||||
for i = 0; i < board.width; i++ {
|
||||
if board.colors[i][j] == blankColor && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) {
|
||||
if board.colors[i][j] == colorBlank && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) {
|
||||
board.fullLinesY[j] = false
|
||||
break
|
||||
}
|
||||
|
@ -210,7 +206,7 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int
|
|||
if board.fullLinesY[j] {
|
||||
fullLinesFound++
|
||||
} else {
|
||||
if board.colors[i][j] != blankColor || mino1.isMinoAtLocation(i, j) || mino2.isMinoAtLocation(i, j) {
|
||||
if board.colors[i][j] != colorBlank || mino1.isMinoAtLocation(i, j) || mino2.isMinoAtLocation(i, j) {
|
||||
found = j
|
||||
break
|
||||
}
|
||||
|
@ -229,7 +225,7 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int
|
|||
foundLast = found + fullLines - fullLinesFound
|
||||
|
||||
for j++; j < board.height; j++ {
|
||||
if board.colors[i][j] == blankColor && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) {
|
||||
if board.colors[i][j] == colorBlank && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) {
|
||||
holes++
|
||||
}
|
||||
}
|
||||
|
|
90
board.go
90
board.go
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// NewBoard creates a new clear board
|
||||
|
@ -20,14 +20,14 @@ func ChangeBoardSize(width int, height int) {
|
|||
}
|
||||
|
||||
newBoard := &Board{width: width, height: height, boardsIndex: board.boardsIndex}
|
||||
newBoard.colors = make([][]termbox.Attribute, width)
|
||||
newBoard.colors = make([][]tcell.Color, width)
|
||||
for i := 0; i < width; i++ {
|
||||
newBoard.colors[i] = make([]termbox.Attribute, height)
|
||||
newBoard.colors[i] = make([]tcell.Color, 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.colors[i][j] = colorBlank
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ func ChangeBoardSize(width int, height int) {
|
|||
func (board *Board) Clear() {
|
||||
board.width = len(boards[board.boardsIndex].colors)
|
||||
board.height = len(boards[board.boardsIndex].colors[0])
|
||||
board.colors = make([][]termbox.Attribute, board.width)
|
||||
board.colors = make([][]tcell.Color, board.width)
|
||||
for i := 0; i < board.width; i++ {
|
||||
board.colors[i] = make([]termbox.Attribute, board.height)
|
||||
board.colors[i] = make([]tcell.Color, board.height)
|
||||
copy(board.colors[i], boards[board.boardsIndex].colors[i])
|
||||
}
|
||||
board.rotation = make([][]int, board.width)
|
||||
|
@ -72,7 +72,7 @@ func (board *Board) Clear() {
|
|||
func (board *Board) EmptyBoard() {
|
||||
for i := 0; i < board.width; i++ {
|
||||
for j := 0; j < board.height; j++ {
|
||||
board.colors[i][j] = blankColor
|
||||
board.colors[i][j] = colorBlank
|
||||
}
|
||||
}
|
||||
for i := 0; i < board.width; i++ {
|
||||
|
@ -272,7 +272,7 @@ func (board *Board) fullLines() []int {
|
|||
// isFullLine checks if line is full
|
||||
func (board *Board) isFullLine(j int) bool {
|
||||
for i := 0; i < board.width; i++ {
|
||||
if board.colors[i][j] == blankColor {
|
||||
if board.colors[i][j] == colorBlank {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ func (board *Board) isFullLine(j int) bool {
|
|||
// deleteLine deletes the line
|
||||
func (board *Board) deleteLine(line int) {
|
||||
for i := 0; i < board.width; i++ {
|
||||
board.colors[i][line] = blankColor
|
||||
board.colors[i][line] = colorBlank
|
||||
}
|
||||
for j := line; j > 0; j-- {
|
||||
for i := 0; i < board.width; i++ {
|
||||
|
@ -291,12 +291,12 @@ func (board *Board) deleteLine(line int) {
|
|||
}
|
||||
}
|
||||
for i := 0; i < board.width; i++ {
|
||||
board.colors[i][0] = blankColor
|
||||
board.colors[i][0] = colorBlank
|
||||
}
|
||||
}
|
||||
|
||||
// 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 tcell.Color, rotation int) {
|
||||
board.colors[x][y] = color
|
||||
if rotation < 0 {
|
||||
return
|
||||
|
@ -337,7 +337,7 @@ func (board *Board) ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool {
|
|||
}
|
||||
}
|
||||
if y > -1 {
|
||||
if board.colors[x][y] != blankColor {
|
||||
if board.colors[x][y] != colorBlank {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ func ValidDisplayLocation(x int, y int) bool {
|
|||
func (board *Board) DrawBoard() {
|
||||
for i := 0; i < board.width; i++ {
|
||||
for j := 0; j < board.height; j++ {
|
||||
if board.colors[i][j] != blankColor {
|
||||
if board.colors[i][j] != colorBlank {
|
||||
view.DrawBlock(i, j, board.colors[i][j], board.rotation[i][j])
|
||||
}
|
||||
}
|
||||
|
@ -393,21 +393,21 @@ func (board *Board) printDebugBoard() {
|
|||
for j := 0; j < board.height; j++ {
|
||||
for i := 0; i < board.width; i++ {
|
||||
switch board.colors[i][j] {
|
||||
case blankColor:
|
||||
case colorBlank:
|
||||
fmt.Print(".")
|
||||
case termbox.ColorBlue:
|
||||
case colorBlue:
|
||||
fmt.Print("B")
|
||||
case termbox.ColorCyan:
|
||||
case colorCyan:
|
||||
fmt.Print("C")
|
||||
case termbox.ColorGreen:
|
||||
case colorGreen:
|
||||
fmt.Print("G")
|
||||
case termbox.ColorMagenta:
|
||||
case colorMagenta:
|
||||
fmt.Print("M")
|
||||
case termbox.ColorRed:
|
||||
case colorRed:
|
||||
fmt.Print("R")
|
||||
case termbox.ColorWhite:
|
||||
case colorWhite:
|
||||
fmt.Print("W")
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
fmt.Print("Y")
|
||||
default:
|
||||
fmt.Print("U")
|
||||
|
@ -423,21 +423,21 @@ func (board *Board) getDebugBoard() []string {
|
|||
for j := 0; j < board.height; j++ {
|
||||
for i := 0; i < board.width; i++ {
|
||||
switch board.colors[i][j] {
|
||||
case blankColor:
|
||||
case colorBlank:
|
||||
lines[j] += "."
|
||||
case termbox.ColorBlue:
|
||||
case colorBlue:
|
||||
lines[j] += "B"
|
||||
case termbox.ColorCyan:
|
||||
case colorCyan:
|
||||
lines[j] += "C"
|
||||
case termbox.ColorGreen:
|
||||
case colorGreen:
|
||||
lines[j] += "G"
|
||||
case termbox.ColorMagenta:
|
||||
case colorMagenta:
|
||||
lines[j] += "M"
|
||||
case termbox.ColorRed:
|
||||
case colorRed:
|
||||
lines[j] += "R"
|
||||
case termbox.ColorWhite:
|
||||
case colorWhite:
|
||||
lines[j] += "W"
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
lines[j] += "Y"
|
||||
default:
|
||||
lines[j] += "U"
|
||||
|
@ -453,40 +453,40 @@ func (board *Board) getDebugBoardWithMino(mino *Mino) []string {
|
|||
for j := 0; j < board.height; j++ {
|
||||
for i := 0; i < board.width; i++ {
|
||||
switch mino.getMinoColorAtLocation(i, j) {
|
||||
case blankColor:
|
||||
case colorBlank:
|
||||
switch board.colors[i][j] {
|
||||
case blankColor:
|
||||
case colorBlank:
|
||||
lines[j] += "."
|
||||
case termbox.ColorBlue:
|
||||
case colorBlue:
|
||||
lines[j] += "B"
|
||||
case termbox.ColorCyan:
|
||||
case colorCyan:
|
||||
lines[j] += "C"
|
||||
case termbox.ColorGreen:
|
||||
case colorGreen:
|
||||
lines[j] += "G"
|
||||
case termbox.ColorMagenta:
|
||||
case colorMagenta:
|
||||
lines[j] += "M"
|
||||
case termbox.ColorRed:
|
||||
case colorRed:
|
||||
lines[j] += "R"
|
||||
case termbox.ColorWhite:
|
||||
case colorWhite:
|
||||
lines[j] += "W"
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
lines[j] += "Y"
|
||||
default:
|
||||
lines[j] += "U"
|
||||
}
|
||||
case termbox.ColorBlue:
|
||||
case colorBlue:
|
||||
lines[j] += "b"
|
||||
case termbox.ColorCyan:
|
||||
case colorCyan:
|
||||
lines[j] += "c"
|
||||
case termbox.ColorGreen:
|
||||
case colorGreen:
|
||||
lines[j] += "g"
|
||||
case termbox.ColorMagenta:
|
||||
case colorMagenta:
|
||||
lines[j] += "m"
|
||||
case termbox.ColorRed:
|
||||
case colorRed:
|
||||
lines[j] += "r"
|
||||
case termbox.ColorWhite:
|
||||
case colorWhite:
|
||||
lines[j] += "w"
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
lines[j] += "y"
|
||||
default:
|
||||
lines[j] += "u"
|
||||
|
|
58
boards.go
58
boards.go
|
@ -6,7 +6,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// loadBoards loads the internal boards
|
||||
|
@ -24,29 +24,29 @@ func loadBoards() error {
|
|||
|
||||
for boardNum, boardLoad := range boardsJSON {
|
||||
aBoards := Boards{name: boardLoad.Name}
|
||||
aBoards.colors = make([][]termbox.Attribute, len(boardLoad.Mino))
|
||||
aBoards.colors = make([][]tcell.Color, len(boardLoad.Mino))
|
||||
aBoards.rotation = boardLoad.Rotation
|
||||
|
||||
for i := 0; i < len(boardLoad.Mino); i++ {
|
||||
aBoards.colors[i] = make([]termbox.Attribute, len(boardLoad.Mino[i]))
|
||||
aBoards.colors[i] = make([]tcell.Color, len(boardLoad.Mino[i]))
|
||||
for j := 0; j < len(boardLoad.Mino[i]); j++ {
|
||||
switch boardLoad.Mino[i][j] {
|
||||
case "b":
|
||||
aBoards.colors[i][j] = blankColor
|
||||
aBoards.colors[i][j] = colorBlank
|
||||
case "i":
|
||||
aBoards.colors[i][j] = termbox.ColorCyan
|
||||
aBoards.colors[i][j] = colorCyan
|
||||
case "j":
|
||||
aBoards.colors[i][j] = termbox.ColorBlue
|
||||
aBoards.colors[i][j] = colorBlue
|
||||
case "l":
|
||||
aBoards.colors[i][j] = termbox.ColorWhite
|
||||
aBoards.colors[i][j] = colorWhite
|
||||
case "o":
|
||||
aBoards.colors[i][j] = termbox.ColorYellow
|
||||
aBoards.colors[i][j] = colorYellow
|
||||
case "s":
|
||||
aBoards.colors[i][j] = termbox.ColorGreen
|
||||
aBoards.colors[i][j] = colorGreen
|
||||
case "t":
|
||||
aBoards.colors[i][j] = termbox.ColorMagenta
|
||||
aBoards.colors[i][j] = colorMagenta
|
||||
case "z":
|
||||
aBoards.colors[i][j] = termbox.ColorRed
|
||||
aBoards.colors[i][j] = colorRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,29 +90,29 @@ func loadUserBoards() error {
|
|||
|
||||
for _, boardLoad := range settings.Boards {
|
||||
aBoards := Boards{name: boardLoad.Name}
|
||||
aBoards.colors = make([][]termbox.Attribute, len(boardLoad.Mino))
|
||||
aBoards.colors = make([][]tcell.Color, len(boardLoad.Mino))
|
||||
aBoards.rotation = boardLoad.Rotation
|
||||
|
||||
for i := 0; i < len(boardLoad.Mino); i++ {
|
||||
aBoards.colors[i] = make([]termbox.Attribute, len(boardLoad.Mino[i]))
|
||||
aBoards.colors[i] = make([]tcell.Color, len(boardLoad.Mino[i]))
|
||||
for j := 0; j < len(boardLoad.Mino[i]); j++ {
|
||||
switch boardLoad.Mino[i][j] {
|
||||
case "b":
|
||||
aBoards.colors[i][j] = blankColor
|
||||
aBoards.colors[i][j] = colorBlank
|
||||
case "i":
|
||||
aBoards.colors[i][j] = termbox.ColorCyan
|
||||
aBoards.colors[i][j] = colorCyan
|
||||
case "j":
|
||||
aBoards.colors[i][j] = termbox.ColorBlue
|
||||
aBoards.colors[i][j] = colorBlue
|
||||
case "l":
|
||||
aBoards.colors[i][j] = termbox.ColorWhite
|
||||
aBoards.colors[i][j] = colorWhite
|
||||
case "o":
|
||||
aBoards.colors[i][j] = termbox.ColorYellow
|
||||
aBoards.colors[i][j] = colorYellow
|
||||
case "s":
|
||||
aBoards.colors[i][j] = termbox.ColorGreen
|
||||
aBoards.colors[i][j] = colorGreen
|
||||
case "t":
|
||||
aBoards.colors[i][j] = termbox.ColorMagenta
|
||||
aBoards.colors[i][j] = colorMagenta
|
||||
case "z":
|
||||
aBoards.colors[i][j] = termbox.ColorRed
|
||||
aBoards.colors[i][j] = colorRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,21 +140,21 @@ func saveUserBoards() error {
|
|||
aBoards.Mino[i] = make([]string, len(boards[x].colors[i]))
|
||||
for j := 0; j < len(boards[x].colors[i]); j++ {
|
||||
switch boards[x].colors[i][j] {
|
||||
case blankColor:
|
||||
case colorBlank:
|
||||
aBoards.Mino[i][j] = "b"
|
||||
case termbox.ColorCyan:
|
||||
case colorCyan:
|
||||
aBoards.Mino[i][j] = "i"
|
||||
case termbox.ColorBlue:
|
||||
case colorBlue:
|
||||
aBoards.Mino[i][j] = "j"
|
||||
case termbox.ColorWhite:
|
||||
case colorWhite:
|
||||
aBoards.Mino[i][j] = "l"
|
||||
case termbox.ColorYellow:
|
||||
case colorYellow:
|
||||
aBoards.Mino[i][j] = "o"
|
||||
case termbox.ColorGreen:
|
||||
case colorGreen:
|
||||
aBoards.Mino[i][j] = "s"
|
||||
case termbox.ColorMagenta:
|
||||
case colorMagenta:
|
||||
aBoards.Mino[i][j] = "t"
|
||||
case termbox.ColorRed:
|
||||
case colorRed:
|
||||
aBoards.Mino[i][j] = "z"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
var (
|
||||
screen tcell.Screen
|
||||
x = 0
|
||||
y = 1
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
screen, err = tcell.NewScreen()
|
||||
if err != nil {
|
||||
fmt.Println("NewScreen error:", err)
|
||||
}
|
||||
err = screen.Init()
|
||||
if err != nil {
|
||||
fmt.Println("screen Init error:", err)
|
||||
}
|
||||
|
||||
screen.Clear()
|
||||
|
||||
for i := 0; i < 379; i++ {
|
||||
printNum(i)
|
||||
style := tcell.StyleDefault.Foreground(tcell.Color(i)).Background(tcell.Color(i)).Dim(true)
|
||||
screen.SetContent(x, y, '▄', nil, style)
|
||||
x++
|
||||
screen.SetContent(x, y, '▄', nil, style)
|
||||
x += 2
|
||||
if x > 80 {
|
||||
x = 0
|
||||
y += 2
|
||||
}
|
||||
if i == 15 {
|
||||
i = 255
|
||||
}
|
||||
}
|
||||
|
||||
screen.Show()
|
||||
}
|
||||
|
||||
func printNum(num int) {
|
||||
word := strconv.FormatInt(int64(num), 10) + ":"
|
||||
if num < 10 {
|
||||
word = " " + word
|
||||
} else if num < 100 {
|
||||
word = " " + word
|
||||
}
|
||||
if len(word)+x+2 > 80 {
|
||||
x = 0
|
||||
y += 2
|
||||
}
|
||||
style := tcell.StyleDefault.Foreground(tcell.ColorLightGray).Background(tcell.ColorBlack)
|
||||
for _, char := range word {
|
||||
screen.SetContent(x, y, char, nil, style)
|
||||
x++
|
||||
}
|
||||
|
||||
}
|
7
edit.go
7
edit.go
|
@ -3,7 +3,7 @@ package main
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// NewEdit creates a new edit mode
|
||||
|
@ -72,6 +72,7 @@ func (edit *Edit) BoardHeightDecrement() {
|
|||
// ChangeBoardSize create new board
|
||||
func (edit *Edit) ChangeBoardSize() {
|
||||
ChangeBoardSize(edit.width, edit.height)
|
||||
edit.saved = false
|
||||
edit.boardSize = false
|
||||
}
|
||||
|
||||
|
@ -125,7 +126,7 @@ func (edit *Edit) CursorLeft() {
|
|||
}
|
||||
|
||||
// SetColor sets the board color
|
||||
func (edit *Edit) SetColor(color termbox.Attribute) {
|
||||
func (edit *Edit) SetColor(color tcell.Color) {
|
||||
if edit.moved {
|
||||
edit.moved = false
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ func (edit *Edit) SaveBoard() {
|
|||
// 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))
|
||||
aBoards.colors = make([][]tcell.Color, len(board.colors))
|
||||
for i := 0; i < len(board.colors); i++ {
|
||||
aBoards.colors[i] = append(aBoards.colors[i], board.colors[i]...)
|
||||
}
|
||||
|
|
90
engine.go
90
engine.go
|
@ -3,36 +3,67 @@ package main
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// EventEngineStopRun stop the run of the engine
|
||||
type EventEngineStopRun struct {
|
||||
EventGame
|
||||
}
|
||||
|
||||
// NewEngine creates new engine
|
||||
func NewEngine() {
|
||||
engine = &Engine{
|
||||
chanStop: make(chan struct{}, 1),
|
||||
gameOver: true,
|
||||
tickTime: time.Hour,
|
||||
ai: NewAi(),
|
||||
chanStop: make(chan struct{}),
|
||||
chanEventKey: make(chan *tcell.EventKey, 8),
|
||||
mode: engineModeGameOver,
|
||||
tickTime: time.Hour,
|
||||
ranking: NewRanking(),
|
||||
ai: NewAi(),
|
||||
}
|
||||
board.Clear()
|
||||
go engine.Run()
|
||||
}
|
||||
|
||||
// Run runs the engine
|
||||
func (engine *Engine) Run() {
|
||||
logger.Println("Engine Run start")
|
||||
|
||||
var event *termbox.Event
|
||||
var event tcell.Event
|
||||
|
||||
loop:
|
||||
for {
|
||||
event = screen.PollEvent()
|
||||
switch eventType := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
select {
|
||||
case engine.chanEventKey <- eventType:
|
||||
default:
|
||||
}
|
||||
case *EventEngineStopRun:
|
||||
break loop
|
||||
case *tcell.EventResize:
|
||||
view.RefreshScreen()
|
||||
default:
|
||||
logger.Printf("event type %T", eventType)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Println("Engine Run end")
|
||||
}
|
||||
|
||||
// Start the game
|
||||
func (engine *Engine) Start() {
|
||||
logger.Println("Engine Start start")
|
||||
|
||||
engine.timer = time.NewTimer(engine.tickTime)
|
||||
engine.timer.Stop()
|
||||
engine.aiTimer = time.NewTimer(engine.tickTime)
|
||||
engine.aiTimer.Stop()
|
||||
|
||||
engine.ranking = NewRanking()
|
||||
board.Clear()
|
||||
view.RefreshScreen()
|
||||
|
||||
engine.keyInput = NewKeyInput()
|
||||
go engine.keyInput.Run()
|
||||
var eventKey *tcell.EventKey
|
||||
|
||||
loop:
|
||||
for {
|
||||
|
@ -41,8 +72,8 @@ loop:
|
|||
break loop
|
||||
default:
|
||||
select {
|
||||
case event = <-engine.keyInput.chanKeyInput:
|
||||
engine.keyInput.ProcessEvent(event)
|
||||
case eventKey = <-engine.chanEventKey:
|
||||
engine.ProcessEventKey(eventKey)
|
||||
view.RefreshScreen()
|
||||
case <-engine.timer.C:
|
||||
engine.tick()
|
||||
|
@ -55,15 +86,18 @@ loop:
|
|||
}
|
||||
}
|
||||
|
||||
logger.Println("Engine Run end")
|
||||
screen.PostEventWait(&EventEngineStopRun{})
|
||||
|
||||
logger.Println("Engine Start end")
|
||||
}
|
||||
|
||||
// Stop stops the engine
|
||||
// Stop the game
|
||||
func (engine *Engine) Stop() {
|
||||
logger.Println("Engine Stop start")
|
||||
|
||||
if !engine.stopped {
|
||||
engine.stopped = true
|
||||
engine.mode = engineModeStopped
|
||||
close(engine.chanStop)
|
||||
}
|
||||
engine.timer.Stop()
|
||||
|
@ -72,7 +106,7 @@ func (engine *Engine) Stop() {
|
|||
logger.Println("Engine Stop end")
|
||||
}
|
||||
|
||||
// Pause pauses the engine
|
||||
// Pause the game
|
||||
func (engine *Engine) Pause() {
|
||||
if !engine.timer.Stop() {
|
||||
select {
|
||||
|
@ -86,21 +120,23 @@ func (engine *Engine) Pause() {
|
|||
default:
|
||||
}
|
||||
}
|
||||
engine.paused = true
|
||||
engine.mode = engineModePaused
|
||||
}
|
||||
|
||||
// UnPause resumes running the engine
|
||||
// UnPause the game
|
||||
func (engine *Engine) UnPause() {
|
||||
engine.timer.Reset(engine.tickTime)
|
||||
if engine.aiEnabled {
|
||||
engine.aiTimer.Reset(engine.tickTime / aiTickDivider)
|
||||
engine.mode = engineModeRunWithAI
|
||||
} else {
|
||||
engine.mode = engineModeRun
|
||||
}
|
||||
engine.paused = false
|
||||
}
|
||||
|
||||
// PreviewBoard sets previewBoard to true
|
||||
func (engine *Engine) PreviewBoard() {
|
||||
engine.previewBoard = true
|
||||
engine.mode = engineModePreview
|
||||
}
|
||||
|
||||
// NewGame resets board and starts a new game
|
||||
|
@ -116,16 +152,17 @@ func (engine *Engine) NewGame() {
|
|||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-engine.keyInput.chanKeyInput:
|
||||
case <-engine.chanEventKey:
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
engine.previewBoard = false
|
||||
engine.gameOver = false
|
||||
if engine.aiEnabled {
|
||||
engine.ai.GetBestQueue()
|
||||
engine.mode = engineModeRunWithAI
|
||||
} else {
|
||||
engine.mode = engineModeRun
|
||||
}
|
||||
engine.UnPause()
|
||||
|
||||
|
@ -223,14 +260,14 @@ func (engine *Engine) GameOver() {
|
|||
logger.Println("Engine GameOver start")
|
||||
|
||||
engine.Pause()
|
||||
engine.gameOver = true
|
||||
engine.mode = engineModeGameOver
|
||||
|
||||
view.ShowGameOverAnimation()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-engine.keyInput.chanKeyInput:
|
||||
case <-engine.chanEventKey:
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
|
@ -252,6 +289,7 @@ func (engine *Engine) EnabledAi() {
|
|||
// DisableAi disables the AI
|
||||
func (engine *Engine) DisableAi() {
|
||||
engine.aiEnabled = false
|
||||
engine.mode = engineModeRun
|
||||
if !engine.aiTimer.Stop() {
|
||||
select {
|
||||
case <-engine.aiTimer.C:
|
||||
|
@ -263,11 +301,11 @@ func (engine *Engine) DisableAi() {
|
|||
// EnabledEditMode enables edit mode
|
||||
func (engine *Engine) EnabledEditMode() {
|
||||
edit.EnabledEditMode()
|
||||
engine.editMode = true
|
||||
engine.mode = engineModeEdit
|
||||
}
|
||||
|
||||
// DisableEditMode disables edit mode
|
||||
func (engine *Engine) DisableEditMode() {
|
||||
edit.DisableEditMode()
|
||||
engine.editMode = false
|
||||
engine.mode = engineModePreview
|
||||
}
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// ProcessEventKey process the key input event
|
||||
func (engine *Engine) ProcessEventKey(eventKey *tcell.EventKey) {
|
||||
if eventKey.Key() == tcell.KeyCtrlL {
|
||||
// Ctrl l (lower case L) to log stack trace
|
||||
buffer := make([]byte, 1<<16)
|
||||
length := runtime.Stack(buffer, true)
|
||||
logger.Println("Stack trace")
|
||||
logger.Println(string(buffer[:length]))
|
||||
return
|
||||
}
|
||||
|
||||
switch engine.mode {
|
||||
|
||||
// edit
|
||||
case engineModeEdit:
|
||||
|
||||
if edit.boardSize {
|
||||
switch eventKey.Key() {
|
||||
case tcell.KeyUp:
|
||||
edit.BoardHeightIncrement()
|
||||
case tcell.KeyDown:
|
||||
edit.BoardHeightDecrement()
|
||||
case tcell.KeyLeft:
|
||||
edit.BoardWidthDecrement()
|
||||
case tcell.KeyRight:
|
||||
edit.BoardWidthIncrement()
|
||||
case tcell.KeyRune:
|
||||
if eventKey.Rune() == 'q' {
|
||||
edit.ChangeBoardSize()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch eventKey.Key() {
|
||||
case tcell.KeyUp:
|
||||
edit.CursorUp()
|
||||
case tcell.KeyDown:
|
||||
edit.CursorDown()
|
||||
case tcell.KeyLeft:
|
||||
edit.CursorLeft()
|
||||
case tcell.KeyRight:
|
||||
edit.CursorRight()
|
||||
case tcell.KeyCtrlB:
|
||||
edit.BoardSizeMode()
|
||||
case tcell.KeyCtrlS:
|
||||
edit.SaveBoard()
|
||||
case tcell.KeyCtrlN:
|
||||
edit.SaveBoardNew()
|
||||
case tcell.KeyCtrlK:
|
||||
edit.DeleteBoard()
|
||||
case tcell.KeyCtrlO:
|
||||
edit.EmptyBoard()
|
||||
case tcell.KeyCtrlQ, tcell.KeyCtrlC:
|
||||
engine.DisableEditMode()
|
||||
case tcell.KeyRune:
|
||||
switch eventKey.Rune() {
|
||||
case 'c':
|
||||
edit.SetColor(colorCyan)
|
||||
case 'b':
|
||||
edit.SetColor(colorBlue)
|
||||
case 'w':
|
||||
edit.SetColor(colorWhite)
|
||||
case 'e':
|
||||
edit.SetColor(colorYellow)
|
||||
case 'g':
|
||||
edit.SetColor(colorGreen)
|
||||
case 'a':
|
||||
edit.SetColor(colorMagenta)
|
||||
case 'r':
|
||||
edit.SetColor(colorRed)
|
||||
case 'f':
|
||||
edit.SetColor(colorBlank)
|
||||
case 'z':
|
||||
edit.RotateLeft()
|
||||
case 'x':
|
||||
edit.RotateRight()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// game over
|
||||
case engineModeGameOver, engineModePreview:
|
||||
|
||||
switch eventKey.Key() {
|
||||
case tcell.KeyCtrlC:
|
||||
engine.Stop()
|
||||
case tcell.KeyLeft:
|
||||
board.PreviousBoard()
|
||||
case tcell.KeyRight:
|
||||
board.NextBoard()
|
||||
case tcell.KeyCtrlE:
|
||||
engine.EnabledEditMode()
|
||||
case tcell.KeyRune:
|
||||
switch eventKey.Rune() {
|
||||
case 'q':
|
||||
engine.Stop()
|
||||
case ' ':
|
||||
engine.NewGame()
|
||||
}
|
||||
}
|
||||
|
||||
// paused
|
||||
case engineModePaused:
|
||||
|
||||
switch eventKey.Rune() {
|
||||
case 'q':
|
||||
engine.Stop()
|
||||
case 'p':
|
||||
engine.UnPause()
|
||||
}
|
||||
|
||||
// run with AI
|
||||
case engineModeRunWithAI:
|
||||
|
||||
switch eventKey.Rune() {
|
||||
case 'q':
|
||||
engine.Stop()
|
||||
case 'p':
|
||||
engine.Pause()
|
||||
case 'i':
|
||||
engine.DisableAi()
|
||||
}
|
||||
|
||||
// run
|
||||
case engineModeRun:
|
||||
|
||||
switch eventKey.Key() {
|
||||
case tcell.KeyUp:
|
||||
board.MinoDrop()
|
||||
case tcell.KeyDown:
|
||||
board.MinoMoveDown()
|
||||
case tcell.KeyLeft:
|
||||
board.MinoMoveLeft()
|
||||
case tcell.KeyRight:
|
||||
board.MinoMoveRight()
|
||||
case tcell.KeyRune:
|
||||
switch eventKey.Rune() {
|
||||
case 'q':
|
||||
engine.Stop()
|
||||
case ' ':
|
||||
board.MinoDrop()
|
||||
case 'z':
|
||||
board.MinoRotateLeft()
|
||||
case 'x':
|
||||
board.MinoRotateRight()
|
||||
case 'p':
|
||||
engine.Pause()
|
||||
case 'i':
|
||||
engine.EnabledAi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
53
globals.go
53
globals.go
|
@ -4,11 +4,10 @@ import (
|
|||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
const (
|
||||
blankColor = termbox.ColorBlack
|
||||
boardXOffset = 4
|
||||
boardYOffset = 2
|
||||
aiTickDivider = 8
|
||||
|
@ -21,13 +20,32 @@ const (
|
|||
MinoCurrent = iota
|
||||
// MinoDrop is for the drop mino
|
||||
MinoDrop = iota
|
||||
|
||||
colorBlank = tcell.ColorBlack
|
||||
colorCyan = tcell.ColorAqua // I
|
||||
colorBlue = tcell.ColorBlue // J
|
||||
colorWhite = tcell.ColorWhite // L
|
||||
colorYellow = tcell.ColorYellow // O
|
||||
colorGreen = tcell.ColorLime // S
|
||||
colorMagenta = tcell.ColorFuchsia // T
|
||||
colorRed = tcell.ColorRed // Z
|
||||
|
||||
engineModeRun engineMode = iota
|
||||
engineModeRunWithAI
|
||||
engineModeStopped
|
||||
engineModeGameOver
|
||||
engineModePaused
|
||||
engineModePreview
|
||||
engineModeEdit
|
||||
)
|
||||
|
||||
type (
|
||||
engineMode int
|
||||
|
||||
// MinoType is the type of mino
|
||||
MinoType int
|
||||
// MinoBlocks is the blocks of the mino
|
||||
MinoBlocks [][]termbox.Attribute
|
||||
MinoBlocks [][]tcell.Color
|
||||
// MinoRotation is the rotation of the mino
|
||||
MinoRotation [4]MinoBlocks
|
||||
|
||||
|
@ -52,7 +70,7 @@ type (
|
|||
boardsIndex int
|
||||
width int
|
||||
height int
|
||||
colors [][]termbox.Attribute
|
||||
colors [][]tcell.Color
|
||||
rotation [][]int
|
||||
previewMino *Mino
|
||||
currentMino *Mino
|
||||
|
@ -63,7 +81,7 @@ type (
|
|||
// Boards holds all the boards
|
||||
Boards struct {
|
||||
name string
|
||||
colors [][]termbox.Attribute
|
||||
colors [][]tcell.Color
|
||||
rotation [][]int
|
||||
}
|
||||
|
||||
|
@ -74,13 +92,6 @@ type (
|
|||
Rotation [][]int
|
||||
}
|
||||
|
||||
// KeyInput is the key input engine
|
||||
KeyInput struct {
|
||||
stopped bool
|
||||
chanStop chan struct{}
|
||||
chanKeyInput chan *termbox.Event
|
||||
}
|
||||
|
||||
// View is the display engine
|
||||
View struct {
|
||||
}
|
||||
|
@ -101,20 +112,17 @@ type (
|
|||
Engine struct {
|
||||
stopped bool
|
||||
chanStop chan struct{}
|
||||
keyInput *KeyInput
|
||||
chanEventKey chan *tcell.EventKey
|
||||
ranking *Ranking
|
||||
timer *time.Timer
|
||||
tickTime time.Duration
|
||||
paused bool
|
||||
gameOver bool
|
||||
previewBoard bool
|
||||
mode engineMode
|
||||
score int
|
||||
level int
|
||||
deleteLines int
|
||||
ai *Ai
|
||||
aiEnabled bool
|
||||
aiTimer *time.Timer
|
||||
editMode bool
|
||||
}
|
||||
|
||||
// Edit is the board edit mode
|
||||
|
@ -132,11 +140,22 @@ type (
|
|||
Settings struct {
|
||||
Boards []BoardsJSON
|
||||
}
|
||||
|
||||
// EventGame is an game event
|
||||
EventGame struct {
|
||||
when time.Time
|
||||
}
|
||||
)
|
||||
|
||||
// When returns event when
|
||||
func (EventGame *EventGame) When() time.Time {
|
||||
return EventGame.when
|
||||
}
|
||||
|
||||
var (
|
||||
baseDir string
|
||||
logger *log.Logger
|
||||
screen tcell.Screen
|
||||
minos *Minos
|
||||
board *Board
|
||||
view *View
|
||||
|
|
185
keyInput.go
185
keyInput.go
|
@ -1,185 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewKeyInput creates a new KeyInput
|
||||
func NewKeyInput() *KeyInput {
|
||||
return &KeyInput{
|
||||
chanStop: make(chan struct{}, 1),
|
||||
chanKeyInput: make(chan *termbox.Event, 8),
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts the KeyInput engine
|
||||
func (keyInput *KeyInput) Run() {
|
||||
logger.Println("KeyInput Run start")
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-keyInput.chanStop:
|
||||
break loop
|
||||
default:
|
||||
}
|
||||
event := termbox.PollEvent()
|
||||
if event.Type == termbox.EventKey && len(keyInput.chanKeyInput) < 8 {
|
||||
select {
|
||||
case <-keyInput.chanStop:
|
||||
break loop
|
||||
case keyInput.chanKeyInput <- &event:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Println("KeyInput Run end")
|
||||
}
|
||||
|
||||
// ProcessEvent process the key input event
|
||||
func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||
if event.Key == termbox.KeyCtrlL {
|
||||
// Ctrl l (lower case L) to log stack trace
|
||||
buffer := make([]byte, 1<<16)
|
||||
length := runtime.Stack(buffer, true)
|
||||
logger.Println("Stack trace")
|
||||
logger.Println(string(buffer[:length]))
|
||||
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 !keyInput.stopped {
|
||||
keyInput.stopped = true
|
||||
close(keyInput.chanStop)
|
||||
}
|
||||
engine.Stop()
|
||||
return
|
||||
}
|
||||
|
||||
if engine.gameOver {
|
||||
if event.Ch == 0 {
|
||||
switch event.Key {
|
||||
case termbox.KeySpace:
|
||||
engine.NewGame()
|
||||
case termbox.KeyArrowLeft:
|
||||
board.PreviousBoard()
|
||||
case termbox.KeyArrowRight:
|
||||
board.NextBoard()
|
||||
case termbox.KeyCtrlE:
|
||||
engine.EnabledEditMode()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if engine.paused {
|
||||
if event.Ch == 'p' {
|
||||
engine.UnPause()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if engine.aiEnabled {
|
||||
switch event.Ch {
|
||||
case 'p':
|
||||
engine.Pause()
|
||||
case 'i':
|
||||
engine.DisableAi()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch event.Ch {
|
||||
case 0:
|
||||
switch event.Key {
|
||||
case termbox.KeySpace:
|
||||
board.MinoDrop()
|
||||
case termbox.KeyArrowUp:
|
||||
board.MinoDrop()
|
||||
case termbox.KeyArrowDown:
|
||||
board.MinoMoveDown()
|
||||
case termbox.KeyArrowLeft:
|
||||
board.MinoMoveLeft()
|
||||
case termbox.KeyArrowRight:
|
||||
board.MinoMoveRight()
|
||||
}
|
||||
case 'z':
|
||||
board.MinoRotateLeft()
|
||||
case 'x':
|
||||
board.MinoRotateRight()
|
||||
case 'p':
|
||||
engine.Pause()
|
||||
case 'i':
|
||||
engine.EnabledAi()
|
||||
}
|
||||
|
||||
}
|
18
mino.go
18
mino.go
|
@ -3,7 +3,7 @@ package main
|
|||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// NewMino creates a new Mino
|
||||
|
@ -100,7 +100,7 @@ func (mino *Mino) ValidLocation(mustBeOnBoard bool) bool {
|
|||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
for j := 0; j < mino.length; j++ {
|
||||
if minoBlocks[i][j] == blankColor {
|
||||
if minoBlocks[i][j] == colorBlank {
|
||||
continue
|
||||
}
|
||||
if !board.ValidBlockLocation(mino.x+i, mino.y+j, mustBeOnBoard) {
|
||||
|
@ -116,7 +116,7 @@ func (mino *Mino) SetOnBoard() {
|
|||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
for j := 0; j < mino.length; j++ {
|
||||
if minoBlocks[i][j] != blankColor {
|
||||
if minoBlocks[i][j] != colorBlank {
|
||||
board.SetColor(mino.x+i, mino.y+j, minoBlocks[i][j], mino.rotation)
|
||||
}
|
||||
}
|
||||
|
@ -128,12 +128,12 @@ func (mino *Mino) DrawMino(minoType MinoType) {
|
|||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
for j := 0; j < mino.length; j++ {
|
||||
if minoBlocks[i][j] != blankColor {
|
||||
if minoBlocks[i][j] != colorBlank {
|
||||
switch minoType {
|
||||
case MinoPreview:
|
||||
view.DrawPreviewMinoBlock(i, j, minoBlocks[i][j], mino.rotation, mino.length)
|
||||
case MinoDrop:
|
||||
view.DrawBlock(mino.x+i, mino.y+j, blankColor, mino.rotation)
|
||||
view.DrawBlock(mino.x+i, mino.y+j, colorBlank, mino.rotation)
|
||||
case MinoCurrent:
|
||||
if ValidDisplayLocation(mino.x+i, mino.y+j) {
|
||||
view.DrawBlock(mino.x+i, mino.y+j, minoBlocks[i][j], mino.rotation)
|
||||
|
@ -149,7 +149,7 @@ func (mino *Mino) minoOverlap(mino1 *Mino) bool {
|
|||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
for j := 0; j < mino.length; j++ {
|
||||
if minoBlocks[i][j] == blankColor {
|
||||
if minoBlocks[i][j] == colorBlank {
|
||||
continue
|
||||
}
|
||||
if mino1.isMinoAtLocation(mino.x+i, mino.y+j) {
|
||||
|
@ -168,7 +168,7 @@ func (mino *Mino) isMinoAtLocation(x int, y int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if mino.minoRotation[mino.rotation][xIndex][yIndex] != blankColor {
|
||||
if mino.minoRotation[mino.rotation][xIndex][yIndex] != colorBlank {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -176,11 +176,11 @@ func (mino *Mino) isMinoAtLocation(x int, y int) bool {
|
|||
}
|
||||
|
||||
// getMinoColorAtLocation gets the mino color at a location
|
||||
func (mino *Mino) getMinoColorAtLocation(x int, y int) termbox.Attribute {
|
||||
func (mino *Mino) getMinoColorAtLocation(x int, y int) tcell.Color {
|
||||
xIndex := x - mino.x
|
||||
yIndex := y - mino.y
|
||||
if xIndex < 0 || xIndex >= mino.length || yIndex < 0 || yIndex >= mino.length {
|
||||
return blankColor
|
||||
return colorBlank
|
||||
}
|
||||
|
||||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
|
|
30
mino_test.go
30
mino_test.go
|
@ -1,39 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testMinoStruct struct {
|
||||
minoRotation MinoRotation
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
setupForTesting()
|
||||
retCode := m.Run()
|
||||
os.Exit(retCode)
|
||||
}
|
||||
|
||||
func setupForTesting() {
|
||||
logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.LUTC|log.Llongfile)
|
||||
|
||||
rand.Seed(1)
|
||||
|
||||
err := loadBoards()
|
||||
if err != nil {
|
||||
log.Fatal("error loading boards:", err)
|
||||
}
|
||||
|
||||
NewMinos()
|
||||
NewBoard()
|
||||
NewEngine()
|
||||
}
|
||||
|
||||
func TestMinoValidLocation(t *testing.T) {
|
||||
// this must be set to the blank boards
|
||||
for _, i := range []int{0, 3} {
|
||||
|
|
46
minos.go
46
minos.go
|
@ -3,45 +3,45 @@ package main
|
|||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// NewMinos creates the minos and minoBag
|
||||
func NewMinos() {
|
||||
minoI := MinoBlocks{
|
||||
[]termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor},
|
||||
[]tcell.Color{colorBlank, colorCyan, colorBlank, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorCyan, colorBlank, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorCyan, colorBlank, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorCyan, colorBlank, colorBlank},
|
||||
}
|
||||
minoJ := MinoBlocks{
|
||||
[]termbox.Attribute{termbox.ColorBlue, termbox.ColorBlue, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorBlue, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorBlue, blankColor},
|
||||
[]tcell.Color{colorBlue, colorBlue, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorBlue, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorBlue, colorBlank},
|
||||
}
|
||||
minoL := MinoBlocks{
|
||||
[]termbox.Attribute{blankColor, termbox.ColorWhite, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorWhite, blankColor},
|
||||
[]termbox.Attribute{termbox.ColorWhite, termbox.ColorWhite, blankColor},
|
||||
[]tcell.Color{colorBlank, colorWhite, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorWhite, colorBlank},
|
||||
[]tcell.Color{colorWhite, colorWhite, colorBlank},
|
||||
}
|
||||
minoO := MinoBlocks{
|
||||
[]termbox.Attribute{termbox.ColorYellow, termbox.ColorYellow},
|
||||
[]termbox.Attribute{termbox.ColorYellow, termbox.ColorYellow},
|
||||
[]tcell.Color{colorYellow, colorYellow},
|
||||
[]tcell.Color{colorYellow, colorYellow},
|
||||
}
|
||||
minoS := MinoBlocks{
|
||||
[]termbox.Attribute{blankColor, termbox.ColorGreen, blankColor},
|
||||
[]termbox.Attribute{termbox.ColorGreen, termbox.ColorGreen, blankColor},
|
||||
[]termbox.Attribute{termbox.ColorGreen, blankColor, blankColor},
|
||||
[]tcell.Color{colorBlank, colorGreen, colorBlank},
|
||||
[]tcell.Color{colorGreen, colorGreen, colorBlank},
|
||||
[]tcell.Color{colorGreen, colorBlank, colorBlank},
|
||||
}
|
||||
minoT := MinoBlocks{
|
||||
[]termbox.Attribute{blankColor, termbox.ColorMagenta, blankColor},
|
||||
[]termbox.Attribute{termbox.ColorMagenta, termbox.ColorMagenta, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorMagenta, blankColor},
|
||||
[]tcell.Color{colorBlank, colorMagenta, colorBlank},
|
||||
[]tcell.Color{colorMagenta, colorMagenta, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorMagenta, colorBlank},
|
||||
}
|
||||
minoZ := MinoBlocks{
|
||||
[]termbox.Attribute{termbox.ColorRed, blankColor, blankColor},
|
||||
[]termbox.Attribute{termbox.ColorRed, termbox.ColorRed, blankColor},
|
||||
[]termbox.Attribute{blankColor, termbox.ColorRed, blankColor},
|
||||
[]tcell.Color{colorRed, colorBlank, colorBlank},
|
||||
[]tcell.Color{colorRed, colorRed, colorBlank},
|
||||
[]tcell.Color{colorBlank, colorRed, colorBlank},
|
||||
}
|
||||
|
||||
var minoRotationI MinoRotation
|
||||
|
@ -91,7 +91,7 @@ func minosCloneRotateRight(minoBlocks MinoBlocks) MinoBlocks {
|
|||
length := len(minoBlocks)
|
||||
newMinoBlocks := make(MinoBlocks, length, length)
|
||||
for i := 0; i < length; i++ {
|
||||
newMinoBlocks[i] = make([]termbox.Attribute, length, length)
|
||||
newMinoBlocks[i] = make([]tcell.Color, length, length)
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
|
|
12
tetris.go
12
tetris.go
|
@ -13,7 +13,7 @@ func main() {
|
|||
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)
|
||||
if err != nil {
|
||||
logger.Fatal("error opening log file:", err)
|
||||
logger.Fatal("opening log file error:", err)
|
||||
}
|
||||
defer logFile.Close()
|
||||
logger.SetOutput(logFile)
|
||||
|
@ -22,21 +22,21 @@ func main() {
|
|||
|
||||
err = loadBoards()
|
||||
if err != nil {
|
||||
logger.Fatal("error loading internal boards:", err)
|
||||
logger.Fatal("loading internal boards error:", err)
|
||||
}
|
||||
|
||||
err = loadUserBoards()
|
||||
if err != nil {
|
||||
logger.Fatal("error loading user boards:", err)
|
||||
logger.Fatal("loading user boards error:", err)
|
||||
}
|
||||
|
||||
NewView()
|
||||
NewMinos()
|
||||
NewBoard()
|
||||
NewView()
|
||||
NewEngine()
|
||||
NewEdit()
|
||||
NewEngine()
|
||||
|
||||
engine.Run()
|
||||
engine.Start()
|
||||
|
||||
view.Stop()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
type testMinoStruct struct {
|
||||
minoRotation MinoRotation
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
setupForTesting()
|
||||
retCode := m.Run()
|
||||
os.Exit(retCode)
|
||||
}
|
||||
|
||||
func setupForTesting() {
|
||||
logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.LUTC|log.Llongfile)
|
||||
|
||||
rand.Seed(1)
|
||||
|
||||
err := loadBoards()
|
||||
if err != nil {
|
||||
log.Fatal("error loading boards:", err)
|
||||
}
|
||||
|
||||
screen, err = tcell.NewScreen()
|
||||
if err != nil {
|
||||
logger.Fatal("NewScreen error:", err)
|
||||
}
|
||||
|
||||
NewMinos()
|
||||
NewBoard()
|
||||
NewEngine()
|
||||
}
|
324
view.go
324
view.go
|
@ -5,17 +5,24 @@ import (
|
|||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// NewView creates a new view
|
||||
func NewView() {
|
||||
err := termbox.Init()
|
||||
var err error
|
||||
|
||||
screen, err = tcell.NewScreen()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logger.Fatal("NewScreen error:", err)
|
||||
}
|
||||
termbox.SetInputMode(termbox.InputEsc)
|
||||
termbox.Flush()
|
||||
err = screen.Init()
|
||||
if err != nil {
|
||||
logger.Fatal("screen Init error:", err)
|
||||
}
|
||||
|
||||
screen.Clear()
|
||||
|
||||
view = &View{}
|
||||
}
|
||||
|
||||
|
@ -23,74 +30,80 @@ func NewView() {
|
|||
func (view *View) Stop() {
|
||||
logger.Println("View Stop start")
|
||||
|
||||
termbox.Close()
|
||||
screen.Fini()
|
||||
|
||||
logger.Println("View Stop end")
|
||||
}
|
||||
|
||||
// RefreshScreen refreshs the updated view to the screen
|
||||
// RefreshScreen refreshes the updated view to the screen
|
||||
func (view *View) RefreshScreen() {
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
|
||||
view.drawBoardBoarder()
|
||||
switch engine.mode {
|
||||
|
||||
if engine.editMode {
|
||||
case engineModeRun, engineModeRunWithAI:
|
||||
view.drawBoardBoarder()
|
||||
view.drawPreviewBoarder()
|
||||
view.drawTexts()
|
||||
board.DrawBoard()
|
||||
board.DrawPreviewMino()
|
||||
board.DrawDropMino()
|
||||
board.DrawCurrentMino()
|
||||
screen.Show()
|
||||
|
||||
case engineModePaused:
|
||||
screen.Fill(' ', tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorBlack))
|
||||
view.drawBoardBoarder()
|
||||
view.drawPreviewBoarder()
|
||||
view.drawTexts()
|
||||
view.drawPaused()
|
||||
screen.Show()
|
||||
|
||||
case engineModeGameOver:
|
||||
view.drawBoardBoarder()
|
||||
view.drawPreviewBoarder()
|
||||
view.drawTexts()
|
||||
view.drawGameOver()
|
||||
view.drawRankingScores()
|
||||
screen.Show()
|
||||
|
||||
case engineModePreview:
|
||||
screen.Fill(' ', tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorBlack))
|
||||
view.drawBoardBoarder()
|
||||
view.drawPreviewBoarder()
|
||||
view.drawTexts()
|
||||
board.DrawBoard()
|
||||
view.drawGameOver()
|
||||
screen.Show()
|
||||
|
||||
case engineModeEdit:
|
||||
screen.Fill(' ', tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorBlack))
|
||||
view.drawBoardBoarder()
|
||||
board.DrawBoard()
|
||||
if edit.boardSize {
|
||||
board.DrawBoard()
|
||||
view.drawEditTextsBoardSize()
|
||||
} else {
|
||||
board.DrawBoard()
|
||||
edit.DrawCursor()
|
||||
view.drawEditTexts()
|
||||
}
|
||||
termbox.Flush()
|
||||
return
|
||||
screen.Show()
|
||||
}
|
||||
|
||||
view.drawPreviewBoarder()
|
||||
view.drawTexts()
|
||||
|
||||
if engine.previewBoard {
|
||||
board.DrawBoard()
|
||||
view.drawGameOver()
|
||||
termbox.Flush()
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
// drawBoard draws the board boarder
|
||||
// drawBoardBoarder draws the board boarder
|
||||
func (view *View) drawBoardBoarder() {
|
||||
// playing board
|
||||
xOffset := boardXOffset
|
||||
yOffset := boardYOffset
|
||||
xEnd := boardXOffset + board.width*2 + 4
|
||||
yEnd := boardYOffset + board.height + 2
|
||||
styleBoarder := tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorLightGray)
|
||||
styleBoard := tcell.StyleDefault.Foreground(tcell.ColorLightGray).Background(tcell.ColorBlack)
|
||||
for x := xOffset; x < xEnd; x++ {
|
||||
for y := yOffset; y < yEnd; y++ {
|
||||
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 ||
|
||||
y == yOffset || y == yEnd-1 {
|
||||
termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorWhite)
|
||||
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 || y == yOffset || y == yEnd-1 {
|
||||
screen.SetContent(x, y, ' ', nil, styleBoarder)
|
||||
} else {
|
||||
termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorBlack)
|
||||
screen.SetContent(x, y, ' ', nil, styleBoard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,13 +115,14 @@ func (view *View) drawPreviewBoarder() {
|
|||
yOffset := boardYOffset
|
||||
xEnd := xOffset + 14
|
||||
yEnd := yOffset + 6
|
||||
styleBoarder := tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorLightGray)
|
||||
styleBoard := tcell.StyleDefault.Foreground(tcell.ColorLightGray).Background(tcell.ColorBlack)
|
||||
for x := xOffset; x < xEnd; x++ {
|
||||
for y := yOffset; y < yEnd; y++ {
|
||||
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 ||
|
||||
y == yOffset || y == yEnd-1 {
|
||||
termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorWhite)
|
||||
if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 || y == yOffset || y == yEnd-1 {
|
||||
screen.SetContent(x, y, ' ', nil, styleBoarder)
|
||||
} else {
|
||||
termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorBlack)
|
||||
screen.SetContent(x, y, ' ', nil, styleBoard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,39 +134,39 @@ func (view *View) drawTexts() {
|
|||
xOffset := boardXOffset + board.width*2 + 8
|
||||
yOffset := boardYOffset + 7
|
||||
|
||||
view.drawText(xOffset, yOffset, "SCORE:", termbox.ColorWhite, termbox.ColorBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%7d", engine.score), termbox.ColorBlack, termbox.ColorWhite)
|
||||
view.drawText(xOffset, yOffset, "SCORE:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%7d", engine.score), tcell.ColorBlack, tcell.ColorLightGray)
|
||||
|
||||
yOffset += 2
|
||||
|
||||
view.drawText(xOffset, yOffset, "LINES:", termbox.ColorWhite, termbox.ColorBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%7d", engine.deleteLines), termbox.ColorBlack, termbox.ColorWhite)
|
||||
view.drawText(xOffset, yOffset, "LINES:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%7d", engine.deleteLines), tcell.ColorBlack, tcell.ColorLightGray)
|
||||
|
||||
yOffset += 2
|
||||
|
||||
view.drawText(xOffset, yOffset, "LEVEL:", termbox.ColorWhite, termbox.ColorBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%4d", engine.level), termbox.ColorBlack, termbox.ColorWhite)
|
||||
view.drawText(xOffset, yOffset, "LEVEL:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%4d", engine.level), tcell.ColorBlack, tcell.ColorLightGray)
|
||||
|
||||
yOffset += 2
|
||||
|
||||
// ascii arrow characters add extra two spaces
|
||||
view.drawText(xOffset, yOffset, "← - left", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "← - left", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "→ - right", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "→ - right", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↓ - soft drop", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↓ - soft drop", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↑ - hard drop", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↑ - hard drop", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "sbar - hard drop", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "sbar - hard drop", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "z - rotate left", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "z - rotate left", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "x - rotate right", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "x - rotate right", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "p - pause", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "p - pause", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "q - quit", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
}
|
||||
|
||||
// drawEditTexts draws the edit text
|
||||
|
@ -160,58 +174,58 @@ 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)
|
||||
view.drawText(xOffset, yOffset, "Name:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, boards[board.boardsIndex].name, tcell.ColorBlack, tcell.ColorLightGray)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "Saved:", termbox.ColorWhite, termbox.ColorBlue)
|
||||
view.drawText(xOffset, yOffset, "Saved:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
if edit.saved {
|
||||
view.drawText(xOffset+7, yOffset, "yes", termbox.ColorBlack, termbox.ColorWhite)
|
||||
view.drawText(xOffset+7, yOffset, "yes", tcell.ColorBlack, tcell.ColorLightGray)
|
||||
} else {
|
||||
view.drawText(xOffset+7, yOffset, "no", termbox.ColorBlack, termbox.ColorWhite)
|
||||
view.drawText(xOffset+7, yOffset, "no", tcell.ColorBlack, tcell.ColorLightGray)
|
||||
}
|
||||
|
||||
yOffset += 2
|
||||
|
||||
// ascii arrow characters add extra two spaces
|
||||
view.drawText(xOffset, yOffset, "← - left", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "← - left", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "→ - right", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "→ - right", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↓ - down", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↓ - down", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↑ - up", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↑ - up", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "z - rotate left", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "z - rotate left", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "x - rotate right", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "x - rotate right", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "c - cyan", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "c - cyan", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "b - blue", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "b - blue", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "w - white", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "w - white", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "e - yellow", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "e - yellow", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "g - green", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "g - green", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "a - magenta", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "a - magenta", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "r - red", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "r - red", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "f - free", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "f - free", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl b - change board size", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl b - change board size", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl s - save board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl s - save board", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl n - save board as new", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl n - save board as new", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl k - delete board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl k - delete board", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl o - empty board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl o - empty board", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "ctrl q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "ctrl q - quit", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
}
|
||||
|
||||
// drawEditTextsBoardSize draws the edit text for board size mode
|
||||
|
@ -219,119 +233,124 @@ 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)
|
||||
view.drawText(xOffset, yOffset, "Name:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, boards[board.boardsIndex].name, tcell.ColorBlack, tcell.ColorLightGray)
|
||||
|
||||
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)
|
||||
view.drawText(xOffset, yOffset, "Size:", tcell.ColorLightGray, tcell.ColorDarkBlue)
|
||||
view.drawText(xOffset+7, yOffset, fmt.Sprintf("%2d X %2d", edit.width, edit.height), tcell.ColorBlack, tcell.ColorLightGray)
|
||||
|
||||
yOffset += 2
|
||||
|
||||
// ascii arrow characters add extra two spaces
|
||||
view.drawText(xOffset, yOffset, "← - board width decrement", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "← - board width decrement", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "→ - board width increment", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "→ - board width increment", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↓ - board height decrement", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↓ - board height decrement", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "↑ - board height increment", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "↑ - board height increment", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
yOffset++
|
||||
view.drawText(xOffset, yOffset, "q - done", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawText(xOffset, yOffset, "q - done", tcell.ColorLightGray, tcell.ColorBlack)
|
||||
}
|
||||
|
||||
// DrawPreviewMinoBlock draws the preview mino
|
||||
func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, rotation int, length int) {
|
||||
char1 := ' '
|
||||
char2 := ' '
|
||||
func (view *View) DrawPreviewMinoBlock(x int, y int, color tcell.Color, rotation int, length int) {
|
||||
char1 := '█'
|
||||
char2 := '█'
|
||||
switch rotation {
|
||||
case 0:
|
||||
char1 = '▄'
|
||||
char2 = '▄'
|
||||
case 1:
|
||||
char1 = '█'
|
||||
char2 = ' '
|
||||
case 2:
|
||||
char1 = '▀'
|
||||
char2 = '▀'
|
||||
case 3:
|
||||
char2 = '█'
|
||||
char1 = ' '
|
||||
}
|
||||
xOffset := 2*x + 2*board.width + boardXOffset + 11 + (4 - length)
|
||||
termbox.SetCell(xOffset, y+boardYOffset+2, char1, color, color^termbox.AttrBold)
|
||||
termbox.SetCell(xOffset+1, y+boardYOffset+2, char2, color, color^termbox.AttrBold)
|
||||
style := tcell.StyleDefault.Foreground(color).Background(color).Dim(true)
|
||||
screen.SetContent(xOffset, y+boardYOffset+2, char1, nil, style)
|
||||
screen.SetContent(xOffset+1, y+boardYOffset+2, char2, nil, style)
|
||||
}
|
||||
|
||||
// DrawBlock draws a block
|
||||
func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int) {
|
||||
char1 := ' '
|
||||
char2 := ' '
|
||||
func (view *View) DrawBlock(x int, y int, color tcell.Color, rotation int) {
|
||||
char1 := '█'
|
||||
char2 := '█'
|
||||
switch rotation {
|
||||
case 0:
|
||||
char1 = '▄'
|
||||
char2 = '▄'
|
||||
case 1:
|
||||
char1 = '█'
|
||||
char2 = ' '
|
||||
case 2:
|
||||
char1 = '▀'
|
||||
char2 = '▀'
|
||||
case 3:
|
||||
char2 = '█'
|
||||
char1 = ' '
|
||||
}
|
||||
if color == blankColor {
|
||||
// blankColor means drop Mino
|
||||
termbox.SetCell(2*x+boardXOffset+2, y+boardYOffset+1, char1, termbox.ColorBlack|termbox.AttrBold, termbox.ColorWhite)
|
||||
termbox.SetCell(2*x+boardXOffset+3, y+boardYOffset+1, char2, termbox.ColorBlack|termbox.AttrBold, termbox.ColorWhite)
|
||||
if color == colorBlank {
|
||||
// colorBlank means drop Mino
|
||||
style := tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorSilver).Bold(true)
|
||||
screen.SetContent(2*x+boardXOffset+2, y+boardYOffset+1, char1, nil, style)
|
||||
screen.SetContent(2*x+boardXOffset+3, y+boardYOffset+1, char2, nil, style)
|
||||
} else {
|
||||
termbox.SetCell(2*x+boardXOffset+2, y+boardYOffset+1, char1, color, color^termbox.AttrBold)
|
||||
termbox.SetCell(2*x+boardXOffset+3, y+boardYOffset+1, char2, color, color^termbox.AttrBold)
|
||||
style := tcell.StyleDefault.Foreground(color).Background(color).Dim(true)
|
||||
screen.SetContent(2*x+boardXOffset+2, y+boardYOffset+1, char1, nil, style)
|
||||
screen.SetContent(2*x+boardXOffset+3, y+boardYOffset+1, char2, nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
// drawPaused draws Paused
|
||||
func (view *View) drawPaused() {
|
||||
yOffset := (board.height+1)/2 + boardYOffset
|
||||
view.drawTextCenter(yOffset, "Paused", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset, "Paused", tcell.ColorWhite, tcell.ColorBlack)
|
||||
}
|
||||
|
||||
// drawGameOver draws GAME OVER
|
||||
func (view *View) drawGameOver() {
|
||||
yOffset := boardYOffset + 2
|
||||
view.drawTextCenter(yOffset, " GAME OVER", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset, " GAME OVER", tcell.ColorWhite, tcell.ColorBlack)
|
||||
yOffset += 2
|
||||
view.drawTextCenter(yOffset, "sbar for new game", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset, "sbar for new game", tcell.ColorWhite, tcell.ColorBlack)
|
||||
|
||||
if engine.previewBoard {
|
||||
if engine.mode == engineModePreview {
|
||||
return
|
||||
}
|
||||
|
||||
yOffset += 2
|
||||
// ascii arrow characters add extra two spaces
|
||||
view.drawTextCenter(yOffset, "←previous board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset, "←previous board", tcell.ColorWhite, tcell.ColorBlack)
|
||||
yOffset += 2
|
||||
view.drawTextCenter(yOffset, "→next board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset, "→next board", tcell.ColorWhite, tcell.ColorBlack)
|
||||
}
|
||||
|
||||
// drawRankingScores draws the ranking scores
|
||||
func (view *View) drawRankingScores() {
|
||||
yOffset := boardYOffset + 10
|
||||
for index, line := range engine.ranking.scores {
|
||||
view.drawTextCenter(yOffset+index, fmt.Sprintf("%1d: %6d", index+1, line), termbox.ColorWhite, termbox.ColorBlack)
|
||||
view.drawTextCenter(yOffset+index, fmt.Sprintf("%1d: %6d", index+1, line), tcell.ColorWhite, tcell.ColorBlack)
|
||||
}
|
||||
}
|
||||
|
||||
// drawText draws the provided text
|
||||
func (view *View) drawText(x int, y int, text string, fg termbox.Attribute, bg termbox.Attribute) {
|
||||
func (view *View) drawText(x int, y int, text string, fg tcell.Color, bg tcell.Color) {
|
||||
style := tcell.StyleDefault.Foreground(fg).Background(bg)
|
||||
for index, char := range text {
|
||||
termbox.SetCell(x+index, y, rune(char), fg, bg)
|
||||
screen.SetContent(x+index, y, rune(char), nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
// drawTextCenter draws text in the center of the board
|
||||
func (view *View) drawTextCenter(y int, text string, fg termbox.Attribute, bg termbox.Attribute) {
|
||||
func (view *View) drawTextCenter(y int, text string, fg tcell.Color, bg tcell.Color) {
|
||||
xOffset := board.width - (len(text)+1)/2 + boardXOffset + 2
|
||||
style := tcell.StyleDefault.Foreground(fg).Background(bg)
|
||||
for index, char := range text {
|
||||
termbox.SetCell(index+xOffset, y, rune(char), fg, bg)
|
||||
screen.SetContent(index+xOffset, y, rune(char), nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,9 +360,9 @@ func (view *View) ShowDeleteAnimation(lines []int) {
|
|||
|
||||
for times := 0; times < 3; times++ {
|
||||
for _, y := range lines {
|
||||
view.colorizeLine(y, termbox.ColorCyan)
|
||||
view.colorizeLine(y, tcell.ColorLightGray)
|
||||
}
|
||||
termbox.Flush()
|
||||
screen.Show()
|
||||
time.Sleep(140 * time.Millisecond)
|
||||
|
||||
view.RefreshScreen()
|
||||
|
@ -357,20 +376,23 @@ func (view *View) ShowGameOverAnimation() {
|
|||
|
||||
switch rand.Intn(3) {
|
||||
case 0:
|
||||
logger.Println("View ShowGameOverAnimation case 0")
|
||||
for y := board.height - 1; y >= 0; y-- {
|
||||
view.colorizeLine(y, termbox.ColorBlack)
|
||||
termbox.Flush()
|
||||
view.colorizeLine(y, tcell.ColorLightGray)
|
||||
screen.Show()
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
}
|
||||
|
||||
case 1:
|
||||
logger.Println("View ShowGameOverAnimation case 1")
|
||||
for y := 0; y < board.height; y++ {
|
||||
view.colorizeLine(y, termbox.ColorBlack)
|
||||
termbox.Flush()
|
||||
view.colorizeLine(y, tcell.ColorLightGray)
|
||||
screen.Show()
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
}
|
||||
|
||||
case 2:
|
||||
logger.Println("View ShowGameOverAnimation case 2")
|
||||
sleepTime := 50 * time.Millisecond
|
||||
topStartX := boardXOffset + 3
|
||||
topEndX := board.width*2 + boardXOffset + 1
|
||||
|
@ -384,33 +406,34 @@ func (view *View) ShowGameOverAnimation() {
|
|||
leftStartY := rightEndY - 1
|
||||
leftEndY := rightStartY - 1
|
||||
leftX := boardXOffset + 2
|
||||
style := tcell.StyleDefault.Foreground(tcell.ColorLightGray).Background(tcell.ColorLightGray)
|
||||
|
||||
for topStartX <= topEndX && rightStartY <= rightEndY {
|
||||
for x := topStartX; x < topEndX; x++ {
|
||||
termbox.SetCell(x, topY, ' ', termbox.ColorBlack, termbox.ColorBlack)
|
||||
screen.SetContent(x, topY, ' ', nil, style)
|
||||
}
|
||||
topStartX++
|
||||
topEndX--
|
||||
topY++
|
||||
for y := rightStartY; y < rightEndY; y++ {
|
||||
termbox.SetCell(rightX, y, ' ', termbox.ColorBlack, termbox.ColorBlack)
|
||||
screen.SetContent(rightX, y, ' ', nil, style)
|
||||
}
|
||||
rightStartY++
|
||||
rightEndY--
|
||||
rightX--
|
||||
for x := bottomStartX; x > bottomEndX; x-- {
|
||||
termbox.SetCell(x, bottomY, ' ', termbox.ColorBlack, termbox.ColorBlack)
|
||||
screen.SetContent(x, bottomY, ' ', nil, style)
|
||||
}
|
||||
bottomStartX--
|
||||
bottomEndX++
|
||||
bottomY--
|
||||
for y := leftStartY; y > leftEndY; y-- {
|
||||
termbox.SetCell(leftX, y, ' ', termbox.ColorBlack, termbox.ColorBlack)
|
||||
screen.SetContent(leftX, y, ' ', nil, style)
|
||||
}
|
||||
leftStartY--
|
||||
leftEndY++
|
||||
leftX++
|
||||
termbox.Flush()
|
||||
screen.Show()
|
||||
time.Sleep(sleepTime)
|
||||
sleepTime += 4 * time.Millisecond
|
||||
}
|
||||
|
@ -420,16 +443,21 @@ func (view *View) ShowGameOverAnimation() {
|
|||
}
|
||||
|
||||
// colorizeLine changes the color of a line
|
||||
func (view *View) colorizeLine(y int, color termbox.Attribute) {
|
||||
func (view *View) colorizeLine(y int, color tcell.Color) {
|
||||
style := tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(color)
|
||||
for x := 0; x < board.width; x++ {
|
||||
termbox.SetCell(x*2+boardXOffset+2, y+boardYOffset+1, ' ', termbox.ColorDefault, color)
|
||||
termbox.SetCell(x*2+boardXOffset+3, y+boardYOffset+1, ' ', termbox.ColorDefault, color)
|
||||
screen.SetContent(x*2+boardXOffset+2, y+boardYOffset+1, ' ', nil, style)
|
||||
screen.SetContent(x*2+boardXOffset+3, y+boardYOffset+1, ' ', nil, style)
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
func (view *View) DrawCursor(x int, y int, color tcell.Color) {
|
||||
style := tcell.StyleDefault.Foreground(color).Background(tcell.ColorBlack)
|
||||
if color == colorBlank {
|
||||
style = tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorLightGrey)
|
||||
}
|
||||
screen.SetContent(x*2+boardXOffset+2, y+boardYOffset+1, '◄', nil, style)
|
||||
screen.SetContent(x*2+boardXOffset+3, y+boardYOffset+1, '►', nil, style)
|
||||
screen.Show()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue