Skip to main content


  • The forums have now switched to ElkArte, an SMF fork which is more modern and maintained better!

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

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.
:pig_nose: *MUNCH*

This is a placeholder topic for the eventual Sphere 2.0.  I've decided to maintain minisphere for a while longer as a backward-compatible engine, and have forked the project for the purposes of the 2.0 overhaul.  The GitHub repository is here:

edit: Removed Sphere 2.0 repository for now (I still have the code saved locally), need to get minisphere 3.1 work out of the way first so that the new engine can be based on that instead of 3.0.8.  Too many merge conflicts to deal with trying to keep the two engines in sync right now.
Sphere General / Galileo improvements
So I took a second look at the Galileo API (I pretty much haven't touched it since implementing it in one of the 1.x versions), and noticed there were a lot of warts to it that made it awkward to use or too rigid.  I came up with what I think is a more robust and usable design which will debut in minisphere 3.1.

The new API supports a transformation matrix per-Group, coordinates in 3D space (XYZ) as well as the ability to set uniforms for a Group's shader.  Here's the API documentation for what's in the git repo now:

In theory it should also be possible to do basic 3D rendering by using a projection matrix, but I haven't tested that yet.  In any case it's not that far away from the original design as stolen from TurboSphere ;), but is much more flexible.
I started playing with shaders in earnest a few days ago, and I find that they're actually pretty nifty, so I'm working on improving the shader API in minisphere 3.1.  But I'm having issues understanding how OpenGL handles them, particularly this issue below:

It seems the GL API only allows you to set uniforms on the active shader program set by glUseProgram(), so could someone familiar with GL tell me (FJ maybe?), are the values you set for uniforms lost when you change programs, or are they in fact saved as part of the state of the shader program itself?  I can't find anything about this in the OpenGL docs.

The reason I ask is that I'm trying to figure out the best way to set up the shader API for minisphere 3.1, and whether it makes more sense to have the uniform setting methods on the Group object vs. the ShaderProgram itself.  I'm leaning towards the former but if OpenGL only tracks uniforms for the active shader, that requires me to cache the values.