The game's built-in scripting language makes it possible to create firing patterns for characters as well as program entire stages. The language has a surprising number of similarities with Logo. If you've never programmed before, or if you find it difficult to adapt to the language, it might be a good idea to learn a bit of Logo.
When you start the program, almost immediately you're required to select a game. A game consists of one or more routes and a route of one or more stages. If you just want to create a single stage, you'll first have to create a game and add a route to that game. An easy way to start is by using this template. The template already contains a game ("game_template"), a route ("normal") and a first stage.
The first hing you'll want to change is the game's ID. Right now it's game_template -- the name of the .ini file without the file extension (game_template.ini -> game_template). Since the ID is determined by a filename, renaming game_template.ini to example.ini will change the game ID to example. Make sure to also rename the game_template subfolder to the new ID. The game_template.ini file contains some information about the game:
script_version=1.0 script_version=1.0 version=1.0.0 name=(game name) desc=(game desc) banner=banner.pngThe version number in a.b.c format, numbers only (1.12.63 is valid, 1.3.6c isn't). Second, the game's name and description as they'll appear on the game selection screen. Lastly, a banner property that points to the banner image that's also shown on the selection screen. The image should be a 256x192 pixel PNG.
Looking inside the game's folder you'll find a file named "normal.ini". There's a .ini file in this folder for each route in the game. A route is just a named collection of stages. If you want to have multiple difficulty settings, you should make a route for each difficulty. But let's look at normal.ini first:
name=Normal locked=falseThe name property should speak for itself, but you also see a locked property. Settings locked to false doesn't really do anything -- false is the default value -- but when locked is set to true, the route is hidden from the player. Since you can lock a stage, it's only natural that you can also unlock it. Unlocking is done by adding a unlocks property to the .ini of a specific stage. When the player clears that stage, the route with ID equal to the stage's unlocks property is then unlocked.
The route folder contains stages, once again each with its own .ini and subfolder. stage1.ini looks like this:
name=(stage name) desc=(stage description)The stage name and description are shown at the beginning of the stage. Aside from the previously discussed unlocks property, there are also these properties:
tex_player_fx tex_bullet tex_item tex_enemy tex_explosion tex_boss tex_backgroundThey can be used to override the default textures for that specific stage, allowing you to use your own images for enemies, projectiles, etc. An example usage is:
tex_boss=tex_boss_cirno:A3I5Where tex_boss_cirno is the filename and A3I5 is the filetype. You have to convert your images to a specific format before you can use them.
The stage folder contains a file called main.pds. That's the main script file, let's take a look inside:
define spell main wait 180 end_stageThis is pretty much the simplest stage you can make. It just waits a while and then ends. The first line
define spell maindefines a spell called main. Every stage should have a main spell, that's the spell which is executed as the stage starts. All other spells can then be called from the main spell. Not every define has to be a spell, besides spell you can also use object to define enemies/projectiles and boss to define bosses. More on those later.
A define looks like this:
define %TYPE %NAME %COMMAND %COMMAND ... %COMMAND (empty line)Where %TYPE is one of (spell, object, boss) and name is a single word starting with a letter of underscore, followed by any number of letters, underscores and numbers ([A-Za-z_]([A-Za-z_0-9])*). The line starting with define is followed by any number of commands, each one on a seperate line. An empty line indicates the end of the definition.
A command is written like this
%COMMAND_NAME %VAR %VAR %VARfor a command with thre parameters. So basically, the command name, followed by the parameters seperated by spaces. A more concrete example would be:
image tex_enemy 96 0 32 32This executes the "image" command with parameters (tex_enemy, 96, 0, 32, 32). If we look at the image command in the command reference, we see:
image texture:Texture x:u8 y:u8 w:u8 h:u8So the first parameter, tex_enemy, is a reference to the texture we want to use. And x, y, w, h define the part of that texture we're going to use.
Of course, we also want to be able to define objects (enemies ans projectiles are objects). An object define is slightly different:
define object fairy :init: %COMMAND %COMMAND ... %COMMAND :life: %COMMAND %COMMAND ... %COMMAND :death: %COMMAND %COMMAND ... %COMMANDObjects have their commands split in three parts: init, life and death. The commands under :init: are immediately executed when the object is created and the commands after :death: are exectuted when the object is destroyed. Commands under :life: are executed while the object is alive. Don't put any long running commands or waits in :init: or :death: they block the program untile they're done.
Boss defines work the same as object defines, except they can use boss-specific commands like boss_name, boss_num_spellcards and boss_spell. The way they're created is also different. Enemies are created using create, projectiles using fire and bosses using create_boss
You should now know enough to be able to start scripting. If you're unsure how to use a certain command or how to create a certain effect, try to find another script and look at the code.
When using call, create, create_boss or fire, you can pass values to the spell/object. The values are then available in that spell/object as $1, $2, $3, etc. If you wanted to create the "fairy" object as declared above, you'd use: "create fairy -32" (or something else than "-32", whatever). Then in "turn $1", $1 is replaced by -32.
You can also use randomized values, to generate a random value between 0.0 and 100.0, you would use: "~0.0:100.0". You can also specify the step size, for example: "~32:128;32" returns a value of 32, 64, 96 or 128.
When scripting stages, you can use multiple script files. All files with a .pds extension in the stage folder are parsed as scripts. You can use defines from other files by prepending the filename without extension to the spell name. So if you define a boss chen in boss.pds you can call it from boss.pds as chen and from main.pds as boss.chen
There's a way to loop spellcards indefinitely, just use _loop as the final spell of a spellcard. You can also use _loop at the end of the "sub-spellcards" of objects. And you can specify the number of iterations by adding a loop count; "_loop 5" repeats the spellcard's spells five times.
A limited version of a for loop also exists. Example:
_for 0.0 10.0 0.1 call subroutine $$The _for command executes the next command in the spellcard a number of times, replacing $$ with a different value each time. The params of for are startValue, endValue and step which loosely corrsesponds to "$$ = 0; do { exec_spell(); $$ += step; } while ($$ != end);".