Added main menu.

This commit is contained in:
Sander Schobers 2021-08-09 08:25:05 +02:00
parent 0532534142
commit f120de375b
5 changed files with 219 additions and 58 deletions

View File

@ -1,9 +1,6 @@
package main
import (
"image"
"opslag.de/schobers/geom"
"opslag.de/schobers/tins2021"
"opslag.de/schobers/zntg/play"
"opslag.de/schobers/zntg/ui"
@ -14,7 +11,7 @@ type app struct {
settings *tins2021.Settings
intro *introView
context *appContext
}
type fontDescriptor struct {
@ -41,6 +38,7 @@ func (a *app) Init(ctx ui.Context) error {
if err := a.loadFonts(ctx,
fontDescriptor{"debug", "fonts/FiraMono-Regular.ttf", 12},
fontDescriptor{"default", "fonts/escheresk.ttf", 32},
fontDescriptor{"menu", "fonts/escheresk.ttf", 60},
fontDescriptor{"small", "fonts/escheresk.ttf", 16},
fontDescriptor{"title", "fonts/escher.ttf", 80},
); err != nil {
@ -58,8 +56,12 @@ func (a *app) Init(ctx ui.Context) error {
ctx.Overlays().AddOnTop(fpsOverlayName, &play.FPS{Align: ui.AlignRight}, false)
a.intro = newIntroView(ctx)
a.Content = a.intro
a.context = &appContext{
setView: func(control ui.Control) {
a.Content = control
},
}
a.context.ShowMainMenu(ctx)
return nil
}
@ -75,8 +77,6 @@ func (a *app) Handle(ctx ui.Context, e ui.Event) bool {
// a.settings.Window.Size = &size
case *ui.KeyDownEvent:
switch e.Key {
case ui.KeyEscape:
ctx.Quit()
case ui.KeyF3:
ctx.Overlays().Toggle(ui.DefaultDebugOverlay)
ctx.Overlays().Toggle(fpsOverlayName)
@ -89,52 +89,3 @@ func (a *app) Render(ctx ui.Context) {
ctx.Renderer().Clear(ctx.Style().Palette.Background)
a.Proxy.Render(ctx)
}
type introView struct {
ui.StackPanel
}
type Scene struct {
ui.ControlBase
Sprites []Sprite
}
func (s *Scene) Render(ctx ui.Context) {
renderer := ctx.Renderer()
for _, sprite := range s.Sprites {
renderer.DrawTexturePoint(sprite.Texture, sprite.Position)
}
}
type Sprite struct {
Position geom.PointF32
Texture ui.Texture
}
func newSpriteImage(ctx ui.Context, im image.Image) Sprite {
texture, err := ctx.Textures().CreateTextureGo("cube_1", im, false)
if err != nil {
panic("couldn't create texture")
}
return Sprite{geom.ZeroPtF32, texture}
}
func (s Sprite) Destroy() { s.Texture.Destroy() }
func newIntroView(ctx ui.Context) *introView {
view := &introView{}
level := tins2021.NewLevel()
level.Randomize(100, 10)
view.Children = []ui.Control{
label("QBITTER", "title"),
paragraph("Welcome at Qbitter!\n"+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ, abcdefghijklmnopqrstuvwxyz\n"+
"",
"default"),
newLevelControl(ctx, level),
}
return view
}

View File

@ -0,0 +1,28 @@
package main
import (
"opslag.de/schobers/tins2021"
"opslag.de/schobers/zntg/ui"
)
type appContext struct {
setView func(ui.Control)
}
func (app *appContext) Play(ctx ui.Context) {
level := tins2021.NewLevel()
level.Randomize(100, 10)
app.show(newLevelControl(ctx, level))
}
func (app *appContext) show(control ui.Control) {
app.setView(control)
}
func (app *appContext) ShowCredits(ctx ui.Context) {}
func (app *appContext) ShowInfo(ctx ui.Context) {}
func (app *appContext) ShowMainMenu(ctx ui.Context) {
app.show(newMainMenu(app, ctx))
}

54
cmd/tins2021/mainmenu.go Normal file
View File

@ -0,0 +1,54 @@
package main
import (
"opslag.de/schobers/geom"
"opslag.de/schobers/zntg/ui"
)
type center struct {
ui.Proxy
}
func Center(control ui.Control) ui.Control {
return &center{Proxy: ui.Proxy{Content: control}}
}
func (c *center) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
availableWidth := bounds.Dx()
availableHeight := bounds.Dy()
desired := c.Proxy.DesiredSize(ctx, bounds.Size())
if geom.IsNaN32(desired.X) || desired.X > availableWidth {
desired.X = availableWidth
}
if geom.IsNaN32(desired.Y) || desired.Y > availableHeight {
desired.Y = availableHeight
}
inset := bounds.Size().Sub(desired).Mul(.5)
c.Proxy.Arrange(ctx, geom.RectF32(bounds.Min.X+inset.X, bounds.Min.Y+inset.Y, bounds.Max.X-inset.X, bounds.Max.Y-inset.Y), offset, parent)
}
type mainMenu struct {
ui.StackPanel
}
func newMainMenu(app *appContext, ctx ui.Context) ui.Control {
menu := NewMenu()
// menu.Add("Info", func(ctx ui.Context) { app.ShowInfo(ctx) })
menu.Add("Play", func(ctx ui.Context) {
app.Play(ctx)
})
menu.Add("Credits", func(ctx ui.Context) { app.ShowCredits(ctx) })
menu.Add("Quit", func(ctx ui.Context) { ctx.Quit() })
return Center(&mainMenu{
StackPanel: ui.StackPanel{
ContainerBase: ui.ContainerBase{
Children: []ui.Control{
label("QBITTER", "title"),
menu,
},
},
Orientation: ui.OrientationVertical,
},
})
}

128
cmd/tins2021/menu.go Normal file
View File

@ -0,0 +1,128 @@
package main
import (
"opslag.de/schobers/zntg/ui"
)
type Menu struct {
ui.StackPanel
OnEscape func(ui.Context)
active int
buttons []*MenuButton
}
func NewMenu() *Menu {
return &Menu{
StackPanel: ui.StackPanel{
Orientation: ui.OrientationVertical,
},
}
}
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, click func(ui.Context)) {
button := NewMenuButton(text, click)
if len(m.buttons) == 0 {
button.Over = true
}
m.buttons = append(m.buttons, button)
m.AddChild(button)
}
func (m *Menu) Handle(ctx ui.Context, e ui.Event) bool {
if m.StackPanel.Handle(ctx, e) {
return true
}
if len(m.buttons) == 0 {
return false
}
switch e := e.(type) {
case *ui.KeyDownEvent:
switch e.Key {
case ui.KeyEscape:
if onEscape := m.OnEscape; onEscape != nil {
onEscape(ctx)
}
case ui.KeyDown:
m.updateActiveButton((m.active + 1) % len(m.buttons))
case ui.KeyUp:
m.updateActiveButton((m.active + len(m.buttons) - 1) % len(m.buttons))
case ui.KeyEnter:
m.buttons[m.active].InvokeClick(ctx)
}
case *ui.MouseMoveEvent:
for i, button := range m.buttons {
if button.IsOver() {
m.updateActiveButton(i)
break
}
}
m.updateActiveButton(m.active)
}
return false
}
func (m *Menu) updateActiveButton(active int) {
m.active = active
for i, btn := range m.buttons {
btn.Over = i == m.active
}
}
type MenuButton struct {
ui.Label
Over bool
Click func(ui.Context)
}
func NewMenuButton(text string, click func(ui.Context)) *MenuButton {
b := &MenuButton{
Label: ui.Label{
Text: text,
},
Click: click,
}
b.ControlClicked().AddHandler(func(ctx ui.Context, _ ui.ControlClickedArgs) {
b.InvokeClick(ctx)
})
return b
}
func (b *MenuButton) Handle(ctx ui.Context, e ui.Event) bool {
if b.ControlBase.Handle(ctx, e) {
return true
}
if b.IsOver() {
b.Over = true
}
return false
}
func (b *MenuButton) InvokeClick(ctx ui.Context) {
if b.Click != nil {
b.Click(ctx)
}
}
func (b *MenuButton) Render(ctx ui.Context) {
font := b.ActualFont(ctx)
textWidth := font.WidthOf(b.Text)
bounds := b.Bounds()
left := .5 * (bounds.Dx() - textWidth)
color := ctx.Style().Palette.Text
if b.Over {
color = ctx.Style().Palette.Primary
}
ctx.Renderer().Text(font, bounds.Min.Add2D(left, 0), color, b.Text)
}

View File

@ -79,7 +79,7 @@ func run() error {
style.Palette = &ui.Palette{
Background: zntg.MustHexColor(`#494949`),
Disabled: zntg.MustHexColor(`#DEDEDE`),
Primary: zntg.MustHexColor(`#356DAD`),
Primary: zntg.MustHexColor(tins2021.Orange),
PrimaryDark: zntg.MustHexColor(`#15569F`),
PrimaryLight: zntg.MustHexColor(`#ABCAED`),
Secondary: zntg.MustHexColor(`#4AC69A`),