Moved initialization of textures to main (appContext).
Added info screen.
This commit is contained in:
parent
45b64a46ec
commit
157ec6d42d
@ -55,11 +55,9 @@ func (a *app) Init(ctx ui.Context) error {
|
|||||||
|
|
||||||
ctx.Overlays().AddOnTop(fpsOverlayName, &play.FPS{Align: ui.AlignRight}, false)
|
ctx.Overlays().AddOnTop(fpsOverlayName, &play.FPS{Align: ui.AlignRight}, false)
|
||||||
|
|
||||||
a.context = &appContext{
|
a.context = newAppContext(ctx, func(control ui.Control) {
|
||||||
setView: func(control ui.Control) {
|
a.Content = control
|
||||||
a.Content = control
|
})
|
||||||
},
|
|
||||||
}
|
|
||||||
a.context.ShowMainMenu(ctx)
|
a.context.ShowMainMenu(ctx)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
"opslag.de/schobers/tins2021"
|
"opslag.de/schobers/tins2021"
|
||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
@ -9,6 +11,36 @@ type appContext struct {
|
|||||||
setView func(ui.Control)
|
setView func(ui.Control)
|
||||||
|
|
||||||
Debug bool
|
Debug bool
|
||||||
|
|
||||||
|
MonsterTextureNames map[tins2021.MonsterType]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAppContext(ctx ui.Context, setView func(ui.Control)) *appContext {
|
||||||
|
newAnimatedTexture(ctx, "star", "resources/images/star.png", func() image.Image {
|
||||||
|
return tins2021.AnimatePolygon(tins2021.CreateStar(5), tins2021.Yellow, tins2021.NewRotateAnimation(defaultAnimationFrames))
|
||||||
|
})
|
||||||
|
newAnimatedTexture(ctx, "heart", "resources/images/heart.png", func() image.Image {
|
||||||
|
return tins2021.AnimatePolygon(tins2021.CreateHeart(), tins2021.Red, tins2021.NewRotateAnimation(defaultAnimationFrames))
|
||||||
|
})
|
||||||
|
|
||||||
|
app := &appContext{
|
||||||
|
setView: setView,
|
||||||
|
MonsterTextureNames: map[tins2021.MonsterType]string{
|
||||||
|
tins2021.MonsterTypeStraight: "straight-walking-monster",
|
||||||
|
tins2021.MonsterTypeRandom: "random-walking-monster",
|
||||||
|
tins2021.MonsterTypeChaser: "chasing-monster",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
newAnimatedTexture(ctx, app.MonsterTextureNames[tins2021.MonsterTypeStraight], "resources/images/monster-straight.png", func() image.Image {
|
||||||
|
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Green, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
||||||
|
})
|
||||||
|
newAnimatedTexture(ctx, app.MonsterTextureNames[tins2021.MonsterTypeRandom], "resources/images/monster-random.png", func() image.Image {
|
||||||
|
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Blue, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
||||||
|
})
|
||||||
|
newAnimatedTexture(ctx, app.MonsterTextureNames[tins2021.MonsterTypeChaser], "resources/images/monster-chaser.png", func() image.Image {
|
||||||
|
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Purple, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
||||||
|
})
|
||||||
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
const numberOfStars = 5
|
const numberOfStars = 5
|
||||||
@ -41,7 +73,9 @@ func (app *appContext) ShowCredits(ctx ui.Context) {
|
|||||||
app.setView(newCredits(app, ctx))
|
app.setView(newCredits(app, ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) ShowInfo(ctx ui.Context) {}
|
func (app *appContext) ShowInfo(ctx ui.Context) {
|
||||||
|
app.setView(newInfo(app, ctx))
|
||||||
|
}
|
||||||
|
|
||||||
func (app *appContext) ShowMainMenu(ctx ui.Context) {
|
func (app *appContext) ShowMainMenu(ctx ui.Context) {
|
||||||
app.show(newMainMenu(app, ctx))
|
app.show(newMainMenu(app, ctx))
|
||||||
|
89
cmd/tins2021/info.go
Normal file
89
cmd/tins2021/info.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"opslag.de/schobers/geom"
|
||||||
|
"opslag.de/schobers/tins2021"
|
||||||
|
"opslag.de/schobers/zntg/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type info struct {
|
||||||
|
ui.StackPanel
|
||||||
|
|
||||||
|
app *appContext
|
||||||
|
legend *ui.StackPanel
|
||||||
|
}
|
||||||
|
|
||||||
|
const infoText = "Qbitter is a game loosly based on a work \"LW305 Kringloop\" of M.C. Escher where a gnome runs down a stairs and morphs into its 2D abstract shape. The game also lends ideas from Q*Bert, a game from the eighties that was itself based on the works of M.C. Escher. In the game you (represented as a gnome) have to collect stars while trying to avoid enemies (hexagons). Every level has increasing difficulty."
|
||||||
|
|
||||||
|
type infoLegend struct {
|
||||||
|
ui.ControlBase
|
||||||
|
|
||||||
|
Icon ui.Texture
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *infoLegend) DesiredSize(ctx ui.Context, size geom.PointF32) geom.PointF32 {
|
||||||
|
return geom.PtF32(geom.NaN32(), .4*tins2021.TextureSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
const infoLegenIconSize = .36
|
||||||
|
|
||||||
|
var infoLegendIconRectangle = geom.RectRelF32(0, 0, infoLegenIconSize*tins2021.TextureSize, infoLegenIconSize*tins2021.TextureSize)
|
||||||
|
|
||||||
|
func (l *infoLegend) Render(ctx ui.Context) {
|
||||||
|
bounds := l.Bounds()
|
||||||
|
separator := .3 * bounds.Dx()
|
||||||
|
textureHeight := float32(l.Icon.Height())
|
||||||
|
renderer := ctx.Renderer()
|
||||||
|
renderer.DrawTexturePointOptions(l.Icon, bounds.Min.Add2D(separator-textureHeight, 0), ui.DrawOptions{Source: &infoLegendIconRectangle})
|
||||||
|
font := ctx.Fonts().Font("score")
|
||||||
|
fontHeight := float32(font.Height())
|
||||||
|
renderer.Text(font, bounds.Min.Add2D(separator+12, .5*(textureHeight-fontHeight)), ctx.Style().Palette.Text, l.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInfo(app *appContext, ctx ui.Context) ui.Control {
|
||||||
|
legend := ui.BuildStackPanel(ui.OrientationVertical, func(p *ui.StackPanel) {
|
||||||
|
p.AddChild(&infoLegend{
|
||||||
|
Icon: ctx.Textures().ScaledByName("star", infoLegenIconSize),
|
||||||
|
Description: "Collect them to complete the level.",
|
||||||
|
})
|
||||||
|
p.AddChild(&infoLegend{
|
||||||
|
Icon: ctx.Textures().ScaledByName("heart", infoLegenIconSize),
|
||||||
|
Description: "Gives (back) a life.",
|
||||||
|
})
|
||||||
|
p.AddChild(&infoLegend{
|
||||||
|
Icon: ctx.Textures().ScaledByName("straight-walking-monster", infoLegenIconSize),
|
||||||
|
Description: "Monster that walks over a fixed diagonal.",
|
||||||
|
})
|
||||||
|
p.AddChild(&infoLegend{
|
||||||
|
Icon: ctx.Textures().ScaledByName("random-walking-monster", infoLegenIconSize),
|
||||||
|
Description: "Monster that walks randomly.",
|
||||||
|
})
|
||||||
|
p.AddChild(&infoLegend{
|
||||||
|
Icon: ctx.Textures().ScaledByName("chasing-monster", infoLegenIconSize),
|
||||||
|
Description: "Monster that walks towards you.",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return Center(&info{StackPanel: ui.StackPanel{
|
||||||
|
ContainerBase: ui.ContainerBase{
|
||||||
|
Children: []ui.Control{
|
||||||
|
labelOpts("QBITTER", "title", labelOptions{TextAlignment: ui.AlignCenter}),
|
||||||
|
label("", "score"), // spacing
|
||||||
|
paragraphOpts(infoText, "score", labelOptions{TextAlignment: ui.AlignCenter}),
|
||||||
|
label("", "score"), // spacing
|
||||||
|
legend,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Orientation: ui.OrientationVertical,
|
||||||
|
}, app: app})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *info) Handle(ctx ui.Context, e ui.Event) bool {
|
||||||
|
switch e := e.(type) {
|
||||||
|
case *ui.KeyDownEvent:
|
||||||
|
if e.Key == ui.KeyEscape || e.Key == ui.KeyEnter {
|
||||||
|
i.app.ShowMainMenu(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i.ControlBase.Handle(ctx, e)
|
||||||
|
}
|
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -24,50 +23,22 @@ type levelController struct {
|
|||||||
Cubes cubeTexture
|
Cubes cubeTexture
|
||||||
Animations map[string]*tins2021.Animations
|
Animations map[string]*tins2021.Animations
|
||||||
|
|
||||||
MonsterTextureNames map[tins2021.MonsterType]string
|
IdleMonsters *tins2021.Animations
|
||||||
IdleMonsters *tins2021.Animations
|
MovingMonsters *tins2021.Animations
|
||||||
MovingMonsters *tins2021.Animations
|
|
||||||
|
|
||||||
SmallFont *tins2021.BitmapFont
|
SmallFont *tins2021.BitmapFont
|
||||||
Font *tins2021.BitmapFont
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLevelControl(app *appContext, ctx ui.Context, level *tins2021.Level) *levelController {
|
func newLevelControl(app *appContext, ctx ui.Context, level *tins2021.Level) *levelController {
|
||||||
control := &levelController{app: app}
|
control := &levelController{app: app}
|
||||||
textures := ctx.Textures()
|
textures := ctx.Textures()
|
||||||
control.Cubes = newCubeTexture(textures, tins2021.Orange)
|
control.Cubes = newCubeTexture(textures, tins2021.Orange)
|
||||||
newAnimatedTexture(ctx, "star", "resources/images/star.png", func() image.Image {
|
|
||||||
return tins2021.AnimatePolygon(tins2021.CreateStar(5), tins2021.Yellow, tins2021.NewRotateAnimation(defaultAnimationFrames))
|
|
||||||
})
|
|
||||||
newAnimatedTexture(ctx, "heart", "resources/images/heart.png", func() image.Image {
|
|
||||||
return tins2021.AnimatePolygon(tins2021.CreateHeart(), tins2021.Red, tins2021.NewRotateAnimation(defaultAnimationFrames))
|
|
||||||
})
|
|
||||||
|
|
||||||
control.MonsterTextureNames = map[tins2021.MonsterType]string{
|
|
||||||
tins2021.MonsterTypeStraight: "straight-walking-monster",
|
|
||||||
tins2021.MonsterTypeRandom: "random-walking-monster",
|
|
||||||
tins2021.MonsterTypeChaser: "chasing-monster",
|
|
||||||
}
|
|
||||||
newAnimatedTexture(ctx, control.MonsterTextureNames[tins2021.MonsterTypeStraight], "resources/images/monster-straight.png", func() image.Image {
|
|
||||||
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Green, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
|
||||||
})
|
|
||||||
newAnimatedTexture(ctx, control.MonsterTextureNames[tins2021.MonsterTypeRandom], "resources/images/monster-random.png", func() image.Image {
|
|
||||||
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Blue, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
|
||||||
})
|
|
||||||
newAnimatedTexture(ctx, control.MonsterTextureNames[tins2021.MonsterTypeChaser], "resources/images/monster-chaser.png", func() image.Image {
|
|
||||||
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Purple, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
|
|
||||||
})
|
|
||||||
|
|
||||||
small, err := tins2021.NewBitmapFont(ctx.Renderer(), ctx.Fonts().Font("small"), tins2021.NumericCharacters...)
|
small, err := tins2021.NewBitmapFont(ctx.Renderer(), ctx.Fonts().Font("small"), tins2021.NumericCharacters...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
control.SmallFont = small
|
control.SmallFont = small
|
||||||
font, err := tins2021.NewBitmapFont(ctx.Renderer(), ctx.Fonts().Font("default"), tins2021.AllCharacters...)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
control.Font = font
|
|
||||||
|
|
||||||
control.Play(level)
|
control.Play(level)
|
||||||
|
|
||||||
@ -183,7 +154,7 @@ func (r *levelController) Play(level *tins2021.Level) {
|
|||||||
for monster := range level.Monsters {
|
for monster := range level.Monsters {
|
||||||
r.IdleMonsters.Frame(monster)
|
r.IdleMonsters.Frame(monster)
|
||||||
}
|
}
|
||||||
for _, monster := range r.MonsterTextureNames {
|
for _, monster := range r.app.MonsterTextureNames {
|
||||||
r.Animations[monster] = tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true)
|
r.Animations[monster] = tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +199,7 @@ func (r levelController) Render(ctx ui.Context) {
|
|||||||
star := tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName("star", scale*.4), defaultAnimationFrames)
|
star := tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName("star", scale*.4), defaultAnimationFrames)
|
||||||
heart := tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName("heart", scale*.4), defaultAnimationFrames)
|
heart := tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName("heart", scale*.4), defaultAnimationFrames)
|
||||||
monsterTextures := map[tins2021.MonsterType]tins2021.AnimatedTexture{}
|
monsterTextures := map[tins2021.MonsterType]tins2021.AnimatedTexture{}
|
||||||
for typ, name := range r.MonsterTextureNames {
|
for typ, name := range r.app.MonsterTextureNames {
|
||||||
monsterTextures[typ] = tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName(name, scale*.4), defaultAnimationFrames)
|
monsterTextures[typ] = tins2021.NewAnimatedTexture(ctx.Textures().ScaledByName(name, scale*.4), defaultAnimationFrames)
|
||||||
}
|
}
|
||||||
propOffset := geom.PtF32(-.5*float32(star.Texture.Height()), -.8*float32(star.Texture.Height()))
|
propOffset := geom.PtF32(-.5*float32(star.Texture.Height()), -.8*float32(star.Texture.Height()))
|
||||||
@ -283,7 +254,7 @@ func (r levelController) Render(ctx ui.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, platformPos := positionOfTile(pos, tile)
|
_, platformPos := positionOfTile(pos, tile)
|
||||||
name := r.MonsterTextureNames[monsterType.Type()]
|
name := r.app.MonsterTextureNames[monsterType.Type()]
|
||||||
monsterTextures[monsterType.Type()].Draw(renderer, platformPos.Add(propOffset), r.Animations[name].Frame(pos))
|
monsterTextures[monsterType.Type()].Draw(renderer, platformPos.Add(propOffset), r.Animations[name].Frame(pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,18 +33,21 @@ type mainMenu struct {
|
|||||||
|
|
||||||
func newMainMenu(app *appContext, ctx ui.Context) ui.Control {
|
func newMainMenu(app *appContext, ctx ui.Context) ui.Control {
|
||||||
menu := NewMenu()
|
menu := NewMenu()
|
||||||
// menu.Add("Info", func(ctx ui.Context) { app.ShowInfo(ctx) })
|
menu.Add("Info", func(ctx ui.Context) { app.ShowInfo(ctx) })
|
||||||
menu.Add("Play", func(ctx ui.Context) {
|
menu.Add("Play", func(ctx ui.Context) {
|
||||||
app.Play(ctx)
|
app.Play(ctx)
|
||||||
})
|
})
|
||||||
menu.Add("Credits", func(ctx ui.Context) { app.ShowCredits(ctx) })
|
menu.Add("Credits", func(ctx ui.Context) { app.ShowCredits(ctx) })
|
||||||
menu.Add("Quit", func(ctx ui.Context) { ctx.Quit() })
|
menu.Add("Quit", func(ctx ui.Context) { ctx.Quit() })
|
||||||
|
|
||||||
|
menu.Activate(1) // play
|
||||||
|
|
||||||
return Center(&mainMenu{
|
return Center(&mainMenu{
|
||||||
StackPanel: ui.StackPanel{
|
StackPanel: ui.StackPanel{
|
||||||
ContainerBase: ui.ContainerBase{
|
ContainerBase: ui.ContainerBase{
|
||||||
Children: []ui.Control{
|
Children: []ui.Control{
|
||||||
label("QBITTER", "title"),
|
label("QBITTER", "title"),
|
||||||
|
label("", "default"), // spacing
|
||||||
menu,
|
menu,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -24,3 +24,10 @@ func paragraph(text, font string) *ui.Paragraph {
|
|||||||
l.Font.Name = font
|
l.Font.Name = font
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func paragraphOpts(text, font string, opts labelOptions) *ui.Paragraph {
|
||||||
|
return ui.BuildParagraph(text, func(l *ui.Paragraph) {
|
||||||
|
l.Font.Name = font
|
||||||
|
l.TextAlignment = opts.TextAlignment
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user