Added main menu.
This commit is contained in:
parent
0532534142
commit
f120de375b
@ -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
|
||||
}
|
||||
|
28
cmd/tins2021/appcontext.go
Normal file
28
cmd/tins2021/appcontext.go
Normal 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
54
cmd/tins2021/mainmenu.go
Normal 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 ¢er{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
128
cmd/tins2021/menu.go
Normal 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)
|
||||
}
|
@ -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`),
|
||||
|
Loading…
Reference in New Issue
Block a user