Initial Commit
This commit is contained in:
parent
5c335540e9
commit
89f16d6351
1
.gitignore
vendored
1
.gitignore
vendored
@ -20,3 +20,4 @@ _cgo_export.*
|
|||||||
_testmain.go
|
_testmain.go
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
|
gopher-battle
|
133
main.go
Normal file
133
main.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
//"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const programName = "gopher-battle"
|
||||||
|
|
||||||
|
var debugMode bool
|
||||||
|
var debugText string
|
||||||
|
var gameMode int
|
||||||
|
|
||||||
|
// ScreenWidth is how wide the Actual screen is
|
||||||
|
var ScreenWidth int
|
||||||
|
|
||||||
|
// ScreenHeight is how tall the Actual screen is
|
||||||
|
var ScreenHeight int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
debugMode = true
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = termbox.Init()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer termbox.Close()
|
||||||
|
|
||||||
|
style := defaultStyle()
|
||||||
|
termbox.SetOutputMode(termbox.Output256)
|
||||||
|
ScreenWidth, ScreenHeight = termbox.Size()
|
||||||
|
mainLoop(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readUserInput(e chan termbox.Event) {
|
||||||
|
for {
|
||||||
|
e <- termbox.PollEvent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendNoneEvent(e chan termbox.Event) {
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Second / 32)
|
||||||
|
e <- termbox.Event{Type: termbox.EventNone}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GameState is that.
|
||||||
|
type GameState struct {
|
||||||
|
helpText string
|
||||||
|
}
|
||||||
|
|
||||||
|
var state *GameState
|
||||||
|
|
||||||
|
func mainLoop(style style) {
|
||||||
|
// Initialize the Game
|
||||||
|
if state == nil {
|
||||||
|
state = new(GameState)
|
||||||
|
}
|
||||||
|
screens := defaultScreens()
|
||||||
|
displayScreen := screens[titleScreenIndex]
|
||||||
|
layoutAndDrawScreen(displayScreen, style)
|
||||||
|
eventchan := make(chan termbox.Event)
|
||||||
|
go readUserInput(eventchan)
|
||||||
|
go sendNoneEvent(eventchan)
|
||||||
|
|
||||||
|
//var fps, fpsTrack, trackTime int
|
||||||
|
for {
|
||||||
|
// Read User Input
|
||||||
|
event := <-eventchan // := termbox.PollEvent()
|
||||||
|
/*
|
||||||
|
if getNowTime()-trackTime >= int(time.Second) {
|
||||||
|
fps = fpsTrack
|
||||||
|
fpsTrack = 0
|
||||||
|
trackTime = getNowTime()
|
||||||
|
}
|
||||||
|
fpsTrack++
|
||||||
|
*/
|
||||||
|
var newScreenIndex int
|
||||||
|
if event.Type == termbox.EventKey {
|
||||||
|
if event.Key == termbox.KeyCtrlC {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
newScreenIndex = displayScreen.handleKeyEvent(event)
|
||||||
|
if newScreenIndex < len(screens) {
|
||||||
|
displayScreen = screens[newScreenIndex]
|
||||||
|
} else if newScreenIndex == exitScreenIndex {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
gameMode = newScreenIndex
|
||||||
|
}
|
||||||
|
// Update Game State
|
||||||
|
if gameMode == mainScreenIndex {
|
||||||
|
// In game updates
|
||||||
|
displayScreen.update()
|
||||||
|
}
|
||||||
|
// Draw Screen
|
||||||
|
layoutAndDrawScreen(displayScreen, style)
|
||||||
|
//debugText = fmt.Sprintf("FPS: %d", fps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Screens Setup
|
||||||
|
const (
|
||||||
|
titleScreenIndex = iota
|
||||||
|
mainScreenIndex
|
||||||
|
exitScreenIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultScreens() []Screen {
|
||||||
|
//var view_port ViewPort
|
||||||
|
titleScreen := titleScreen{}
|
||||||
|
mainScreen := mainScreen{}
|
||||||
|
screens := [...]Screen{
|
||||||
|
&titleScreen,
|
||||||
|
&mainScreen,
|
||||||
|
}
|
||||||
|
return screens[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToLog Writes to the Log
|
||||||
|
func WriteToLog(d string) {
|
||||||
|
f, err := os.OpenFile(programName+".log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
f.WriteString(d)
|
||||||
|
f.Close()
|
||||||
|
}
|
35
screen.go
Normal file
35
screen.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
"gogs.bullercodeworks.com/brian/termbox-util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Screen TODO: Comment
|
||||||
|
type Screen interface {
|
||||||
|
handleKeyEvent(event termbox.Event) int
|
||||||
|
performLayout(style style)
|
||||||
|
drawScreen(style style)
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ViewPort TODO: Comment
|
||||||
|
type ViewPort struct {
|
||||||
|
bytesPerRow int
|
||||||
|
numberOfRows int
|
||||||
|
firstRow int
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawBackground(bg termbox.Attribute) {
|
||||||
|
termbox.Clear(0, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func layoutAndDrawScreen(screen Screen, style style) {
|
||||||
|
screen.performLayout(style)
|
||||||
|
drawBackground(style.defaultBg)
|
||||||
|
screen.drawScreen(style)
|
||||||
|
if debugMode {
|
||||||
|
termboxUtil.DrawStringAtPoint(debugText, 0, 0, style.defaultFg, style.defaultBg)
|
||||||
|
}
|
||||||
|
termbox.Flush()
|
||||||
|
}
|
204
screen_main.go
Normal file
204
screen_main.go
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gogs.bullercodeworks.com/brian/termbox-util"
|
||||||
|
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
modeInit = iota
|
||||||
|
modeRun
|
||||||
|
modeRunInput
|
||||||
|
)
|
||||||
|
|
||||||
|
type player struct {
|
||||||
|
x, y int
|
||||||
|
projSpeed int
|
||||||
|
projAngle int
|
||||||
|
screen *mainScreen
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *player) draw() {
|
||||||
|
drawGopher(p.x, p.y, termbox.ColorCyan)
|
||||||
|
}
|
||||||
|
|
||||||
|
type building struct {
|
||||||
|
width, height int
|
||||||
|
color termbox.Attribute
|
||||||
|
windowsOn []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *building) draw(x int) {
|
||||||
|
// Fill
|
||||||
|
for i := 0; i < b.height; i++ {
|
||||||
|
for j := 0; j < b.width; j++ {
|
||||||
|
c := b.color
|
||||||
|
/*
|
||||||
|
if i > 0 && i < b.height && j > 0 && j < b.width {
|
||||||
|
if i%2 == 1 && j%2 == 1 {
|
||||||
|
c = termbox.ColorBlack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
termbox.SetCell(x+j, ScreenHeight-i, ' ', c, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mainScreen struct {
|
||||||
|
GameMode int
|
||||||
|
PlayerTurn int
|
||||||
|
tabIdx int
|
||||||
|
Player1 player
|
||||||
|
Player2 player
|
||||||
|
Buildings []building
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *mainScreen) handleKeyEvent(event termbox.Event) int {
|
||||||
|
if screen.GameMode == modeRunInput {
|
||||||
|
}
|
||||||
|
return mainScreenIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *mainScreen) performLayout(style style) {
|
||||||
|
var bldCity int
|
||||||
|
if screen.GameMode == modeInit {
|
||||||
|
// Create a random seed (from time)
|
||||||
|
seed := fmt.Sprintf("%d", time.Now().UnixNano())
|
||||||
|
r := rand.New(rand.NewSource(getSeedFromString(seed + "-world")))
|
||||||
|
for bldCity < ScreenWidth {
|
||||||
|
w := r.Intn(8) + 5
|
||||||
|
h := r.Intn(ScreenHeight-10) + 2
|
||||||
|
var c termbox.Attribute
|
||||||
|
switch r.Intn(3) {
|
||||||
|
case 0:
|
||||||
|
c = termbox.ColorRed
|
||||||
|
case 1:
|
||||||
|
c = termbox.ColorGreen
|
||||||
|
case 2:
|
||||||
|
c = termbox.ColorBlue
|
||||||
|
}
|
||||||
|
b := building{width: w, height: h, color: c}
|
||||||
|
screen.Buildings = append(screen.Buildings, b)
|
||||||
|
bldCity += w
|
||||||
|
}
|
||||||
|
// Player 1 should be on the first 1/3 of the screen
|
||||||
|
p1x := r.Intn(ScreenWidth / 3)
|
||||||
|
p1y := 0
|
||||||
|
// Make sure that p1x is fully on a building
|
||||||
|
// Find the building for the player's x
|
||||||
|
var calcX int
|
||||||
|
for i := range screen.Buildings {
|
||||||
|
calcX += screen.Buildings[i].width
|
||||||
|
if calcX > p1x {
|
||||||
|
if calcX > p1x+5 {
|
||||||
|
mv := (p1x + 5) - calcX
|
||||||
|
p1x -= mv
|
||||||
|
}
|
||||||
|
p1y = ScreenHeight - screen.Buildings[i].height
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
screen.Player1 = player{x: p1x, y: p1y, screen: screen}
|
||||||
|
// Player 2 should be on the third 1/3 of the screen
|
||||||
|
p2x := r.Intn(ScreenWidth/3) + ((ScreenWidth * 2) / 3)
|
||||||
|
p2y := 0
|
||||||
|
for i := range screen.Buildings {
|
||||||
|
calcX += screen.Buildings[i].width
|
||||||
|
if calcX > p1x {
|
||||||
|
if calcX > p2x+5 {
|
||||||
|
mv := (p2x + 5) - calcX
|
||||||
|
p2x -= mv
|
||||||
|
}
|
||||||
|
p2y = ScreenHeight - screen.Buildings[i].height
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make sure that p2x is fully on a building
|
||||||
|
screen.Player2 = player{x: p2x, y: p2y, screen: screen}
|
||||||
|
}
|
||||||
|
screen.GameMode = modeRun
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger all updates
|
||||||
|
func (screen *mainScreen) update() {
|
||||||
|
if screen.GameMode == modeRun {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *mainScreen) drawScreen(style style) {
|
||||||
|
// Draw Player 1
|
||||||
|
screen.Player1.draw()
|
||||||
|
// Draw Player 2
|
||||||
|
screen.Player2.draw()
|
||||||
|
// Draw Landscape
|
||||||
|
var x int
|
||||||
|
for i := range screen.Buildings {
|
||||||
|
screen.Buildings[i].draw(x)
|
||||||
|
x += screen.Buildings[i].width
|
||||||
|
}
|
||||||
|
if screen.GameMode == modeRun {
|
||||||
|
// Draw Projectile(s)
|
||||||
|
} else if screen.GameMode == modeRunInput {
|
||||||
|
// Draw inputs
|
||||||
|
if screen.PlayerTurn == 1 {
|
||||||
|
termboxUtil.DrawStringAtPoint("Angle:", 0, 0, style.defaultFg, style.defaultBg)
|
||||||
|
termboxUtil.DrawStringAtPoint("Speed:", 0, 1, style.defaultFg, style.defaultBg)
|
||||||
|
} else {
|
||||||
|
termboxUtil.DrawStringAtPoint("Angle:", ScreenWidth-11, 0, style.defaultFg, style.defaultBg)
|
||||||
|
termboxUtil.DrawStringAtPoint("Speed:", ScreenWidth-11, 1, style.defaultFg, style.defaultBg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNowTime() int {
|
||||||
|
return int(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSeedFromString(seed string) int64 {
|
||||||
|
// How does this algorithm work for string->seed generation?
|
||||||
|
// ~\_(o.o)_/~
|
||||||
|
var ret int64
|
||||||
|
for i, k := range seed {
|
||||||
|
ret += int64(k) * int64(i)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawGopher(x, y int, c termbox.Attribute) {
|
||||||
|
termbox.SetCell(x, y-4, ' ', c, c)
|
||||||
|
termbox.SetCell(x+1, y-4, ' ', c, c)
|
||||||
|
termbox.SetCell(x+2, y-4, ' ', c, c)
|
||||||
|
termbox.SetCell(x+3, y-4, ' ', c, c)
|
||||||
|
termbox.SetCell(x+4, y-4, ' ', c, c)
|
||||||
|
|
||||||
|
termbox.SetCell(x, y-3, ' ', c, c)
|
||||||
|
termbox.SetCell(x+1, y-3, '@', termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
termbox.SetCell(x+2, y-3, ' ', c, c)
|
||||||
|
termbox.SetCell(x+3, y-3, '@', termbox.ColorBlack, termbox.ColorWhite)
|
||||||
|
termbox.SetCell(x+4, y-3, ' ', c, c)
|
||||||
|
|
||||||
|
termbox.SetCell(x, y-2, ' ', c, c)
|
||||||
|
termbox.SetCell(x+1, y-2, ' ', c, c)
|
||||||
|
termbox.SetCell(x+2, y-2, 'w', termbox.ColorWhite, c)
|
||||||
|
termbox.SetCell(x+3, y-2, ' ', c, c)
|
||||||
|
termbox.SetCell(x+4, y-2, ' ', c, c)
|
||||||
|
|
||||||
|
termbox.SetCell(x, y-1, ' ', c, c)
|
||||||
|
termbox.SetCell(x+1, y-1, ' ', c, c)
|
||||||
|
termbox.SetCell(x+2, y-1, ' ', c, c)
|
||||||
|
termbox.SetCell(x+3, y-1, ' ', c, c)
|
||||||
|
termbox.SetCell(x+4, y-1, ' ', c, c)
|
||||||
|
|
||||||
|
termbox.SetCell(x, y, ' ', c, c)
|
||||||
|
termbox.SetCell(x+1, y, ' ', c, c)
|
||||||
|
termbox.SetCell(x+2, y, ' ', c, c)
|
||||||
|
termbox.SetCell(x+3, y, ' ', c, c)
|
||||||
|
termbox.SetCell(x+4, y, ' ', c, c)
|
||||||
|
}
|
70
screen_title.go
Normal file
70
screen_title.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
"gogs.bullercodeworks.com/brian/termbox-util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type command struct {
|
||||||
|
key string
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
type titleScreen struct {
|
||||||
|
titleArt *termboxUtil.ASCIIArt
|
||||||
|
menu *termboxUtil.Menu
|
||||||
|
initialized bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *titleScreen) handleKeyEvent(event termbox.Event) int {
|
||||||
|
if screen.menu.HandleKeyPress(event) {
|
||||||
|
if screen.menu.IsDone() {
|
||||||
|
selOpt := screen.menu.GetSelectedOption()
|
||||||
|
if selOpt.GetText() == "Exit" {
|
||||||
|
return exitScreenIndex
|
||||||
|
} else if selOpt.GetText() == "New Game" {
|
||||||
|
screen.initialized = false
|
||||||
|
return mainScreenIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return titleScreenIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *titleScreen) performLayout(style style) {
|
||||||
|
if !screen.initialized {
|
||||||
|
var tmplt []string
|
||||||
|
tmplt = append(tmplt, " ")
|
||||||
|
tmplt = append(tmplt, " ")
|
||||||
|
tmplt = append(tmplt, " gopher.bas ")
|
||||||
|
tmplt = append(tmplt, " ")
|
||||||
|
tmplt = append(tmplt, " ")
|
||||||
|
tmplt = append(tmplt, " ")
|
||||||
|
|
||||||
|
defaultFg := style.defaultFg
|
||||||
|
defaultBg := style.defaultBg
|
||||||
|
screen.titleArt = termboxUtil.CreateASCIIArt(tmplt, 0, 0, defaultFg, defaultBg)
|
||||||
|
w, h := termbox.Size()
|
||||||
|
screen.titleArt.Align(termboxUtil.AlignCenter, w)
|
||||||
|
|
||||||
|
menuX := w/2 - 10
|
||||||
|
menuY := h/2 - 5
|
||||||
|
|
||||||
|
screen.menu = termboxUtil.CreateMenu("",
|
||||||
|
[]string{"New Game", "Continue", "Exit"},
|
||||||
|
menuX, menuY, 20, 10, defaultFg, defaultBg,
|
||||||
|
)
|
||||||
|
// TODO: Check if we have a suspended game
|
||||||
|
screen.menu.SetOptionDisabled(1)
|
||||||
|
screen.menu.SetBordered(true)
|
||||||
|
screen.menu.EnableVimMode()
|
||||||
|
screen.initialized = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (screen *titleScreen) update() {}
|
||||||
|
|
||||||
|
func (screen *titleScreen) drawScreen(style style) {
|
||||||
|
screen.titleArt.Draw()
|
||||||
|
screen.menu.Draw()
|
||||||
|
}
|
23
style.go
Normal file
23
style.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/nsf/termbox-go"
|
||||||
|
|
||||||
|
type style struct {
|
||||||
|
defaultBg termbox.Attribute
|
||||||
|
defaultFg termbox.Attribute
|
||||||
|
titleBg termbox.Attribute
|
||||||
|
titleFg termbox.Attribute
|
||||||
|
cursorBg termbox.Attribute
|
||||||
|
cursorFg termbox.Attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultStyle() style {
|
||||||
|
var style style
|
||||||
|
style.defaultBg = termbox.ColorBlack
|
||||||
|
style.defaultFg = termbox.ColorWhite
|
||||||
|
style.titleBg = style.defaultBg
|
||||||
|
style.titleFg = style.defaultFg | termbox.AttrBold
|
||||||
|
style.cursorBg = termbox.ColorWhite
|
||||||
|
style.cursorFg = termbox.ColorBlack
|
||||||
|
return style
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user