Initial Commit
This commit is contained in:
parent
5c335540e9
commit
89f16d6351
3
.gitignore
vendored
3
.gitignore
vendored
@ -19,4 +19,5 @@ _cgo_export.*
|
||||
|
||||
_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