November 2022-August 2023 Progress Report


Um... been a while, hasn't it? ^^;

For the past nine months, I've been busy with the usual: struggling through college, tending to my ever-increasing burnout, and working on other projects. These projects include a redesign of my website (nearing completion; please watch warmly until it is ready), a story for the Welcome to Gensokyo fanzine, a prototype for a new game, and another entry for the Touhou Pride Game Jam: Princess-Officer Investigations. Just like in 2022, the Pride Jam entry wasn't finished by the deadline, but unlike last year, I fully intend to see it through to completion.

Fortunately, my part on the no-longer-a-jam game is nearly complete, so I should be able to start working on Devil's Emergence again, temperament permitting! Fingers crossed. Please, for the love of the gods, just let me...

That said, here are all the updates I've made to Devil's Emergence since the last progress report. Please note that the updates listed here have not been released yet.

Progress from 23 November 2022 – 16 August 2023

  • The spriteset info file format has been changed to RON. This removes a preprocessing step when updating spritesheets and should make life infinitely easier for fan translators/graphics hackers.
  • You are now awarded with extra lives for attaining certain scores, as in Lotus Land Story and the Embodiment of Scarlet Devil.
  • Tweaked the probabilities for stage clear rewards. Notably, stage clear rewards are now disabled in lunatic mode.
  • Clearing a stage will now take you to the next stage, if applicable.
  • Add a wipe transition and eyecatch between stages, like in Story of Eastern Wonderland, Lotus Land Story, and Mystic Square.
  • Fixed an integer overflow that would occur after continuing with more than three continues.
  • Added and made use of the ability to fade music.
  • Collisions were refactored to support other projects. This might have a slight negative effect on performance in Devil's Emergence.
  • Wrote draft dialogue for parts of Yuuka's and Meiling's routes.
  • Added titles and abilities to the character profiles.
  • Revised Meiling's stage 1 dialogue. Orange should sound a little less stiff now.
  • Added support for boss backgrounds.
  • Added tile-based transitions from stage backgrounds to boss backgrounds.
  • Tweaked the title screen theme. It should sound a bit more complete, though it still seems a little off...
  • Added turning sprites for Orange.
  • Fixed a timing bug in Orange's second nonspell.
  • Redrew the title screen completely. It now features every playable character (sans Yukari, who slept through the photo shoot) on a brighter, slightly more Touhou-ish background. The art's still pretty shabby, but... um, well, at least Meiling looks kind of okay?
  • Reimu's playfield sprites were altered to give her the red top she's worn since Shuusou Gyoku.
  • Added character profiles for two bosses.
  • The scripting system now kills entities when their script finishes. This does not appear to have changed the behaviour of Meiling's first stage, but it might cause subtle discrepancies.
  • Added a way to define custom bullet behaviours. This is necessary for any sort of interesting bullet patterns.
  • Created a background for Reimu's first stage.
  • Wrote most of the stage titles.
  • In dialogue cutscenes, the dialogue of the character who isn't speaking is now dimmed.
  • Added the ability for text to have drop shadows and added one to the stage title.
  • Dialogue scripts can now stop the background music, hide the dialogue UI, wait for a specified duration before proceeding, and more.
    • These were originally implemented for Princess-Officer Investigations, but they should come in handy for Devil's Emergence as well.
  • Several internal refactors designed to improve maintainability and make it far easier to write new code.

For nine months, that seems like strikingly little progress. To be fair, there's been a lot more going on behind the scenes. "Several internal refactors" is a severe understatement for the amount of work that's gone into the base engine since November, and the game's scripting engine had even more work put into it (just over 4.5 pages/~229 commits' worth). Nevertheless, it's quite disappointing that these are the only surface level changes made over such a long span of time. All I can do is apologize and hope that I can make up for it by pushing ever onward.

For the curious, here's some of the behind-the-scenes work that you won't necessarily be able to see in the final product:

Behind the scenes progress from 23 November 2022 – 16 August 2023

Triplicata

  • Removed redundant code in collision checks.
  • Added a system to display hitboxes for debugging.
  • Added rectangular hitboxes. These currently aren't used in Devil's Emergence; they were implemented for a prototype of a platformer.
  • Hitboxes now take a custom collision mask type, so collision masks can now be defined by each game to fit their needs.
    • For instance, Devil's Emergence has support for player hitbox, item grab-box, grazebox, player bullet, enemy, and enemy bullet collisions, while Princess-Officer Investigations only supports solid and interactable collisions.
  • Colours are now defined as a 32-bit integer rather than a set of four floats. The fact that I hadn't done this from the outset is honestly quite embarassing.
  • Added a way to customize how sprites are sorted before drawing. This doesn't affect Devil's Emergence, as it uses the default behaviour (sort sprites based on manually-assigned layers).
  • Removed a few unnecessary traits related to application backends. They are now handled using enums.
  • Added the ability to store game-specific data required for state updates in the application manager. This is useful for things like high-score tables.
  • Moved the last remaining bits of high-score handling into Devil's Emergence.
  • Added the ability to have empty tiles in tilemaps.
  • Tiles in tilemaps can now be marked as solid.
  • Added a tilemap collider.
  • Updated several dependencies.
  • Fixed a soundness issue that would occur when destroying an application backend. Backends are now leaked by default; they can still be destroyed manually if the user can guarantee that any resources tied to them have been destroyed.
  • Meshes and textures now take up less space on the stack (automatic storage, whatever). This should have a ripple effect that makes common copies/moves slightly faster.
  • UI text now uses a builder rather than having several constructors.
  • Fixed the display of proportional bitmap fonts.
  • Fixed several other rendering bugs in bitmap fonts.
  • Added the ability to customize the scaling filter used for bitmap fonts.
  • Added support for branching control flow and game-specific events in dialogue scripts.
  • Character IDs in dialogue scripts are now identifiers instead of numbers.
  • The texture cache is now flushed after changing game states rather than immediately before. This allows more unnecessary textures to be unloaded.
  • Adjusted documentation to improve readability.

Devil's Emergence

  • Bundled a bunch of data needed for the enemy death function to avoid having to repeat it multiple times.
  • The main gameplay state's current mode (eg. pause, game over, playing) is now controlled by a state machine rather than a set of mutually exclusive booleans.
  • The function to create a new enemy now requires fewer arguments — sensible defaults for point value (1000), tangibility (yes), and vulnerability (yes) are now assumed.
  • Further, creating an enemy from a script now uses a builder. For simple enemies, this cuts the number of required arguments down from seven to three.
  • Added a script that checks Laria scripts for any issues at compile time. This takes up almost no time but surfaces errors much more quickly than testing normally, so it's very convenient.
  • Added the ability to delete options/bullet sources in the shot type editor.
  • Entities are now passed to scripts using an opaque type rather than a number. This makes working with entities slightly more convenient.
  • Adjusted scripts to account for changes to Laria, the scripting engine.

Laria

  • Added lambda parsing.
  • Replaced the && and || operators with and and or, respectively.
  • Added error recovery to the parser. This should allow it to report more errors per compilation attempt.
  • Reserved keywords co and await for coroutines.
  • Added opaque types, which are defined by the application.
  • Strengthen a santiy check to ensure that type checking fully resolves all types.
  • Fixed a bug where while loop conditions weren't typechecked.
  • Added feature gate attributes. These gates control access to unstable and internal features, such as implementing methods on primitives.
  • The compiler now uses string interning, which makes comparisons between identifiers much faster.
  • Implemented enums. Like in Rust, these are generalized sum types.
  • Replaced the name resolver. This new resolver has a much cleaner architecture and is, on the whole, significantly easier to work with.
  • Removed several workarounds for bugs in the old name resolver.
  • Added support for special search locations in paths, such as script for the script root.
  • Added pattern matching in the form of matches expressions. These are essentially a generalization of Rust's  if let and  while letconstructs.
  • Added  use statements, which can be used to import items from modules.
  •  never is no longer a keyword to match the behaviour of other primitives.
  • Added support for hexidecimal and octal integer literals (eg. 0xFF is equivalent to 255).
  • Added a validation pass for the AST.
  • Added statics, which are essentially constants that are stored in a specific location in the VM. This allows them to be accessed from native bindings.
    • Inlined constants, like in Rust, have not been implemented yet.
  • Added constant evaluation, which allows certain computations to be run at compile time. This is currently only used in statics.
  • Add multi-token lookahead to both the lexer and parser.
  • Add qualified paths. This should allow you to call methods and associated functions on certain primitives (such as references and tuples).
  • Added support for placing attributes on arbitrary items.
  • Fixed shebang-skipping logic interacting poorly with attributes on the first line of the file.
  • Added intrinsics, which are essentially builtin native bindings.
  • Coloured output is now disabled when when error output is being written to a file or when the NO_COLOR environment variable is set.
  • Renamed the arguments to a fundamental function in the type checker to make it much easier to understand.
  • Added a special error message for type errors caused by two types with the same name.
  • Command line arguments are now parsed with clap 3 rather than pico_args.
  • The default command line interface now uses subcommands rather than switches (ex. laria -c is now laria build ).
  • Updated dependencies to avoid a security vulnerability.
  • Improved method typechecking.
  • Added unit structs (struct Foo;).
  • Added effects, whose purpose is twofold:
    • They can be used to plumb data through functions without having to write it at the callsite (though places where an effect can be used must be marked with either a with expression or a with clause in the function header).
    • They can be used to explicitly declare intent with compile-time checking (similar to Rust's unsafe).
  • Split path parsing in use statements from general path parsing.
  • Banned recursive glob imports (eg. use script::*; in the script root).
  • Added import trees (use std::mem::{MaybeUninit, swap};).
  • Fixed typechecking in struct literals.
  • Name resolution is now run repeatedly until it fails to resolve anything. This is currently used for import resolution and will be required for macros.
  • Added macro parsing.
  • Added visibility modifiers (eg. pub). By default, items are only visible within their defining module and its children.
  • Made primitives super-private — they can't be imported from any other module unless they're explicitly exported using pub use.
  • Names that exist in multiple namespaces are now resolved correctly. For instance, if a module contains a type named  foo and a function named foo, you can now import and use both.
  • Reworked diagnostic handling to be more ergonomic.
  • Added traits.
  • Native bindings were reworked to be infinitely more ergonomic. They now look like normal Rust functions tagged with a #[laria_fn] attribute. All necessary stack manipulation is done behind the scenes.
  • Native bindings now have access to the entirety of the virtual machine state.
  • Instructions are now decoded when the script is loaded rather than decoding them as they're encountered.
  • Added proper tuple indexing (ex. (1, 2, 3).0 yields 1).
  • Interned types are now deduplicated.
  • Added infrastructure for trait bounds in generics. This infrastructure is currently unused, as generics haven't been implemented yet.
  • Desugar while loops to basic loops. This removes some redundant code from code generation.
  • Added break and continue expressions.
  • Desugar counter loops (eg. loop 5 {}) into basic  loops.
  • Added parsing for break value.
  • Added prelude injection.
  • Added a standard library (currently hacked in using prelude injection).

With that, thank you for reading! See you next time! (In a little less than nine months, I hope...)

Get [Demo] Touhou Mashutsugen ~ Devil's Emergence.

Leave a comment

Log in with itch.io to leave a comment.