Skip to main content


Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Fat Cerberus

Programming / So I wrote a monad tutorial...
I recently learned what monads are, and predictably, had just as much trouble "getting it" as everyone else.  But they're not actually cursed; it's an extremely simple concept, it's just that everyone either 1) Tries to explain the mathematical background, which is not necessary (You don't need to know anything about set theory to add two numbers!), 2) Uses a bunch of Haskell code which is gibberish to imperative/OOP programmers, or 3) Starts with a box metaphor, which is just in medias res non-sequitur: you have to explain why the boxes are there first!

Long story short, I'm pretty sure I can break the curse.  Here's my monad tutorial:
Projects / OFF: Puppetmaster
OFF is a surreal game originally released in 2008 and developed in RPG Maker:

In OFF you play as The Batter, who is on a sacred mission to purify the world of specters, malevolent ghosts which are haunting the populace for unknown reasons.  But all may not be as it seems, and the game will soon make you question your own role in all of this...

The way the game's narrative treats the fourth wall is pretty unique even among games exploring similar concepts.  I played it recently and fell in love with it, but RPG Maker 2003 is quite an old engine and doesn't run so well on modern systems, so I've decided to try porting the game to Sphere, both to keep a great game alive and as a showcase of what our modern engine can do.  I'm not really an artist so my game projects tend to go nowhere, but doing a port like this means I can use the pre-existing assets and focus on what I am good at, which is JavaScript coding.

The original author of OFF is very accepting of fan works, having deliberately left a lot of things in the game open to interpretation, so I don't think there will be a problem with a project like this in that regard, but I'll be sure to try to get formal permission if anything becomes of this.

I'm not sure yet if I want to recreate the RPG Maker-style turn-based battle system or try for something more unique, like what's seen in Spectacles.  The original game's combat was honestly pretty tedious and boring (not to mention easy), so it'd be nice to spice things up for a remake.

Screenshots of the title screen are attached.
Projects / mp3 SoundStream demo: mp3 playback in JS!
This is a demonstration of playing an mp3 file completely in script.  Decoding is done directly in JavaScript without any help from the engine, using the Aurora.js library.  Playback is facilitated by a Sphere v2 SoundStream object.  miniSphere 5.0b2+ is recommended; while the demo will work in 4.8.8, the audio might stutter due to Duktape not really being up to the task.

Update 2017-09-22: Updated for API changes in miniSphere 5.0b2/4.8.8
Update 2017-09-17: Added a cool visualization effect.

Get the demo:
Sphere General / What is SFXR?
While reviewing the Sphere 1.x docs I came across a bunch of sound-related functions with "SFXR" in their names.  What are these functions for?  Some sort of DSP filter system?
Game Development / RPG battle system balancing
So I had an insight the other day while struggling to balance the damage output in Spectacles.  For a while I'd been trying to balance things by changing multipliers, but no matter what I did, making one battle fair negatively impacted battles at other points in the story.  Then I realized: In a modern JRPG battle engine, input variables are normally multiplied in some fashion, not added.  Thus, the most important thing for balance is the number of variables in the formula, not the specific factors used.

It turned out that I had a fundamental imbalance due to a mismatch in the number of variables between the Max HP and damage formulas.  Max HP is a linear progression:
Code: (javascript) [Select]

// note: statAverage is weighted, heavily favoring VIT
25 * tier * statAverage

All storyline bosses save for the final boss are defined as Tier 3, so that over the course of the game boss HP rises linearly, directly proportional to the stat average.  Damage on the other hand is calculated as:
Code: (javascript) [Select]

2.5 * pow * weapon * str / def

str / def, being on the same scale, cancel either other out on average.  So for this purpose we can treat the damage formula as having two variables: move power and weapon power.  Therefore, over the course of the game the damage increase is quadratic.  Depending on the factors used, that either means you do far too much damage to late-game enemies, or else not nearly enough to early ones.  In order to balance, HP also needs to be quadratic.  Without introducing a new variable in the HP formula, this can be accomplished by squaring the stat average.

Just thought I'd share this experience as it was kind of a big eureka moment for me after a long balancing struggle.  I think as amateur game developers we tend to take things like RPG battle formulas for granted, but there's actually a lot more nuance to it than it seems at first glance.
Sphere General / Cellscript for Sphere 1.x games
Here's a Cellscript that will compile most Sphere 1.x games and allow use of ES6 syntax.  Save the code below as Cellscript.mjs in the root of the game directory and enter cell from the command line.  That's it!

Code: (javascript) [Select]
 *  Cellscript for Sphere v1 Migration
 *  (c) 2017 Fat Cerberus
 *  save this as `Cellscript.mjs` in the root of your Sphere project, and you're
 *  ready to start taking advantage of everything the Sphere v2 toolchain has to
 *  offer!

import { transpile } from 'cell-runtime';

// any metadata defined here is written to game.json and is available to game
// code through `Sphere.Game`.
name: "Game Title",
version: 1,  // Sphere v1 compatibility
author: "Some Guy",
summary: "This game probably sucks.",
resolution: '320x240',
main: 'scripts/main.js',

// Duktape doesn't support ES2015 syntax yet so we need to transpile if we want
// access to those features.
transpile('@/scripts', files('scripts/*.js', true));

// this should cover everything needed to run the majority of Sphere v1 games.
install('@/animations',   files('animations/*.mng', true));
install('@/fonts',        files('fonts/*.rfn', true));
install('@/images',       files('images/*.bmp', true));
install('@/images',       files('images/*.jpg', true));
install('@/images',       files('images/*.png', true));
install('@/maps',         files('maps/*.rmp', true));
install('@/maps',         files('maps/*.rts', true));
install('@/sounds',       files('sounds/*.wav', true));
install('@/sounds',       files('sounds/*.ogg', true));
install('@/sounds',       files('sounds/*.mp3', true));
install('@/sounds',       files('sounds/*.flac', true));
install('@/sounds',       files('sounds/*.it', true));
install('@/sounds',       files('sounds/*.xm', true));
install('@/sounds',       files('sounds/*.s3m', true));
install('@/spritesets',   files('spritesets/*.rss', true));
install('@/windowstyles', files('windowstyles/*.rws', true));
install('@/',             files('icon.png'));
Engine Development / Sphere 1.x error behavior
In the process of assessing minisphere backwards compatibility, I found out that Sphere 1.x is quite misbehaved when certain kinds of errors occur.

If one does this in Sphere 1.5:
Code: (javascript) [Select]
try { LoadImage("nonexistent"); }
catch(e) { }

It produces an uncatchable error and terminates the engine, bypassing the try/catch entirely.  This is not really desirable behavior: I don't think I'll emulate that particular quirk. :P
Engine Development / Oozaru: Sphere for the Web
Just posting this as a placeholder for the new HTML5/JS based Sphere v2 implementation in development.  Now that Sphere v2 is getting closer to finalization, it's time to start thinking about how to implement it for the Web.

GitHub link:
Sphere General / Future of Sphere: Sphere v2 and the Web
I recently opened this GitHub issue for implementing browser-like behavior in the main engine so that we could experimment with writing Web-friendly Sphere games:

The fact is, most of what's needed already exists.  The Dispatch API, to be introduced with minisphere 4.3, is an important piece of the puzzle as it brings the ability to set update and render hooks that work engine-wide rather than just in the map engine.  However because there is it yet an engine-provided frame loop, games still need to be written in the classic way:
Code: (javascript) [Select]

while ( {

Which works well for a PC game but would never fly on the Web unless you want your game to get killed by the browser in short order for "running too long".

In fact anything that blocks is right out, for exactly the same reason.  APIs like system.sleep() need to be disabled, but more importantly, we need some sort of nonblocking I/O.  It's proven that Sphere formats can be used on the Web, but Sphere's file API (including v2) blocks.  That will need to change.

Anything else I'm missing?
Off-Topic Discussions / I just built myself a gaming PC
So basically, I got tired of keeping up with the console wars and jumped off the carousel.  I've decided to try PC gaming for a while instead.  This is my first experience with a true modern graphics card (GTX 1070), and the investment was more than worth it.


  • Silverstone RVZ02B-W (mini-ITX, this is an AWESOME case)

  • Gigabyte GA-Z170N motherboard

  • Intel Core i7-6700K @ 4GHz (no overclock)

  • EVGA GeForce GTX 1070 FTW

  • 16GB HyperX DDR4 RAM @ 2133MHz

  • SanDisk X400 1TB SSD (M.2)

  • Panasonic UJ-265 slot-loading BluRay burner

It turned out that the graphics card is nicely showcased by the window on top of the case.  I'm glad I didn't know this before installing it, or I would have been severely tempted to splurge on a GTX 1080. :P

I also have two additional 1TB Seagate HDDs for additional data storage.


Sphere General / Sphere v2 API discussion
The release of minisphere 4.0 is imminent.  This version will introduce a brand-new API, dubbed "Sphere v2".  Sphere v2 is a complete reimagining of the Sphere API and I'd like to get some input on the different aspects of it before it's finalized in minisphere 5.0, locking us into backwards compatibility.

Note that Sphere v1 functions will still be available for the foreseeable future and can be freely used side-by-side with the new API, easing some of the pain of migration for existing large Sphere codebases.

I'll post more here in the coming days, but to kickstart the discussion, here is the API documentation for Sphere v2 as it currently exists in the minisphere Git repository:
...and it was awesome.  The game is easy of course (except for the True Arena), but nobody really plays Kirby games for a challenge, it's all about the experience, which here gets almost cinematic at times--half the fun is in watching boss battles unfold as the bosses progressively change up their attack patterns throughout the fight.  And the final boss... well, it was something else, let me just say.  As someone who grew up playing Kirby Super Star it must be seen to be believed.
Sphere General / The Sphere 1.x API is enormous
I didn't realize just how many functions the API had until now.  I recently started moving all the legacy functions in minisphere into a separate file (to keep the engine and API layer separate), and, well, this is what I ended up with:

Note that doesn't even include the map engine functions!

The file currently stands at ~150KB.  The file with the Sphere 2.0 API (pegasus.c) for comparison is around 80KB.  That's a good thing I think: It will lower the learning curve for the new API if there are less functions, and the API will be more consistent because everything was designed together.  Sphere 1.x slowly evolved over time and you can tell by some of the inconsistencies in how APIs are set up.
In Sphere 1.x, the effect of SetClippingRectangle() persists across FlipScreen calls.  In practice this usually forces me to save and restore the clipping rectangle in order to maintain modularity.  For Sphere 2.0, I was debating making it so that screen.clip() lasts only until the next flip.  How does everyone feel about that?
Sphere General / Future of Sphere: New map engine
The default Sphere map engine, even with the enhancements made to it in minisphere, is beginning to get a bit long in the tooth.  It's not object-oriented, and extending it often requires awkward hacks.

I would like to introduce a new map engine with minisphere 4.0, one coded in JavaScript from the ground up which is designed from the start to be extensible but nonetheless includes a great deal of functionality out of the box (in order not to sacrifice Sphere's biggest strength of being easy to pick up and start programming).  So I'm posting this thread to gather ideas and see what people would like to see in a map engine.