Source File: curse-you-go-rogue/01_the_screen/ui.go

package main

import (
  "log"
  "fmt"
  "github.com/gdamore/tcell/v2"
  "github.com/gdamore/tcell/v2/encoding"
)

//// DRAWING

func (game *Game) DrawText(x int, y int, text string) {
  for i, cell := range text {
    game.Screen.SetContent(x+i, y, cell, nil, tcell.StyleDefault)
  }
}

func (game *Game) DrawStatus() {
  game.DrawText(0, game.Height, game.Status)

  hp := fmt.Sprintf("HP: %d", game.Player.HP)

  game.DrawText(game.Width - len(hp), game.Height, hp)
}

func (game *Game) SetStatus(msg string) {
  game.Status = msg
}

func (game *Game) DrawEntity(symbol rune, pos Position, color tcell.Color) {
  style := tcell.StyleDefault.Bold(true).Foreground(color)
  game.Screen.SetContent(pos.X, pos.Y, symbol, nil, style)
}

func (game *Game) DrawMap() {
  gray := tcell.StyleDefault.Foreground(tcell.ColorGray)

  for y, line := range game.Level {
    for x, cell := range line {
      if cell == SPACE {
        game.Screen.SetContent(x, y, cell, nil, gray)
      } else {
        game.Screen.SetContent(x, y, cell, nil, tcell.StyleDefault)
      }
    }
  }
}

///// RENDERING

func (game *Game) InitScreen() {
  var err error
  encoding.Register()

  game.Screen, err = tcell.NewScreen()

  // using log.Fatal instead of dbg.Fatal
  // because the screen isn't setup yet
  if err != nil { log.Fatal(err) }

  err = game.Screen.Init()
  if err != nil { log.Fatal(err) }
}

func (game *Game) Render() {
  if !RENDER { return }

  game.Screen.Clear()
  game.DrawMap()
  game.DrawEntity('@', game.Player.Pos, tcell.ColorYellow)
  game.DrawStatus()
  game.Screen.Show()
}

//// EVENTS

func (game *Game) HandleKeys(ev *tcell.EventKey) bool {
  switch ev.Key() {
  case tcell.KeyEscape:
    return false
  case tcell.KeyUp:
    game.MovePlayer(0, -1)
  case tcell.KeyDown:
    game.MovePlayer(0, 1)
  case tcell.KeyRight:
    game.MovePlayer(1, 0)
  case tcell.KeyLeft:
    game.MovePlayer(-1, 0)
  }

  switch ev.Rune() {
  case 'q':
    return false
  }

  return true
}

func (game *Game) HandleEvents() bool {
  if !RENDER { return false }

  switch ev := game.Screen.PollEvent().(type) {
  case *tcell.EventResize:
    game.Screen.Sync()
  case *tcell.EventKey:
    return game.HandleKeys(ev)
  }

  return true
}