Commit Graph

9 Commits (79996ccd346b)

Author SHA1 Message Date
Noah d14eaf7df2 Collision Box Updates
* The F4 key to draw collision boxes works reliably again: it draws the
  player's hitbox in world-space using the canvas.DrawStrokes()
  function, rather than in screen-space so it follows the player
  reliably.
* The F4 key also draws hitboxes for ALL other actors in the level:
  buttons, enemies, doors, etc.
* The level geometry collision function is updated to respect a doodad's
  declared Hitbox from their script, which may result in a smaller box
  than their raw Canvas size. The result is tighter collision between
  doodads, and Boy's sprite is rather narrow for its square Canvas so
  collision on rightward geometry is tighter for the player character.
* Collision checks between actors also respect the actor's declared
  hitboxes now, allowing for Boy to get even closer to a locked door
  before being blocked.
2021-06-02 20:50:28 -07:00
Noah 08e65c32b5 Overhaul the Platformer Physics System
* Player character now experiences acceleration and friction when
  walking around the map!
* Actor position and movement had to be converted from int's
  (render.Point) to float64's to support fine-grained acceleration
  steps.
* Added "physics" package and physics.Vector to be a float64 counterpart
  for render.Point. Vector is used for uix.Actor.Position() for the sake
  of movement math. Vector is flattened back to a render.Point for
  collision purposes, since the levels and hitboxes are pixel-bound.
* Refactor the uix.Actor to no longer extend the doodads.Drawing (so it
  can have a Position that's a Vector instead of a Point). This broke
  some code that expected `.Doodad` to directly reference the
  Drawing.Doodad: now you had to refer to it as `a.Drawing.Doodad` which
  was ugly. Added convenience method .Doodad() for a shortcut.
* Moved functions like GetBoundingRect() from doodads package to
  collision, where it uses its own slimmer Actor interface for just the
  relevant methods it needs.
2020-04-04 21:00:32 -07:00
Noah 0437adfbf8 Change types int32 -> int per upstream render and ui library 2019-12-27 19:16:34 -08:00
Noah ea0b41a781 Cut lib/render into its own package, change all imports 2019-12-22 18:21:58 -08:00
Noah 6af60f1128 Improve Collision Detection: More Active w/ Actors
* Improve the collision detection algorithm so that Actor OnCollide
  scripts get called more often WHILE an actor is moving, to prevent a
  fast-moving actor from zipping right through the "solid" hitbox and
  not giving the subject actor time to protest the movement.
* It's implemented by adding a `Settled` boolean to the OnCollide event
  object. When the game is testing out movement, Settled=false to give
  the actor a chance to say "I'm solid!" and have the moving party be
  stopped early.
* After all this is done, for any pair of actors still with overlapping
  hitboxes, OnCollide is called one last time with Settled=true. This is
  when the actor should run its actions (like publishing messages to
  other actors, changing state as in a trapdoor, etc.)
* The new collision detection algorithm works as follows:
  * Stage 1 is the same as before, all mobile actors are moved and
    tested against level geometry. They record their Original and New
    position during this phase.
  * Stage 2 is where we re-run that movement but ping actors being
    intersected each step of the way. We trace the steps between
    Original and New position, test OnCollide handler, and if it returns
    false we move the mobile actor to the Last Good Position along the
    trace.
  * Stage 3 we run the final OnCollide(Settled=true) to let actors run
    actions they wanted to for their collide handler, WITHOUT spamming
    those actions during Stage 2.
* This should now allow for tweaking of gravity speed and player speed
  without breaking all actor collision checking.
2019-07-16 21:07:38 -07:00
Noah 1523deeb9c Return False: Solid Collision Between Actors
* Implement the handler code for `return false` when actors are
  colliding with each other and wish to act like solid walls.
* The locked doors will `return false` when they're closed and the
  colliding actor does not have the matching key.
* Add arbitrary key/value storage to Actors. The colored keys will set
  an actor value "key:%TITLE%" on the one who touched the key before
  destroying itself. The colored doors check that key when touched to
  decide whether to open.
* The trapdoor now only opens if you're touching it from the top (your
  overlap box Y value is 0), but if you touch it from below and the door
  is closed, it acts like a solid object.
2019-05-28 21:43:30 -07:00
Noah a2e1bd1ccb Improve OnCollide Doodad Script Handling
* Events.OnCollide now receives a CollideEvent object, which makes
  available the .Actor who collided and the .Overlap rect which is
  zero-relative to the target actor. Doodad scripts can use the .Overlap
  to see WHERE in their own box the other actor has intruded.
  * Update the LockedDoor and ElectricDoor doodads to detect when the
    player has entered their inner rect (since their doors are narrower
    than their doodad size)
  * Update the Button doodads to only press in when the player actually
    touches them (because their sizes are shorter than their doodad
    height)
  * Update the Trapdoor to only trigger its animation when the board
    along its top has been touched, not when the empty space below was
    touched from the bottom.
* Events.OnLeave now implemented and fires when an actor who was
  previously intersecting your doodad has left.
* The engine detects when an event JS callback returns false.
  Eventually, the OnCollide can return false to signify the collision is
  not accepted and the actor should be bumped away as if they hit solid
  geometry.
2019-05-06 22:58:09 -07:00
Noah 258b2eb285 Script Timers, Multiple Doodad Frames
* CLI: fix the `doodad convert` command to share the same Palette when
  converting each frame (layer) of a doodad so subsequent layers find
  the correct color swatches for serialization.
* Scripting: add timers and intervals to Doodad scripts to allow them to
  animate themselves or add delayed callbacks. The timers have the same
  API as a web browser: setTimeout(), setInterval(), clearTimeout(),
  clearInterval().
* Add support for uix.Actor to change its currently rendered layer in
  the level. For example a Button Doodad can set its image to Layer 1
  (pressed) when touched by the player, and Trapdoors can cycle through
  their layers to animate opening and closing.
  * Usage from a Doodad script: Self.ShowLayer(1)
* Default Doodads: added scripts for all Buttons, Doors, Keys and the
  Trapdoor to run their various animations when touched (in the case of
  Keys, destroy themselves when touched, because there is no player
  inventory yet)
2019-04-18 18:15:05 -07:00
Noah f8a83cbad9 Detect Collision Between Actors
* Move all collision code into the pkg/collision package.
  * pkg/doodads/collision.go -> pkg/collision/collide_level.go
  * pkg/doodads/collide_actors.go for new Actor collide support
* Add initial collision detection code between actors in Play Mode.
2019-04-15 19:17:25 -07:00