Added in-game menu.
This commit is contained in:
parent
319dc52496
commit
d135139992
93
alui/menu.go
Normal file
93
alui/menu.go
Normal file
@ -0,0 +1,93 @@
|
||||
package alui
|
||||
|
||||
import (
|
||||
"opslag.de/schobers/allg5"
|
||||
"opslag.de/schobers/geom"
|
||||
)
|
||||
|
||||
type Menu struct {
|
||||
Proxy
|
||||
|
||||
panel *StackPanel
|
||||
active int
|
||||
buttons []*Button
|
||||
}
|
||||
|
||||
func NewMenu() *Menu {
|
||||
m := &Menu{}
|
||||
m.Init()
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Menu) Init() {
|
||||
m.panel = &StackPanel{Orientation: OrientationVertical}
|
||||
m.Proxy.Target = m.panel
|
||||
}
|
||||
|
||||
func (m *Menu) Activate(i int) {
|
||||
if len(m.buttons) == 0 || i < 0 {
|
||||
return
|
||||
}
|
||||
m.active = i % len(m.buttons)
|
||||
}
|
||||
|
||||
func (m *Menu) Add(text string, onClick func()) {
|
||||
idx := len(m.buttons)
|
||||
button := &Button{Text: text, TextAlign: allg5.AlignCenter}
|
||||
button.OnClick = onClick
|
||||
button.OnEnter = func() {
|
||||
m.updateActiveButton(idx)
|
||||
}
|
||||
if idx == 0 {
|
||||
button.Over = true
|
||||
}
|
||||
m.buttons = append(m.buttons, button)
|
||||
m.panel.Children = append(m.panel.Children, button)
|
||||
}
|
||||
|
||||
func (m *Menu) Handle(e allg5.Event) {
|
||||
m.Proxy.Handle(e)
|
||||
|
||||
if len(m.buttons) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
switch e := e.(type) {
|
||||
case *allg5.KeyCharEvent:
|
||||
switch e.KeyCode {
|
||||
case allg5.KeyDown:
|
||||
m.updateActiveButton((m.active + 1) % len(m.buttons))
|
||||
case allg5.KeyUp:
|
||||
m.updateActiveButton((m.active + len(m.buttons) - 1) % len(m.buttons))
|
||||
case allg5.KeyEnter:
|
||||
if onClick := m.buttons[m.active].OnClick; onClick != nil {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
case *allg5.MouseMoveEvent:
|
||||
for i, btn := range m.buttons {
|
||||
if btn.Over {
|
||||
m.updateActiveButton(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
m.updateActiveButton(m.active)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Menu) Layout(ctx *Context, bounds geom.RectangleF32) {}
|
||||
|
||||
func (m *Menu) Render(ctx *Context, bounds geom.RectangleF32) {
|
||||
menuHeight := m.Proxy.DesiredSize(ctx).Y
|
||||
width, center := bounds.Dx(), bounds.Center()
|
||||
menuBounds := geom.RectF32(.25*width, center.Y-.5*menuHeight, .75*width, center.Y+.5*menuHeight)
|
||||
m.Proxy.Layout(ctx, menuBounds)
|
||||
m.Proxy.Render(ctx, menuBounds)
|
||||
}
|
||||
|
||||
func (m *Menu) updateActiveButton(active int) {
|
||||
m.active = active
|
||||
for i, btn := range m.buttons {
|
||||
btn.Over = i == m.active
|
||||
}
|
||||
}
|
44
alui/proxy.go
Normal file
44
alui/proxy.go
Normal file
@ -0,0 +1,44 @@
|
||||
package alui
|
||||
|
||||
import (
|
||||
"opslag.de/schobers/allg5"
|
||||
"opslag.de/schobers/geom"
|
||||
)
|
||||
|
||||
var _ Control = &Proxy{}
|
||||
|
||||
type Proxy struct {
|
||||
Target Control
|
||||
}
|
||||
|
||||
func (p *Proxy) Bounds() geom.RectangleF32 {
|
||||
if p.Target != nil {
|
||||
return p.Target.Bounds()
|
||||
}
|
||||
return geom.RectangleF32{}
|
||||
}
|
||||
|
||||
func (p *Proxy) DesiredSize(ctx *Context) geom.PointF32 {
|
||||
if p.Target != nil {
|
||||
return p.Target.DesiredSize(ctx)
|
||||
}
|
||||
return geom.ZeroPtF32
|
||||
}
|
||||
|
||||
func (p *Proxy) Handle(e allg5.Event) {
|
||||
if p.Target != nil {
|
||||
p.Target.Handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) Render(ctx *Context, bounds geom.RectangleF32) {
|
||||
if p.Target != nil {
|
||||
p.Target.Render(ctx, bounds)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) Layout(ctx *Context, bounds geom.RectangleF32) {
|
||||
if p.Target != nil {
|
||||
p.Target.Layout(ctx, bounds)
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ func newConsole(cons *gut.Console) *console {
|
||||
}
|
||||
|
||||
func (c *console) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
||||
back := allg5.NewColorAlpha(0, 0, 0, 0x7f)
|
||||
back := allg5.NewColorAlpha(0, 0, 0, 0xaf)
|
||||
line := allg5.NewColor(0x7f, 0x7f, 0x7f)
|
||||
|
||||
c.height = geom.Min32(c.height, bounds.Dy())
|
||||
|
@ -1,41 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"opslag.de/schobers/allg5"
|
||||
"opslag.de/schobers/geom"
|
||||
"opslag.de/schobers/krampus19/alui"
|
||||
)
|
||||
|
||||
type mainMenu struct {
|
||||
alui.ControlBase
|
||||
alui.Menu
|
||||
|
||||
ctx *Context
|
||||
|
||||
buttons alui.StackPanel
|
||||
}
|
||||
|
||||
func (m *mainMenu) newButton(text string, onClick func()) alui.Control {
|
||||
button := &alui.Button{Text: text, TextAlign: allg5.AlignCenter}
|
||||
button.OnClick = onClick
|
||||
return button
|
||||
}
|
||||
|
||||
func (m *mainMenu) Enter(ctx *Context) error {
|
||||
m.ctx = ctx
|
||||
m.buttons.Orientation = alui.OrientationVertical
|
||||
m.buttons.Children = append(m.buttons.Children, m.newButton("Play", func() { m.ctx.Navigation.playLevel("1") }))
|
||||
m.buttons.Children = append(m.buttons.Children, m.newButton("Quit", func() { m.ctx.Navigation.quit() }))
|
||||
m.Init()
|
||||
m.Add("Play", func() { m.ctx.Navigation.playLevel("1") })
|
||||
m.Add("Quit", func() { m.ctx.Navigation.quit() })
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mainMenu) Leave() {}
|
||||
|
||||
func (m *mainMenu) Handle(e allg5.Event) { m.buttons.Handle(e) }
|
||||
|
||||
func (m *mainMenu) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
||||
buttonsHeight := m.buttons.DesiredSize(ctx).Y
|
||||
width, center := bounds.Dx(), bounds.Center()
|
||||
buttonsBounds := geom.RectF32(.25*width, center.Y-.5*buttonsHeight, .75*width, center.Y+.5*buttonsHeight)
|
||||
m.buttons.Layout(ctx, buttonsBounds)
|
||||
m.buttons.Render(ctx, buttonsBounds)
|
||||
}
|
||||
|
@ -15,8 +15,12 @@ import (
|
||||
type playLevel struct {
|
||||
alui.ControlBase
|
||||
|
||||
ctx *Context
|
||||
|
||||
menu *alui.Menu
|
||||
showMenu bool
|
||||
|
||||
name string
|
||||
ctx *Context
|
||||
offset geom.PointF32
|
||||
scale float32
|
||||
keysDown keyPressedState
|
||||
@ -27,9 +31,8 @@ type playLevel struct {
|
||||
bricks []*entity
|
||||
sunken []*entity
|
||||
steps int
|
||||
|
||||
tick time.Duration
|
||||
ani gut.Animations
|
||||
tick time.Duration
|
||||
ani gut.Animations
|
||||
}
|
||||
|
||||
type keyPressedState map[allg5.Key]bool
|
||||
@ -168,6 +171,11 @@ func (l *playLevel) canMove(from, dir geom.Point) bool {
|
||||
func (l *playLevel) Enter(ctx *Context) error {
|
||||
l.ctx = ctx
|
||||
|
||||
l.menu = alui.NewMenu()
|
||||
l.menu.Add("Resume", func() { l.showMenu = false })
|
||||
l.menu.Add("Quit to main menu", func() { l.ctx.Navigation.showMainMenu() })
|
||||
l.menu.Add("Quit to desktop", func() { l.ctx.Navigation.quit() })
|
||||
|
||||
l.keysDown = keyPressedState{}
|
||||
l.level = l.ctx.Levels[l.name]
|
||||
l.bricks = nil
|
||||
@ -263,8 +271,28 @@ func (l *playLevel) Handle(e allg5.Event) {
|
||||
switch e := e.(type) {
|
||||
case *allg5.KeyDownEvent:
|
||||
l.keysDown[e.KeyCode] = true
|
||||
case *allg5.KeyUpEvent:
|
||||
l.keysDown[e.KeyCode] = false
|
||||
}
|
||||
|
||||
if l.showMenu {
|
||||
l.menu.Handle(e)
|
||||
switch e := e.(type) {
|
||||
case *allg5.KeyDownEvent:
|
||||
switch e.KeyCode {
|
||||
case allg5.KeyEscape:
|
||||
l.showMenu = false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch e := e.(type) {
|
||||
case *allg5.KeyDownEvent:
|
||||
switch e.KeyCode {
|
||||
case allg5.KeyEscape:
|
||||
l.showMenu = true
|
||||
l.menu.Activate(0)
|
||||
case l.ctx.Settings.Controls.MoveUp:
|
||||
l.tryPlayerMove(geom.Pt(0, -1), e.KeyCode)
|
||||
case l.ctx.Settings.Controls.MoveRight:
|
||||
@ -274,8 +302,6 @@ func (l *playLevel) Handle(e allg5.Event) {
|
||||
case l.ctx.Settings.Controls.MoveLeft:
|
||||
l.tryPlayerMove(geom.Pt(-1, 0), e.KeyCode)
|
||||
}
|
||||
case *allg5.KeyUpEvent:
|
||||
l.keysDown[e.KeyCode] = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,4 +368,9 @@ func (l *playLevel) Render(ctx *alui.Context, bounds geom.RectangleF32) {
|
||||
font := ctx.Fonts.Get("default")
|
||||
steps := fmt.Sprintf("STEPS: %d", l.steps)
|
||||
ctx.Fonts.DrawAlignFont(font, bounds.Min.X, 24, bounds.Max.X, ctx.Palette.Text, allg5.AlignCenter, steps)
|
||||
|
||||
if l.showMenu {
|
||||
allg5.DrawFilledRectangle(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, allg5.NewColorAlpha(0, 0, 0, 0xaf))
|
||||
l.menu.Render(ctx, bounds)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user