Initial Commit

This commit is contained in:
Brian Buller 2016-01-06 12:24:08 -06:00
parent 5c335540e9
commit 89f16d6351
6 changed files with 467 additions and 1 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ _cgo_export.*
_testmain.go _testmain.go
*.exe *.exe
gopher-battle

133
main.go Normal file
View 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
View 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
View 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
View 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
View 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
}