Skip to main content

News

Topic: neoSphere 5.10.0 (Read 1572978 times) previous topic - next topic

0 Members and 28 Guests are viewing this topic.
Re: minisphere 3.0.1
Reply #1095
Alright then. So is doing MapEngine(MAPFILE,FPS) ideal then?

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.1
Reply #1096
Ideally I would call SetFrameRate(FPS) at game startup and then call MapEngine without it.  This way if you do any FlipScreen loops, the framerate will be in sync with the map engine (minisphere automatically throttles FlipScreen for you)
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: minisphere 3.0.1
Reply #1097
Alright. I'll keep that in mind from now on.

  • DaVince
  • [*][*][*][*][*]
  • Administrator
  • Used Sphere for, like, half my life
Re: minisphere 3.0.1
Reply #1098
Pressing escape to quit the whole game while in the map engine WAS a thing in regular Sphere, but I'm honestly glad you're not including that functionality in minisphere. It was, as you said, unintuitive.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.1
Reply #1099
Huh, you're right - I'm surprised I never knew this, seems like something I would have hit by accident (and been very annoyed).  It also appears that F1 disables throttling, which might be useful for benchmarking but that's about it.  Even during development I can't see a reason to do this, other than maybe as an ad-hoc fast-forward feature--which wouldn't even work in the case of vsync or laggy sections.  Here's the relevant part of the Sphere 1.x source:

https://github.com/sphere-group/sphere/blob/master/sphere/source/engine/map_engine.cpp#L5855-L5873

I stand by minisphere not supporting it.  Reading the 1.x code, it appears to only way to override it is to call BindKey(), which a beginner might not even think to do since they'd just think it's a hardcoded "system" key.  If you need it, it's easy enough to add a check in an update script or miniRT thread. :)
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: minisphere 3.0.1
Reply #1100

I stand by minisphere not supporting it.  Reading the 1.x code, it appears to only way to override it is to call BindKey(), which a beginner might not even think to do since they'd just think it's a hardcoded "system" key.  If you need it, it's easy enough to add a check in an update script or miniRT thread. :)


Don't worry if it doesn't help support backwards compatibility. All games I've played had more proper ways of quitting the game. :P there's always ALT+F4.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1101
I found a nasty bug in the Sphere Studio debugger (F10 to Step Over didn't work and performed Step Out instead--ouch!), so I uploaded a new release.  As a bonus you also get the new FileStream methods I mentioned earlier to read and write numbers and strings.  I was going to hold that back until 3.1 (which is a ways off), but I fast-tracked that bug fix and didn't feel like moving it onto a separate branch, so now everyone gets the feature early. ;)
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1102
I'm currently working on a miniRT module which will make reading data from binary files in JS much easier, by reading data items into an object based on a JSON schema.  For example, this is a schema to read an RMP map file header:

Code: (javascript) [Select]
[
{ id: 'magic', type: 'fstring', size: 4 },
{ id: 'version', type: 'uintLE', size: 2 },
{ id: 'type', type: 'uintLE', size: 1 },
{ id: 'numLayers', type: 'uintLE', size: 1 },
{ type: 'raw', size: 1 },  // reserved
{ id: 'numEntities', type: 'uintLE', size: 2 },
{ id: 'startX', type: 'uintLE', size: 2 },
{ id: 'startY', type: 'uintLE', size: 2 },
{ id: 'startLayer', type: 'uintLE', size: 1 },
{ id: 'startDir', type: 'uintLE', size: 1 },
{ id: 'numStrings', type: 'uintLE', size: 2 },
{ id: 'numZones', type: 'uintLE', size: 2 },
{ id: 'repeating', type: 'bool' },
{ type: 'raw', size: 234 },  // reserved
{ id: 'strings', type: 'array', count: '@numStrings', subtype: { type: 'pstringLE', size: 2 } },
];


I got this idea from looking at the Turbo runtime. :)
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: minisphere 3.0.2
Reply #1103
Yes, I noticed you were running into the same problems I was with how tedious reading binary data from files is in script :)

I still think it's better to layer this on top of ArrayBuffers than to change the underlying data reading API, though. That way you only need a single native method for each type of object, and the same script methods can operate on, say, a file, a socket, or any ArrayBuffer that the developer wants to use, too.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1104
The main problem I was running into with ArrayBuffers is that there's no built-in JS facility for decoding strings from them.  DataView gives you plenty of stuff for decoding integers and floats, but nothing for strings, so you end up having to construct them character-by-character (possibly including UTF-8 decoding logic) by reading single bytes at a time.  I don't trust Duktape's performance quite enough to do this in script--plus you run into performance issues with string interning when building a string piecemeal like that--so it was easier just to put the string I/O into the engine.

Reading the Turbo code, I saw you had the same problem, and ended up falling back on CreateStringFromByteArray().  Since I consider the ByteArray stuff deprecated at this point, I didn't want to do that.

By the way, here's a schema to read an RMP file through the layer data.  Alas, I don't think I can represent the entire RMP format using a single read call unless I make the schema system Turing complete--persons and triggers have a completely different set of fields, but are both interleaved within the "entities" section.

Code: (javascript) [Select]

var segmentSchema =
[
{ id: 'x1', type: 'uintLE', size: 4 },
{ id: 'y1', type: 'uintLE', size: 4 },
{ id: 'x2', type: 'uintLE', size: 4 },
{ id: 'y2', type: 'uintLE', size: 4 },
];

var layerSchema =
[
{ id: 'width', type: 'uintLE', size: 2 },
{ id: 'height', type: 'uintLE', size: 2 },
{ id: 'flags', type: 'uintLE', size: 2 },
{ id: 'parallaxX', type: 'floatLE' },
{ id: 'parallaxY', type: 'floatLE' },
{ id: 'scrollX', type: 'floatLE' },
{ id: 'scrollY', type: 'floatLE' },
{ id: 'numSegments', type: 'uintLE', size: 4 },
{ id: 'reflective', type: 'bool' },
{ type: 'reserved', size: 3 },
{ id: 'name', type: 'pstringLE', size: 2 },
{ id: 'tilemap', type: 'array', count: '@height', subtype: { type: 'array', count: '@width', subtype: { type: 'uintLE', size: 2 } } },
{ id: 'segments', type: 'array', count: '@numSegments', subtype: { type: 'object', schema: segmentSchema } },
];

var mapSchema =
[
{ id: 'signature', type: 'fstring', size: 4, regex: "\\.rmp" },
{ id: 'version', type: 'uintLE', size: 2 },
{ id: 'type', type: 'uintLE', size: 1 },
{ id: 'numLayers', type: 'uintLE', size: 1 },
{ type: 'reserved', size: 1 },  // reserved
{ id: 'numEntities', type: 'uintLE', size: 2 },
{ id: 'startX', type: 'uintLE', size: 2 },
{ id: 'startY', type: 'uintLE', size: 2 },
{ id: 'startLayer', type: 'uintLE', size: 1 },
{ id: 'startDir', type: 'uintLE', size: 1 },
{ id: 'numStrings', type: 'uintLE', size: 2 },
{ id: 'numZones', type: 'uintLE', size: 2 },
{ id: 'repeating', type: 'bool' },
{ type: 'reserved', size: 234 },  // reserved
{ id: 'strings', type: 'array', count: '@numStrings', subtype: { type: 'pstringLE', size: 2 } },
{ id: 'layers', type: 'array', count: '@numLayers', subtype: { type: 'object', schema: layerSchema } },
];
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: minisphere 3.0.2
Reply #1105

Reading the Turbo code, I saw you had the same problem, and ended up falling back on CreateStringFromByteArray().  Since I consider the ByteArray stuff deprecated at this point, I didn't want to do that.


I did not fall back on it in that sense. There is no engine-supplied CreateStringFromByteArray in TurboSphere. It is a script function that takes any iterable object, and constructs a string using the contents as codepoints. It has the name "CreateStringFromByteArray" solely because it is compatible with that function from Sphere 1.5

Regarding the more complex schema, I decided I wanted very simple schema, and it was OK to add a little bit of format-specific branching for each reader. This was also quite important for supporting all the RSS Spriteset versions.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1106
One problem with that approach is that it doesn't handle multi-byte character sets like UTF-8 well - if you just blindly build up a JS string from individual bytes you'll end up with a different string than if you decoded it as UTF-8.  And there's the string interning issue I mentioned also.

Node.js solves all of this nicely - its Buffer object has a toString() function which actually encodes the buffer contents as a string.  ArrayBuffer.toString() just uselessly returns "[object ArrayBuffer]". :-\
  • Last Edit: April 01, 2016, 05:12:50 pm by Lord English
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: minisphere 3.0.2
Reply #1107
Well, it could handle UTF-8. I just never got around to adding that.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1108
I did it - I got miniRT to be able to load a complete RMP map file with a single read call!  See attached screenshot.  The trick was to add a simple conditional mechanism to the schema, like so:

Code: (javascript) [Select]

var entitySchema =
[
{ type: 'uintLE', size: 2, id: 'x' },
{ type: 'uintLE', size: 2, id: 'y' },
{ type: 'uintLE', size: 2, id: 'layer' },
{ type: 'uintLE', size: 2, id: 'type' },
{ type: 'reserved', size: 8 },
{ type: 'switch', field: 'type', id: 'data', cases: [
{ value: 1, type: 'object', schema: personSchema },
{ value: 2, type: 'object', schema: triggerSchema },
]},
];


...then proceeded to spend almost two hours in the JS debugger (I am *so* glad I made that thing!) trying to debug why I couldn't load the file despite all the schemas being correct and double- and triple-checking them, but FileStream.read() seemed to be reading too many bytes anyway.  Come to find out that dumb ol' me had opened the file in text mode so that whenever it encountered a CRLF pair it would convert it to LF (thus reading 2 bytes but only counting it as 1).  DOH! :-X

And yes, the Vegeta wallpaper is entirely appropriate considering how much time I spent in SSJ2. :P
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: minisphere 3.0.2
Reply #1109
New feature in the latest build: XML parsing!  I found this lightweight XML parser for JavaScript yesterday:
https://github.com/isaacs/sax-js

It was made with Node.js in mind but thanks to me implementing the CommonJS module system in minisphere, it runs just fine there too. :)  However because Node is async, the event-based streaming API the XML library exposes isn't really a good match for the Sphere architecture... so I added an easy-to-use wrapper for it as part of miniRT.  That lets you skip all the event listener setup rigamarole and just do this:

Code: (javascript) [Select]

var xml = require('miniRT/xml');
// ...fetch some XML from a file or something...
var dom = xml.parse(xmlText);


Which makes decoding XML as easy as JSON! :D

There's an ulterior motive, of course.  I eventually want to support the Tiled map editor, which uses XML as its default save format.
neoSphere 5.10.0 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub