~tslocum/netris

ca6d12ef8cf3573d11bc2c45cedd4f147af90648 — Trevor Slocum 2 months ago 133d956
Allow ghost piece to be disabled

Resolves #19
M cmd/netris/gui.go => cmd/netris/gui.go +14 -2
@@ 48,10 48,14 @@ var (
	nickname      = "Anonymous"
	nicknameDraft string

	drawGhostPiece        = true
	drawGhostPieceUnsaved bool

	inputHeight, mainHeight, previewWidth, newLogLines int

	profileCPU *os.File

	buttonGhostPiece       *tview.Button
	buttonKeybindRotateCCW *tview.Button
	buttonKeybindRotateCW  *tview.Button
	buttonKeybindMoveLeft  *tview.Button


@@ 276,7 280,7 @@ func renderPlayerGUI() {
	if !player.Matrix.GameOver {
		err := player.Preview.Add(p, p.Solid, mino.Point{0, 0}, false)
		if err != nil {
			log.Fatalf("failed to render preview matrix: failed to add ghost piece: %+v", err)
			log.Fatalf("failed to render preview matrix: failed to add preview piece: %+v", err)
		}
	}



@@ 435,7 439,15 @@ func renderMatrixes(mx []*mino.Matrix) {

	for i := range mx {
		mx[i].Lock()
		mx[i].DrawPiecesL()
		if mt == mino.MatrixCustom {
			continue
		}

		mx[i].ClearOverlayL()
		if drawGhostPiece {
			mx[i].DrawGhostPieceL()
		}
		mx[i].DrawActivePieceL()
	}

	if mt == mino.MatrixStandard {

M cmd/netris/gui_init.go => cmd/netris/gui_init.go +37 -23
@@ 271,6 271,12 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
		SetWrap(false).
		SetWordWrap(false).SetText("Game Settings")

	buttonGhostPiece = tview.NewButton("Enabled")

	ghostPieceGrid := tview.NewGrid().SetColumns(19, -1).
		AddItem(tview.NewTextView().SetText("Ghost Piece"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonGhostPiece, 0, 1, 1, 1, 0, 0, false)

	buttonKeybindRotateCCW = tview.NewButton("Set")
	buttonKeybindRotateCW = tview.NewButton("Set")
	buttonKeybindMoveLeft = tview.NewButton("Set")


@@ 280,27 286,27 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
	buttonKeybindCancel = tview.NewButton("Cancel")
	buttonKeybindSave = tview.NewButton("Save")

	rotateCCWGrid := tview.NewGrid().
	rotateCCWGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Rotate CCW"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindRotateCCW, 0, 1, 1, 1, 0, 0, false)

	rotateCWGrid := tview.NewGrid().
	rotateCWGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Rotate CW"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindRotateCW, 0, 1, 1, 1, 0, 0, false)

	moveLeftGrid := tview.NewGrid().
	moveLeftGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Move Left"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindMoveLeft, 0, 1, 1, 1, 0, 0, false)

	moveRightGrid := tview.NewGrid().
	moveRightGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Move Right"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindMoveRight, 0, 1, 1, 1, 0, 0, false)

	softDropGrid := tview.NewGrid().
	softDropGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Soft Drop"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindSoftDrop, 0, 1, 1, 1, 0, 0, false)

	hardDropGrid := tview.NewGrid().
	hardDropGrid := tview.NewGrid().SetColumns(27, -1).
		AddItem(tview.NewTextView().SetText("Hard Drop"), 0, 0, 1, 1, 0, 0, false).
		AddItem(buttonKeybindHardDrop, 0, 1, 1, 1, 0, 0, false)



@@ 313,29 319,37 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
		AddItem(pad, 0, 4, 1, 1, 0, 0, false)

	gameSettingsGrid = tview.NewGrid().
		SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1).
		SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1).
		SetColumns(-1, 34, -1).
		AddItem(titleL, 0, 0, 16, 1, 0, 0, false).
		AddItem(titleL, 0, 0, 18, 1, 0, 0, false).
		AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
		AddItem(titleR, 0, 2, 16, 1, 0, 0, false).
		AddItem(titleR, 0, 2, 18, 1, 0, 0, false).
		AddItem(gameSettingsTitle, 1, 1, 1, 1, 0, 0, false).
		AddItem(rotateCCWGrid, 2, 1, 1, 1, 0, 0, false).
		AddItem(pad, 3, 1, 1, 1, 0, 0, false).
		AddItem(rotateCWGrid, 4, 1, 1, 1, 0, 0, false).
		AddItem(pad, 5, 1, 1, 1, 0, 0, false).
		AddItem(moveLeftGrid, 6, 1, 1, 1, 0, 0, false).
		AddItem(pad, 7, 1, 1, 1, 0, 0, false).
		AddItem(moveRightGrid, 8, 1, 1, 1, 0, 0, false).
		AddItem(pad, 9, 1, 1, 1, 0, 0, false).
		AddItem(softDropGrid, 10, 1, 1, 1, 0, 0, false).
		AddItem(pad, 11, 1, 1, 1, 0, 0, false).
		AddItem(hardDropGrid, 12, 1, 1, 1, 0, 0, false).
		AddItem(pad, 13, 1, 1, 1, 0, 0, false).
		AddItem(gameSettingsSubmitGrid, 14, 1, 1, 1, 0, 0, false).
		AddItem(pad, 2, 1, 1, 1, 0, 0, false).
		AddItem(tview.NewTextView().
			SetTextAlign(tview.AlignCenter).
			SetWrap(false).
			SetWordWrap(false).SetText("Options"), 3, 1, 1, 1, 0, 0, false).
		AddItem(ghostPieceGrid, 4, 1, 1, 1, 0, 0, false).
		AddItem(ghostPieceGrid, 5, 1, 1, 1, 0, 0, false).
		AddItem(pad, 6, 1, 1, 1, 0, 0, false).
		AddItem(tview.NewTextView().
			SetTextAlign(tview.AlignCenter).
			SetWrap(false).
			SetWordWrap(false).SetText("Keybindings"), 7, 1, 1, 1, 0, 0, false).
		AddItem(pad, 8, 1, 1, 1, 0, 0, false).
		AddItem(rotateCCWGrid, 9, 1, 1, 1, 0, 0, false).
		AddItem(rotateCWGrid, 10, 1, 1, 1, 0, 0, false).
		AddItem(moveLeftGrid, 11, 1, 1, 1, 0, 0, false).
		AddItem(moveRightGrid, 12, 1, 1, 1, 0, 0, false).
		AddItem(softDropGrid, 13, 1, 1, 1, 0, 0, false).
		AddItem(hardDropGrid, 14, 1, 1, 1, 0, 0, false).
		AddItem(pad, 15, 1, 1, 1, 0, 0, false).
		AddItem(gameSettingsSubmitGrid, 16, 1, 1, 1, 0, 0, false).
		AddItem(tview.NewTextView().
			SetTextAlign(tview.AlignCenter).
			SetWrap(false).
			SetWordWrap(false).SetText("\nPrevious: Shift+Tab - Next: Tab"), 15, 1, 1, 1, 0, 0, false)
			SetWordWrap(false).SetText("\nPrevious: Shift+Tab - Next: Tab"), 17, 1, 1, 1, 0, 0, false)

	titleContainerGrid = tview.NewGrid().SetColumns(-1, 80, -1).SetRows(-1, 24, -1).
		AddItem(pad, 0, 0, 1, 3, 0, 0, false).

M cmd/netris/gui_input.go => cmd/netris/gui_input.go +21 -11
@@ 87,17 87,17 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {

		var action event.GameAction
		switch gameSettingsSelectedButton {
		case 0:
			action = event.ActionRotateCCW
		case 1:
			action = event.ActionRotateCW
			action = event.ActionRotateCCW
		case 2:
			action = event.ActionMoveLeft
			action = event.ActionRotateCW
		case 3:
			action = event.ActionMoveRight
			action = event.ActionMoveLeft
		case 4:
			action = event.ActionSoftDrop
			action = event.ActionMoveRight
		case 5:
			action = event.ActionSoftDrop
		case 6:
			action = event.ActionHardDrop
		default:
			log.Fatal("setting keybind for unknown action")


@@ 136,8 136,8 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
				switch k {
				case tcell.KeyTab:
					gameSettingsSelectedButton++
					if gameSettingsSelectedButton > 7 {
						gameSettingsSelectedButton = 7
					if gameSettingsSelectedButton > 8 {
						gameSettingsSelectedButton = 8
					}

					updateGameSettings()


@@ 151,8 151,15 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
					updateGameSettings()
					return nil
				case tcell.KeyEnter:
					if gameSettingsSelectedButton == 6 || gameSettingsSelectedButton == 7 {
						if gameSettingsSelectedButton == 7 {
					if gameSettingsSelectedButton == 0 {
						// TODO Cache until saved
						drawGhostPieceUnsaved = !drawGhostPieceUnsaved
						updateGameSettings()
						return nil
					} else if gameSettingsSelectedButton == 7 || gameSettingsSelectedButton == 8 {
						if gameSettingsSelectedButton == 8 {
							drawGhostPiece = drawGhostPieceUnsaved

							keybindings = make([]*Keybinding, len(draftKeybindings))
							copy(keybindings, draftKeybindings)
						}


@@ 294,10 301,13 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
					titleSelectedButton = 0
					gameSettingsSelectedButton = 0

					drawGhostPieceUnsaved = drawGhostPiece

					draftKeybindings = make([]*Keybinding, len(keybindings))
					copy(draftKeybindings, keybindings)

					app.SetRoot(gameSettingsContainerGrid, true).SetFocus(buttonKeybindRotateCCW)
					app.SetRoot(gameSettingsContainerGrid, true)
					updateGameSettings()
					return nil
				case 2:
					titleScreen = 0

M cmd/netris/gui_title.go => cmd/netris/gui_title.go +15 -7
@@ 89,22 89,30 @@ func nextTitleButton() {
}

func updateGameSettings() {
	if drawGhostPieceUnsaved {
		buttonGhostPiece.SetLabel("Enabled")
	} else {
		buttonGhostPiece.SetLabel("Disabled")
	}

	switch gameSettingsSelectedButton {
	case 0:
		app.SetFocus(buttonKeybindRotateCCW)
		app.SetFocus(buttonGhostPiece)
	case 1:
		app.SetFocus(buttonKeybindRotateCW)
		app.SetFocus(buttonKeybindRotateCCW)
	case 2:
		app.SetFocus(buttonKeybindMoveLeft)
		app.SetFocus(buttonKeybindRotateCW)
	case 3:
		app.SetFocus(buttonKeybindMoveRight)
		app.SetFocus(buttonKeybindMoveLeft)
	case 4:
		app.SetFocus(buttonKeybindSoftDrop)
		app.SetFocus(buttonKeybindMoveRight)
	case 5:
		app.SetFocus(buttonKeybindHardDrop)
		app.SetFocus(buttonKeybindSoftDrop)
	case 6:
		app.SetFocus(buttonKeybindCancel)
		app.SetFocus(buttonKeybindHardDrop)
	case 7:
		app.SetFocus(buttonKeybindCancel)
	case 8:
		app.SetFocus(buttonKeybindSave)
	}
}

M pkg/mino/matrix.go => pkg/mino/matrix.go +11 -23
@@ 380,10 380,10 @@ func (m *Matrix) ClearOverlay() {
	m.Lock()
	defer m.Unlock()

	m.clearOverlay()
	m.ClearOverlayL()
}

func (m *Matrix) clearOverlay() {
func (m *Matrix) ClearOverlayL() {
	for i, b := range m.O {
		if b == BlockNone {
			continue


@@ 421,30 421,12 @@ func (m *Matrix) Clear() {
	}
}

func (m *Matrix) DrawPieces() {
	m.Lock()
	defer m.Unlock()

	m.DrawPiecesL()
}

func (m *Matrix) DrawPiecesL() {
	if m.Type != MatrixStandard {
		return
	}

	m.clearOverlay()

	if m.GameOver {
		return
	}

func (m *Matrix) DrawGhostPieceL() {
	p := m.P
	if p == nil {
	if m.Type != MatrixStandard || m.GameOver || p == nil {
		return
	}

	// Draw ghost piece
	for y := p.Y; y >= 0; y-- {
		if y == 0 || !m.canAddAt(p, Point{p.X, y - 1}) {
			err := m.add(p, p.Ghost, Point{p.X, y}, true)


@@ 455,8 437,14 @@ func (m *Matrix) DrawPiecesL() {
			break
		}
	}
}

func (m *Matrix) DrawActivePieceL() {
	p := m.P
	if m.Type != MatrixStandard || m.GameOver || p == nil {
		return
	}

	// Draw active piece
	err := m.add(p, p.Solid, Point{p.X, p.Y}, true)
	if err != nil {
		log.Fatalf("failed to draw active piece: %+v", err)