Increased difficulty.
Can play through levels/difficulty.
This commit is contained in:
parent
96ab55e62a
commit
7321cf3c9d
@ -11,13 +11,24 @@ type appContext struct {
|
|||||||
Debug bool
|
Debug bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const numberOfStars = 5
|
||||||
|
|
||||||
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(0, numberOfStars)
|
||||||
|
|
||||||
app.show(newLevelControl(app, ctx, level))
|
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) {
|
func (app *appContext) show(control ui.Control) {
|
||||||
app.setView(control)
|
app.setView(control)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ type levelController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, Level: level}
|
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 {
|
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.Font = font
|
||||||
|
|
||||||
control.Animations = map[string]*tins2021.Animations{
|
control.Play(level)
|
||||||
"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)
|
|
||||||
}
|
|
||||||
|
|
||||||
return control
|
return control
|
||||||
}
|
}
|
||||||
@ -89,7 +78,7 @@ func IsModifierPressed(modifiers ui.KeyModifier, pressed ui.KeyModifier) bool {
|
|||||||
return modifiers&pressed == pressed
|
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) {
|
switch e := e.(type) {
|
||||||
case *ui.KeyDownEvent:
|
case *ui.KeyDownEvent:
|
||||||
switch e.Key {
|
switch e.Key {
|
||||||
@ -102,6 +91,17 @@ func (r levelController) Handle(ctx ui.Context, e ui.Event) bool {
|
|||||||
return false
|
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) {
|
switch e := e.(type) {
|
||||||
case *ui.KeyDownEvent:
|
case *ui.KeyDownEvent:
|
||||||
switch e.Key {
|
switch e.Key {
|
||||||
@ -171,6 +171,23 @@ func (r levelController) Handle(ctx ui.Context, e ui.Event) bool {
|
|||||||
return false
|
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
|
const defaultAnimationFrames = 20
|
||||||
|
|
||||||
func (r levelController) Render(ctx ui.Context) {
|
func (r levelController) Render(ctx ui.Context) {
|
||||||
@ -189,7 +206,7 @@ func (r levelController) Render(ctx ui.Context) {
|
|||||||
|
|
||||||
delta = delta.Mul(textureWidth)
|
delta = delta.Mul(textureWidth)
|
||||||
centerTopSquare = centerTopSquare.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.X = geom.Round32(delta.X)
|
||||||
delta.Y = geom.Round32(delta.Y)
|
delta.Y = geom.Round32(delta.Y)
|
||||||
@ -274,6 +291,7 @@ func (r levelController) Render(ctx ui.Context) {
|
|||||||
scoreFont := ctx.Fonts().Font("score")
|
scoreFont := ctx.Fonts().Font("score")
|
||||||
fontOffsetY := .5 * (float32(star.Texture.Height()) - scoreFont.Height())
|
fontOffsetY := .5 * (float32(star.Texture.Height()) - scoreFont.Height())
|
||||||
|
|
||||||
|
// stars & hearts
|
||||||
scoreTopLeft := scoreView.Min
|
scoreTopLeft := scoreView.Min
|
||||||
star.Draw(renderer, scoreTopLeft, 0)
|
star.Draw(renderer, scoreTopLeft, 0)
|
||||||
renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d / %d", r.Level.StarsCollected, r.Level.Stars))
|
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)
|
heart.Draw(renderer, scoreTopLeft, 0)
|
||||||
renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d", r.Level.Lives))
|
renderer.Text(scoreFont, scoreTopLeft.Add2D(textureWidth, fontOffsetY), textColor, fmt.Sprintf("x %d", r.Level.Lives))
|
||||||
|
|
||||||
if r.Level.GameOver {
|
// 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()
|
bounds := r.Bounds()
|
||||||
|
centerX := .5 * bounds.Dx()
|
||||||
titleFont := ctx.Fonts().Font("title")
|
titleFont := ctx.Fonts().Font("title")
|
||||||
|
|
||||||
|
if r.Level.GameOver {
|
||||||
renderer.FillRectangle(bounds, zntg.MustHexColor(`#0000007F`))
|
renderer.FillRectangle(bounds, zntg.MustHexColor(`#0000007F`))
|
||||||
offsetY := .5*bounds.Dy() - titleFont.Height()
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
14
level.go
14
level.go
@ -15,6 +15,8 @@ type Level struct {
|
|||||||
Monsters Monsters
|
Monsters Monsters
|
||||||
MonsterTargets map[geom.Point]geom.Point
|
MonsterTargets map[geom.Point]geom.Point
|
||||||
GameOver bool
|
GameOver bool
|
||||||
|
Difficulty int
|
||||||
|
Score int
|
||||||
Bounds geom.Rectangle
|
Bounds geom.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,15 +101,19 @@ func (l *Level) MovePlayer(dir Direction) bool {
|
|||||||
if tile.Heart {
|
if tile.Heart {
|
||||||
l.Lives++
|
l.Lives++
|
||||||
tile.Heart = false
|
tile.Heart = false
|
||||||
|
l.Score += 10
|
||||||
}
|
}
|
||||||
if tile.Star {
|
if tile.Star {
|
||||||
l.StarsCollected++
|
l.StarsCollected++
|
||||||
tile.Star = false
|
tile.Star = false
|
||||||
|
l.Score += 25
|
||||||
}
|
}
|
||||||
if l.Monsters[towards] != nil {
|
if l.Monsters[towards] != nil {
|
||||||
l.DecrementLive()
|
l.DecrementLive()
|
||||||
l.DestroyMonster(towards)
|
l.DestroyMonster(towards)
|
||||||
|
l.Score -= 5
|
||||||
}
|
}
|
||||||
|
l.Score -= 1 // for every move
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +121,7 @@ func (l *Level) Randomize(difficulty int, stars int) {
|
|||||||
if difficulty < 0 {
|
if difficulty < 0 {
|
||||||
difficulty = 0
|
difficulty = 0
|
||||||
}
|
}
|
||||||
|
l.Difficulty = difficulty
|
||||||
positions := make([]geom.Point, 0, len(l.Tiles))
|
positions := make([]geom.Point, 0, len(l.Tiles))
|
||||||
for pos := range l.Tiles {
|
for pos := range l.Tiles {
|
||||||
positions = append(positions, pos)
|
positions = append(positions, pos)
|
||||||
@ -157,9 +164,9 @@ func (l *Level) Randomize(difficulty int, stars int) {
|
|||||||
l.Tiles[pos].Heart = true
|
l.Tiles[pos].Heart = true
|
||||||
hearts--
|
hearts--
|
||||||
}
|
}
|
||||||
monsters := 1 + (4 * difficulty / 100)
|
monsters := 2 + (6 * difficulty / 100)
|
||||||
minRandomMonster := (100 - difficulty)
|
minRandomMonster := (100-difficulty)*80/100 + 10 // [90..10]
|
||||||
minChaserMonster := (200 - difficulty) / 2
|
minChaserMonster := (100-difficulty)*50/100 + 50 // [100..50]
|
||||||
for monsters > 0 {
|
for monsters > 0 {
|
||||||
i := rand.Intn(len(positions))
|
i := rand.Intn(len(positions))
|
||||||
pos := positions[i]
|
pos := positions[i]
|
||||||
@ -183,7 +190,6 @@ func (l *Level) Randomize(difficulty int, stars int) {
|
|||||||
l.Monsters[pos] = &ChasingMonster{}
|
l.Monsters[pos] = &ChasingMonster{}
|
||||||
default:
|
default:
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
// l.Monsters[pos] = monster
|
|
||||||
}
|
}
|
||||||
monsters--
|
monsters--
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user