Commit Graph

264 Commits

Author SHA1 Message Date
a79601f983 D++ Default Author and Embedded Doodads Error
* Update native.DefaultAuthor to get the name registered from the user's JWT
  license in a way that avoids cyclic dependency errors.
* When plus_dpp.go#GetRegistration succeeds, it updates DefaultAuthor to the
  registered name. The main.go now gets and prints the registered owner to
  ensure this is populated on startup.
* Return correct ErrRegisteredFeature error when the FOSS version fails
  to load embedded doodads.
2024-04-18 22:31:11 -07:00
a06787411d Resolve circular import errors for Doodle++ plugin
* pkg/plus/dpp is the main plugin bridge, and defines nothing but an interface
  that defines the Doodle++ surface area (referring to internal game types such
  as doodad.Doodad or level.Level), but not their implementations.
  * dpp.Driver (an interface) is the main API that other parts of the game will
    call, for example "dpp.Driver.IsLevelSigned()"
  * plus_dpp.go and plus_foss.go provide the dpp.Driver implementation for their
    build; with plus_dpp.go generally forwarding function calls directly to the
    proprietary dpp package and plus_foss.go generally returning false/errors.
  * The bootstrap package simply assigns the above stub function to dpp.Driver
* pkg/plus/bootstrap is a package directly imported by main (in the doodle and
  doodad programs) and it works around circular dependency issues: this package
  simply assigns dpp.Driver to the DPP or FOSS version.

Miscellaneous fixes:

* File->Open in the editor and PlayScene will use the new Open Level window
  instead of loading the legacy GotoLoadMenu scene.
* Deprecated legacy scenes: d.GotoLoadMenu() and d.GotoPlayMenu().
* The doodle-admin program depends on the private dpp package, so can not be
  compiled in FOSS mode.
2024-04-18 22:12:56 -07:00
7eb7f6148c WIP Doodle++ 2024-04-18 20:23:07 -07:00
f4ef0f8d8f Fix doodad properties button hitbox 2024-02-11 17:00:19 -08:00
6def8f7625 Walk up slopes smoothly, texture freeing improvement
* Fix collision detection to allow actors to walk up slopes smoothly, without
  losing any horizontal velocity.
* Fix scrolling a level canvas so that chunks near the right or bottom edge
  of the viewpoint were getting culled prematurely.
* Centralize JavaScript exception catching logic to attach Go and JS stack
  traces where possible to be more useful for debugging.
* Performance: flush all SDL2 textures from memory between scene transitions
  in the app. Also add a `flush-textures` dev console command to flush the
  textures at any time - they all should regenerate if still needed based on
  underlying go.Images which can be garbage collected.
2024-02-07 22:14:48 -08:00
85523d8311 Coyote time 2024-02-06 20:56:07 -08:00
8216e5863b Tweak gravity and player physics 2024-02-06 19:04:47 -08:00
1a9706c09f Level Thumbnails on Story Mode Select
* Rework the Story Mode UI to display level thumbnails.
  * Responsive UI: defaults to wide screen mode and shows 3 levels horizontally
    but on narrow/mobile display, shows 2 levels per page in portrait.
  * Add "Tiny" screenshot size (224x126) to fit the Story Mode UI.
  * Make the pager buttons bigger and more touchable.
* Maximize the game window on startup unless the -w option with a specific
  window resolution is provided.
2023-12-09 14:59:31 -08:00
9cce93f431 Dust off WASM build support 2023-12-08 21:52:34 -08:00
da83231559 Level Screenshots and Thumbnails
Adds some support for "less giant" level screenshots.

* In the Editor, the Level->Take Screenshot menu will render a cropped screen
  shot of just the level viewport on screen. Note: it is not an SDL2 screen
  copy but generated from scratch from the level data.
* In levels themselves, screenshots can be stored inside the level data in
  three different sizes: large (1280x720), medium and small (each a halved
  size of the previous).
* The first screenshot is created when the level is saved, starting from
  wherever the scroll position in the editor is at, and recording the 720p
  view of the level from there.
* The level screenshot can be previewed and updated in the Level Properties
  window of the editor: so you can scroll the editor to just the right position
  and take a good screenshot to represent your level.
* In the future: these embedded level screenshots will be displayed on the
  Story Mode and other screens to see a preview of each level.

Other tweaks:

* When taking a Giant Screenshot: a confirm modal will warn the player that
  it may take a while. And during the screenshot, show the new Wait Modal to
  block player interaction until the screenshot has finished.
2023-12-08 19:48:02 -08:00
481638bea6 PlaySound: Support OGG fallback over MP3 2023-12-02 14:15:41 -08:00
ffb9068fb6 Unit test fixes and code cleanup 2023-12-02 12:33:14 -08:00
79996ccd34 ListBoxes Overhaul
* Overhaul the clunky old alpha Edit Level/Doodad menu with a modernized
  version featuring the new ListBox widget.
* The new level loader is a Window that can be spawned from anywhere instead
  of on a dedicated MenuScene.

Updates to doodad scripts:

* Actor.IsOnScreen() checks whether an actor's visual sprite box is on-screen
  in the level viewport. `Self.IsOnScreen()` will check for the current actor.

Other changes

* PlaySound() to deduplicate the same sound effect from playing at once.
2023-04-08 21:26:08 -07:00
cf1bc81f25 Update savegame format, Allow out-of-bounds camera
Updates the savegame.json file format:

* Levels now have a UUID value assigned at first save.
* The savegame.json will now track level completion/score based on UUID,
making it robust to filename changes in either levels or levelpacks.
* The savegame file is auto-migrated on startup - for any levels not
found or have no UUID, no change is made, it's backwards compatible.
* Level Properties window adds an "Advanced" tab to show/re-roll UUID.

New JavaScript API for doodad scripts:

* `Actors.CameraFollowPlayer()` tells the camera to return focus to the
  player character. Useful for "cutscene" doodads that freeze the player,
  call `Self.CameraFollowMe()` and do a thing before unfreezing and sending the
  camera back to the player. (Or it will follow them at their next directional
  input control).
* `Self.MoveBy(Point(x, y int))` to move the current actor a bit.

New option for the `doodad` command-line tool:

* `doodad resave <.level or .doodad>` will load and re-save a drawing, to
  migrate it to the newest file format versions.

Small tweaks:

* On bounded levels, allow the camera to still follow the player if the player
  finds themselves WELL far out of bounds (40 pixels margin). So on bounded
  levels you can create "interior rooms" out-of-bounds to Warp Door into.
* New wallpaper: "Atmosphere" has a black starscape pattern that fades into a
  solid blue atmosphere.
* Camera strictly follows the player the first 20 ticks, not 60 of level start
* If player is frozen, directional inputs do not take the camera focus back.
2023-03-07 21:55:10 -08:00
82884c79ae Signed Levels and Levelpacks
Add the ability for the free version of the game to allow loading levels that
use embedded custom doodads if those levels are signed.

* Uses the same signing keys as the JWT token for license registrations.
* Levels and Levelpacks can both be signed. So individual levels with embedded
  doodads can work in free versions of the game.
* Levelpacks now support embedded doodads properly: the individual levels in
  the pack don't need to embed a custom doodad, but if the doodad exists in
  the levelpack's doodads/ folder it will load from there instead - for full
  versions of the game OR when the levelpack is signed.

Signatures are computed by getting a listing of embedded assets inside the
zipfile (the assets/ folder in levels, and the doodads/ + levels/ folders
in levelpacks). Thus for individual signed levels, the level geometry and
metadata may be changed without breaking the signature but if custom doodads
are changed the signature will break.

The doodle-admin command adds subcommands to `sign-level` and `verify-level`
to manage signatures on levels and levelpacks.

When using the `doodad levelpack create` command, any custom doodads the
levels mention that are found in your profile directory get embedded into
the zipfile by default (with --doodads custom).
2023-02-18 17:37:54 -08:00
856de848c9 Add cheat code to send power to all actors 2023-02-18 14:21:07 -08:00
03cd1d4ca0 Binary format for chunks in zipfiles 2023-02-18 12:45:36 -08:00
1e37509421 Update README and fix perfect run icon display 2023-02-17 21:49:19 -08:00
31097881ff Finalize Non-square Doodads
* Fix display bug with rectangular doodads scrolling off screen.
* The default Author of new files will be your registration name, if available
  before using your $USER name.
2023-02-17 21:09:11 -08:00
ddcad27485 WIP: Chunker size to uint8 and Rectangular Doodads
Convert the Chunker size to a uint8 so chunk sizes are limited to 255px. This
means that inside of a chunk, uint8's can track the relative pixel coordinates
and result in a great memory savings since all of these uint8's are currently
64-bits wide apiece.

WIP on rectangular shaped doodads:
* You can create such a doodad in the editor and draw it normally.
* It doesn't draw the right size when dragged into your level however:
  - In uix.Actor.Size() it gets a rect of the doodad's square Chunker size,
    instead of getting the proper doodad.Size rect.
  - If you give it the doodad.Size rect, it draws the Canvas size correctly
    instead of a square - the full drawing appears and in gameplay its hitbox
    (assuming the same large rectangle size) works correctly in-game.
  - But, the doodad has scrolling issues when it gets to the top or left edge
    of the screen! This old gnarly bug has come back. For some reason square
    canvas doodads draw correctly but rectangular ones have the drawing scroll
    just a bit - how far it scrolls is proportional to how big the doodad is,
    with the Start Flag only scrolling a few pixels before it stops.
2023-02-16 21:47:18 -08:00
a10a09a818 Cheats Menu UI
* Added a Cheats Menu UI accessible from the Settings window's "Experimental"
  tab and from there you can enable the Cheats Menu from the "Help" screen of
  the gameplay mode.
* Commonly used cheats all have corresponding buttons to click on, especially
  helpful for touchscreen devices like the Pinephone where keyboard input
  doesn't always work reliably.
* The buttons in the Cheats Menu just automate entry of the cheat commands.
* `boolProp` command has a new `flip` option to toggle their value (e.g.
  `boolProp show-hidden-doodads flip`)
2023-01-02 12:36:12 -08:00
06dd30893c Editor: Allow using doodad settings buttons in Pan Tool 2022-12-08 20:03:53 -08:00
56c03dda45 Unpin goja and fix callback registry functions 2022-10-10 19:14:38 -07:00
2dd6b5e34b Update default level palettes for new pixel attributes
* Default palette: adds "semisolid"
* Colored Pencil: adds "planks" (semisolid) and "ice" (slippery)
* Neon Bright: make "electric" semisolid and add "ice blue"
* Blueprint: make "electric" semisolid and add "ice" (slippery)
2022-10-10 11:17:11 -07:00
8b5dab6d6f Slippery Pixels + Update Changelog for 0.13.1 2022-10-10 10:52:28 -07:00
ecaa8c6cef SemiSolid Pixels + Icons
* Add new pixel attributes: SemiSolid and Slippery (the latter is WIP)
* SemiSolid pixels are only solid below the player character. You can walk on
  them and up and down SemiSolid slopes, but can freely pass through from the
  sides or jump through from below.
* Update the Palette Editor UI to replace the Attributes buttons: instead of
  text labels they now have smaller icons (w/ tooltips) for the Solid,
  SemiSolid, Fire, Water and Slippery attributes.
* Bugfix in Palette Editor: use cropped (24x24) images for the Tex buttons so
  that the large Bubbles texture stays within its designated space!
* uix.Actor.SetGrounded() to also set the Y velocity to zero when an actor
  becomes grounded. This fixes a minor bug where the player's Y velocity (due
  to gravity) was not updated while they were grounded, which may eventually
  become useful to allow them to jump down thru a SemiSolid floor. Warp Doors
  needed a fix to work around the bug, to set the player's Grounded(false) or
  else they would hover a few pixels above the ground at their destination,
  since Grounded status paused gravity calculations.
2022-10-09 21:39:43 -07:00
701073cecc Doodad/Actor Runtime Options
* Add "Options" support for Doodads: these allow for individual Actor instances
  on your level to customize properties about the doodad. They're like "Tags"
  except the player can customize them on a per-actor basis.
* Doodad Editor: you can specify the Options in the Doodad Properties window.
* Level Editor: when the Actor Tool is selected, on mouse-over of an actor,
  clicking on the gear icon will open a new "Actor Properties" window which
  shows metadata (title, author, ID, position) and an Options tab to configure
  the actor's options.

Updates to the scripting API:

* Self.Options() returns a list of option names defined on the Doodad.
* Self.GetOption(name) returns the value for the named option, or nil if
  neither the actor nor its doodad have the option defined. The return type
  will be correctly a string, boolean or integer type.

Updates to the doodad command-line tool:

* `doodad show` will print the Options on a .doodad file and, when showing a
  .level file with --actors, prints any customized Options with the actors.
* `doodad edit-doodad` adds a --option parameter to define options.

Options added to the game's built-in doodads:

* Warp Doors: "locked (exit only)" will make it so the door can not be opened
  by the player, giving the "locked" message (as if it had no linked door),
  but the player may still exit from the door if sent by another warp door.
* Electric Door & Electric Trapdoor: "opened" can make the door be opened by
  default when the level begins instead of closed. A switch or a button that
  removes power will close the door as normal.
* Colored Doors & Small Key Door: "unlocked" will make the door unlocked at
  level start, not requiring a key to open it.
* Colored Keys & Small Key: "has gravity" will make the key subject to gravity
  and set its Mobile flag so that if it falls onto a button, it will activate.
* Gemstones: they had gravity by default; you can now uncheck "has gravity" to
  remove their Gravity and IsMobile status.
* Gemstone Totems: "has gemstone" will set the totem to its unlocked status by
  default with the gemstone inserted. No power signal will be emitted; it is
  cosmetic only.
* Fire Region: "name" can let you set a name for the fire region similarly to
  names for fire pixels: "Watch out for ${name}!"
* Invisible Warp Door: "locked (exit only)" added as well.
2022-10-09 17:41:24 -07:00
7d15651ff6 "Look At Me" for Doodad Scripts
* New script API method: Self.CameraFollowMe() to draw camera focus toward
  your doodad (it sets the Canvas.FollowActor target.)
* The camera will go back to following the player on any action inputs
  (arrow keys, jump, use, etc.); if the player is constantly on the move
  the camera stays on him even if another actor is trying to take the focus.
* The first few ticks of Play Mode the player character is always followed,
  to allow for Anvils to settle into place without taking the focus.
* Canvas FollowActor: if the actor is 4 times the max scroll speed away,
  allow scrolling in greater leaps of 4 times the max scroll speed.

New and Changed Doodads

* Anvils will take the camera focus while they are falling.
* New doodad: "Look At Me" - a 'camera region' technical doodad. Link it to
  any power source such as a Button - when this doodad receives power it will
  take the camera focus for a few frames. Use it to highlight a door that
  opened far off screen by linking the Button to both an Electric Door and
  a "Look At Me" near the door.
2022-09-24 23:54:51 -07:00
653184b8f8 JavaScript Exception Catcher UI
* Add an exception catcher that pops open a UI window showing errors that
  occur in doodad scripts during gameplay.
* Shows a preview of the header of the error (character wrapped) with a
  Copy button to copy the full raw text to clipboard for inspection.
* Buttons to dismiss the modal once or stop any further errors from
  opening during this gameplay session (until next restart).
* Add developer shell commands to test the exception catcher:
  - 'throw <message>' to throw a custom message.
  - 'throw2' to stress test a "long" message.
  - 'throw3' to throw a realistic message copied from an actual error.
* Scripting engine: console.log() and friends will now insert the script
  VM's name in front of its messages (the filename + actor ID).
2022-09-24 21:58:01 -07:00
cd103f06c7 Touchscreen fixes 2022-09-24 19:05:42 -07:00
73421d27f2 Wait Modal
* Add modal.Wait() that creates a global progress bar modal which is not
  dismissable by the user; the caller must Dismiss() the modal
  themselves when ready.
* It will be useful in the future in case e.g. saving a Level needs to
  take a while to rebalance chunks and the modal prevents ALL
  interaction with the game so the user can't further modify the level
  while it's busy refactoring itself.
* Cheat code: "test wait screen" to show the Wait modal for 10 seconds.
2022-09-24 18:39:02 -07:00
546b5705db Detect touchscreen and tweak some behaviors 2022-09-24 17:45:54 -07:00
ec0b5ba6ca Rename Go module 2022-09-24 15:17:25 -07:00
34c45095b5 Idle animations for Boy 2022-05-07 20:18:44 -07:00
434416d3a4 Spit and polish
* Made the loadscreen useful again (give it work to do async so the game
  doesn't simply freeze during): does a first call to LoadUnloadChunks
  to preload the viewport chunks.
* Hide the mouse cursor when movement keys are pressed.
2022-05-07 18:54:37 -07:00
450c6b3bb2 Spit and polish
* On the failure (but still success) dialog on Survival Mode levels
  (e.g. Azulian Tag): make the default be to retry the level but
  show a "pity" Next Level button below, as the level is marked as
  completed (silver score) and the next one is unlocked.
2022-05-07 17:42:38 -07:00
ffc2c6f69b Performance?: Don't unload chunks so eagerly
Previously: the Chunker tracks with chunks were gotten during the
current game tick and the N-1 and N-2 ticks, and chunks not accessed in
two ticks were freed immediately.

Now: they go into a "garbage collection" pool with a minimum number of
game ticks to free. So if they're needed again, they're saved from the
gc pool. F3 overlay data shows the count of the gc pool.
2022-05-07 17:16:03 -07:00
94d0da78e7 Swimming Physics and Bubble Pattern
Water pixels finally do something other than turn your character blue!

* When the player character is "wet" (touching water pixels, and so appearing in
  a blue mask), water physics apply: gravity is slower, your jump height is
  halved, but you get infinite jumps to swim higher in the water.
* Holding the jump key under water will incur a short delay between jumps, so
  that you don't just fly straight up to the surface. Tap the jump button to
  move up quicker, you can spam it all you want.

Azulians are also able to handle being under water:

* They'll sink to the bottom and keep walking back and forth normally.
* If you are above them and noticed, they'll jump (swim) up towards you,
  aware of the water and it jumps like you do.
* The Blue Azulian has the poorest vertical aggro range so it isn't a
  very good swimmer. The White Azulian is very good at navigating water
  as it can pursue the player from the furthest distance of them all.

Changes to the editor:

* New brush pattern added: bubbles.png
  * It's the default pattern now for the "water" color of all
    of the built-in palettes instead of ink.png
  * A repeating pattern of bubbles carved out showing the
    level wallpaper.
  * The old "Bubbles (circles.png)" is renamed "Circles"
* The last scroll position is saved with the Level file, so when you reload
  the level later it's scrolled at where you left it.
2022-05-05 21:35:32 -07:00
4efa8d00fc Fancy Mouse Cursors
The gamepad mouse cursor has become THE mouse cursor. It is always visible and your
real cursor is hidden, and this way the game can swap out other cursors for certain
scenarios:

* The Pencil Tool in the editor will use a pencil cursor over the level canvas.
* The Flood Tool has a custom Flood cursor so you don't forget it's selected!

Other improvements:

* The Palette buttons in the editor now render using their swatch's pattern
  instead of only using its color.
* If you have an ultra HD monitor and open a Bounded level in the editor which
  is too small to fill your screen, the editor canvas limits its size to fit
  the level (preferable over showing parts of the level you can't actually play
  as it's out of bounds).
* The "brush size" box is only drawn around the cursor when a relevant tool is
  selected (Pencil, Line, Rect, Ellipse, Eraser)
2022-05-04 22:38:26 -07:00
9b75f1b039 Spit and polish
* New built-in wallpaper: "Dotted paper (dark)" is a dark-themed wallpaper.
* New built-in palette: "Neon Bright" with bright colors for dark levels.
* New cheat: "warp whistle" to automatically win the level.
* In case the user has a VERY LARGE screen resolution bigger than the full
  bounds of a Bounded level, the Play Scene will cap the size and center
  the level canvas onto the window. This is preferable to being able to see
  beyond the level's boundaries and hitting an invisible wall in-game.
* Make the titlescreen Lazy Scroll work on unbounded levels. It can't bounce
  off scroll boundaries but it will reverse course if it reaches the level's
  furthest limits.
* Bugfix: characters' white eyes were transparent in-game. Multiple culprits
  from the `doodad convert` tool defaulting the chroma key to white, to the
  SDL2 textures considering white to be transparent. For the latter, the game
  offsets the color by -1 blue.
2022-05-03 21:15:39 -07:00
75fa0c7e56 Stability and Bugfixes
* Editor: Auto-save on a background goroutine so you don't randomly freeze
  the editor up during.
* Fix actor linking issues when you drag and re-place a linked doodad: the
  level was too eagerly calling PruneLinks() whenever a doodad was 'destroyed'
  (such as the one just picked up) breaking half of the link connection.
* Chunk unloader: do not unload a chunk that has been modified (Set or Delete
  called on), keep them in memory until the next ZIP file save to flush them
  out to disk.
* Link Tool: if you clicked an actor and don't want to connect a link, click
  the first actor again to de-select it.

Updates to the `doodad` tool:

* `doodad edit-level --resize <int>` can re-chunk a level to use a different
  chunk size than the default 128. Large chunk sizes 512+ lead to performance
  problems.
2022-05-02 20:35:53 -07:00
fc736abd5f Doodads: Gems, Snake and Crusher
Adds several new doodads to the game and 5 new wallpapers (parchment
paper in blue, green, red, white and yellow).

New doodads:

* Crusher: A purple block-headed mob wearing an iron helmet. It tries
  to crush the player when you get underneath. Its flat helmet can be
  ridden on like an elevator back up.
* Snake: A green stationary mob that always faces toward the player.
  If the player is nearby and jumps, the Snake will jump too and hope
  to catch the player in mid-air.
* Gems and Totems: A new key & lock collectible. Gems have quantity so
  you can collect multiple, and place them into matching Totems. A
  Totem gives off a power signal when its gem is placed and all other
  Totems it is linked to have also been activated. A single Totem may
  link to an Electric Door and require only one gem to open it, or it
  can link to other Totems and they all require gems before the power
  signal is sent out.
2022-05-01 15:18:23 -07:00
ad67e2b42b New Doodad: Blue Bird
* The blue bird follows the same base AI as the red bird (it has a
  target altitude that it tries to maintain, and it will dive at the
  player) but the blue bird flies in a sine wave pattern around its
  target altitude. It also has a longer scan radius to search for the
  player than the red bird.
* The sine wave pattern of the blue bird means you may fly under its
  radar depending how high it is on average.

Cheat codes that replace the player character are refactored to make
it easier to extend, and new cheats have been added:

* super azulian: play as the Red Azulian.
* hyper azulian: play as the White Azulian.
* bluebird: play as the new Bird (blue).
2022-04-30 17:59:55 -07:00
402b5efa7e Zipfiles for Attached Files Too
* The level.FileSystem type has updated to support ZIP files too.
* Legacy levels loaded from gz/json have their old FileSystem as a
  simple map[filename]data and this parses from JSON OK.
* On save to zip, the legacy loaded file data gets exported to ZIP.
* Going forward: newly added or deleted files during runtime are kept in
  the legacy file map until the next save when the filemap is again
  flushed out to ZIP.
* For regular read-access, the FileSystem reads from the ZIP file if the
  data is not in the hot map (legacy file or recently modified
  attachment).
* Bugfix: be sure to Inflate() the Level/Doodad after loading from
  zipfile - it used to be that directly after a save, trying to play the
  level failed because the Level.Actors struct was missing their IDs,
  and similarly recently written chunks would error out (become black
  voids) on levels/doodads so we Inflate() both after save/replacing
  their zip handle.
2022-04-30 12:50:00 -07:00
302506eda9 Cheat: $ d.SetPlayerCharacter("anything.doodad")
Too restricted by the cheat codes to play as certain characters
on-demand? Use the JS shell in the developer console to set any doodad
you want:

    $ d.SetPlayerCharacter("key-blue")
    $ d.SetPlayerCharacter("anvil")
    $ d.SetPlayerCharacter("box.doodad")

The .doodad suffix is optional.

Interesting behaviors when playing as odd doodads:

* Most non-mobile doodads don't collide with each other, so you can pass
  through doors and not activate buttons if you play as a key or a
  trapdoor. Non-mobile doodads also generally have antigravity so you
  can fly freely around the map.
* Non-mobile doodads can not open Warp Doors or interact with the Exit
  Flag. You'll have to change back to a creature such as "boy" or
  "azu-blue" to win the level.
* If you are a key, the Thief can collect you! This removes your player
  doodad from the level and soft locks the game. No worries, another
  call to d.SetPlayerCharacter() will put you back on the map!
* If the doodad name isn't found, you'll play as the built-in fallback
  doodad, which is just a red "X" shape. It has anti-gravity and does
  not generally interact with any doodad (can not push buttons or
  collect keys - but it can pass through doors and other obstacles. Can
  not win the level goal flag, though!)
2022-04-29 21:39:53 -07:00
93623e4e8a Zipfiles as File Format for Levels and Doodads
Especially to further optimize memory for large levels, Levels and
Doodads can now read and write to a ZIP file format on disk with
chunks in external files within the zip.

Existing doodads and levels can still load as normal, and will be
converted into ZIP files on the next save:

* The Chunker.ChunkMap which used to hold ALL chunks in the main json/gz
  file, now becomes the cache of "hot chunks" loaded from ZIP. If there is
  a ZIP file, chunks not accessed recently are flushed from the ChunkMap
  to save on memory.
* During save, the ChunkMap is flushed to ZIP along with any non-loaded
  chunks from a previous zipfile. So legacy levels "just work" when
  saving, and levels loaded FROM Zip will manage their ChunkMap hot
  memory more carefully.

Memory savings observed on "Azulian Tag - Forest.level":

* Before: 1716 MB was loaded from the old level format into RAM along
  with a slow load screen.
* After: only 243 MB memory was used by the game and it loaded with
  a VERY FAST load screen.

Updates to the F3 Debug Overlay:

* "Chunks: 20 in 45 out 20 cached" shows the count of chunks inside the
  viewport (having bitmaps and textures loaded) vs. chunks outside which
  have their textures freed (but data kept), and the number of chunks
  currently hot cached in the ChunkMap.

The `doodad` tool has new commands to "touch" your existing levels
and doodads, to upgrade them to the new format (or you can simply
open and re-save them in-game):

    doodad edit-level --touch ./example.level
    doodad edit-doodad --touch ./example.doodad

The output from that and `doodad show` should say "File format: zipfile"
in the headers section.

To do:

* File attachments should also go in as ZIP files, e.g. wallpapers
2022-04-29 20:34:59 -07:00
9cdc7260bb Prepare v0.12.1 for release 2022-04-16 17:50:40 -07:00
c5353df211 LoadUnloadChunk for Memory Optimization
Instead of the loadscreen eager-loading ALL level chunks to Go Images, only
load the chunks within the "LoadingViewport" - which is the on-screen
Viewport plus a margin of chunks off the screen edges.

During gameplay, every few ticks, reevaluate which chunks are inside or
outside the LoadingViewport; for chunks outside, free their SDL2 textures
and free their cached bitmaps to keep overall memory usage down. The
AzulianTag-Forest level now stays under 200 Textures at any given time
and the loadscreen goes faster as it doesn't have to load every chunk's
images up front.

The LoadUnloadChunk feature can be turned on/off with feature flags. If
disabled the old behavior is restored: loadscreen loads all images and
the LoadUnloadChunks function is not run.

Other changes:

* loadscreen: do not free textures in the Hide() function as this runs on
  a different goroutine and may break. The 4 wallpaper textures are OK
  to keep in memory anyway, the loadscreen is reused often!
* Free more leaked textures: on the Inventory frame and when an actor
  calls Self.Destroy()
* Stop leaking goroutines in the PubSub feature of the doodad script
  engine; scripting.Supervisor.Teardown() sends a stop signal to all
  scripts to clean up neatly. Canvas.Destroy() tears down its scripting
  supervisor automatically.
2022-04-10 12:40:25 -07:00
d694fcc7c2 Fix climbing on the right bug + eager-render boolprop
* New boolProp to help debug memory issues: eager-render, set it to
  false and the loadscreen will not eagerload Go images for all the
  level chunks.
* Finally fix the level collision bug where the player could climb walls
  to the right.
2022-04-09 18:21:26 -07:00
6b8c7a1efe Update Go dependencies 2022-04-09 16:01:56 -07:00