diff --git a/pkg/balance/numbers.go b/pkg/balance/numbers.go index 5376737..da4444f 100644 --- a/pkg/balance/numbers.go +++ b/pkg/balance/numbers.go @@ -46,6 +46,11 @@ var ( SwimJumpCooldown uint64 = 24 // number of frames of cooldown between swim-jumps SlopeMaxHeight = 8 // max pixel height for player to walk up a slope + // Number of game ticks to insist the canvas follows the player at the start + // of a level - to overcome Anvils settling into their starting positions so + // they don't steal the camera focus straight away. + FollowPlayerFirstTicks uint64 = 60 + // Default chunk size for canvases. ChunkSize = 128 diff --git a/pkg/play_scene.go b/pkg/play_scene.go index 1977a99..5c73bec 100644 --- a/pkg/play_scene.go +++ b/pkg/play_scene.go @@ -68,16 +68,17 @@ type PlayScene struct { debLoadUnload *string // Player character - Player *uix.Actor - playerPhysics *physics.Mover - lastCheckpoint render.Point - playerLastDirection float64 // player's heading last tick - antigravity bool // Cheat: disable player gravity - noclip bool // Cheat: disable player clipping - godMode bool // Cheat: player can't die - godModeUntil time.Time // Invulnerability timer at respawn. - playerJumpCounter int // limit jump length - jumpCooldownUntil uint64 // future game tick for jump cooldown (swimming esp.) + Player *uix.Actor + playerPhysics *physics.Mover + lastCheckpoint render.Point + playerLastDirection float64 // player's heading last tick + antigravity bool // Cheat: disable player gravity + noclip bool // Cheat: disable player clipping + godMode bool // Cheat: player can't die + godModeUntil time.Time // Invulnerability timer at respawn. + playerJumpCounter int // limit jump length + jumpCooldownUntil uint64 // future game tick for jump cooldown (swimming esp.) + mustFollowPlayerUntil uint64 // first frames where anvils don't take focus from player // Inventory HUD. Impl. in play_inventory.go invenFrame *ui.Frame diff --git a/pkg/player_physics.go b/pkg/player_physics.go index 29a073a..ec8b3c2 100644 --- a/pkg/player_physics.go +++ b/pkg/player_physics.go @@ -115,5 +115,18 @@ func (s *PlayScene) movePlayer(ev *event.State) { // If the "Use" key is pressed, set an actor flag on the player. s.Player.SetUsing(keybind.Use(ev)) + // Camera behaviors: Anvils can take the camera's focus while they're falling + // but player inputs will take control back to the player. Most anvils will fall + // a couple pixels upon level load - prevent them taking the camera's focus for + // the first few frames of gameplay. + if s.mustFollowPlayerUntil == 0 { + s.mustFollowPlayerUntil = shmem.Tick + balance.FollowPlayerFirstTicks + } + + // If we insist that the canvas follow the player doodad. + if shmem.Tick < s.mustFollowPlayerUntil || keybind.Up(ev) || keybind.Left(ev) || keybind.Right(ev) || keybind.Use(ev) { + s.drawing.FollowActor = s.Player.ID() + } + s.scripting.To(s.Player.ID()).Events.RunKeypress(keybind.FromEvent(ev)) } diff --git a/pkg/uix/actor.go b/pkg/uix/actor.go index 322038c..7632475 100644 --- a/pkg/uix/actor.go +++ b/pkg/uix/actor.go @@ -413,7 +413,9 @@ func (a *Actor) ShowLayerNamed(name string) error { a.Actor.Filename, name, ) - return fmt.Errorf("the layer named %s was not found", name) + + // XX: returning an error raises a JavaScript exception in doodads. :/ Warning log is enough. + return nil } // Destroy deletes the actor from the running level. diff --git a/pkg/uix/canvas_scrolling.go b/pkg/uix/canvas_scrolling.go index 8c1a978..cb07a4a 100644 --- a/pkg/uix/canvas_scrolling.go +++ b/pkg/uix/canvas_scrolling.go @@ -246,6 +246,18 @@ func (w *Canvas) loopFollowActor(ev *event.State) error { scrollBy.Y = delta } + // If we are VERY FAR away, allow greater leaps. + if scrollBy.X > balance.FollowActorMaxScrollSpeed*4 { + scrollBy.X = balance.FollowActorMaxScrollSpeed * 4 + } else if scrollBy.X < -balance.FollowActorMaxScrollSpeed*4 { + scrollBy.X = -balance.FollowActorMaxScrollSpeed * 4 + } + if scrollBy.Y > balance.FollowActorMaxScrollSpeed*4 { + scrollBy.Y = balance.FollowActorMaxScrollSpeed * 4 + } else if scrollBy.Y < -balance.FollowActorMaxScrollSpeed*4 { + scrollBy.Y = -balance.FollowActorMaxScrollSpeed * 4 + } + // Constrain the maximum scroll speed. if scrollBy.X > balance.FollowActorMaxScrollSpeed { scrollBy.X = balance.FollowActorMaxScrollSpeed diff --git a/pkg/uix/scripting.go b/pkg/uix/scripting.go index fb91ba7..23e04ce 100644 --- a/pkg/uix/scripting.go +++ b/pkg/uix/scripting.go @@ -132,5 +132,11 @@ func (w *Canvas) MakeSelfAPI(actor *Actor) map[string]interface{} { } return result }, + + // Attract the camera's attention. + "CameraFollowMe": func() { + // Update the doodad that the camera should focus on. + w.FollowActor = actor.ID() + }, } }