Commit Graph

28 Commits (2d3f36379ca6ff1d26b204e66e96c52a10e65d78)

Author SHA1 Message Date
Noah 1205dc2cd3 Invulnerable Anvil and other fixes
* Add methods `Invulnerable() bool` and `SetInvulnerable(bool)` to the
  Actor API accessible in JavaScript (e.g. `Self.SetInvulnerable(true)`)
* The Anvil is invulnerable - when played as, it can crush other mobs by
  jumping on them but is not defeated by those mobs at the same time.
* Anvils don't destroy invulnerable mobs, such as other Anvils.
* Bugfix: the Electric Door is considered to be opened from the first
  frame of animation when the door begins opening, and remains opened
  until the final frame of animation when it is closing.
* New cheat code: `megaton weight` to play as the Anvil by default.
2022-02-20 11:48:36 -08:00
Noah 4d08bf1d85 Switch JavaScript engine to goja
* Switch from otto to goja for JavaScript engine.
* goja supports many ES6 syntax features like arrow functions,
  const/let, for-of with more coming soon.
* Same great features as otto, more modern environment for doodads!
2022-01-16 20:09:27 -08:00
Noah 1a8a5eb94b Polish and bugfixes
- Fix a memory sharing bug in the Giant Screenshot feature.
- Main Menu to eagerload chunks in the background to make scrolling less
  jittery. No time for a loadscreen!
- Extra script debugging: names/IDs of doodads are shown when they send
  messages to one another.
- Level Properties: you can edit the Bounded max width/height values for
  the level.

Doodad changes:

- Buttons: fix a timing bug and keep better track of who is stepping on it,
  only popping up when all colliders have left. The effect: they pop up
  immediately (not after 200ms) and are more reliable.
- Keys: zero-qty keys will no longer put themselves into the inventory of
  characters who already have one except for the player character. So
  the Thief will not steal them if she already has the key.

Added to the JavaScript API:

* time.Hour, time.Minute, time.Second, time.Millisecond, time.Microsecond
2021-10-09 20:45:38 -07:00
Noah 13ae66e1fa Bash for Makefiles 2021-09-06 14:06:55 -07:00
Noah d7a96d1770 Thief and Inventory APIs
This commit adds the Thief character with starter graphics
(no animations).

The Thief walks back and forth and will steal items from other
doodads, including the player. For singleton items that have no
quantity, like the Colored Keys, the Thief will only steal one
if he does not already have it. Quantitied items like the
Small Key are always stolen.

Flexibility in the playable character is introduced: Boy,
Azulian, Bird, and Thief all respond to playable controls.
There is not currently a method to enable these apart from
modifying balance.PlayerCharacterDoodad at compile time.

New and Changed Doodads

* Thief: new doodad that walks back and forth and will steal
  items from other characters inventory.
* Bird: has no inventory and cannot pick up items, unless player
  controlled. Its hitbox has also been fixed so it collides with
  floors correctly - not something normally seen in the Bird.
* Boy: opts in to have inventory.
* Keys (all): only gives themselves to actors having inventories.

JavaScript API - New functions available

* Self.IsPlayer() - returns if the current actor IS the player.
* Self.SetInventory(bool) - doodads must opt-in to having an
  inventory. Keys should only give themselves to doodads having
  an inventory.
* Self.HasInventory() bool
* Self.AddItem(filename, qty)
* Self.RemoveItem(filename, qty)
* Self.HasItem(filename)
* Self.Inventory() - returns map[string]int
* Self.ClearInventory()
* Self.OnLeave(func(e)) now receives a CollideEvent as parameter
  instead of the useless actor ID. Notably, e.Actor is the
  leaving actor and e.Settled is always true.

Other Changes

* Play Mode: if playing as a character which doesn't obey gravity,
  such as the bird, antigravity controls are enabled by default.
  If you `import antigravity` you can turn gravity back on.
* Doodad collision scripts are no longer run in parallel
  goroutines. It made the Thief's job difficult trying to steal
  items in many threads simultaneously!
2021-08-09 22:42:22 -07:00
Noah 810ba193d9 Doodads: Electric Trapdoor and Resettable Box
* New doodad: Electric Trapdoor. It is a horizontal version of the
  Electric Door. Opens while powered by a button or a switch and closes
  when it loses power.
* The Box doodad will reset to its original location if it receives a
  power signal from a linked Button or Switch. So for box pushing
  puzzles you can add a reset button in case the boxes get stuck.
* Refactored the Doodad build scripts into many Makefiles for easier
  iteration (don't need to compile ALL doodads to test one).

Updates to the JavaScript API for doodads:

* Self.MoveTo(Point) is now available to set the actor's position in
  world coordinates.
2021-08-08 20:10:42 -07:00
Noah 49876c4fdf New TabFrame Widget for Doodads and Settings
* Install the new ui.TabFrame widget into the Settings and Doodad
  Dropper windows to give them properly tabbed interfaces.
* Doodad Dropper's new tabs divide the list of doodads into categories
  to make them easier to find.
* The officially defined categories so far are:
  - Objects (Start/End Flags and Box)
  - Doors (All locked doors and keys, Warp Doors, and Electric Door)
  - Gizmos (All buttons, switches, state blocks/doors, Electric Door)
  - Creatures (Blue/Red Azulian, Bird, Boy)
* The "All" tab of the Doodad Dropper will show every doodad regardless
  of its category or whether it fit one of the official categories.
* How doodads are assigned categories is by a special "category" tag in
  their metadata, e.g. "category=doors,gizmos" - multiple supported.
2021-07-25 21:46:55 -07:00
Noah 76b7dfa4f8 Various updates
New doodad interactions:
* Sticky Buttons will emit a "sticky:down" event to linked doodads, with
  a boolean value showing the Sticky Button's state.
* Normal Buttons will listen for "sticky:down" -- when a linked Sticky
  Button is pressed, the normal Button presses in as well, and stays
  pressed while the sticky:down signal is true.
* When the Sticky Button is released (e.g. because it received power
  from another doodad), any linked buttons which were sticky:down
  release as well.
* Switch doodads emit a new "switch:toggle" event JUST BEFORE sending
  the "power" event. Sensitive Doodads can listen for switches in
  particular this way.
* The Electric Door listens for switch:toggle; if a Switch is activated,
  the Electric Door always flips its current state (open to close, or
  vice versa) and ignores the immediately following power event. This
  allows doors to toggle on/off regardless of sync with a Switch.

Other changes:
* When the player character dies by fire, instead of the message saying
  "Watch out for fire!" it will use the name of the fire swatch that
  hurt the player. This way levels could make it say "Watch out for
  spikes!" or "lava" or whatever they want. The "Fire" attribute now
  just means "instantly kills the player."
* Level Editor: You can now edit the Title and Author name of your level
  in the Page Settings window.
* Bugfix: only the player character ends the game by dying in fire.
  Other mobile doodads just turn dark but don't end the game.
* Increase the size of Trapdoor doodad sprites by 150% as they were a
  bit small for the player character.
* Rename the game from "Project: Doodle" to "Sketchy Maze"
2021-03-30 23:40:41 -07:00
Noah 837960c477 Doodads: Small Key Door + Bigger Crumbly Floor
* The crumbly floor doodad was made 50% larger.
* New doodad: Small Key and Small Key Door. These work like the colored
  doors and locks except each Small Key is consumed when it unlocks a
  door. The door's appearance is of iron bars.
* The inventory HUD displays a small quantity label in the lower-right
  corner of items that have a quantity, such as the Small Key. This is
  done as a Canvas.CornerLabel string attribute on uix.Canvas.
* The "give all keys" cheat adds 99 Small Keys to your inventory.
2021-01-03 17:06:33 -08:00
Noah 3892087932 Doodads: Use Key and Working Warp Doors
* The "Use Key" (Q or Spacebar) now activates the Warp Door instead of a
  collision event doing so.
* Warp Doors are now functional: the player opens a door, disappears,
  the door closes; player is teleported to the linked door which opens,
  appears the player and closes.
* If the player exits thru a Blue or Orange door which is disabled
  (dotted outline), the door still opens and drops the player off but
  returns to a Disabled state, acting as a one-way door.
* Clean up several debug log lines from Doodle and doodad scripts.
2021-01-03 15:19:21 -08:00
Noah 11afc7b522 New Doodads: Bigger Doors
* The colored locked doors and the Electric Door are increased in size
  to better match Boy's sprite size.
* Colored doors now have a "locked" and "unlocked" state when closed;
  when locked, a gold padlock hangs on the door with a keyhole shaped to
  match the corresponding Colored Key.
2020-12-29 17:24:42 -08:00
Noah 27896a9253 Add Initial Sound Effects
Adds support for sound effects in Doodle and configures some for various
doodads to start out with:

* Buttons and Switches: "Clicked down" and "clicked up" sounds.
* Colored Doors: an "unlocked" sound and a "door opened" sound.
* Electric Door: sci-fi sounds when opening and closing.
* Keys: sound effect for collecting keys.

JavaScript API for Doodads adds a global function `Sound.Play(filename)`
to play sounds. All sounds in the `rtp/sfx/` folder are pre-loaded on
startup for efficient use in the app. Otherwise sounds are lazy-loaded
on first playback.
2020-05-22 20:07:48 -07:00
Noah 38614ee280 Tighten Doodad JavaScript API, User Documentation
* Tightens up the surface area of API methods available to the
  JavaScript VMs for doodads. Variables and functions are carefully
  passed in one-by-one so the doodad script can only access intended
  functions and not snoop on undocumented APIs.
* Wrote tons of user documentation for Doodad Scripts: documented the
  full surface area of the exposed JavaScript API now that the surface
  area is known and limited.
* Early WIP code for the Campaign JSON
2020-04-21 23:50:45 -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 c3d7348843 Inventory System for Level Actors
* Added an inventory system for actors as a replacement to the arbitrary
  key/value data store. Colored keys now add themselves to the player's
  inventory, and colored doors check the inventory.
* Inventory is a map[string]int between doodad filenames
  (red-key.doodad) and quantity (0 for key items/unlimited qty).
* API methods to add and remove inventory.
* Items HUD appears in Play Mode in lower-left corner showing doodad
  sprites of all the items in the Player's inventory.
2020-04-02 23:09:46 -07:00
Noah 3cb99ad5f8 New (Colored) Locked Door Doodads
* Revamped the sprites for the four colored locked doors. They now have
  a side-view profile perspective rather than a front view.
* Doors open facing the left or the right based on what direction the
  colliding actor approached it from.
2020-04-02 21:43:41 -07:00
Noah 7142c76b86 Initial Guidebook code 2020-03-09 22:21:59 -07:00
Noah b4922edf5d Doodad Tool: Add Tag Support for edit-doodad
* The `doodad edit-doodad` command now allows setting custom key/value
  tags in doodad files, for extra data storage useful to their scripts.
* Colored keys and doors now store a `color` tag with the appropriate
  color so that their scripts don't have to parse their Title to find
  that information.
* Trapdoors now store a `direction` tag to hold the direction the door
  is facing.
2020-01-02 22:12:20 -08:00
Noah 8965a7d86a Doodads: Crumbly Floor, Start Flag & State Blocks
Add new doodads:

* Start Flag: place this in a level to set the spawn point of the player
  character. If no flag is found, the player spawns at 0,0 in the top
  corner of the map. Only use one Start Flag per level, otherwise the
  player will randomly spawn at one of them.
* Crumbly Floor: a solid floor that begins to shake and then fall apart
  after a moment when a mobile character steps on it. The floor respawns
  after 5 seconds.
* State Blocks: blue and orange blocks that toggle between solid and
  pass-thru whenever a State Button is activated.
* State Button: a solid "ON/OFF" block that toggles State Blocks back
  and forth when touched. Only activates if touched on the side or bottom;
  acts as a solid floor when walked on from the top.

New features for doodad scripts:

* Actor scripts: call SetMobile(true) to mark an actor as a mobile mob
  (i.e. player character or enemy). Other doodads can check if the actor
  colliding with them IsMobile so they don't activate if placed too close
  to other (non-mobile) doodads in a level. The Blue and Red Azulians
  are the only mobile characters so far.
* Message.Broadcast allows sending a pub/sub message out to ALL doodads
  in the level, instead of only to linked doodads as Message.Publish does.
  This is used for the State Blocks to globally communicate on/off status
  without needing to link them all together manually.
2019-12-30 18:13:28 -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 cb02feff1d Add Switches, Fire/Water Collision and Play Menu
* New doodads: Switches.
  * They come in four varieties: wall switch (background element, with
    "ON/OFF" text) and three side-profile switches for the floor, left
    or right walls.
  * On collision with the player, they flip their state from "OFF" to
    "ON" or vice versa. If the player walks away and then collides
    again, the switch flips again.
  * Can be used to open/close Electric Doors when turned on/off. Their
    default state is "off"
  * If a switch receives a power signal from another linked switch, it
    sets its own state to match. So, two "on/off" switches that are
    connected to a door AND to each other will both flip on/off when one
    of them flips.
* Update the Level Collision logic to support Decoration, Fire and Water
  pixel collisions.
  * Previously, ALL pixels in the level were acting as though solid.
  * Non-solid pixels don't count for collision detection, but their
    attributes (fire and water) are collected and returned.
* Updated the MenuScene to support loading a map file in Play Mode
  instead of Edit Mode. Updated the title screen menu to add a button
  for playing levels instead of editing them.
* Wrote some documentation.
2019-07-06 18:30:03 -07:00
Noah 99eab19c5b Pub/Sub Messages Between Linked Actors (JavaScript)
* Implement the pub/sub message passing system that lets the JavaScript
  VM of one actor (say, a Button) send messages to other linked actors
  in the level (say, an Electric Door)
* Buttons now emit a "power(true)" message while pressed and
  "power(false)" when released. Sticky Buttons do not release and so do
  not send the power(false) message.
* Electric Doors listen for the "power" event and open or close
  themselves based on the boolean value received.
* If a Sticky Button receives power and is currently pressed down, it
  will pop back up (reset to "off" position) and notify its linked
  actors that they have lost power too. So if a Sticky Button held an
  Electric Door open, and another Button powers the Sticky Button, it
  would pop back up and also close the Electric Door.
2019-06-23 17:34:11 -07:00
Noah 567b3158f1 Minor Tweaks 2019-06-08 17:02:28 -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 a73dec9f31 Doodad Animations Managed In-Engine
* Add animation support for Doodad actors (Play Mode) into the core
  engine, so that the Doodad script can register named animations and
  play them without managing all the details themselves.
  * Doodad API functions on Self: AddAnimation, PlayAnimation,
    StopAnimation, IsAnimating
* CLI: the `doodad convert` command will name each layer after the
  filename used as the input image.
* CLI: fix the `doodad convert` command creating duplicate Palette
  colors when converting a series of input images into a Doodad.
2019-05-06 15:30:43 -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 81cb3bd617 1st Round of Doodad Sprites + Improve Doodad Tool
* Improve the `doodad convert` command to convert a series of input
  images into multiple Frames of a Doodad:
  `doodad convert frame1.png frame2.png frameN.png output.doodad`
* Add the initial round of dev-asset sprites for the default Doodads:
  * Button, Button-TypeB and Sticky Button
  * Red, Blue, Green and Yellow Locked Doors and Keys
  * Electric Door
  * Trapdoor Down
* Add dev-assets/palette.json that defines our default doodad color
  palette. Eventually the JSON will be used by the `doodad` tool to give
  the layers meaningful names.
2019-04-17 00:02:41 -07:00