Releases: PurpleKingdomGames/indigo
Release list
v0.22.0
Going with the (lightly pruned) auto-generated notes this time as it's pretty accurate (...and I'm low on time today...).
Overview
This release contains a series of improvements and bug fixes. The largest change is the continuing efforts of @hobnob to improve input device handling!
Many thanks to the three new first time contributors, @kabuumu, @felher, and @susliko! π
Breaking changes
The main API breaking change in this release are:
- That use of
NonEmptyList- notably in Scenes - has been swapped forNonEmptyBatch. FontInfodefinitions / constructors no longer take a size / width and height.
What's Changed
- Added new Animation constructor, Animations use NonEmptyBatch now by @davesmith00000 in #922
- Fixed #921: Reduce use of NonEmptyList by @davesmith00000 in #923
- Allows buttons to have a hover state by @hobnob in #931
- Adds JS events during engine load by @hobnob in #933
- Removes deprecated methods and classes by @hobnob in #935
- Removes requirement for directories with Custom Template by @hobnob in #934
- Added module name in generator to ensure unique CharBatch object name by @kabuumu in #937
- fix bug in FontInfo where
addCharwould duplicate unknown font char by @felher in #940 - Adds
withMasterVolumetoSceneAudioby @hobnob in #939 - Improving Input Handling by @hobnob in #936
- Update sbt, scripted-plugin to 1.11.4 by @scala-steward in #951
- Cross-builds indigo-plugin module for Scala 3 by @susliko in #950
New Contributors
- @kabuumu made their first contribution in #937
- @felher made their first contribution in #940
- @susliko made their first contribution in #950
Full Changelog: v0.21.1...v0.22.0
v0.21.1
Bug fix release for issues with performers that came up while producing examples for the docs.
What's Changed
- Added tests and fixed bugs around duplicates messages in performers by @davesmith00000 in #907
Full Changelog: v0.21.0...v0.21.1
v0.21.0
Indigo is now built against Scala 3.6.4 and Scala.js 0.19.0, your projects will need to use at least those versions to be compatible.
This release is called: "There's more to do, but sometimes you need to call it and cut a release." π
Below is a brief summary of changes and features included in version 0.21.0.
Actors & Performers
The major addition that comes with this release, is the notion of Actors and Performers, two flavours of the same solution to a core problem.
Finding the Fun
Indigo (via the Elm Architecture) was designed for 'correctness'. Well, not absolute correctness. Actually, not even the level of correctness many Scala developers strive for commercially, but a level of correctness I'd never experienced as a Flash developer at least.
Correctness, and related topics like type safety and borrow checkers and so on, lend themselves very well to highly specified and generally understood software builds such as data pipelines, backend services, systems tools, and even games engines.
What frameworks, libraries and languages aimed at correctness are not good at, it turns out, is having fun. Finding fun. Making something that feels fun, and making it quickly.
This is very important in game development. Anyone who is trying to learn gamedev or take part in a game jam, needs to see results quickly to know if they're making progress or not.
Take for example someone trying out a game idea. That person needs to be able to test and reject lots of ideas and prototypes quickly to figure out which ones are worth pursuing. If they can't do that with a 'correct' engine, they'll find a more relaxed one, and probably just stick with it, willingly sacrificing correctness for a sense of productivity. Later in the build they may pay the price for that decision, but that's a high quality problem for later when they have something worth finishing.
Refactoring game wiring to appease a type checker is a waste of time and energy when your goal is to test an idea.
So the problem is: How do we introduce a way to build quickly, sacrificing a little correctness and ability to reason about the game's behaviour, in exchange for a productivity boost, and dare I say it, for having some fun? How do we make Indigo gamejam friendly?
The good news is that Indigo uses the Elm architecture, and the Elm architecture composes quite well. So all we need to do, is provide convenient ways for people to describe mini-elm architecture based things that can communicate with each other and the rest of the game via messages. Sounds a bit like an actor to me..
Actors
better_followers.mov
Actors are a building block. They're an intentionally incredibly simple construct. You wire an ActorPool into your game model and update and present loop, and the ActorPool does the rest. Actors can be spawned, killed, and discovered directly on the pool in a type safe way.
An Actor can be any type at all, as long as you can provide an instance of the Actor typeclass for it. As such, you can think of actors as the more FP solution, but that doesn't make them the better option, at least initially. Actors work nicely, but they do require more manual management than performers. For example, being a building block, if you want to use actors with physics, then you'll need to join them onto the physics world 'building block' yourself, manually.
Performers
zombies.mov
Performers are very similar to actors, but are a much more opinionated solution and intentionally lean slightly more towards OO (but don't let that put you off!). Performers run in a subsystem, so the set up is much easier and there's no wiring to do. If you want to add / remove performers you do so with PerformerEvents. Some of them also work with physics out of the box!
Performers lean on a 'Stage & Screen' metaphor, and offer a range of types you can extend (inherit from) that provide different levels of functionality at the cost of increasing interface complexity. They are:
Performer.Extra- Extra performers are the background characters of the performance. They are responsible for rendering themselves and updating their state, but they cannot interact with the game directly since they have no way to listen to or emit events.Performer.Stunt- Stunt performers are like Extras, but they can do their own stunts! In practical terms, they are background performers like extras, but have their motion automatically controlled by a managed physics simulation.Performer.Support- Support performers are the main character actors. They are responsible for rendering themselves, updating their state, and can also listen to and emit events, but they leave physical work to Stunt and Lead performers.Performer.Lead- Lead performers are the stars of the show. They are responsible for rendering themselves, updating their state, listen to and emitting events, and even doing their own stunts! They are the most complex type of performer, but also the most powerful.
Using performers is the fastest way to start building a game that requires the least mental gymnastics! ...the drawback is that the pattern is limiting and opinionated, and as your game grows, you'll probably want to try other organisation methods.
Where Actors and Performers live in relation to the main game loop
We'll see how it pans out, but the intention is that people will start with performers as the quickest solution, as their game develops they could selectively introduce actors for more control at the cost of more overhead / wiring, and ultimately manage the core game state and logic in the main game loop.
...but who knows what people do with them, it'll be fun finding out! π
UI Window improvements
Window Anchoring
window-achoring.mov
Window's now have two positioning modes:
- You can give them a fixed position as you always could before.
- You can now tell a window to anchor somewhere on the page, using exactly the same
AnchorandPaddingdata types that components use.
The use case for anchoring is that, for example, you want a pause menu to appear in the center of the screen, or a menu to be fixed in the top right corner - with some padding to keep it away from the edges, naturally.
Windows can decide whether they are active or not
Sometimes you need a window to disable itself. Using the pause menu as an example again, when the game is paused you want the rest of the UI to decide that it is disabled temporarily. Or perhaps you're dragging something around on the screen and don't want to interactive with menu's until you drop it, again, the window can determine if it should be enabled or disabled based on the game state.
You can now achieve this using the 'activeCheck' in a window definition.
Physics improvements
Below is a brief summary of Physics improvements. These were either in service of Actors and Performers, or are paving the way to a more substantial reworking of the physics code that keeps-threatening-but-never-quite-makes-it to the top of my list of things to do.
- World bounds are now optional - You no longer need to say how big the simulation is although it is more efficient if you can.
- Added a
Worldcollectmethod - so that you can return / look up a partial set of colliders - Added a
WorldmodifyAllmethod - so that you can update all or a sub-set of colliders based on the game model. E.g., telling a hoard of zombies to move towards the player. - Added a
WorldremoveAllByTagto remove a batch of colliders by tag - Added a
WorldwithSimulatationSettingshelper method - Colliders can now report velocityDirectionAngle - Handy if you want to know which way they're travelling, say, to make a spaceship point in the right direction.
- Physics code reorganised ahead of future work - big plans, big plans...
Layer rendering performance
Layers are useful things that have a dreadful impact on game / rendering performance. Without a serious rethink of the rendering pipeline, this remains the case.
Layer rendering performance has come to be a real problem since the release of the UI framework, which uses prodigious numbers of layers to lay everything out.
However, a change has been done so that the engine will now attempt to render (far) fewer layers without changing the expected output, via a process of 'layer compacting'. Simple put, if two layers are sufficiently similar, they get squashed. Top level layers, where you might find a layer key, are unaffected.
In the case of UI layouts at least, this produces a vast performance improvement.
Plugins
The IndigoOptions type has had a few new helpers added to it, which I hope are self explanatory:
openDeveloperToolsmodifyGameMetadatamodifyElectronOptions
Other notable changes
Viewport information in the frame context
I love this change, I just wish I'd thought of it before. If you want to know how big the screen is, it's now right there in the frame context. No need to listed to ViewportResize events if you don't want to! There is also a reference to the globally configured magnification setting too.
Radians, better wrap + centeredWrap functions
wrap now works better and more efficiently in the range (0, 2 * PI], and the new centeredWrap produces a range (-PI, PI].
Batch
Added a dropWhile function. πͺ
FPSCounter
FPSCounter can now be placed dynamically based on the Context, this is thanks to the viewpoint info being in the frame context.
Generated notes:
What's Changed
v0.20.0
This is mostly a bug fix and minor feature enhancements release, many thanks to the contributors! Full details at the end.
Waypoints
The most substantial enhancement is the addition of Waypoints, which allow you to tell screen elements to follow a set path over time. This feature has also been set up to work with timeline animations.
@JPonte added a hilarious demo of the waypoint functionality to the internal sandbox. Glorious. π
Mill users, take note
The only real noticeable breaking change in this release is the way Mill projects are set up. The change is there to make the imports easier to work with, avoiding collisions. Please convert this:
import $ivy.`io.indigoengine::mill-indigo:0.20.0`, millindigo._
import indigoplugin._To this:
import $ivy.`io.indigoengine::mill-indigo:0.20.0`, indigoplugin._What's Changed
- Update sbt, scripted-plugin to 1.10.11 by @scala-steward in #866
- 864: Introduce a CloseFocused WindowEvent by @ivan-tatsenko-cci in #873
- 863: Add constructor from SceneContext to UIContext by @ivan-tatsenko-cci in #872
- fontgen: Split characters into batches to avoid "method too large" errors by @exoego in #881
- Add option to open electron devtool by @exoego in #879
- Refactor use of Map.put for perf and clarity by @exoego in #878
- Add WaypointPath trait by @JPonte in #865
- Fixed #874: Dragging a window does not focus it by @davesmith00000 in #886
- Fixed #857: UIContext ignores snapgrid after construction by @davesmith00000 in #885
- Fixed #870: Allow context startup data type to be changed by @davesmith00000 in #884
- Fixed #882: Removed Mill import collisions by @davesmith00000 in #883
- Fixed #858: Allow asset renaming during generation by @davesmith00000 in #887
- Add PlaybackPolicy option to PlaySound by @exoego in #877
New Contributors
- @ivan-tatsenko-cci made their first contribution in #873
Full Changelog: v0.19.0...v0.20.0
v0.19.0
The UI Framework is Dead, Long live the UI Framework!
The previous release, 0.18.0, introduced a new UI framework / system to Indigo. It had taken most of last year to get working, and honestly it was a long hard road to reach a point where it looking kinda-plausibly-shippable.
Unfortunately, the new UI framework did not survive first contact with the real world, and major issues quickly became apparent with the design. The root cause of this was that the UI system had been originally designed as part of the Roguelike-Starterkit, and while it worked great in that context, the design wasn't flexible enough for other types of graphical layout.
However, many of the issues have now been resolved, and a set of UI examples can be found with working code and live demos, in the docs.
A bonfire of 'nice ideas'
This release also removes a number of features that seemed ok but had serious flaws.
TextBox has been removed
TextBox was a stinker. The idea was to provide a way to quickly put text on the screen without too much ceremony for the purposes of debugging and temporary graphics. Also at the time, we had no mechanism by which to include arbitrary fonts in games. Textbox hit the brief, but came with hidden costs:
- Ugly rendering with no way to make it better. This was because under the covers it was using Canvas API, and that has no way to disable anti-alising.
- Performance. Textbox was very, very slow. It was ok for the occasional text instance but using it for a lot of labels was a framerate killer. This was because it required a lot of side effecting calls to canvas api, and they were not quick.
- Not a portable solution. There is a dream, one day, of running Indigo outside the browser (JVM or native) and text box was wholly incompatible with that notion!
- Engine complexity. To make text box work require a lot of hacky processes in the engine, and removing it goes some way towards making the rendering pipeline more sensible.
Depth has been removed
The whole notion of 'Depth' has been removed, but this is not such a big deal as it might seem.
Depth in indigo was weird and caused people a lot of problems, because how it worked and how it behaved along side other depth control mechanisms really wasn't clear. Additionally, the engine had to sort the whole scene on every frame just in case you were using depth.
Depth now is simply 'the order in which you present elements'. So if you want to sort your on-screen elements for some reason, you just have to do it yourself! ...which in the grad scheme of things a) isn't difficult, b) is much more efficient and c) is easier to reason about.
Old UI components have been removed
Now that we have a new UI system in place ...one that works... the old standalone components were just causing confusion, and have been removed.
Better Font generators
Finally I wanted to mention that the Font embedding / generators have been improved. Since we no longer have TextBox, using Text is now the only way to get text into your games, and the font embedding needed some improvement.
A working text example with a live demo can be found in the docs.
...and more!
There were many more smaller fixes and improvements made in this release, see below!
Big thanks!
...to our contributors! Your efforts are greatly appreciated. π
What's Changed
- Added moveBoundsBy(x: Int, y: Int) and withAdditionalOffset(x: Int, y: Int) for convenience by @exoego in #823
- Added BlankEntity size modifiers by @exoego in #824
- remove unused type params by @exoego in #826
- Stabilize Batch#hashCode by @exoego in #831
- Fixed #796: Removed Depth by @davesmith00000 in #839
- Fixed #838: Deprecate the old UI Elements by @davesmith00000 in #840
- Fail build fast in windows by @mtrigueira in #835
- Fixed #836: Deprecate textbox by @davesmith00000 in #841
- Fixed #753 & #737: Make layer modification easier by @davesmith00000 in #844
- All Component functions take a full context instance by @davesmith00000 in #832
- Issue/743/generate fontsheet indexed by charcode by @davesmith00000 in #851
- Fixed #843: Allow Indigo to be elegantly halted by @davesmith00000 in #852
- Button drag released when the pointer leaves the app by @davesmith00000 in #853
New Contributors
- @mtrigueira made their first contribution in #835
Full Changelog: v0.18.0...v0.19.0
v0.18.0
Screen Capture, a new look frame context, and a UI Framework
Big thanks to everyone who has contributed to this release, it's been a long time coming!
For once, the autogenerated release notes have done a pretty good job of summarising what's happened in this release! However there are a few changes I'd like to call out in particular:
FrameContext has been replaced by Context
Breaking API change.
The FrameContext object, which stored information about the current frame and an assortment of 'helpers' was looking old and no longer fit for purpose. It also caused problems in testing because it was difficult to stub out.
FrameContext has now been recreated and restructured as Context, which is organised into ctx.frame and ctx.services. frame data is referentially transparent and side effect free, for example, the game's running time. services however are useful tools and often perform side effects to complete their tasks.
Screen capture
In the newly updated Context object, you'll find new options for performing screen capture, which is intended for functionality such as saving screenshots next to save games.
Nine-slice FillType
Along side FillType.Tile and FillType.Stretch, you can now select FillType.NineSlice which allows you to define a way to scale an image to fill an Entity keeps the corners intact and stretches the middles. Useful for windows, UI components, backgrounds, and anything else you can come up with.
Example below (the tiling designs could have been better planned out... but you get the idea.)
nineslicex3.mov
Indigo's new UI component system
This is the big change that caused the enormous delay between releases. This release includes a new component based UI system for Indigo. It's designed to be pretty generic, and Indigo does not yet ship with nice pre-made stylish components (contributions welcome!). The purpose of this system is to allow you to - with reasonable ease - make your own. It supports components, windows, scrolling, and layouts that flow and respond to their containers.
It is not perfect, but hopefully it is a foundation to build on.
The new release of the Roguelike-Starterkit, which is specifically for building ASCII style games in Indigo, does have a simple set of pre-made components built on top of the new UI system. Here are two examples from that project:
What's Changed
- Add helper functions to Radians. by @yilinwei in #758
- Add vector convenience functions. by @yilinwei in #759
- Modifies Keyboard events to use the
codeproperty by @hobnob in #772 - Screen Capturing by @hobnob in #771
- Fixes a number of Pointer related issues by @hobnob in #774 #782
- GameViewport is an opaque type by @david-lebl-adastra in #778
- Fix Gamepad handling when only one axis is present by @sherpal in #761
- Replace FrameContext with Context by @davesmith00000 in #784
- Fixed #788: Encode/derive case classes as UniformBlocks by @davesmith00000 in #789
- Fixed #787: IndigoShader, expose ability to add UniformBlocks by @davesmith00000 in #790
- Issue/455/nine slice shader by @davesmith00000 in #791
- Rename Pointer events by @exoego in #800
- Issue 801 SceneContext Refactor by @joshualeecoss in #803
- Component based UI system by @davesmith00000 in #802
- Issue/809/rectangle min max size by @davesmith00000 in #810
- Bowyer-Watson Delaunay Triangulation implementation by @davesmith00000 in #811
New Contributors
- @yilinwei made their first contribution in #758
- @david-lebl-adastra made their first contribution in #778
- @sherpal made their first contribution in #761
- @exoego made their first contribution in #800
- @joshualeecoss made their first contribution in #803
Full Changelog: v0.17.0...v0.18.0
v0.17.0
This release brings Indigo up to Scala 3.4.1 and Scala.js to 1.16.0. You will need to upgrade your projects to at least these version numbers.
As always, a big thank you to all those who contributed to this release in any capacity.
Give it a try, and please report any issues!
Notable changes
Many of these changes represent breaking changes to Indigo's APIs.
Physics iterative solver
Indigo's physics solution continues to be crude and naive, but now includes a simple iterative solver. This provides more accurate results by solving for up to a configurable maximum number of attempts per frame, or until a stable solution is found.
SubSystems have read-only access to the game model
Previously, sub-systems where kept strictly separate from the main game. They were mini-games unto themselves, and could only communicate via events. This worked well, but could be a little cumbersome.
The SubSystem definition now includes a reference method, that you must implement:
type ReferenceData
def reference(model: Model): ReferenceData = ???This allows you to extract information from your game's model that the sub-system would like access to. Access is provided in the SubSystemFrameContext under a new reference field.
This means that you no longer need to tediously pass model data to sub-systems via events, should the sub-system's logic require state information from the game in order to do it's job.
Layer improvements
Prior to this release, a SceneUpdateFragment held a Batch (a list) of layers, and those layers could be given keys (identifiers) to help you manage the order - particularly when merging scene fragments.
That approach has served us well until now ...but what if you want to dynamically create N layers and have them positioned in a known place in the tree, without interfering with something else? You could try and wrangle a pool of keys, but a much simpler solution is to allow layers to be nested.
Solving that problem creates another, because keys suddenly become difficult to manage. The solution is to move the keys out of the layer, like this:
Original:
Layer(key, ...)Now:
LayerEntry(key, Layer(...))Which for convenience, you can construct like this:
SceneUpdateFragment(
key1 -> layer1,
key2 -> layer2
)So far, all we've done is rearrange things a bit, but what about the nesting? Layer is now an ADT formed of Layer.Content which is the equivalent of the old Layer format (all the old constructors assume a content layer, to make migration/upgrading easier), and Layer.Stack, allowing you to create a tree of layers and assign it to a single key. Stacks are flattened during the rendering process, so they are a purely organisational device.
Finally, Layers (that is, content layers: Layer.Content) have gotten a little cleverer, and can now hold CloneBlanks - which could previously only be done by SceneUpdateFragments. This makes sense, as layers are all about organising elements to be rendered, and some of them will need clone blanks.
Plugin: Font generator
Another exciting improvement (prompted by @mprevel): The plugin generators have a new addition! You can now generate font sheets and FontInfo instances from font files! This makes it much, much easier to work with font's and Text instances. No doubt, there is further room for improvement, but it's a great step forward.
Example:
val options: FontOptions =
FontOptions("my font", 16, CharSet.Alphanumeric)
.withColor(RGB.Green)
.withMaxCharactersPerLine(16)
.noAntiAliasing
val files =
IndigoGenerators("com.example.test")
.embedFont("MyFont", sourceFontTTF, options, targetDir / Generators.OutputDirName / "images")
.toSourcePaths(targetDir)Generates this font sheet:
And this FontInfo code:
package com.example.test
import indigo.*
// DO NOT EDIT: Generated by Indigo.
object MyFont {
val fontKey: FontKey = FontKey("my font")
val fontInfo: FontInfo =
FontInfo(
fontKey,
151,
68,
FontChar(" ", 129, 51, 9, 17)
).isCaseSensitive
.addChars(
Batch(
FontChar("a", 0, 0, 9, 17),
FontChar("b", 9, 0, 9, 17),
FontChar("c", 18, 0, 9, 17),
FontChar("d", 27, 0, 9, 17),
FontChar("e", 36, 0, 9, 17),
FontChar("f", 45, 0, 9, 17),
FontChar("g", 54, 0, 9, 17),
...
FontChar("9", 120, 51, 9, 17),
FontChar(" ", 129, 51, 9, 17)
)
)
}Custom HTML templates
Finally, a long requested improvement (ok, mostly by @hobnob π): You can now provide your own HTML templates for your games, rather than being stuck with the defaults we generate. This mechanism isn't clever, we assume you know what you're doing!
To use this feature, you can modify your build's IndigoOptions as follows:
Default
// Set up your game options with the default template, meaning Indigo will generate the template as normal.
val indigoOptions =
IndigoOptions.defaults
.withAssets(indigoAssets)
.useDefaultTemplate // You can set this explicitly, but it is the default. Custom
// Set up your game options with a custom template
val indigoOptions =
IndigoOptions.defaults
.withAssets(indigoAssets)
.useCustomTemplate(
IndigoTemplate.Inputs(os.pwd / "test-custom-template"), // A directory containing you template files
IndigoTemplate.Outputs(
os.rel / "custom-assets-directory", // The name of the assets directory in your output directory
os.rel / "custom-scripts-directory" // The name of the assets directory in your output directory
)
)Other Improvements
*.eotadded to list of supported font typesCamera.topLeftcan take a Size param- New options to get a Camera's bounds/frustum
SceneEventFirstandLastevents addedSceneEventLoopNextandLoopPreviousevents added
Additional bug fixes
ConfigGentakes mixed case hex values (#688)- SceneFinder: Jump to index is clamped
Further generated notes:
What's Changed
- Mouse button filter was incorrect by @hobnob in #682
- Ensures fonts are auto-generated correctly by @hobnob in #686
- Physics iterations by @davesmith00000 in #694
- Updates the Mouse Wheel to allow for more than 1 axis by @hobnob in #696
- Improving camera frustum methods by @davesmith00000 in #701
- Fixed #698: mod operator for Point-like types by @davesmith00000 in #702
- Update sbt to 1.9.9 by @davesmith00000 in #700
- Fixed #707: Xbox One Controller not working on FF/Chrome by @bilki in #708
- Fixed #706: Expand/contract BoundingBox/Rectangle by Size/Vec2 by @davesmith00000 in #717
- Fixed #705: Circles and Rectangles agree on overlap by @davesmith00000 in #721
- Fixed #713: SubSystemFrame/SceneContext have toFrameContext method by @davesmith00000 in #719
- Scene event improvements by @davesmith00000 in #718
- Fixed #715: SubSystems have read-only access to the model by @davesmith00000 in #716
- Upgrade Scala.js to 1.16.0 by @davesmith00000 in #723
- Upgrade to Scala 3.4.1 by @davesmith00000 in #724
- Issue #714: Nested layers by @davesmith00000 in #727
- Fixed #709: Random basic data types by @davesmith00000 in #728
- Fixed #695: Allow custom HTML templates by @davesmith00000 in #729
- Issue #726: Adding a Font generator to the plugin by @davesmith00000 in #731
- Fixed #732: Content Layers support clone blanks by @davesmith00000 in #734
Full Changelog: v0.16.0...v0.17.0
0.16.0
Great to have a couple of contributors on this release, thank you for your help @JPonte and @mprevel, much appreciated!
As usual, this release has been driven by using Indigo, finding problems, and fixing them.
Noteworthy changes
Scala.js 1.15.0
All newly release Purple Kingdom Games libs are now on Scala.js 1.15.0, and Indigo is no exception.
Electron Executable option is now working properly
This was a tiny fix that is worth it's weight in gold. By default, when you use the indigoRun command to run your game via Electron, your build will install the latest version via NPM and then run. This works ok, and gives you the latest and greatest Electron version with almost no effort on your part.
The only problem is that NPM will try to check the install is up to date on every single run, slowing down development.
What you can now do instead, is install Electron by some other means, e.g. yarn add --dev electron, and then add the following line to your build's IndigoOptions:
.useElectronExecutable("npx electron")This does the local install manually just once, and then just reuses it with no installation checks, resulting in much faster game start times.
Polygon shader fixed!
During the original port to Ultraviolet, a mistake was made in the polygon shader translation from GLSL to Scala 3. This has now been corrected by @JPonte.
Tyrian / Indigo bridge
The Tyrian / Indigo bridge is a module that allows Tyrian web apps to communicate with embedded Indigo games.
The release of Tyrian 0.9.0 removed the tyrian/indigo bridge module in order the correct the library dependency order.
This module is now published with Indigo, and so follows Indigo version scheme, i.e. it has jumped from 0.8.0 to 0.16.0.
Improved PathFinder
This is the first release of a new A* PathFinder by @mprevel. It is both more flexible and more correct than previous attempts!
Please note that the old, suspect SearchGrid implementation has now been marked as deprecated, and will likely be removed soon.
Improved Physics Scene Scaling
Indigo includes a rudimentary physics engine that is squarely aimed at pixel art games and nothing more. It uses discrete rather than continuous simulation, and so suffers from issues like tunnelling (to be addressed in future updates), but nonetheless is good fun and quite helpful.
Previous versions did not scale well as the simulation had no 'broad phase' to cull unnecessary collision comparisons. This has now been fixed, allowing for much larger simulations.
Adding this new phase has required some changes to the API:
- Worlds are now bounded, i.e. you will need to provide a
BoundingBoxcovering the simulation area. - You must also supply a
SimulationSettingsinstance as part of the world set up, that gives clues about the size and density of the simulation.
Physics: Transient colliders are static
Another change is that transient colliders (colliders that only exist in this frame and are not officially part of the world instance, typically user controller) are now treated as static in all cases, and you no longer need to set them as such.
Physics: Collider Terminal Velocity
You can now set a terminal velocity on your colliders. This gives you much better control over how your game's play, and helps reduce the possibility of tunnelling.
Bresenham's line algorithm
Bresenham's line algorithm is a useful tool for working out a line across a grid with no overlapping squares. Super handy for drawing pixel art lines or lines of sight across a grid.
There is now an implementation of the algorithm in the Indigo extras library, that was ported from the Roguelike-Starterkit:
indigoextras.utils.Bresenham.line(from, to)QuadTree overhaul
QuadTree's are data structures used to store spatial data so that it can be quickly queried. QuadTree's are now the underlying data structure used to allow the physics engine to scale.
There has been a "QuadTree" implementation bundled with Indigo in the extras package for many years now. It was based on work done in Indigo's core that handles the texture atlases. Unfortunately, borne out of that very specific use case, it wasn't a true QuadTree, and could only handle data associated with vertices, and then only one entry per leaf, leading to some interesting design choices. What it ended up being used for, in a number of places, was actually not a query-able tree at all, but a sort of sparse data look up for grids.
The QuadTree implementation has now been totally re-worked to meet the physics use case, and can now support data stored against all of the standard spatial types, i.e. Point, Rectangle, Circle, BoundingBox, BoundingCircle, LineSegment, and Vertex, or any custom type with a SpatialOps instance. The implementation is also much more robust, and can store many entries at the leaf level. How many entries and how deep the tree should go is specified by you.
All this change has resulted in a substantial API rethink and the behaviour is now significantly different. QuadTree's are also now part of the main Indigo library, not the extras package.
SparseGrid
The use case that the old QuadTree's was fulfilling as a sparse data grid was a real need, and since QuadTree's can no longer meet that requirement, a new data type has been made, cunningly named: SparseGrid!
SparseGrid is a straight-up grid data structure, that provides a nice API for managing the data in that grid.
Minor bug fixes and improvements
- BoundingBox.resizeBy now takes
Doubles instead ofInts - Fixed #658: Large box
overlapof small circle check - Vector2/3/4 all now have a clamp operation that takes the same type, i.e. you can clamp a Vector2 with another Vector2.
Generated notes below
What's Changed
- minor improvements by @mprevel in #645
- Fix Polygon shader by @JPonte in #654
- Update sbt to 1.9.8 by @davesmith00000 in #655
- Issue #656: Move Tyrian Bridge to Indigo repo by @davesmith00000 in #657
- Fixed #658: Large box overlap small circle check by @davesmith00000 in #664
- Add pathfinder by @mprevel in #648
- Physics engine: Improved scaling performance by @davesmith00000 in #666
- Fixed #671: Bresenham's line algorithm port by @davesmith00000 in #673
- Fixed #672: Added SparseGrid datatype by @davesmith00000 in #674
- Fixed #647: Entry points use defs not vals by @davesmith00000 in #675
- Physics: Terminal Velocity by @davesmith00000 in #679
New Contributors
Full Changelog: v0.15.2...v0.16.0
0.15.2
Many small fixes...
Bug fixes
lastOptionnow works correctly onBatchwhether the underlying structure was aBatch.Combine.- Support multiple newlines in
Text(and thereforeInputField) instances. - Plugin: Use of period (
.) in a cell does not throw a number exception. - Plugin: Negative
Ints andDoubles are correctly recognised. - Plugin: Generators can handle trailing quotes.
Camera.LookAtbehaves correctly with different levels / combinations or global + layer magnification.Camera.LookAtdoes no produce gaps betweenCloneTilesdue to rounding errors.
General Improvements
Textcan now have it's letter space and line height set.Rectangle.toCircledeprecated - Disambiguation of whether the circle is inside or outside the rectangle. UsetoIncircleortoCircumcircleinstead.RectangleandBoundingBoxnow haveresizeBymethods for relative sizing.- Canvas name is now simply the parent ID plus a
-canvassuffix, to make CSS work easier by removing the square brackets. - Friendly mouse event extractors - the mouse event extractors now only extracts the common case of the position field (e.g.
case MouseEvent.onClick(position) => ???) instead of all 8-10 fields, and all other properties need to be accessed from a reference to the event. LineSegmentfromandtoaliases are provided forstartandend.SceneUpdateFragmentnow has awithLayersmethod to replace the existing layers with another set.SceneUpdateFragmentnow has amapLayersmethod, for example if you want to set the magnification on all layers.- Added an alias to
QuickCacheundermutable.QuickCache.QuickCacheis a handy type if you need to avoid recalculating values, but it's been hidden under themutablepackage as a warning to tread carefully. Batch: Addedlastoperation.Batch: AddeddistintanddistinctByoperations.Batch: AddedpadTooperation.
Plugin Improvements
IndigoOptionsnow supports antialiasing flag, defaults to false.- Generators:
embedTextnow supports apresentfunction simply of typeString => Stringthat allows you to transform any arbitrary file contents into Scala code, to be included as a source file in your game. - Generators: Trailing delimiters are supported.
- Generators: Empty cells are seen as
nullvalues (the wordnullis assumed to be a string!). - Generators: Columns containing
nullvalues are typed as optional.
Full Changelog: v0.15.1...v0.15.2
0.15.1
Bug fix release
Indigo 0.15.0 included the biggest changes to the Indigo plugins, more or less since they were created, and with that... a couple of bugs, too.
Issue with fullLinkJS in sbt
At the point when Scala.js switched naming from fullOpt to fullLinkJS and fastOptJS to fastLinkJS, the output files and paths were changed, and work was done to support both the old and new arrangements in sbt and Mill. Unfortunately an issue has crept in with fullLinkJS's output file not be found correctly. This has now been resolved.
Mill Indigo Plugin Generators were inadequate...
Before any release, Indigo goes through quite a lot of testing, but not enough on this occasion. After the release of 0.15.0, two issues quickly became apparent with how the new generators worked with Mill, specifically.
mill clean <module>was not removing generated classes. This wasn't noticed because during plugin development, a lot of "hard cleaning" (i.e. removing the out directory) happens to be sure of what has been loaded, and in that scenario,mill cleanhas no work to do.- Working with generators on multi-module builds was terrible, because unlike the sbt version, all the generated files were being written to a common shared output folder, instead of a folder that was part of each module's build.
The fix for both was to make generators adhere to Mill's T.dest, which is obvious in hindsight... oh well...
Reformulating the plugin's a little to make this work properly now requires the following changes (taken from real examples):
Mill
Before:
val indigoGenerators: IndigoGenerators =
IndigoGenerators
.mill("snake.generated")
.listAssets("Assets", indigoOptions.assets)
.generateConfig("SnakeConfig", indigoOptions)After:
val indigoGenerators: IndigoGenerators =
IndigoGenerators("snake.generated")
.listAssets("Assets", indigoOptions.assets)
.generateConfig("SnakeConfig", indigoOptions)
sbt
Before:
IndigoGenerators
.sbt((Compile / sourceManaged).value, "pirate.generated")
.listAssets("Assets", pirateOptions.assets)
.generateConfig("Config", pirateOptions)
.embedAseprite("CaptainAnim", baseDirectory.value / "assets" / "captain" / "Captain Clown Nose Data.json")
.toSourceFiles
.toSetAfter:
IndigoGenerators("pirate.generated")
.listAssets("Assets", pirateOptions.assets)
.generateConfig("Config", pirateOptions)
.embedAseprite("CaptainAnim", baseDirectory.value / "assets" / "captain" / "Captain Clown Nose Data.json")
.toSourceFiles((Compile / sourceManaged).value)
.toSet



