Skip to main content

News

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

31
To go along with the upcoming minisphere 2.0, I started work on a new Sphere compiler, which I've named Cell.

Alll the issues in the past with game.sgm contents being overwritten by various editors?  Well, that's solved handily with Cell.  With a script like this, called cell.js in your game source directory:
Code: (javascript) [Select]
function make()
{
game({
name: "Spectacles: Bruce's Story",
author: "Fat Cerberus",
description: "Follow Scott Starcross in his quest to stop the Primus.",
resolution: "320x240",
script: "main.js"
});
}


You run cell on the command-line and get this output:
Code: [Select]
$ cell
Cell 2.0.0  (c) 2015 Fat Cerberus
One minute left! There's nothing you can do now... ha ha ha ha!

Processing target 'make'
Success!


Since the build script is JS, it potentially has a lot of power, as long as the bindings are there.  Besides the basic stuff like copying files, there could be functions to, e.g. generate an RSS spriteset from a set of images, or perhaps if there's a vector-based map format in the future it could be converted into a Sphere-compatible RMP by a Cell script.  The possibilities are, quite literally, endless.

The idea for this came about due to Radnen's idea for a scriptable build pipeline in Sphere Studio.  I actually started implementing that (the initial effort can be seen in the Studio build included with minisphere 1.7.11), then realized it would be very useful to have this kind of functionality universally, accessible from the command-line as well as in the GUI.

What do you guys think of this development?
32
Programming / C# await/async: This is great
So I recently discovered async/await in C#:
https://msdn.microsoft.com/en-us/library/vstudio/Hh191443%28v=VS.110%29.aspx

async is a modifier specifying a function which runs in a separate thread, and you use the await operator to pause execution of that method until the called method returns.  It's basically like what a Promise is in JS, but better integrated because it's part of the language.  C# is awesome.
33
Off-Topic Discussions / Atomic Game Engine
So, it turns out we're not the only ones with a JavaScript-based game engine:
http://atomicgameengine.com/

And it uses Duktape!
34
Sphere General / Future of Sphere: Sphere Debugger
Very recently, I learned that Duktape has full built-in support to act as a debug server.  This means it would be entirely feasible to implement a Sphere debugger right now.

Duktape's debug API and protocol are full-featured, with single-step, step-over, etc., the ability to evaluate arbitrary code in the current scope, view and modify variables, and more.  My question is, would anyone other than me be interested in this?
35
So this is an idea prompted by NEO's earlier posting of his YM2612 emulator.  I realized that using it required some lower-level way to access the audio hardware than Sphere currently provides, so I came up with this idea.  I call this new API "Audial".

With Audial, you create Streams and Mixers instead of Sound objects.  The Stream is fed with audio data and played by way of a Mixer object.

I haven't implemented anything for this yet in minisphere, but my basic idea is something like this:
Code: (javascript) [Select]
var mixer = new Mixer(2, 44100, 16);  // stereo, 44.1kHz 16-bit
var stream = new Stream(2, 44100, 16);
// maybe do some pre-buffering...
stream.play();

// in update script...
// get the audio data into a buffer/bytearray somehow
stream.feed(buffer);
mixer.update();  // or maybe the engine can even do this?

36
Sphere General / What exactly is a Complex?
This is the one set of legacy APIs I didn't implement in minisphere, the Complex primitive.  Mainly because I'm not sure what it is, exactly!  Best I can tell from the documentation, it renders a circle inscribed inside a rectangle, but then I read more and it seems more complicated than that.  Either way it hasn't been a big loss as I haven't run into a game that uses it yet, but I'm still curious what purpose it serves.
37
Engine Development / Sphere 2.0 API: SphereFS
This is a rough draft of the SphereFS standard I'm working on.  It is designed to be backwards compatible with the Sphere 1.x sandbox but with much more flexibility while abstracting away whether the game is running locally or from a package, whatever.

Sphere 2.0: SphereFS
optional extensions:

  • sphere_fs_absolute_path

  • sphere_fs_system_alias



SphereFS is a standard for sandboxing the file system exposed to a Sphere game, part of the Sphere 2.0 initiative ("Pegasus").

• The standard path separator is the forward slash (/).

• Unprefixed paths are relative and cannot subvert the sandbox.  Attempts to move upwards (via "../") past the directory containing game.sgm will fail and throw a sandbox violation error.

• Several built-in aliases are available for paths which may vary depending on the platform, engine installation location, etc.  Available aliases:

@/... (or bare relative path)
Specifies a path relative to the location of game.sgm on the running game's file system (either SPK or physical).  Not writable.

#/..
Specifies a path relative to the engine's System Asset Collection (SAC). Not writable.  The engine should declare the sphere_fs_system_alias extension if it supports this.

~/...
Specifies a path relative to the current user's save data directory.  This is the recommended location for storing game save data and is guaranteed to be writable (barring OS misconfiguration).  ~/ refers to the same location for all games, allowing save data to be shared between sequels, for example.

<Absolute Path>
A SphereFS implemention may allow absolute paths only if it declares the extension sphere_fs_absolute_path.
38
I gave the Pegasus repo another lookover this morning and I have to say, I'm not liking what I see.  It's woefully incomplete, but that doesn't bother me--there's enough there that I could take some liberties to fill in the blanks.  What does bother me is how much of it completely breaks compatibility with Sphere 1.x.  I get that it's supposed to be this revolutionary re-imagining of the Sphere API, but... I don't know, so much of it strikes me as just change for the sake of it.

Great example: Pegasus defines ~/path to be relative to the user profile directory, so that it's guaranteed to be writable.  This is a great idea, except we've completely changed the meaning of the escape.  In Sphere, this same escape means "relative to game.sgm".  There's no easy way to reconcile the discrepancy in the same engine--you either have one or the other.

Long story short: I advocate we start over with Sphere 2.0 and set it up in such a way that the legacy API and the new one are not mutually exclusive.
39
Engine Development / Sphere path escapes
In Sphere, ~/... is a path which is relative to the game directory.  TurboSphere adds #~/... for the system directory.  Are there any other escapes I should know about?  I will add them to minisphere for the 1.1 release. :)
40
This is the main component that's missing from minisphere for full parity.  Well, that and ColorMatrixes, but I've yet to encounter a game that uses them.

MNG should be easy, I'd just need libmng I think.  But what of the other formats, like FLIC?  Or is it even worth supporting those...?
41
Libraries / minipact 1.1b4
So what started as a strict polyfill for ES6 Promise became this:

[gist=422d45812b6f402360d9][/gist]

See, as defined by spec, a Promise can only be fulfilled or rejected by the code inside of it.  This makes them very difficult to use for their intended purpose of asynchronous fulfillment.  Basically you end up having to juggle two things for every single promise--the promise itself, and the callback it registers with to resolve itself.  How did I fix it?  By extending the metaphor, of course!  Now instead of just Promises...

Code: (javascript) [Select]
var pact = new mini.Pact();
var promise = pact.makePromise();
// now you give out the promise, and then later on...
pact.resolve(promise, value);


You also have Pacts!  A given Pact can only resolve promises made from it, so you can't pull dirty tricks of making up a pact to fulfill promises on others' behalf--or if you were feeling particularly nasty, rejecting them(!). That would be VERY VERY bad! :P  Attempting to do so will throw a TypeError.
42
Off-Topic Discussions / ES6: Promises
Just found out about these.  Promises are neat, if somewhat difficult to wrap your mind around at first.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

You create a Promise, which registers a callback or three to resolve the promise at the appropriate time.  When the promise is eventually resolved, the function passed to .then() is called.  Essentially it's a glorified one-off delegate, nothing too impressive.  But unlike traditional delegates, you can chain .then() clauses.  This allows you to write asynchronous code that reads like a normal sequential operation.  And unlike delegates, there's no chance of a race condition: if the operation happens to complete before a handler can be attached, the call will be deferred until one is.

Oh, and I've already written a polyfill for it. :)

43
Engine Development / Scene graphs
So I was reading about scene graphs on Wikipedia, and the concept intrigued me.  It's kind of like what Galileo is supposed to be, but at a more general level.  You create various entities as nodes, and then the nodes can be "attached" to one another in any arbitrary arrangement (hence "graph" and not, say "tree").

The example in the Wikipedia article is that you might have a knight and a horse; the knight is attached to the horse so that when the horse moves, the knight does too.  But the awesome part is that this relationship is not rigid: you can detach nodes and reattach them elsewhere any time you wish (say, when the knight dismounts, he's detached from the horse).  This has the potential to be very powerful, and I'm really considering implementing something like this in minisphere.

Is anything like this in the current Pegasus specification?  If not, it's definitely something worth considering as a standard feature. :)
44
There used to be a script that would dynamically change the layer of persons on a map to make them render in front of or behind objects depending on where they are in relation to it.  I wanted to try it out in minisphere as a test case for map engine compatibility, but I don't remember the name of it and nothing like that appears to be in the Downloads repo.  I originally thought it was Lithonite, but that turned out to be something different and WAY more advanced. :)  Anyone know the script I'm talking about?
45
So, I use the Sphere source as reference material in order to keep minisphere's compatibility as high as possible, and I found this gem in the map loading logic:

Code: (cpp) [Select]
inline std::string ReadMapString(IFile* file)
{
    std::string s;
    word length = ReadMapWord(file);

    for (int i = 0; i < length; i++)
    {
        char c;
        file->Read(&c, 1);
        s += c;
    }
    return s;
}


It's the function that reads lstrings from an RMP map file.  Note that it reads the string one character at a time. :o

Sorry for the spam, just found this amusing and had to share it!

edit - changed code tag to syntax highlight +neo