ui starting, menu screen, ingame help
This commit is contained in:
parent
4532320ce3
commit
cb7718860a
@ -59,7 +59,6 @@ func main() {
|
||||
// set up context
|
||||
mainCtx := util.NewClientContext(config, &logger)
|
||||
|
||||
|
||||
//set up main window
|
||||
mw := mainwindow.Init(mainCtx)
|
||||
defer mw.Close()
|
||||
@ -69,7 +68,6 @@ func main() {
|
||||
//set up input decoder
|
||||
go decodeInput(mainCtx, mw.GetLayer("base"))
|
||||
|
||||
|
||||
//fixme set up (load / generate) level
|
||||
level, rooms := mapgens.DefaultGen(gamemap.NewLevel(mainCtx, "test", 1))
|
||||
State.Level = level
|
||||
@ -78,7 +76,6 @@ func main() {
|
||||
vp := mainwindow.NewViewPort(30, 0, (mw.W - 30), (mw.H - 0), mw.GetLayer("base"))
|
||||
go vp.Listen(State)
|
||||
|
||||
|
||||
//set up controller
|
||||
|
||||
controller := ecs.NewController()
|
||||
@ -93,13 +90,36 @@ func main() {
|
||||
Level: level,
|
||||
}
|
||||
|
||||
|
||||
//Set up Screen Manager
|
||||
screenMgr := types.NewScreenManager(mainCtx)
|
||||
screenMgr.AddScreen("title", &screens.TitleScreen{})
|
||||
screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp, controller))
|
||||
screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr))
|
||||
screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp, controller, screenMgr))
|
||||
screenMgr.AddScreen("help", screens.NewMenuScreen(
|
||||
mw,
|
||||
screenMgr,
|
||||
"Help",
|
||||
"Keybindings:",
|
||||
//"[color=yellow]Note[/color]: Many of these are not implemented yet",
|
||||
"[color=yellow]Note[/color]: Many of these are not implemented yet",
|
||||
types.NewCenteredRect(mw.Rect, 50, 15),
|
||||
true, ).
|
||||
SetBgColor("#ef1d494f").
|
||||
SetFgColor("white").
|
||||
SetItems([]interface{}{
|
||||
"hjklyubn 12346789 or arrow keys - move",
|
||||
"s or . - pass turn",
|
||||
"g or , - pick up item",
|
||||
"i - inventory",
|
||||
"? - this screen",
|
||||
"Ctrl+q - exit",
|
||||
"f or F - fire or throw weapon",
|
||||
"z or Z - cast a spell",
|
||||
"p - pray",
|
||||
"Ctrl+p - message log",
|
||||
}),
|
||||
)
|
||||
|
||||
screenMgr.SetScreenByName("game")
|
||||
screenMgr.SetScreenByName("title")
|
||||
|
||||
//fixme
|
||||
//player := &mob.Player{
|
||||
@ -119,7 +139,6 @@ func main() {
|
||||
//vp.PlayerCoords = player.Coords
|
||||
//vp.Render(&State)
|
||||
|
||||
|
||||
//fixme set up (load / generate) player
|
||||
player := controller.CreateEntity([]ecs.Component{})
|
||||
|
||||
@ -153,9 +172,10 @@ func main() {
|
||||
mainCtx.Logger().Warn().Msg("quitting NOW")
|
||||
exit = true
|
||||
break
|
||||
// не оставляйте default в бесконесчном select {} - сожрет всё CPU
|
||||
// не оставляйте default в бесконечном select {} - сожрет всё CPU
|
||||
default:
|
||||
screenMgr.CurrentScreen.Render()
|
||||
blt.Layer(0) //return to base layer
|
||||
blt.Refresh()
|
||||
}
|
||||
|
||||
@ -166,7 +186,8 @@ func main() {
|
||||
func setupLayers(mainwindow *mainwindow.MainWindow) {
|
||||
mainwindow.AddLayer("base", 0, "white")
|
||||
mainwindow.AddLayer("overlay", 1, "white")
|
||||
mainwindow.AddLayer("menu", 2, "white")
|
||||
mainwindow.AddLayer("menubg", 2, "white")
|
||||
mainwindow.AddLayer("menu", 3, "white")
|
||||
}
|
||||
|
||||
func decodeInput(ctx util.ClientCtx, baseLayer *mainwindow.Layer) {
|
||||
@ -208,8 +229,8 @@ func decodeInput(ctx util.ClientCtx, baseLayer *mainwindow.Layer) {
|
||||
blt.Set("window: size=100x47; font: ./resources/fonts-ttf/UbuntuMono-R.ttf, size=11;")
|
||||
})
|
||||
case "Ctrl+q":
|
||||
fallthrough
|
||||
case "Escape":
|
||||
//fallthrough
|
||||
//case "Escape":
|
||||
ctx.Logger().Info().Msg("exiting on quit command...")
|
||||
State.Exit <- struct{}{}
|
||||
ctx.Logger().Info().Msg("...done")
|
||||
|
@ -24,6 +24,9 @@ func DefaultGen(l *gamemap.Level) (*gamemap.Level, []*gamemap.Room) {
|
||||
|
||||
rooms := make([]*gamemap.Room, 0)
|
||||
|
||||
//one wall around whole level guaranteed
|
||||
levelBoundary := types.NewRect(l.X + 1, l.Y + 1, l.W - 2, l.H - 2)
|
||||
|
||||
for i := 0; i < maxrooms; i++ {
|
||||
newRoom := &gamemap.Room{
|
||||
Rect: types.NewRect(
|
||||
@ -36,7 +39,7 @@ func DefaultGen(l *gamemap.Level) (*gamemap.Level, []*gamemap.Room) {
|
||||
|
||||
failed := false
|
||||
|
||||
if !l.InBounds(types.Coords{newRoom.X, newRoom.Y}) {
|
||||
if !levelBoundary.InBounds(types.Coords{newRoom.X, newRoom.Y}) {
|
||||
failed = true
|
||||
}
|
||||
|
||||
|
@ -14,18 +14,24 @@ type GameScreen struct {
|
||||
state *gamestate.GameState
|
||||
vp *mainwindow.ViewPort
|
||||
controller *ecs.Controller
|
||||
scm *types.ScreenManager
|
||||
}
|
||||
|
||||
func NewGameScreen(mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller) *GameScreen {
|
||||
return &GameScreen{mw: mw, state: state, vp: viewPort, controller: controller}
|
||||
func NewGameScreen(mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen {
|
||||
ts := &GameScreen{mw: mw, state: state, vp: viewPort, controller: controller, scm: scm}
|
||||
renderMobs := systems.MobRenderSystem{EntityController: ts.controller}
|
||||
ts.controller.AddSystem(renderMobs, 1)
|
||||
return ts
|
||||
}
|
||||
|
||||
func (ts *GameScreen) UseEcs() bool { return true }
|
||||
func (ts *GameScreen) Enter() {
|
||||
renderMobs := systems.MobRenderSystem{EntityController: ts.controller}
|
||||
ts.controller.AddSystem(renderMobs, 1)
|
||||
ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H - 3, 30, 3)
|
||||
ts.mw.GetLayer("overlay").WithColor("#77777777").
|
||||
Print(1, ts.mw.H - 2, "Press [color=white]?[/color] for help")
|
||||
}
|
||||
func (ts *GameScreen) Exit() {
|
||||
ts.mw.GetLayer("base").ClearArea(1, ts.mw.H -2, 30, 1)
|
||||
//remove what we dont need
|
||||
}
|
||||
|
||||
@ -56,6 +62,9 @@ func (ts *GameScreen) HandleInput(input string) {
|
||||
case "n", "3":
|
||||
ts.walk(ts.state, 1, 1)
|
||||
break
|
||||
case "Shift+/":
|
||||
ts.scm.SetScreenByName("help")
|
||||
break
|
||||
default:
|
||||
ts.mw.GetLayer("base").ClearArea(0, 3, 40, 1)
|
||||
ts.mw.GetLayer("base").Print(1, 3, "Key: "+input)
|
||||
|
116
engine/screens/menu.go
Normal file
116
engine/screens/menu.go
Normal file
@ -0,0 +1,116 @@
|
||||
package screens
|
||||
|
||||
import (
|
||||
"lab.zaar.be/thefish/alchemyst-go/engine/types"
|
||||
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
|
||||
blt "lab.zaar.be/thefish/bearlibterminal"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const runeIndex = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
type MenuScreen struct {
|
||||
*types.Rect
|
||||
|
||||
mw *mainwindow.MainWindow
|
||||
scm *types.ScreenManager
|
||||
renderParent bool
|
||||
|
||||
items []interface{}
|
||||
title string
|
||||
header string
|
||||
footer string
|
||||
redraw bool
|
||||
bgColor string
|
||||
fgColor string
|
||||
}
|
||||
|
||||
func NewMenuScreen(mw *mainwindow.MainWindow, scm *types.ScreenManager, title, header, footer string, rect *types.Rect, renderParent bool) *MenuScreen {
|
||||
return &MenuScreen{
|
||||
title: title,
|
||||
header: header,
|
||||
footer: footer,
|
||||
Rect: rect,
|
||||
mw: mw,
|
||||
scm: scm,
|
||||
renderParent: renderParent,
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) SetBgColor(color string) *MenuScreen {
|
||||
ms.bgColor = color
|
||||
return ms
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) SetFgColor(color string) *MenuScreen {
|
||||
ms.fgColor = color
|
||||
return ms
|
||||
}
|
||||
|
||||
//fixme!!
|
||||
|
||||
func (ms *MenuScreen) SetItems(items []interface{}) *MenuScreen {
|
||||
ms.items = items
|
||||
return ms
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) UseEcs() bool { return false }
|
||||
|
||||
func (ms *MenuScreen) Enter() {
|
||||
ms.redraw = true
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) HandleInput(input string) {
|
||||
//
|
||||
//if input != "" {
|
||||
// ms.redraw = true
|
||||
//}
|
||||
|
||||
switch input {
|
||||
case "Space":
|
||||
ms.scm.SetScreen(ms.scm.PreviousScreen)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) Exit() {
|
||||
menuLayer := ms.mw.GetLayer("menu")
|
||||
menuLayer.ClearRect(ms.Rect)
|
||||
bgLayer := ms.mw.GetLayer("menubg")
|
||||
bgLayer.ClearRect(ms.Rect)
|
||||
}
|
||||
|
||||
func (ms *MenuScreen) Render() {
|
||||
if ms.renderParent {
|
||||
ms.scm.PreviousScreen.Render()
|
||||
}
|
||||
if (ms.redraw || ms.renderParent) {
|
||||
ms.redraw = false
|
||||
menuLayer := ms.mw.GetLayer("menu")
|
||||
menuLayer.ClearRect(ms.Rect)
|
||||
bgLayer := ms.mw.GetLayer("menubg")
|
||||
bgLayer.ClearRect(ms.Rect)
|
||||
bgLayer.WithColor(ms.bgColor).NewWindow(ms.Rect).Splash()
|
||||
menuLayer.WithColor(ms.fgColor).NewWindow(ms.Rect).DoubleBordered(ms.title)
|
||||
menuLayer.Print(ms.X+(ms.W/2)-7, ms.Y+ms.H-1, "╡"+"[color=green]Space[/color] to close"+"╞")
|
||||
footerHeight := 0
|
||||
if ms.footer != "" {
|
||||
_, footerHeight = menuLayer.PrintInside(ms.Rect, ms.footer, 9)
|
||||
footerHeight = footerHeight + 2
|
||||
}
|
||||
_, headerHeight := menuLayer.PrintInside(ms.Rect, ms.header, blt.TK_ALIGN_LEFT)
|
||||
itemField := types.Rect{ms.X, ms.Y + headerHeight + 1, ms.W, ms.H - headerHeight - footerHeight}
|
||||
_ = itemField
|
||||
if (len(ms.items) > 0) {
|
||||
//fixme itemfield object, scroller, inputhandler, current selected item
|
||||
menuItems := make([]string, 0)
|
||||
for i, _ := range ms.items {
|
||||
if string(ms.items[i].(string)) != "" {
|
||||
menuItems = append(menuItems, ms.items[i].(string))
|
||||
}
|
||||
}
|
||||
menuLayer.PrintInside(&itemField, strings.Join(menuItems, "\n"), blt.TK_ALIGN_LEFT)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
11
engine/screens/sample.go
Normal file
11
engine/screens/sample.go
Normal file
@ -0,0 +1,11 @@
|
||||
package screens
|
||||
|
||||
type SampleScreen struct {
|
||||
|
||||
}
|
||||
|
||||
func (ss *SampleScreen) UseEcs() bool {return false}
|
||||
func (ss *SampleScreen) Enter() {}
|
||||
func (ss *SampleScreen) HandleInput(input string) {}
|
||||
func (ss *SampleScreen) Exit() {}
|
||||
func (ss *SampleScreen) Render() {}
|
@ -1,11 +1,66 @@
|
||||
package screens
|
||||
|
||||
type TitleScreen struct {
|
||||
import (
|
||||
"lab.zaar.be/thefish/alchemyst-go/engine/types"
|
||||
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
|
||||
blt "lab.zaar.be/thefish/bearlibterminal"
|
||||
)
|
||||
|
||||
type TitleScreen struct {
|
||||
mw *mainwindow.MainWindow
|
||||
scm *types.ScreenManager
|
||||
}
|
||||
|
||||
func (ts *TitleScreen) UseEcs() bool {return false}
|
||||
func (ts *TitleScreen) Enter() {}
|
||||
func (ts *TitleScreen) HandleInput(input string) {}
|
||||
func (ts *TitleScreen) Exit() {}
|
||||
func (ts *TitleScreen) Render() {}
|
||||
func NewTitleScreen(mw *mainwindow.MainWindow, scm *types.ScreenManager) *TitleScreen {
|
||||
return &TitleScreen{mw: mw, scm: scm}
|
||||
}
|
||||
|
||||
func (ts *TitleScreen) UseEcs() bool { return false }
|
||||
func (ts *TitleScreen) Enter() {
|
||||
blt.Clear()
|
||||
}
|
||||
func (ts *TitleScreen) HandleInput(input string) {
|
||||
switch input {
|
||||
case "n":
|
||||
ts.scm.SetScreenByName("game")
|
||||
}
|
||||
}
|
||||
func (ts *TitleScreen) Exit() {
|
||||
blt.Clear()
|
||||
}
|
||||
func (ts *TitleScreen) Render() {
|
||||
blt.PrintExt(0, 0, ts.mw.W, ts.mw.H, 15, logo)
|
||||
}
|
||||
|
||||
var logo = `
|
||||
.ddxo. .c c xlx
|
||||
.kd. .0o:O, c0uO'
|
||||
xc 0; x: ko ,,
|
||||
;l Y; c, .Yct;
|
||||
.. .. .......
|
||||
:o: :k; .cxloOo x0. kO .olldk; do .;k lO. dO 'xllxk; ocokk:dl
|
||||
.lKO, .kl 'dl c l0l..;dK lkx..;d: dOx .cOx ,0o c0 kk. .Y .Oo
|
||||
.l0.k0. .0l lK. l0oxxxOK OK;xxx kKOklOkx ,kO;'do. ;xO: .Oo
|
||||
:OoooxO .Ol ;Xc , cK' dK xX. , Ox YY xx ,O0. . .oKx. .0o
|
||||
;k. .Ox Ok..'.,l ;Kk:;dk cKl lX: dKc,;oc kx kk OO dKl;lk: .0O
|
||||
l; ,o .kK0KKK; :Ok; c; l: .oxc. x: Ol xl .dk: .o
|
||||
|
||||
|
||||
|
||||
Alchemyst (c) 2011-2014 thefish <thefish@zaar.be>
|
||||
|
||||
|
||||
|
||||
[color=green]N[/color]ew dungeon run
|
||||
[color=green]L[/color]oad saved game
|
||||
Read [color=green]h[/color]elp file
|
||||
Highest [color=green]S[/color]cores
|
||||
|
||||
|
||||
|
||||
Roguebasin Libtcod Tutorial (c) 2010-2011, Jotaf Henriques
|
||||
Brogue 1.3 (c) 2010 Brian Walker
|
||||
Madness (c) 2010 hmp <humpolec@gmail.com>
|
||||
BearLibTerminal (c) Cfyz 2009-2019 <http://foo.wyrd.name/en:bearlibterminal>
|
||||
Gogue (c) jcerise
|
||||
`
|
@ -12,10 +12,16 @@ func NewRect(x, y, w, h int) *Rect {
|
||||
return &Rect{x, y, w, h}
|
||||
}
|
||||
|
||||
func NewCenteredRect(source *Rect, w, h int) *Rect {
|
||||
targetX := source.X + source.W / 2 - w / 2
|
||||
targetY := source.Y + source.H / 2 - h / 2
|
||||
return &Rect{targetX, targetY, w, h}
|
||||
}
|
||||
|
||||
func (r *Rect) Blit(fillage RectFill, layer Putable) {
|
||||
|
||||
if fillage.Body != "" {
|
||||
for i := r.X + 1; i < r.X+r.W; i++ {
|
||||
for i := r.X+1; i < r.X+r.W - 1; i++ {
|
||||
for j := r.Y + 1; j < r.Y+r.H; j++ {
|
||||
layer.Put(i, j, fillage.Body)
|
||||
//lii.Put(i, j, "X");
|
||||
@ -23,27 +29,27 @@ func (r *Rect) Blit(fillage RectFill, layer Putable) {
|
||||
}
|
||||
}
|
||||
|
||||
for i := r.X + 1; i < r.X+r.W; i++ {
|
||||
for i := r.X; i < r.X+r.W - 1; i++ {
|
||||
layer.Put(i, r.Y, fillage.Top)
|
||||
//lii.Put(i, Y-1, "Q");
|
||||
layer.Put(i, r.Y+r.H, fillage.Bottom)
|
||||
layer.Put(i, r.Y+r.H - 1, fillage.Bottom)
|
||||
//lii.Put(i, Y+H, "H");
|
||||
}
|
||||
|
||||
for j := r.Y + 1; j < r.Y+r.H; j++ {
|
||||
for j := r.Y; j < r.Y+r.H; j++ {
|
||||
layer.Put(r.X, j, fillage.Left)
|
||||
//lii.Put(X-1, j, "U");
|
||||
layer.Put(r.X+r.W, j, fillage.Right)
|
||||
layer.Put(r.X+r.W - 1, j, fillage.Right)
|
||||
//lii.Put(X+W, j, "M");
|
||||
}
|
||||
|
||||
layer.Put(r.X, r.Y, fillage.TopLeft)
|
||||
//lii.Put(X-1, Y-1, "T");
|
||||
layer.Put(r.X, r.Y+r.H, fillage.BottomLeft)
|
||||
layer.Put(r.X, r.Y+r.H - 1, fillage.BottomLeft)
|
||||
//lii.Put(X-1, Y+H, "q");
|
||||
layer.Put(r.X+r.W, r.Y, fillage.TopRight)
|
||||
layer.Put(r.X+r.W - 1, r.Y, fillage.TopRight)
|
||||
//lii.Put(X+W, Y-1, "L");
|
||||
layer.Put(r.X+r.W, r.Y+r.H, fillage.BottomRight)
|
||||
layer.Put(r.X+r.W - 1, r.Y+r.H - 1, fillage.BottomRight)
|
||||
}
|
||||
|
||||
func (self *Rect) Intersects(other *Rect) bool {
|
||||
|
@ -6,12 +6,12 @@ import (
|
||||
)
|
||||
|
||||
type Layer struct {
|
||||
idx int
|
||||
Idx int
|
||||
defaultColor uint32
|
||||
}
|
||||
|
||||
func (layer *Layer) before() *Layer {
|
||||
blt.Layer(layer.idx)
|
||||
blt.Layer(layer.Idx)
|
||||
return layer
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@ func (Layer *Layer) PutToBase(x,y int, symbol interface{}, fg uint32, bg uint32)
|
||||
rnes := []rune(symbol.(string))
|
||||
prevColor := uint32(blt.State(blt.TK_COLOR))
|
||||
prevBgColor := uint32(blt.State(blt.TK_BKCOLOR))
|
||||
blt.Layer(0)
|
||||
blt.BkColor(bg)
|
||||
blt.Color(fg)
|
||||
if (len(rnes)) > 0 {
|
||||
@ -87,7 +88,13 @@ func (layer Layer) Put(x, y int, symbol interface{}) {
|
||||
}
|
||||
|
||||
func (layer Layer) Print(x, y int, txt string) (w, h int) {
|
||||
return blt.Print(x, y, txt)
|
||||
w, h = blt.Print(x, y, txt)
|
||||
//blt.Layer(0)
|
||||
return w, h
|
||||
}
|
||||
|
||||
func (layer Layer) PrintInside(rect *types.Rect, text string, alignment int) (width int, height int) {
|
||||
return blt.PrintExt(rect.X + 2, rect.Y + 2, rect.W - 4, rect.H - 4, alignment, text)
|
||||
}
|
||||
|
||||
func (layer *Layer) Decorate(f func(args ...interface{})) func(args ...interface{}) {
|
||||
@ -99,7 +106,10 @@ func (layer *Layer) Decorate(f func(args ...interface{})) func(args ...interface
|
||||
}
|
||||
|
||||
func (layer *Layer) ClearRect(r *types.Rect) {
|
||||
prevLayer := int(blt.State(blt.TK_LAYER))
|
||||
blt.Layer(layer.Idx)
|
||||
blt.ClearArea(r.X, r.Y, r.W, r.H)
|
||||
blt.Layer(prevLayer)
|
||||
}
|
||||
|
||||
func (layer *Layer) ClearArea(x,y,w,h int) {
|
||||
|
@ -24,7 +24,7 @@ func Init(ctx util.ClientCtx) *MainWindow {
|
||||
|
||||
func (mw *MainWindow) AddLayer(name string, idx int, colorName string) *MainWindow {
|
||||
c := blt.ColorFromName(colorName)
|
||||
mw.layers[name] = &Layer{idx: idx, defaultColor: c}
|
||||
mw.layers[name] = &Layer{Idx: idx, defaultColor: c}
|
||||
return mw
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,9 @@ type UiWindow struct {
|
||||
fillage types.RectFill
|
||||
}
|
||||
|
||||
func (layer *Layer) NewWindow(x, y, w, h int) *UiWindow {
|
||||
func (layer *Layer) NewWindow(rect *types.Rect) *UiWindow {
|
||||
return &UiWindow{
|
||||
Rect: types.NewRect(x, y, w, h),
|
||||
Rect: rect,
|
||||
layer: layer,
|
||||
}
|
||||
}
|
||||
|
@ -105,8 +105,8 @@ func (vp *ViewPort) Render(state *gamestate.GameState) {
|
||||
vp.Fov.ComputeFov(state.Level, playerCoords, vp.TorchRadius)
|
||||
}
|
||||
|
||||
vp.layer.ClearArea(0, 7, 20, 1)
|
||||
vp.layer.Print(0,7, fmt.Sprintf("pcds: %v", playerCoords))
|
||||
//vp.layer.ClearArea(0, 7, 20, 1)
|
||||
//vp.layer.Print(0,7, fmt.Sprintf("pcds: %v", playerCoords))
|
||||
|
||||
|
||||
if redraw {
|
||||
|
Loading…
x
Reference in New Issue
Block a user