From 7321cf3c9db034ee4040204eb8b3fddc83b64430 Mon Sep 17 00:00:00 2001 From: Sander Schobers Date: Mon, 9 Aug 2021 12:08:28 +0200 Subject: [PATCH] Increased difficulty. Can play through levels/difficulty. --- cmd/tins2021/appcontext.go | 13 ++++- cmd/tins2021/levelcontroller.go | 85 ++++++++++++++++++++++++++------- cmd/tins2021/mainmenu.go | 10 ++++ level.go | 14 ++++-- 4 files changed, 99 insertions(+), 23 deletions(-) diff --git a/cmd/tins2021/appcontext.go b/cmd/tins2021/appcontext.go index 4279528..e6b334b 100644 --- a/cmd/tins2021/appcontext.go +++ b/cmd/tins2021/appcontext.go @@ -11,13 +11,24 @@ type appContext struct { Debug bool } +const numberOfStars = 5 + func (app *appContext) Play(ctx ui.Context) { level := tins2021.NewLevel() - level.Randomize(100, 10) + level.Randomize(0, numberOfStars) app.show(newLevelControl(app, ctx, level)) } +func (app *appContext) PlayNext(ctx ui.Context, controller *levelController) { + difficulty := controller.Level.Difficulty + score := controller.Level.Score + level := tins2021.NewLevel() + level.Randomize(difficulty+1, numberOfStars) + level.Score = score + controller.Play(level) +} + func (app *appContext) show(control ui.Control) { app.setView(control) } diff --git a/cmd/tins2021/levelcontroller.go b/cmd/tins2021/levelcontroller.go index f0935b7..fdb8781 100644 --- a/cmd/tins2021/levelcontroller.go +++ b/cmd/tins2021/levelcontroller.go @@ -33,7 +33,7 @@ type levelController struct { } func newLevelControl(app *appContext, ctx ui.Context, level *tins2021.Level) *levelController { - control := &levelController{app: app, Level: level} + control := &levelController{app: app} textures := ctx.Textures() control.Cubes = newCubeTexture(textures, tins2021.Orange) newAnimatedTexture(ctx, "star", "resources/images/star.png", func() image.Image { @@ -69,18 +69,7 @@ func newLevelControl(app *appContext, ctx ui.Context, level *tins2021.Level) *le } control.Font = font - control.Animations = map[string]*tins2021.Animations{ - "star": tins2021.NewAnimations(50*time.Millisecond, defaultAnimationFrames, true, true), - "heart": tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true), - } - control.IdleMonsters = tins2021.NewAnimations(500*time.Millisecond, 100, false, false) - control.MovingMonsters = tins2021.NewAnimations(50*time.Millisecond, 20, false, false) - for monster := range level.Monsters { - control.IdleMonsters.Frame(monster) - } - for _, monster := range control.MonsterTextureNames { - control.Animations[monster] = tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true) - } + control.Play(level) return control } @@ -89,7 +78,7 @@ func IsModifierPressed(modifiers ui.KeyModifier, pressed ui.KeyModifier) bool { return modifiers&pressed == pressed } -func (r levelController) Handle(ctx ui.Context, e ui.Event) bool { +func (r *levelController) Handle(ctx ui.Context, e ui.Event) bool { switch e := e.(type) { case *ui.KeyDownEvent: switch e.Key { @@ -102,6 +91,17 @@ func (r levelController) Handle(ctx ui.Context, e ui.Event) bool { return false } + if r.Level.StarsCollected == r.Level.Stars { + switch e := e.(type) { + case *ui.KeyDownEvent: + switch e.Key { + case ui.KeyEnter: + r.app.PlayNext(ctx, r) + } + } + return false + } + switch e := e.(type) { case *ui.KeyDownEvent: switch e.Key { @@ -171,6 +171,23 @@ func (r levelController) Handle(ctx ui.Context, e ui.Event) bool { return false } +func (r *levelController) Play(level *tins2021.Level) { + r.Level = level + + r.Animations = map[string]*tins2021.Animations{ + "star": tins2021.NewAnimations(50*time.Millisecond, defaultAnimationFrames, true, true), + "heart": tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true), + } + r.IdleMonsters = tins2021.NewAnimations(500*time.Millisecond, 100, false, false) + r.MovingMonsters = tins2021.NewAnimations(50*time.Millisecond, 20, false, false) + for monster := range level.Monsters { + r.IdleMonsters.Frame(monster) + } + for _, monster := range r.MonsterTextureNames { + r.Animations[monster] = tins2021.NewAnimations(80*time.Millisecond, defaultAnimationFrames, true, true) + } +} + const defaultAnimationFrames = 20 func (r levelController) Render(ctx ui.Context) { @@ -189,7 +206,7 @@ func (r levelController) Render(ctx ui.Context) { delta = delta.Mul(textureWidth) centerTopSquare = centerTopSquare.Mul(textureWidth) - scoreView := geom.RectF32(levelView.X*textureWidth, offsetY+delta.Y, view.X, view.Y-offsetY-delta.Y) + scoreView := geom.RectF32(levelView.X*textureWidth, offsetY+delta.Y, view.X, view.Y-delta.Y-offsetY) delta.X = geom.Round32(delta.X) delta.Y = geom.Round32(delta.Y) @@ -274,6 +291,7 @@ func (r levelController) Render(ctx ui.Context) { scoreFont := ctx.Fonts().Font("score") fontOffsetY := .5 * (float32(star.Texture.Height()) - scoreFont.Height()) + // stars & hearts 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)) @@ -282,11 +300,42 @@ func (r levelController) Render(ctx ui.Context) { heart.Draw(renderer, scoreTopLeft, 0) renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d", r.Level.Lives)) + // difficulty & score + scoreTopLeft = geom.PtF32(scoreView.Min.X, scoreView.Max.Y-scoreFont.Height()) + renderer.Text(scoreFont, scoreTopLeft, textColor, strconv.Itoa(r.Level.Difficulty)) + scoreTopLeft.Y -= scoreFont.Height() + renderer.Text(scoreFont, scoreTopLeft, textColor, "Difficulty:") + + scoreTopLeft.Y -= 2 * scoreFont.Height() + renderer.Text(scoreFont, scoreTopLeft, textColor, strconv.Itoa(r.Level.Score)) + scoreTopLeft.Y -= scoreFont.Height() + renderer.Text(scoreFont, scoreTopLeft, textColor, "Score:") + + bounds := r.Bounds() + centerX := .5 * bounds.Dx() + titleFont := ctx.Fonts().Font("title") + if r.Level.GameOver { - bounds := r.Bounds() - titleFont := ctx.Fonts().Font("title") renderer.FillRectangle(bounds, zntg.MustHexColor(`#0000007F`)) offsetY := .5*bounds.Dy() - titleFont.Height() - renderer.TextAlign(titleFont, geom.PtF32(.5*bounds.Dx(), offsetY), textColor, "GAME OVER", ui.AlignCenter) + renderer.TextAlign(titleFont, geom.PtF32(centerX, offsetY), textColor, "GAME OVER", ui.AlignCenter) + + offsetY += titleFont.Height() + scoreFont.Height() + renderer.TextAlign(scoreFont, geom.PtF32(centerX, offsetY), textColor, fmt.Sprintf("Final score: %d", r.Level.Score), ui.AlignCenter) + + offsetY += 2 * scoreFont.Height() + renderer.TextAlign(scoreFont, geom.PtF32(centerX, offsetY), textColor, "Press [escape] to quit.", ui.AlignCenter) + } else if r.Level.StarsCollected == r.Level.Stars { + renderer.FillRectangle(bounds, zntg.MustHexColor(`#0000007F`)) + offsetY := .5*bounds.Dy() - titleFont.Height() + renderer.TextAlign(titleFont, geom.PtF32(.5*bounds.Dx(), offsetY), textColor, "COMPLETED", ui.AlignCenter) + + offsetY += titleFont.Height() + scoreFont.Height() + renderer.TextAlign(scoreFont, geom.PtF32(centerX, offsetY), textColor, fmt.Sprintf("Score: %d", r.Level.Score), ui.AlignCenter) + + offsetY += 2 * scoreFont.Height() + renderer.TextAlign(scoreFont, geom.PtF32(centerX, offsetY), textColor, "Press [enter] to continue.", ui.AlignCenter) + offsetY += scoreFont.Height() + renderer.TextAlign(scoreFont, geom.PtF32(centerX, offsetY), textColor, "Press [escape] to quit.", ui.AlignCenter) } } diff --git a/cmd/tins2021/mainmenu.go b/cmd/tins2021/mainmenu.go index 072f5bf..bd0bd57 100644 --- a/cmd/tins2021/mainmenu.go +++ b/cmd/tins2021/mainmenu.go @@ -52,3 +52,13 @@ func newMainMenu(app *appContext, ctx ui.Context) ui.Control { }, }) } + +func (m *mainMenu) Handle(ctx ui.Context, e ui.Event) bool { + switch e := e.(type) { + case *ui.KeyDownEvent: + if e.Key == ui.KeyEscape { + ctx.Quit() + } + } + return m.StackPanel.Handle(ctx, e) +} diff --git a/level.go b/level.go index 1a01545..fae2523 100644 --- a/level.go +++ b/level.go @@ -15,6 +15,8 @@ type Level struct { Monsters Monsters MonsterTargets map[geom.Point]geom.Point GameOver bool + Difficulty int + Score int Bounds geom.Rectangle } @@ -99,15 +101,19 @@ func (l *Level) MovePlayer(dir Direction) bool { if tile.Heart { l.Lives++ tile.Heart = false + l.Score += 10 } if tile.Star { l.StarsCollected++ tile.Star = false + l.Score += 25 } if l.Monsters[towards] != nil { l.DecrementLive() l.DestroyMonster(towards) + l.Score -= 5 } + l.Score -= 1 // for every move return true } @@ -115,6 +121,7 @@ func (l *Level) Randomize(difficulty int, stars int) { if difficulty < 0 { difficulty = 0 } + l.Difficulty = difficulty positions := make([]geom.Point, 0, len(l.Tiles)) for pos := range l.Tiles { positions = append(positions, pos) @@ -157,9 +164,9 @@ func (l *Level) Randomize(difficulty int, stars int) { l.Tiles[pos].Heart = true hearts-- } - monsters := 1 + (4 * difficulty / 100) - minRandomMonster := (100 - difficulty) - minChaserMonster := (200 - difficulty) / 2 + monsters := 2 + (6 * difficulty / 100) + minRandomMonster := (100-difficulty)*80/100 + 10 // [90..10] + minChaserMonster := (100-difficulty)*50/100 + 50 // [100..50] for monsters > 0 { i := rand.Intn(len(positions)) pos := positions[i] @@ -183,7 +190,6 @@ func (l *Level) Randomize(difficulty int, stars int) { l.Monsters[pos] = &ChasingMonster{} default: panic("not implemented") - // l.Monsters[pos] = monster } monsters-- }