Commit Graph

36 Commits

Author SHA1 Message Date
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
af6b8625d6 Flood Tool, Survival Mode for Azulian Tag
New features:
* Flood Tool for the editor. It replaces pixels of one color with another,
  contiguously. Has limits on how far from the original pixel it will color,
  to avoid infinite loops in case the user clicked on wide open void. The
  limit when clicking an existing color is 1200px or only a 600px limit if
  clicking into the void.
* Cheat code: 'master key' to play locked Story Mode levels.

Level GameRules feature added:
* A new tab in the Level Properties dialog
* Difficulty has been moved to this tab
* Survival Mode: for silver high score, longest time alive is better than
  fastest time, for Azulian Tag maps. Gold high score is still based on
  fastest time - find the hidden level exit without dying!

Tweaks to the Azulians' jump heights:
* Blue Azulian:  12 -> 14
* Red Azulian:   14 -> 18
* White Azulian: 16 -> 20

Bugs fixed:
* When editing your Palette to rename a color or add a new color, it wasn't
  possible to draw with that color until the editor was completely unloaded
  and reloaded; this is now fixed.
* Minor bugfix in Difficulty.String() for Peaceful (-1) difficulty to avoid
  a negative array index.
* Try and prevent user giving the same name to multiple swatches on their
  palette. Replacing the whole palette can let duplication through still.
2022-03-26 13:55:06 -07:00
44122d4130 Spit and polish
UI improvements specifically for mobile (running the game with the
`-w mobile` or `-w landscape` options) screen sizes.

* Rework the Settings window to be mobile friendly to landscape
  oriented screens (`doodle -w landscape`) and migrate Options tab
  to magicform.
* The toolbar in the Editor will be a single column of buttons
  on small screens, such as `-w mobile` (375x812) portrait mode
  smartphone. On larger screens the toolbar shows in two columns
  of buttons.
* Fix tooltips not drawing on top.
* Centralize the hard-coded references to specific font filenames
* Add cheat code: `test load screen` to bring a sample loading screen up
  for a few seconds. It needs improvement on `-w landscape`
2022-03-05 22:44:54 -08:00
77297fd60d Text Tool and Pan Tool
Two new tools added to the Level Editor:

* Pan Tool: left-click to scroll the level around safely.
* Text Tool: write text onto your level.

Features of the Text Tool:

* Can choose from the game's built-in fonts, size and enter the message
  you want to write.
* The mouse cursor previews the text when hovered over the level.
* Click to "stamp" the text onto your level. The currently selected
  color swatch will be used to color the text in.
* Adds two new fonts: Azulian.ttf and Rive.ttf that can be selected in
  the Text Tool.

Some implementation notes:

* Added package native/engine_sdl.go that handles the lower-level
  SDL2_TTF logic to rasterize the text into a black&white image.
* WASM not supported yet (if the game even still built for WASM);
  native/engine_wasm.go stubs out the TextToImage() call with a "not
  supported" error just in case.

Other changes:

* New Toolbar icons: they are 24x24 instead of 32x32 to make more room
  for more tools.
* The toolbar now shows two buttons per row for a more densely packed
  layout. For very narrow screen widths (< 600px) the default Vertical
  Toolbar layout will use one-button-per-row to not eat too much screen
  real estate.
* In the Horizontal Toolbars layout there are 2 buttons per column.
2022-03-05 15:34:20 -08:00
40cb9f15cb Prepare v0.11.0 for release (+ fixes)
* The title screen now loads the default maps from a LevelPack. The game
  no longer ships with the Tutorial levels in the "levels" folder as
  default; they are in the LevelPack so the "Edit Drawing" screen begins
  as a blank slate for only user levels.
* Add the Zoo level to the Tutorial levelpack
* Bugfixes around changing the player character to work around clipping
  issues if the character has changed height drastically.
2022-02-20 17:48:07 -08:00
4de0126b19 Game Controller Support
Adds support for Xbox and Nintendo style game controllers. The gamepad
controls are documented on the README and in the game's Settings window.

The buttons are not customizable yet, except that the player can choose
between two button styles:

* X Style (default): "A" button is on the bottom and "B" on the right.
* N Style: swaps the A/B and the X/Y buttons to use a Nintendo-style
  layout instead of an Xbox-style.
2022-02-19 18:31:22 -08:00
44aba8f1b4 White Azulian, Respawn invincibility timer
* Respawning from a checkpoint grants 3 seconds of immunity in case
  enemies are spawn camping.
* Add the white Azulian as an even faster and harder enemy than the red
  Azulian: twice as fast, jumps higher, and can detect the player from
  further away.
2022-01-18 18:32:15 -08:00
9a51ac39f9 Spit and polish
* New doodad: Invisible Warp Door
* All warp doors require the player to be grounded (if affected by
  gravity) to open them. No jumping or falling thru and opening
  a warp door mid-air!
* Title Screen now randomly selects from a couple of levels.
* Title Screen: if it fails to load a level it sets up a basic
  blank level with a wallpaper instead.
* New developer shell command: titlescreen <level>
  Opens the MainScene with a custom user level as the background.
* Add Auto-save to the Editor to save your drawing every 5 minutes
* Add a MenuBar to the Play Scene for easier navigation to other
  features of the game.
* Doodad JS API: time.Since() now available.
2022-01-02 22:36:32 -08:00
678326540b WIP LevelPack UI + Landscape Mode Title Screen
The title screen is now responsive to landscape mode. If the window is
not tall enough to show all the menu buttons (~600px) it will switch to
a horizontal layout with the title on the left and buttons on the right.

WIP "Story Mode" button that brings up a Level Packs selection window.
2021-12-23 21:11:45 -08:00
e80a3f0446 Various minor tweaks and changes
* Recolor some of the region doodads
* Add command: `doodad edit-level --remove-actor` to remove actors from
  your level.
* Tweak the player jump velocity from playtesting levels.
2021-10-07 20:50:24 -07:00
d6acee5a66 Adjust Gravity and Prevent Moonwalking
* Tweak max gravity speed to match player max velocity.
* Boy's script watches for his velocity to flip suddenly and stops
  animations, limiting the moonwalking a bit.
* JS API: Self.GetVelocity() added.
2021-10-07 18:49:09 -07:00
fb5a8a1ae8 Async Giant Screenshot, Player Physics and UI Polish
* The "Giant Screenshot" feature takes a very long time, so it is made
  asynchronous. If you try and run a second one while the first is busy,
  you get an error flash. You can continue editing the level, even
  playtest it, or load a different level, and it will continue crunching
  on the Giant Screenshot and flash when it's finished.
* Updated the player physics to use proper Velocity to jump off the
  ground rather than the hacky timer-based fixed speed approach.
* FlashError() function to flash "error level" messages to the screen.
  They appear in orange text instead of the usual blue, and most error
  messages in the game use this now. The dev console "error <msg>"
  command can simulate an error message.
* Flashed message fonts are updated. The blue font now uses softer
  stroke and shadow colors and the same algorithm applies to the orange
  error flashes.

Some other changes to player physics:

* Max velocity, acceleration speed, and gravity have been tweaked.
* Fast turn-around if you are moving right and then need to go left.
  Your velocity resets to zero at the transition so you quickly get
  going the way you want to go.

Some levels that need a bit of love for the new platforming physics:

* Tutorial 3.level
2021-10-07 18:27:38 -07:00
489a43ea8c Touch Screen Controls for Play Mode!
The game can now be played using only a touch screen! The left
mouse click (Button1) can now move and control the player
character.

* A box in the very middle of the screen is the "Use" button and
  a deadzone for directional inputs.
* Anywhere outside the middle and to the left registers a Left
  button, to the right a Right button, above the top of the middle
  is a Jump button, and below the bottom of the middle is a down
  input (for antigravity mode).
* Tight platforming is possible: above and below the middle box,
  the left/right split is tight in the middle of the window. You
  can get tight jumps if jumping or go below if you don't want to
  jump. The left/right deadzone is only over the space of the Use
  button.

If the player is idle for a while with no controller inputs, some
hints will fade in about the touch controls.

Note: the ScrollboxOffset to track the player character is changed
to 60,60 from 60,100 so the camera will track tighter to the player
and so the player will mostly be over the Use button on touch
controls as long as he's away from a level boundary.
2021-10-04 19:51:31 -07:00
1ac85c9297 Checkpoint Flag & Retry from Checkpoint
* New Doodad: Checkpoint Flag. They update the player's spawn point
  whenever the player passes one. The most recently activated
  checkpoint is rendered brighter than the others.
* End Level Modal: the fake alert box window drawn by the Play Mode
  is replaced with a fancy modal widget (similar to Alert and Confirm).
  It handles level victory or failure conditions and can show or hide
  all the buttons as needed.
* Gameplay: There is a "Retry from Checkpoint" option added, which
  appears in the level failure modal. It will teleport you back to
  the Start Flag or the last Checkpoint Flag you had touched, without
  resetting the level -- your keys, unlocked doors, etc. will be
  preserved so you can retry.
* Set a maximum speed on the "Camera Follows Actor" logic of 64
  pixels per tick. This results in a smoother scrolling transition
  when the player jumps to a new location on the map, such as by
  a Warp Door.
* Update the default color palettes:
    * All: Add a "hint" magenta color.
    * Colored Pencil: Add a "darkstone" solid color.

Updates to the Doodads JavaScript API:

* SetCheckpoint(Point(x, y)): set the player character's spawn
  position. Giving it Self.Position() is an easy way to set the
  player spawn to your doodad's location.
2021-08-15 20:17:53 -07:00
405aaf509d Link Start Flags to Change Characters
New feature: link a Start Flag to another doodad in your level
and you will play as that doodad instead of Boy. All Creatures
are designed to be playable. Playing as "other" doodads leads
to interesting effects, like not being able to activate buttons,
switches, or warp doors and not having an inventory to pick up
keys. The Anvil is fun: it can destroy other mobile doodads by
jumping on them.

If the actor does not specify that it has gravity, the gameplay
starts in antigravity mode. This will be the vast majority of
non-mobile doodads and the Bird.

Other changes:

* The Blue and Red Azulians now share a doodad script.
* The Azulians AI is still to walk back and forth, pickup keys and
  press buttons. The Blue Azulian walks slower than the red one.
* The Blue Azulian is no longer hidden from the doodads list.
* Actor UUID values in levels are now V1 UUIDs (time-ordered).
  This will help to reliably resolve conflicts in draw order
  of overlapping doodads (newest added to level wins).
* Link Tool: clicking on a pair of already-linked doodads will
  now unlink them, so you don't have to delete one to delete
  the link.
* Actor Tool: deleting an actor immediately calls PruneLinks()
  to clean up any links that the deleted doodad might have.
2021-08-11 20:40:31 -07:00
8603c43c58 Gzip Compression for Levels and Doodads
* Levels and Doodad files will be written in gzip-compressed JSON format
* `boolProp compress-drawings false` to disable compression and save as
  classic JSON format directly
* The game can still read uncompressed JSON files

The file size savings on some built-in assets:

* Tutorial 2.level: 2.2M -> 414K (82% smaller)
* warp-door-orange.doodad: 105K -> 17K (84% smaller)
2021-07-13 20:06:57 -07:00
e6b71f5512 Fix Scroll-Follow-Actor Behavior
* The scrollbox by which the game follows the player character has been
  revised, it is now an offset away from the window's center instead of
  fixed pixel distances from the window's edges.
* Mobile form-factor (Pinephone) now scrolls OK instead of jerking back
  and forth rapidly when moving left.
2021-06-13 20:25:42 -07:00
7093b102e3 Embeddable Doodads In Levels
* The Publisher is all hooked up. No native Save File dialogs yet, so
  uses the dev shell Prompt() to ask for output filename.
* Custom-only or builtin doodads too can be stored in the level's file
  data, at "assets/doodads/*.doodad"
* When loading the embedded level in the Editor: it gets its custom
  doodads out of its file, and you can drag and drop them elsehwere,
  link them, Play Mode can use them, etc. but they won't appear in the
  Doodad Dropper if they are not installed in your local doodads
  directory.
* Fleshed out serialization API for the Doodad files:
  - LoadFromEmbeddable() looks to load a doodad from embeddable file
    data in addition to the usual places.
  - Serialize() returns the doodad in bytes, for easy access to embed
    into level data.
  - Deserialize() to parse and return from bytes.
* When loading a level that references doodads not found in its embedded
  data or the filesystem: an Alert modal appears listing the missing
  doodads. The rest of the level loads fine, but the actors referenced
  by these doodads don't load.
2021-06-13 14:59:03 -07:00
640e75ba4d Custom Wallpapers for Levels
* You can now browse for a custom wallpaper image to use with your
  levels. A platform-native file picker dialog is used (no WASM support)
* In the New/Edit Level Properties dialog, the Wallpaper drop-down
  includes an option to browse for a custom map.
* When editing an existing level: the wallpaper takes effect immediately
  in your level once the file is picked. For NEW levels, the wallpaper
  will appear once the "Continue" button is pressed.
* All common image types supported: png, jpeg, gif.
* The wallpaper is embedded in the level using the filepath
  "assets/wallpapers/custom.b64img" as a Base64-encoded blob of the
  image data.
* The `doodad show` command will list the names and sizes of files
  embedded in levels. `doodad show --attachment <name>` will get an
  attachment and print it to the console window.
* To extract a wallpaper image from a level:
  `doodad show -a assets/wallpapers/custom.b64img | base64 -d > out.png`
2021-06-06 18:59:04 -07:00
be47dc21c7 Decouple gravity from player velocities 2021-06-02 22:18:25 -07:00
0fedcf4fcb Adjust ScrollboxVert and Prepare v0.5.0 for Release 2021-03-31 19:27:40 -07:00
1f274e0ca6 Changelog and Prepare v0.5.0 for Release 2021-03-31 19:16:33 -07:00
71b3eafbe4 Add Player Character Sprites
* Added initial walking sprites for the player character, "Boy."
* Player doodad filename and title screen level are now configurable in
  the balance/numbers.go package.
2020-09-18 22:35:43 -07:00
695ff4da42 Collision: Fix clipping thru left walls, w/ caveats
There was a clipping bug where the player could sometimes clip thru a
left-side wall, if the left wall and floor made a 90 degree bend and the
player was holding the Left key while jumping slightly into the wall.

A band-aid that seems to work involved two steps:
1. When capping their leftward movement, add a "+ 1" to the cap.
2. At the start of the point loop, enforce the left cap like we do the
   ceiling cap.

This seems to patch the problem, BUT it breaks the ability to walk up
slopes while moving left. Right-facing slopes can be climbed fine still.

Note: the original bug never was a problem against right walls, only
left ones, but the true root cause was not identified. See TODO comments
in collide_level.go.
2020-04-11 19:21:12 -07:00
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
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
a43e45fad0 Level Collision and Scrolling Fixes
* Fix the level collision bug that allowed clipping thru a ceiling while
  climbing up a wall.
* Fix the scrolling behavior to keep the character on-screen no matter
  how fast the character is moving, especially downwards.
* Increase player speed and gravity.
* New cheat: "ghost mode" disables clipping for the player character.
* Mark an actor as "grounded" if they fall and are stopped by the lower
  level border, so they may jump again.
2020-01-02 20:23:27 -08:00
0437adfbf8 Change types int32 -> int per upstream render and ui library 2019-12-27 19:16:34 -08:00
cc1e441232 Eraser Tool, Brush Sizes
* Implement Brush Sizes for drawtool.Stroke and add a UI to the tools panel
  to control the brush size.
  * Brush sizes: 1, 2, 4, 8, 16, 24, 32, 48, 64
* Add the Eraser Tool to editor mode. It uses a default brush size of 16
  and a max size of 32 due to some performance issues.
* The Undo/Redo system now remembers the original color of pixels when
  you change them, so that Undo will set them back how they were instead
  of deleting the pixel entirely. Due to performance issues, this only
  happens when your Brush Size is 0 (drawing single-pixel shapes).
* UI: Add an IntVariable option to ui.Label to bind showing the value of
  an int reference.

Aforementioned performance issues:

* When we try to remember whole rects of pixels for drawing thick
  shapes, it requires a ton of scanning for each step of the shape. Even
  de-duplicating pixel checks, tons of extra reads are constantly
  checked.
* The Eraser is the only tool that absolutely needs to be able to
  remember wiped pixels AND have large brush sizes. The performance
  sucks and lags a bit if you erase a lot all at once, but it's a
  trade-off for now.
* So pixels aren't remembered when drawing lines in your level with
  thick brushes, so the Undo action will simply delete your pixels and not
  reset them. Only the Eraser can bring back pixels.
2019-07-11 19:07:46 -07:00
c8620f871e Drawing Strokes and Undo/Redo Functionality
* Add new pkg/drawtool with utilities to abstract away drawing actions
  into Strokes and track undo/redo History for them.
* The freehand Pencil tool in EditorMode has been refactored to create a
  Stroke of Shape=Freehand and queue up its world pixels there instead
  of directly modifying the level chunker in real time. When the mouse
  button is released, the freehand Stroke is committed to the level
  chunker and added to the UndoHistory.
* UndoHistory is (temporarily) stored with the level.Level so it can
  survive trips to PlayScene and back, but is not stored as JSON on
  disk.
* Ctrl-Z and Ctrl-Y in EditorMode for undo and redo, respectively.
2019-07-03 16:25:23 -07:00
35d96b714d Add JavaScript panic catcher to doodads
* Add example mischievous doodad script that alters the logger date
  format and animates its canvas's mask color.
2019-04-18 22:02:59 -07:00
241186209c Play Mode: Fix Level Collision w/ Scrolling
Fixes:
* Move the call to CollidesWithGrid() inside the Canvas instead of
  outside in the PlayScene.movePlayer() so it can apply to all Actors
  in motion.
* PlayScene.movePlayer() in turn just sets the player's Velocity so the
  Canvas.Loop() can move the actor itself.
* When keeping the player inside the level boundaries: previously it was
  assuming the player Position was relative to the window, and was
  checking the WorldIndexAt and getting wrong results.
* Canvas scrolling (loopFollowActor): check that the actor is getting
  close to the screen edge using the Viewport into the world, NOT the
  screen-relative coordinates of the Canvas bounding boxes.
2019-04-14 15:25:03 -07:00
5c08577214 Port over code from old collision dev PR 2019-04-09 19:17:56 -07:00
8fc4f39da0 Improvements to the Debug Overlay Feature
* Scenes can insert custom key/value labels to the debug overlay and
  track string variables in real time
* Added ability to unthrottle FPS in main loop
2019-04-09 18:28:08 -07:00
2b42a072a0 Code Layout Refactor
* All private Doodle source code into the pkg/ folder.
* Potentially public code into the lib/ folder.
* Centralize the logger into a subpackage.
2019-04-09 17:35:44 -07:00