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

Arts / The Porkocalypse
one day the pigs will take over the world
over the ensuing eight months and twelve days
people will begin to mysteriously disappear
its very mysterious
nobody knows how people could just disappear off the face of the earth
never to be seen or heard from ever again
it couldnt possibly have anything to do with the eaty pigs
thats just ridiculous
who ever heard of something so stupid
pigs eating people
next youll be telling me theres a giant cow that eats cats

eventually everyone will disappear
then the pigs will be done with this planet
they will move on to the next
and all the aliens will mysteriously disappear just like the humans before them
the pigs will have nothing to do with that of course
but they will nonetheless carve a trail of eatiness throughout the galaxy
while just being generally fat and pink and eaty and piggish
and nobody will know what to do
or indeed if anything even can be done
but one thing is for sure
one day
after all the intelligent life on all the planets has mysteriously disappeared
for non-pig-related reasons because why would the pigs have anything to do with that
those pigs
they are going to eat the sun

in case it wasnt obvious by now
an enormous pig eating the sun
its kind of a problem
not so much because anyone needs the sunlight to survive
because remember everyone disappeared
which of course had nothing to do with the pigs but i digress
its more just because its a frigging sun
its extremely hot
and so eating it doesnt actually extinguish it
no matter how fat the thing was that ate it
so now theres just this huge pink star with a pig nose floating around the galaxy
eating everything
because it wasnt bad enough when it was just a giant pig eating stuff
now the pig is like
five thousand degrees
and who needs that

but all hope is not lost
which i know is hard to believe
because how do you stop an invasion of eaty pigs
especially when they are fat enough to eat the frigging sun
but you can trust me on this
i have it on good authority
you see
theres a prophecy
the pigs dont want anyone to know about it
but i do
it says
there will come a day when all the stars in all the galaxies align
when all life in the universe has been snuffed out
except for one kitty-eating cow
and on the morning of the rose-colored eclipse
it is said that the cow will stand against the pigs
the cow will lose
but not without thinning the pigs ranks
only then will the pink sun rise
and the last pig fall
into a black hole
never to be seen or heard from ever again

and so it goes
that at the end of time
when everything in existence has been eaten
but not the people or aliens because that would be stupid
because why would pigs eat people
in an ironic twist of fate
the eaty pigs themselves will be eaten
and while this victory will come at great cost
because lets be honest
nothing will survive the porkocalypse
but it turns out
it doesnt matter
because as the last pig is sucked into the singularity
being such a glutton it would eat the frigging sun
the black hole will be clogged
and as the sole surviving pig struggles in vain to get free
the star in its stomach keeping it from being crushed completely
the dead cow will float over the event horizon
only then will the pig know
its time is up
and as the cow and pig are compressed
into a tiny lavender singularity
in its final moments
the pig will be heard to say
let there be light
and there will be light

thus is it left to all intelligent life in the universe
to prepare for the porkacalypse
nobody knows the time or the hour
but its coming soon
you will know the day has come
when the largest pig ever recorded
enters the atmosphere from outer space
crash-lands on earth
shows up on your doorstep
and demands to eat all the food in your refrigerator
and as if that wasn't enough
your little dog too
now you may think you can outrun the pig before it comes
by leaving the planet now
especially since its so fat
surely it must be incredibly slow
way too slow to ever catch up with the space shuttle
but you are sorely mistaken
for you see
sixty five million years ago a meteorite wiped out the dinosaurs
most think they were killed in the blast
but thats a bunch of baloney
it turns out
all the dinosaurs were eaten into extinction
which is kind of ironic
and certainly tragic
but nonetheless necessary
so at any rate
it should be coming into focus now
nobody can ever outrun the pigs
because well
they are already here

so always remember
whenever youre feeling down
because youre afraid
and its okay to be afraid of eaty pigs
dont ever let anyone tell you it isnt
someone else might just have it worse than you
because theyre the one thats going to have to tell you
with tears in their eyes
theres a pig behind you
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 0.5.0 (Web Sphere)
Oozaru is a Web-based implementation of Sphere, coded in TypeScript and designed to work in modern browsers without plugins.  It is currently in beta, but is planned to implement the entire Sphere v2 API so that it'll be able to run any game the desktop implementation, neoSphere, can.

Like neoSphere, Oozaru's source code is hosted on GitHub and is licensed under the terms of a BSD-style license.

Oozaru 0.5.0 - January 5, 2022 - Release Notes - GitHub Repo
Works with the Oozaru Support plugin included with Sphere Studio.

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?