Added stars & lives on screen (and fixed centering of level).

This commit is contained in:
Sander Schobers 2021-08-09 09:25:06 +02:00
parent 9bf56c1386
commit c82ce53433
4 changed files with 54 additions and 17 deletions

View File

@ -37,9 +37,9 @@ func (a *app) Init(ctx ui.Context) error {
if err := a.loadFonts(ctx, if err := a.loadFonts(ctx,
fontDescriptor{"debug", "fonts/FiraMono-Regular.ttf", 12}, fontDescriptor{"debug", "fonts/FiraMono-Regular.ttf", 12},
fontDescriptor{"default", "fonts/escheresk.ttf", 32}, fontDescriptor{"default", "fonts/escheresk.ttf", 48},
fontDescriptor{"menu", "fonts/escheresk.ttf", 60},
fontDescriptor{"small", "fonts/escheresk.ttf", 16}, fontDescriptor{"small", "fonts/escheresk.ttf", 16},
fontDescriptor{"score", "fonts/FiraMono-Regular.ttf", 24},
fontDescriptor{"title", "fonts/escher.ttf", 80}, fontDescriptor{"title", "fonts/escher.ttf", 80},
); err != nil { ); err != nil {
return err return err
@ -79,6 +79,7 @@ func (a *app) Handle(ctx ui.Context, e ui.Event) bool {
switch e.Key { switch e.Key {
case ui.KeyF3: case ui.KeyF3:
ctx.Overlays().Toggle(ui.DefaultDebugOverlay) ctx.Overlays().Toggle(ui.DefaultDebugOverlay)
a.context.Debug = !a.context.Debug
ctx.Overlays().Toggle(fpsOverlayName) ctx.Overlays().Toggle(fpsOverlayName)
} }
} }

View File

@ -7,13 +7,15 @@ import (
type appContext struct { type appContext struct {
setView func(ui.Control) setView func(ui.Control)
Debug bool
} }
func (app *appContext) Play(ctx ui.Context) { func (app *appContext) Play(ctx ui.Context) {
level := tins2021.NewLevel() level := tins2021.NewLevel()
level.Randomize(100, 10) level.Randomize(100, 10)
app.show(newLevelControl(ctx, level)) app.show(newLevelControl(app, ctx, level))
} }
func (app *appContext) show(control ui.Control) { func (app *appContext) show(control ui.Control) {

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"image" "image"
"image/color" "image/color"
"math/rand" "math/rand"
@ -15,7 +16,8 @@ import (
type levelController struct { type levelController struct {
ui.ControlBase ui.ControlBase
Scale float32 app *appContext
Level *tins2021.Level Level *tins2021.Level
Cubes cubeTexture Cubes cubeTexture
@ -26,10 +28,11 @@ type levelController struct {
MovingMonsters *tins2021.Animations MovingMonsters *tins2021.Animations
SmallFont *tins2021.BitmapFont SmallFont *tins2021.BitmapFont
Font *tins2021.BitmapFont
} }
func newLevelControl(ctx ui.Context, level *tins2021.Level) *levelController { func newLevelControl(app *appContext, ctx ui.Context, level *tins2021.Level) *levelController {
control := &levelController{Level: level, Scale: .6} control := &levelController{app: app, Level: level}
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 { newAnimatedTexture(ctx, "star", "resources/images/star.png", func() image.Image {
@ -54,11 +57,17 @@ func newLevelControl(ctx ui.Context, level *tins2021.Level) *levelController {
return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Purple, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30)) return tins2021.AnimatePolygon(tins2021.CreateHexagon(), tins2021.Purple, tins2021.NewWobbleAnimation(defaultAnimationFrames, 30))
}) })
small, err := tins2021.NewBitmapFont(ctx.Renderer(), ctx.Fonts().Font("small"), tins2021.AllCharacters...) 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.Animations = map[string]*tins2021.Animations{ control.Animations = map[string]*tins2021.Animations{
"star": tins2021.NewAnimations(50*time.Millisecond, defaultAnimationFrames, true, true), "star": tins2021.NewAnimations(50*time.Millisecond, defaultAnimationFrames, true, true),
"heart": tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true), "heart": tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true),
@ -144,24 +153,32 @@ const defaultAnimationFrames = 20
func (r levelController) Render(ctx ui.Context) { func (r levelController) Render(ctx ui.Context) {
const twelfth = (1. / 6) * geom.Pi const twelfth = (1. / 6) * geom.Pi
renderer := ctx.Renderer()
size := geom.Floor32(tins2021.TextureSize * r.Scale)
scale := size / tins2021.TextureSize
centerTopSquare := geom.PtF32(.5, .5*geom.Sin32(twelfth)) centerTopSquare := geom.PtF32(.5, .5*geom.Sin32(twelfth))
delta := geom.PtF32(geom.Cos32(twelfth), .5+centerTopSquare.Y).Mul(size) delta := geom.PtF32(geom.Cos32(twelfth), .5+centerTopSquare.Y)
centerTopSquare = centerTopSquare.Mul(size)
view := r.Bounds().Size()
levelView := geom.PtF32(float32(r.Level.Bounds.Dx()+2)*delta.X, float32(r.Level.Bounds.Dy()+2)*delta.Y)
textureWidth := geom.Min32(
geom.Floor32(tins2021.TextureSize*view.X*.75/(levelView.X*tins2021.TextureSize)),
geom.Floor32(tins2021.TextureSize*view.Y/(levelView.Y*tins2021.TextureSize)))
scale := textureWidth / tins2021.TextureSize
offsetY := .5 * (view.Y - (levelView.Y * textureWidth))
delta = delta.Mul(textureWidth)
centerTopSquare = centerTopSquare.Mul(textureWidth)
scoreView := geom.RectF32(levelView.X*textureWidth, offsetY+delta.Y, view.X, view.Y-offsetY-delta.Y)
delta.X = geom.Round32(delta.X) delta.X = geom.Round32(delta.X)
delta.Y = geom.Round32(delta.Y) delta.Y = geom.Round32(delta.Y)
toScreen := func(p geom.Point) geom.PointF32 { toScreen := func(p geom.Point) geom.PointF32 {
if p.Y%2 == 0 { if p.Y%2 == 0 {
return p.ToF32().Mul2D(delta.XY()).Add2D(.5*delta.X, 0) return p.ToF32().Mul2D(delta.XY()).Add2D(.5*delta.X, offsetY)
} }
return p.ToF32().Mul2D(delta.XY()) return p.ToF32().Mul2D(delta.XY()).Add2D(0, offsetY)
} }
renderer := ctx.Renderer()
textures := ctx.Textures() textures := ctx.Textures()
cubes := r.Cubes.Scaled(textures, scale) cubes := r.Cubes.Scaled(textures, scale)
@ -200,7 +217,9 @@ func (r levelController) Render(ctx ui.Context) {
tileTexture = cubes.Inversed.Texture tileTexture = cubes.Inversed.Texture
} }
renderer.DrawTexturePoint(tileTexture, screenPos) renderer.DrawTexturePoint(tileTexture, screenPos)
if r.app.Debug {
r.SmallFont.TextAlign(renderer, platformPos, color.Black, strconv.Itoa(distances[pos]), ui.AlignCenter) r.SmallFont.TextAlign(renderer, platformPos, color.Black, strconv.Itoa(distances[pos]), ui.AlignCenter)
}
if tile.Star { if tile.Star {
star.Draw(renderer, platformPos.Add(propOffset), r.Animations["star"].Frame(pos)) star.Draw(renderer, platformPos.Add(propOffset), r.Animations["star"].Frame(pos))
@ -213,7 +232,7 @@ func (r levelController) Render(ctx ui.Context) {
playerPosition := toScreen(r.Level.Player).Sub(geom.Pt(player.Width()/2, player.Height()).ToF32()) playerPosition := toScreen(r.Level.Player).Sub(geom.Pt(player.Width()/2, player.Height()).ToF32())
if r.Level.Tiles[r.Level.Player].Inversed { if r.Level.Tiles[r.Level.Player].Inversed {
centerBottomSquare := geom.PtF32(centerTopSquare.X, size-centerTopSquare.Y) centerBottomSquare := geom.PtF32(centerTopSquare.X, textureWidth-centerTopSquare.Y)
renderer.DrawTexturePoint(player, playerPosition.Add(centerBottomSquare)) renderer.DrawTexturePoint(player, playerPosition.Add(centerBottomSquare))
} else { } else {
renderer.DrawTexturePoint(player, playerPosition.Add(centerTopSquare)) renderer.DrawTexturePoint(player, playerPosition.Add(centerTopSquare))
@ -228,4 +247,16 @@ func (r levelController) Render(ctx ui.Context) {
name := r.MonsterTextureNames[monsterType.Type()] name := r.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))
} }
textColor := ctx.Style().Palette.Text
scoreFont := ctx.Fonts().Font("score")
fontOffsetY := .5 * (float32(star.Texture.Height()) - scoreFont.Height())
scoreTopLeft := scoreView.Min
star.Draw(renderer, scoreTopLeft, 0)
renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d / %d", r.Level.StarsCollected, r.Level.Stars))
scoreTopLeft.Y += textureWidth
heart.Draw(renderer, scoreTopLeft, 0)
renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d", r.Level.Lives))
} }

View File

@ -9,6 +9,7 @@ import (
type Level struct { type Level struct {
Player geom.Point Player geom.Point
Lives int Lives int
Stars int
StarsCollected int StarsCollected int
Tiles Tiles Tiles Tiles
Monsters Monsters Monsters Monsters
@ -21,6 +22,7 @@ func NewLevel() *Level {
f := &Level{ f := &Level{
Player: geom.Pt(1, 1), Player: geom.Pt(1, 1),
Lives: 3, Lives: 3,
Stars: 0,
StarsCollected: 0, StarsCollected: 0,
Tiles: Tiles{}, Tiles: Tiles{},
Monsters: Monsters{}, Monsters: Monsters{},
@ -113,6 +115,7 @@ func (l *Level) Randomize(difficulty int, stars int) {
l.Tiles[pos].Invert() l.Tiles[pos].Invert()
} }
} }
l.Stars = stars
for stars > 0 { for stars > 0 {
i := rand.Intn(len(positions)) i := rand.Intn(len(positions))
pos := positions[i] pos := positions[i]