Split game into a different module. Closes #1
This commit is contained in:
181
robots/game.go
Normal file
181
robots/game.go
Normal file
@ -0,0 +1,181 @@
|
||||
package robots
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
func GameInit() {
|
||||
game, err := initialize()
|
||||
if err != nil {
|
||||
log.Fatalln("Initilization error: ", err)
|
||||
}
|
||||
go game.gameDirector()
|
||||
game.keyboardProcessor()
|
||||
|
||||
// Quit the screen
|
||||
quit(&game)
|
||||
|
||||
// Give closure
|
||||
if game.gameover == 1 {
|
||||
fmt.Println("You got rekt by a robot")
|
||||
} else if game.gameover == 2 {
|
||||
fmt.Println("You took the easy way out")
|
||||
}
|
||||
|
||||
fmt.Println("Score:", game.player.score)
|
||||
fmt.Println("Level: ", game.level)
|
||||
fmt.Println("Moves:", game.player.moves)
|
||||
fmt.Println("Teleports:", game.player.teleports)
|
||||
|
||||
}
|
||||
|
||||
func initialize() (Game, error) {
|
||||
|
||||
var err error
|
||||
|
||||
screen, err := tcell.NewScreen()
|
||||
if err != nil {
|
||||
log.Println("Error creating screen: ", err)
|
||||
}
|
||||
err = screen.Init()
|
||||
if err != nil {
|
||||
log.Fatalln("Error initializing screen: ", err)
|
||||
}
|
||||
|
||||
style := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
|
||||
|
||||
game := Game{
|
||||
screen: screen,
|
||||
style: style,
|
||||
keypresses: make(chan int),
|
||||
player: Player{
|
||||
position: Position{
|
||||
x: 40,
|
||||
y: 12,
|
||||
},
|
||||
score: 0,
|
||||
moves: 0,
|
||||
teleports: 0,
|
||||
},
|
||||
level: 1,
|
||||
gameover: 0,
|
||||
}
|
||||
|
||||
game.initRobots()
|
||||
|
||||
return game, err
|
||||
}
|
||||
|
||||
func (game *Game) gameDirector() {
|
||||
defer quit(game)
|
||||
|
||||
// TODO reorder this
|
||||
for game.gameover == 0 {
|
||||
|
||||
// Clean the screen
|
||||
game.screen.Clear()
|
||||
|
||||
// Draw robots??
|
||||
if len(game.robots) == 0 {
|
||||
game.level++
|
||||
game.cleanTrash()
|
||||
game.resetPlayer()
|
||||
game.initRobots()
|
||||
}
|
||||
|
||||
// Draw starter conditions
|
||||
game.drawBox()
|
||||
game.drawPlayer()
|
||||
//game.drawCoords()
|
||||
|
||||
game.drawRobots()
|
||||
|
||||
// Draw my ex-wife
|
||||
game.drawTrash()
|
||||
|
||||
// Draw stuff last
|
||||
game.drawScore()
|
||||
game.drawDebug()
|
||||
|
||||
// Draw the screen
|
||||
game.screen.Show()
|
||||
|
||||
// Process input
|
||||
game.movePlayer(<-game.keypresses)
|
||||
|
||||
// Move robots
|
||||
game.moveRobots()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (game *Game) keyboardProcessor() {
|
||||
defer close(game.keypresses)
|
||||
|
||||
for game.gameover == 0 {
|
||||
|
||||
// Poll for an event
|
||||
ev := game.screen.PollEvent()
|
||||
|
||||
// Fetch the type, and check if any other actions are required.
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventKey:
|
||||
// Keys to bug out
|
||||
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC {
|
||||
game.gameover = 2
|
||||
return
|
||||
|
||||
// Screen management
|
||||
} else if ev.Key() == tcell.KeyCtrlL {
|
||||
game.screen.Sync()
|
||||
|
||||
// Player Movement
|
||||
} else if ev.Rune() == 'q' {
|
||||
game.keypresses <- upleft
|
||||
} else if ev.Rune() == 'e' {
|
||||
game.keypresses <- upright
|
||||
} else if ev.Rune() == 'z' {
|
||||
game.keypresses <- downleft
|
||||
} else if ev.Rune() == 'c' {
|
||||
game.keypresses <- downright
|
||||
} else if ev.Key() == tcell.KeyUp || ev.Rune() == 'w' {
|
||||
game.keypresses <- Up
|
||||
} else if ev.Key() == tcell.KeyRight || ev.Rune() == 'd' {
|
||||
game.keypresses <- Right
|
||||
} else if ev.Key() == tcell.KeyDown || ev.Rune() == 's' || ev.Rune() == 'x' {
|
||||
game.keypresses <- Down
|
||||
} else if ev.Key() == tcell.KeyLeft || ev.Rune() == 'a' {
|
||||
game.keypresses <- Left
|
||||
|
||||
// Teleport the player
|
||||
} else if ev.Rune() == 't' {
|
||||
game.keypresses <- teleport
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func quit(game *Game) {
|
||||
maybePanic := recover()
|
||||
game.screen.Fini()
|
||||
if maybePanic != nil {
|
||||
panic(maybePanic)
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) randPos() Position {
|
||||
var pos Position
|
||||
|
||||
x := 2 + rand.Intn(76)
|
||||
y := 2 + rand.Intn(21)
|
||||
|
||||
pos.x = x
|
||||
pos.y = y
|
||||
|
||||
return pos
|
||||
}
|
126
robots/player.go
Normal file
126
robots/player.go
Normal file
@ -0,0 +1,126 @@
|
||||
package robots
|
||||
|
||||
func (game *Game) drawPlayer() {
|
||||
game.screen.SetContent(game.player.position.x, game.player.position.y, '@', nil, game.style)
|
||||
}
|
||||
|
||||
func (game *Game) movePlayer(press int) {
|
||||
|
||||
if game.blockedByTrash(press) {
|
||||
game.player.moves++
|
||||
return
|
||||
}
|
||||
|
||||
if press == Left {
|
||||
if game.player.position.x != 2 {
|
||||
game.player.position.x--
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == Right {
|
||||
if game.player.position.x != 78 {
|
||||
game.player.position.x++
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == Up {
|
||||
if game.player.position.y != 1 {
|
||||
game.player.position.y--
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == Down {
|
||||
if game.player.position.y != 22 {
|
||||
game.player.position.y++
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == upleft {
|
||||
if game.player.position.x != 2 && game.player.position.y != 1 {
|
||||
game.player.position.x--
|
||||
game.player.position.y--
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == upright {
|
||||
if game.player.position.x != 78 && game.player.position.y != 1 {
|
||||
game.player.position.x++
|
||||
game.player.position.y--
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == downright {
|
||||
if game.player.position.x != 78 && game.player.position.y != 22 {
|
||||
game.player.position.x++
|
||||
game.player.position.y++
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == downleft {
|
||||
if game.player.position.x != 2 && game.player.position.y != 22 {
|
||||
game.player.position.x--
|
||||
game.player.position.y++
|
||||
game.player.moves++
|
||||
}
|
||||
} else if press == teleport {
|
||||
game.teleport()
|
||||
game.player.teleports++
|
||||
}
|
||||
}
|
||||
|
||||
// blockedByTrash() Checks if player can move into a direction and if trash isn't blocking
|
||||
func (game *Game) blockedByTrash(press int) bool {
|
||||
var checkPos Position
|
||||
|
||||
if press == Left {
|
||||
checkPos.x = game.player.position.x - 1
|
||||
checkPos.y = game.player.position.y
|
||||
} else if press == Right {
|
||||
checkPos.x = game.player.position.x + 1
|
||||
checkPos.y = game.player.position.y
|
||||
} else if press == Up {
|
||||
checkPos.x = game.player.position.x
|
||||
checkPos.y = game.player.position.y - 1
|
||||
} else if press == Down {
|
||||
checkPos.x = game.player.position.x
|
||||
checkPos.y = game.player.position.y + 1
|
||||
} else if press == upleft {
|
||||
checkPos.x = game.player.position.x - 1
|
||||
checkPos.y = game.player.position.y - 1
|
||||
} else if press == upright {
|
||||
checkPos.x = game.player.position.x + 1
|
||||
checkPos.y = game.player.position.y - 1
|
||||
} else if press == downright {
|
||||
checkPos.x = game.player.position.x + 1
|
||||
checkPos.y = game.player.position.y + 1
|
||||
} else if press == downleft {
|
||||
checkPos.x = game.player.position.x - 1
|
||||
checkPos.y = game.player.position.y + 1
|
||||
}
|
||||
return game.onTrash(checkPos)
|
||||
}
|
||||
|
||||
func (game *Game) teleport() {
|
||||
|
||||
var pos Position
|
||||
var safe bool = false
|
||||
|
||||
for !safe {
|
||||
pos = game.randPos()
|
||||
if !game.onTrash(pos) {
|
||||
safe = true
|
||||
}
|
||||
}
|
||||
|
||||
game.player.position.x = pos.x
|
||||
game.player.position.y = pos.y
|
||||
|
||||
}
|
||||
|
||||
func (game *Game) onPlayer(pos Position) bool {
|
||||
var onPlayer bool
|
||||
if pos.x == game.player.position.x && pos.y == game.player.position.y {
|
||||
onPlayer = true
|
||||
} else {
|
||||
onPlayer = false
|
||||
}
|
||||
return onPlayer
|
||||
}
|
||||
|
||||
func (game *Game) resetPlayer() {
|
||||
game.player.position.x = 40
|
||||
game.player.position.y = 12
|
||||
}
|
67
robots/render.go
Normal file
67
robots/render.go
Normal file
@ -0,0 +1,67 @@
|
||||
package robots
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// drawBox Draw the outline of the box the snake can move in
|
||||
func (game *Game) drawBox() {
|
||||
|
||||
// Assuming we will always have this
|
||||
x1 := 0
|
||||
y1 := 0
|
||||
x2 := 79
|
||||
y2 := 23
|
||||
|
||||
// Fill background
|
||||
for row := y1; row <= y2; row++ {
|
||||
for col := x1; col <= x2; col++ {
|
||||
game.screen.SetContent(col, row, ' ', nil, game.style)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw borders
|
||||
for col := x1; col <= x2; col++ {
|
||||
game.screen.SetContent(col, y1, '═', nil, game.style)
|
||||
game.screen.SetContent(col, y2, '═', nil, game.style)
|
||||
}
|
||||
for row := y1 + 1; row < y2; row++ {
|
||||
game.screen.SetContent(x1, row, '║', nil, game.style)
|
||||
game.screen.SetContent(x2, row, '║', nil, game.style)
|
||||
}
|
||||
|
||||
// Only draw corners if necessary
|
||||
if y1 != y2 && x1 != x2 {
|
||||
game.screen.SetContent(x1, y1, '╔', nil, game.style)
|
||||
game.screen.SetContent(x2, y1, '╗', nil, game.style)
|
||||
game.screen.SetContent(x1, y2, '╚', nil, game.style)
|
||||
game.screen.SetContent(x2, y2, '╝', nil, game.style)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// drawCoords Print the coordinates of the player
|
||||
func (game *Game) drawCoords() {
|
||||
var x, y int = 25, 24
|
||||
for _, r := range []rune("[ x:" + strconv.FormatInt(int64(game.player.position.x), 10) + " y:" + strconv.FormatInt(int64(game.player.position.y), 10) + " ]") {
|
||||
game.screen.SetContent(x, y-1, r, nil, game.style)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) drawDebug() {
|
||||
var x, y int = 40, 24
|
||||
for _, r := range []rune("[ NumGoRoutine: " + strconv.FormatInt(int64(runtime.NumGoroutine()), 10) + " Bots: " + strconv.FormatInt(int64(len(game.robots)), 10) + " ]") {
|
||||
game.screen.SetContent(x, y-1, r, nil, game.style)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) drawScore() {
|
||||
var x, y int = 5, 24
|
||||
for _, r := range []rune("[ Score: " + strconv.FormatInt(int64(game.player.score), 10) + " Level: " + strconv.FormatInt(int64(game.level), 10) + " ]") {
|
||||
game.screen.SetContent(x, y-1, r, nil, game.style)
|
||||
x++
|
||||
}
|
||||
}
|
102
robots/robots.go
Normal file
102
robots/robots.go
Normal file
@ -0,0 +1,102 @@
|
||||
package robots
|
||||
|
||||
func (game *Game) initRobots() {
|
||||
var fabricate int = game.level * 16
|
||||
for i := 0; i < fabricate; i++ {
|
||||
var found bool
|
||||
var rndPos Position
|
||||
for !found {
|
||||
rndPos = game.randPos()
|
||||
if !game.onPlayer(rndPos) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
rndRobot := Robot{
|
||||
id: i,
|
||||
position: rndPos,
|
||||
}
|
||||
game.robots = append(game.robots, rndRobot)
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) drawRobots() {
|
||||
for _, r := range game.robots {
|
||||
game.screen.SetContent(r.position.x, r.position.y, '+', nil, game.style)
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) moveRobots() {
|
||||
// Iterate through the robots
|
||||
for i, r := range game.robots {
|
||||
|
||||
// Determine in which direction to go
|
||||
if game.player.position.x < r.position.x {
|
||||
game.robots[i].position.x--
|
||||
} else if game.player.position.x > r.position.x {
|
||||
game.robots[i].position.x++
|
||||
}
|
||||
|
||||
if game.player.position.y < r.position.y {
|
||||
game.robots[i].position.y--
|
||||
} else if game.player.position.y > r.position.y {
|
||||
game.robots[i].position.y++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// After all the moves, lets check if any of the rowboz collided with anything
|
||||
for _, r := range game.robots {
|
||||
|
||||
// Hit a player? Game over!
|
||||
if game.onPlayer(r.position) {
|
||||
game.gameover = 1
|
||||
return
|
||||
}
|
||||
|
||||
// Robots mingling? Trash!
|
||||
if game.onRobot(r) {
|
||||
|
||||
// Delete robot
|
||||
game.deleteRobot(r)
|
||||
|
||||
// Create trash
|
||||
game.addTrash(r)
|
||||
|
||||
}
|
||||
|
||||
// Hugging Trash? More trash!
|
||||
if game.onTrash(r.position) {
|
||||
|
||||
// Delete robot
|
||||
game.deleteRobot(r)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) onRobot(robot Robot) bool {
|
||||
var found bool = false
|
||||
for _, r := range game.robots {
|
||||
if robot.id != r.id && robot.position == r.position {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func (game *Game) deleteRobot(robot Robot) {
|
||||
|
||||
var rowboz []Robot
|
||||
|
||||
for _, r := range game.robots {
|
||||
if robot != r {
|
||||
rowboz = append(rowboz, r)
|
||||
}
|
||||
}
|
||||
game.robots = nil
|
||||
game.robots = rowboz
|
||||
|
||||
game.player.score++
|
||||
|
||||
}
|
25
robots/trash.go
Normal file
25
robots/trash.go
Normal file
@ -0,0 +1,25 @@
|
||||
package robots
|
||||
|
||||
func (game *Game) drawTrash() {
|
||||
for _, t := range game.trash {
|
||||
game.screen.SetContent(t.x, t.y, '*', nil, game.style)
|
||||
}
|
||||
}
|
||||
|
||||
func (game *Game) onTrash(pos Position) bool {
|
||||
var found bool
|
||||
for _, t := range game.trash {
|
||||
if t == pos {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func (game *Game) addTrash(robot Robot) {
|
||||
game.trash = append(game.trash, robot.position)
|
||||
}
|
||||
|
||||
func (game *Game) cleanTrash() {
|
||||
game.trash = nil
|
||||
}
|
45
robots/types.go
Normal file
45
robots/types.go
Normal file
@ -0,0 +1,45 @@
|
||||
package robots
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
Up = iota
|
||||
Left
|
||||
Right
|
||||
Down
|
||||
upleft
|
||||
upright
|
||||
downleft
|
||||
downright
|
||||
teleport
|
||||
)
|
||||
|
||||
type Position struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
position Position
|
||||
score int
|
||||
moves int
|
||||
teleports int
|
||||
}
|
||||
|
||||
type Game struct {
|
||||
screen tcell.Screen
|
||||
style tcell.Style
|
||||
keypresses chan int
|
||||
player Player
|
||||
level int
|
||||
robots []Robot
|
||||
trash []Position
|
||||
gameover int
|
||||
}
|
||||
|
||||
type Robot struct {
|
||||
id int
|
||||
position Position
|
||||
}
|
Reference in New Issue
Block a user