Difference between revisions of "Developing a Sphere-compatible engine"
(API compat section, table) |
(→Complete or in-progress) |
||
(16 intermediate revisions by 3 users not shown) | |||
Line 6: | Line 6: | ||
==Introduction== | ==Introduction== | ||
− | Throughout this article, the original Sphere implementation shall be referred to as "vanilla" Sphere. | + | Throughout this article, the original Sphere implementation shall be referred to as "vanilla" Sphere and consisted of use of an older version of [https://developer.mozilla.org/en-US/docs/SpiderMonkey SpiderMonkey] as the JavaScript engine, the first-party [http://corona.sf.net Corona library] for the software implementation of video, and the first-party [http://audiere.sf.net Audiere library] for the audio driver. Input was mapped directly in software using whatever API was native to the OS in the case of the Windows and Linux versions of vanilla Sphere. The recent Mac OS X port of vanilla Sphere used SDL to handle all input and output while still using an older version of SpiderMonkey for JavaScript. |
Possible frameworks to implement Sphere: | Possible frameworks to implement Sphere: | ||
Line 33: | Line 33: | ||
==Input== | ==Input== | ||
− | + | ===SDL=== | |
+ | If you want to use SDL, it will be helpful to set up an event filter to catch application close events. Since the main function that needs proper access to events is GetKey, you can disable mouse movement, mouse button, and key-up events so that the event queue will be filled with just keydown events. This simplifies the implementation of the GetKey function, as it is the only function that needs the queue to contain a specific kind of event. Be sure to pump or poll for events whenever input is requested. This also keeps the engine responsive during calls to getkey, and tending the event queue keeps the engine responsive in general. | ||
− | === SFML === | + | Keyboard state polling (as in IsKeyPressed()) can be handled with getting the keystate and comparing keysyms. |
+ | |||
+ | ===SFML=== | ||
If you are using SFML, you need to handle the key pressed and released events. It's a good idea to use a static array for all of the keys, mouse, and joystick buttons. The array's index corresponds with a key, mouse, and joystick code with a true/false value indicating IsPressed. In order to support more than one joystick you may need to bump up that joystick array to a 2D array, where 'x' is the joystick id and 'y' is the button code. | If you are using SFML, you need to handle the key pressed and released events. It's a good idea to use a static array for all of the keys, mouse, and joystick buttons. The array's index corresponds with a key, mouse, and joystick code with a true/false value indicating IsPressed. In order to support more than one joystick you may need to bump up that joystick array to a 2D array, where 'x' is the joystick id and 'y' is the button code. | ||
− | For the key queue, just use a queue data structure. Enqueue keys on the released state, and dequeue keys with GetKey. | + | For the key queue, just use a queue data structure. Enqueue keys on the released state, and dequeue keys with [[API:GetKey|GetKey]]. |
− | === | + | ===Other input libraries=== |
+ | (TODO: list possible input handling libraries and gotchas) | ||
− | + | ===Handling keyboard input notes=== | |
+ | [[API:GetKey|GetKey]]() must be able to block the sphere engine. If the key queue is empty, go into a loop that just updates the game screen. | ||
− | + | (TODO: fill) | |
− | + | ====Key Constant Mapping==== | |
+ | In SDL, SFML, and other game libraries, key code enumerations offered in source may differ from Sphere's. In order to map keys correctly you might need to implement a very large map that is basically a "this key" = "that key" list. Such a technique is optional if you already follow Sphere's key naming conventions, but what this will do is allow other Sphere engines to use those same codes if you saved a game with key mappings from vanilla Sphere. | ||
+ | See Sphere's [[list of keycode constants]] for the official list, also at https://github.com/sphere-group/sphere/blob/v1.6/sphere/docs/development/keys.txt | ||
+ | |||
+ | ===Handling mouse input notes=== | ||
+ | (TODO) | ||
+ | |||
+ | ===Handling joystick input notes=== | ||
+ | (TODO) | ||
− | ( | + | ===Other input methods=== |
+ | (TODO) | ||
==Output== | ==Output== | ||
Line 65: | Line 79: | ||
Audio is split between sounds and music. They have the same API, but music streams intrinsically. | Audio is split between sounds and music. They have the same API, but music streams intrinsically. | ||
Volume however takes a range of 0 to 100. Treat that as a percent of the 0 to 255 range Sphere uses. You might need to cache the volume into a private variable and get set from that, making sure to set the underlying volume as a percent of whatever you used. | Volume however takes a range of 0 to 100. Treat that as a percent of the 0 to 255 range Sphere uses. You might need to cache the volume into a private variable and get set from that, making sure to set the underlying volume as a percent of whatever you used. | ||
+ | |||
+ | ==Sphere-format file loading== | ||
+ | Sphere uses five custom file formats, all containing bitmap data in some form or another: [[API:Font|bitmap fonts]], [[API:Spriteset|spritesets]], [[API:WindowStyle|stylized window frames]], [[API:Map|maps]], and [[API:Map|map tilesets]]. Some of them have metadata interspersed with the bitmap data, others have a dedicated block that contains all the metadata for the file in one section regardless of the bitmap data. Maps in particular have the option of choosing to embed its tileset within its file or to point to an external tileset file. All have fixed size headers that are trivial to read. All integer values are stored in [[wikipedia:endianness#Little-endian|Intel order/little-endian]] and unless otherwise noted all pixel values are 32-bit and stored in the order RGBA. | ||
+ | |||
+ | ===Fonts=== | ||
+ | Pretty straight forward. Version 1 Sphere fonts only allow 8-bit grayscale pixels and are deprecated in favor of version 2 fonts. Version 2 fonts use bitmaps containing full 32-bit RGBA pixels. There are reserved bytes to be aware of, otherwise no metadata. | ||
+ | |||
+ | ===Spritesets=== | ||
+ | Three separate versions with separate loading behaviors. Much more complicated than fonts, some reserved bytes, lots of metadata. (TODO: expand) | ||
+ | |||
+ | ===WindowStyles=== | ||
+ | Two versions to handle. Some reserved bytes, some deprecated properties depending on version, small amount of metadata. (TODO: expand) | ||
+ | |||
+ | ===Maps=== | ||
+ | Lots of metadata, small amount of reserved bytes, can embed tilesets or refer to external tileset files. (TODO: expand) | ||
+ | |||
+ | ===Tilesets=== | ||
+ | Lots of metadata, small amount of reserved bytes, bitmap data is in one large block after header but before metadata. (TODO: expand) | ||
+ | |||
+ | ==The map engine== | ||
+ | (TODO) | ||
+ | |||
+ | ===The MapEngine loop=== | ||
+ | (TODO) | ||
==Maintaining API compatibility== | ==Maintaining API compatibility== | ||
Line 87: | Line 125: | ||
|- | |- | ||
! scope="col"| Implementation | ! scope="col"| Implementation | ||
+ | ! scope="col"| Operating System | ||
! scope="col"| Version | ! scope="col"| Version | ||
! scope="col"| JS engine | ! scope="col"| JS engine | ||
Line 92: | Line 131: | ||
! scope="col"| Audio driver | ! scope="col"| Audio driver | ||
! scope="col"| Input handler | ! scope="col"| Input handler | ||
− | |||
|- | |- | ||
− | |vanilla Sphere | + | |vanilla Sphere<br/>[https://github.com/sphere-group/sphere source], [http://forums.spheredev.org/index.php/topic,155.0.html thread] |
+ | |Win x86, OSX, Linux x86 | ||
|stable: 1.5<br/>unstable: 1.6 beta 4<br/>inactive: 1.7 alpha | |stable: 1.5<br/>unstable: 1.6 beta 4<br/>inactive: 1.7 alpha | ||
|[https://developer.mozilla.org/en-US/docs/SpiderMonkey SpiderMonkey] | |[https://developer.mozilla.org/en-US/docs/SpiderMonkey SpiderMonkey] | ||
Line 100: | Line 139: | ||
|configurable | |configurable | ||
|configurable | |configurable | ||
− | |||
|- | |- | ||
− | |TurboSphere | + | |TurboSphere<br/>[https://github.com/FlyingJester/TurboSphere source], [http://forums.spheredev.org/index.php/topic,13.0.html thread] |
− | |0. | + | |Win x86/64, OSX, Linux x86/64, Solaris 10 amd64 |
+ | |0.4.0 | ||
|[https://code.google.com/p/v8/ V8] | |[https://code.google.com/p/v8/ V8] | ||
+ | |OpenGL via SDL2 | ||
+ | |BASS | ||
|SDL2 | |SDL2 | ||
− | |||
− | |||
− | |||
|- | |- | ||
− | |unnamed Sphere clone in SDL | + | |unnamed Sphere clone in SDL<br/>[https://github.com/postcasio/sphereclone source], [http://forums.spheredev.org/index.php/topic,72.0.html thread] |
+ | |? | ||
|? | |? | ||
|[https://code.google.com/p/v8/ V8] | |[https://code.google.com/p/v8/ V8] | ||
Line 116: | Line 155: | ||
|SDL | |SDL | ||
|SDL | |SDL | ||
− | |||
|- | |- | ||
− | |sphere-sfml | + | |sphere-sfml<br/>[https://github.com/Radnen/sphere-sfml source], [http://forums.spheredev.org/index.php/topic,137.0.html thread] |
− | |? | + | |Win x86, OSX(?) |
+ | |0.65 alpha | ||
|[http://jurassic.codeplex.com/ Jurassic] | |[http://jurassic.codeplex.com/ Jurassic] | ||
− | |OpenGL via SFML | + | |OpenGL via SFML 2 |
− | |libsndfile via SFML | + | |libsndfile via SFML 2 |
− | |SFML | + | |SFML 2 |
− | |||
|- | |- | ||
− | |web-sphere | + | |web-sphere<br/>[https://github.com/sphere-group/web-sphere source], [http://forums.spheredev.org/index.php/topic,154.0.html thread] |
+ | |Chrome, Firefox, and IE9+ | ||
|[http://www.pixijs.com/ pixi.js] version: ?<br/>[http://threejs.org/ three.js] version: ? | |[http://www.pixijs.com/ pixi.js] version: ?<br/>[http://threejs.org/ three.js] version: ? | ||
|browser via pixi.js, three.js | |browser via pixi.js, three.js | ||
Line 132: | Line 171: | ||
|browser via pixi.js, three.js | |browser via pixi.js, three.js | ||
|browser via pixi.js, three.js | |browser via pixi.js, three.js | ||
− | |||
|} | |} | ||
− | + | {{aside|Info|Although some engines are listed as compatible they will need a shim script to maintain compatibility with Sphere's API. For example, [[API:LoadImage|LoadImage]] may indeed return the correct [[API:image|image]] format by using a different API such as <tt>return new Image()</tt>.|template-info.svg}} | |
===Discontinued or abandoned=== | ===Discontinued or abandoned=== |
Latest revision as of 09:13, 27 July 2014
Notice
This article aims to provide a checklist and resources for developing a JavaScript-powered game engine that is compatible with Sphere's JavaScript API.
Contents
Introduction
Throughout this article, the original Sphere implementation shall be referred to as "vanilla" Sphere and consisted of use of an older version of SpiderMonkey as the JavaScript engine, the first-party Corona library for the software implementation of video, and the first-party Audiere library for the audio driver. Input was mapped directly in software using whatever API was native to the OS in the case of the Windows and Linux versions of vanilla Sphere. The recent Mac OS X port of vanilla Sphere used SDL to handle all input and output while still using an older version of SpiderMonkey for JavaScript.
Possible frameworks to implement Sphere:
- JavaScript
- V8
- SpiderMonkey v1.8.5
- Jurassic / IronJS / JavaScript.Net / Jint
- Game Libraries
- SDL
- SFML
- Graphics libraries
- OpenGL
- pixi.js / three.js
- DirectX (DirectDraw)
- hand-rolled software renderer.
- Audio libraries
- Audiere
- Libsndfile
- BASS
- Irrklang
- FMod
(TODO: more)
Input
SDL
If you want to use SDL, it will be helpful to set up an event filter to catch application close events. Since the main function that needs proper access to events is GetKey, you can disable mouse movement, mouse button, and key-up events so that the event queue will be filled with just keydown events. This simplifies the implementation of the GetKey function, as it is the only function that needs the queue to contain a specific kind of event. Be sure to pump or poll for events whenever input is requested. This also keeps the engine responsive during calls to getkey, and tending the event queue keeps the engine responsive in general.
Keyboard state polling (as in IsKeyPressed()) can be handled with getting the keystate and comparing keysyms.
SFML
If you are using SFML, you need to handle the key pressed and released events. It's a good idea to use a static array for all of the keys, mouse, and joystick buttons. The array's index corresponds with a key, mouse, and joystick code with a true/false value indicating IsPressed. In order to support more than one joystick you may need to bump up that joystick array to a 2D array, where 'x' is the joystick id and 'y' is the button code.
For the key queue, just use a queue data structure. Enqueue keys on the released state, and dequeue keys with GetKey.
Other input libraries
(TODO: list possible input handling libraries and gotchas)
Handling keyboard input notes
GetKey() must be able to block the sphere engine. If the key queue is empty, go into a loop that just updates the game screen.
(TODO: fill)
Key Constant Mapping
In SDL, SFML, and other game libraries, key code enumerations offered in source may differ from Sphere's. In order to map keys correctly you might need to implement a very large map that is basically a "this key" = "that key" list. Such a technique is optional if you already follow Sphere's key naming conventions, but what this will do is allow other Sphere engines to use those same codes if you saved a game with key mappings from vanilla Sphere.
See Sphere's list of keycode constants for the official list, also at https://github.com/sphere-group/sphere/blob/v1.6/sphere/docs/development/keys.txt
Handling mouse input notes
(TODO)
Handling joystick input notes
(TODO)
Other input methods
(TODO)
Output
Video
Blitting is a process that draws the image or surface to a screen's render target prior to flipping. In web based engines this is best emulated with a "draw queue". You fill the queue with what to draw prior to a frame and update it when you are ready.
(TODO: more) (TODO: multi-monitor?) (TODO: touch-screen?)
Audio
SFML
Audio is split between sounds and music. They have the same API, but music streams intrinsically. Volume however takes a range of 0 to 100. Treat that as a percent of the 0 to 255 range Sphere uses. You might need to cache the volume into a private variable and get set from that, making sure to set the underlying volume as a percent of whatever you used.
Sphere-format file loading
Sphere uses five custom file formats, all containing bitmap data in some form or another: bitmap fonts, spritesets, stylized window frames, maps, and map tilesets. Some of them have metadata interspersed with the bitmap data, others have a dedicated block that contains all the metadata for the file in one section regardless of the bitmap data. Maps in particular have the option of choosing to embed its tileset within its file or to point to an external tileset file. All have fixed size headers that are trivial to read. All integer values are stored in Intel order/little-endian and unless otherwise noted all pixel values are 32-bit and stored in the order RGBA.
Fonts
Pretty straight forward. Version 1 Sphere fonts only allow 8-bit grayscale pixels and are deprecated in favor of version 2 fonts. Version 2 fonts use bitmaps containing full 32-bit RGBA pixels. There are reserved bytes to be aware of, otherwise no metadata.
Spritesets
Three separate versions with separate loading behaviors. Much more complicated than fonts, some reserved bytes, lots of metadata. (TODO: expand)
WindowStyles
Two versions to handle. Some reserved bytes, some deprecated properties depending on version, small amount of metadata. (TODO: expand)
Maps
Lots of metadata, small amount of reserved bytes, can embed tilesets or refer to external tileset files. (TODO: expand)
Tilesets
Lots of metadata, small amount of reserved bytes, bitmap data is in one large block after header but before metadata. (TODO: expand)
The map engine
(TODO)
The MapEngine loop
(TODO)
Maintaining API compatibility
Sphere's original JavaScript API was written with a procedural mentality. JavaScript is a language with a powerful prototype-based inheritance system, so you may want to change Sphere's native objects such as the Color object to allow variable creation via the new syntax; if you do this natively you must either write the equivalent loading function (in this case, CreateColor) as native code or in a scripted shim. The system script oldsphere.js is an example of such a shim, existing to maintain compatibility with projects written for pre-1.0 versions of Sphere. If you'd rather leave the original procedural-style loading functions but add the ability to create native Sphere objects with a working prototype constructor, visit this forum thread for information on doing it in script.
Compatibility with 1.5
(TODO)
Compatibility with 1.6 beta
(TODO)
Compatibility with 1.7 alpha
(TODO)
Backwards-compatibility with pre-1.5
(TODO)
List of Sphere-compatible engine implementations
Complete or in-progress
Implementation | Operating System | Version | JS engine | Video driver | Audio driver | Input handler |
---|---|---|---|---|---|---|
vanilla Sphere source, thread |
Win x86, OSX, Linux x86 | stable: 1.5 unstable: 1.6 beta 4 inactive: 1.7 alpha |
SpiderMonkey | configurable | configurable | configurable |
TurboSphere source, thread |
Win x86/64, OSX, Linux x86/64, Solaris 10 amd64 | 0.4.0 | V8 | OpenGL via SDL2 | BASS | SDL2 |
unnamed Sphere clone in SDL source, thread |
? | ? | V8 | SDL | SDL | SDL |
sphere-sfml source, thread |
Win x86, OSX(?) | 0.65 alpha | Jurassic | OpenGL via SFML 2 | libsndfile via SFML 2 | SFML 2 |
web-sphere source, thread |
Chrome, Firefox, and IE9+ | pixi.js version: ? three.js version: ? |
browser via pixi.js, three.js | browser via pixi.js, three.js | browser via pixi.js, three.js | browser via pixi.js, three.js |
Info
Discontinued or abandoned
(TODO)
See also
(TODO)