I've been working a scripting layer on top of VergeC for a game I'm making. I think it's pretty cool, but I want to hear your thoughts. It's hard to be objective about how useful something is when you're the only one who's used it.
I'm calling it the Verge Scripting System (VSS) as a working title, but other suggestions would be great. I'm a bit worried that "Verge Scripting System" sounds too official when VSS isn't an official part of VERGE.
The main thing that VSS adds are scripts. Scripts are kind of like functions, but they run semi-concurrently. Every frame, each script that's running gets updated. Scripts automatically keeps track of what statement they're on, so they can restart from where they left off.
Here's an example of a "jukebox" script that plays three songs in order, one after the other (I'm pretending that 'MusicPlaying' is a built-in function):
script JukeboxPlay(string song) {
PlayMusic(song);
suspend while(MusicPlaying());
}
script Jukebox() {
JukeboxPlay("song1.mod");
JukeboxPlay("song2.s3m");
JukeboxPlay("song3.mp3");
}
void autoexec() {
Jukebox();
}
Normally, whenever a script calls another script, the caller is suspended until the callee finishes. You can also 'fork' a script, so that the caller keeps running:
script ParticleManager() {
while(1) {
fork Particle(); // create a new particle
suspend; // wait for next frame
}
}
You can also 'chain' a script from another script. When you do this, the callee takes over completely from the caller. This is so you can use scripts to represent states:
script IdleGuard(int ent) {
while(1) {
// ...
if(SeePlayer(ent)) {
chain AlertGuard(ent); // stops IdleGuard()
}
} }
'on' and 'during' are also useful. 'on' blocks appear at the beginning of a script. The code in an 'on' block gets run whenever the condition is true, regardles of whether the script it appears in is suspended:
script IdleGuard(int ent) {
on(SeePlayer(ent)) {
chain AlertGuard(ent);
}
// pace back and forth. these calls suspend the
// IdleGuard() script, but the 'on' block will
// still be checked.
while(1) {
moveLeft(ent, 4);
wait(2);
moveRight(ent, 4);
wait(2);
}
}
'during' blocks are similar; they encompass a block of code. If the condition in the 'during' header becomes false, control automatically jumps to the end of the 'during' block. So the block only executes "during" the time when the condition is true. Kind of like a while loop that checks its condition constantly, instead of only at one point.
You can also have 'retrace' blocks, which allow scripts to draw things. So if you had a script that represented a particle, you'd put the code to draw the particle in the script's 'retrace' block.
Oh, and you can also access script data from outside the script, so they're kind of like structs too:
script[10] bullet(int x, int y) {
halt(); // no code for bullets
}
void SomeFunc() {
int bulletId;
bulletId = bullet(10, 10);
$bullet[bulletId].x = 5;
$bullet[bulletId].y = 7;
}
(The [10] means that 10 copies of the 'bullet' script can run at once. If this is omitted, it defaults to 16 or whatever you set the default to.)
What do you think? Comments? Suggestions? Praise? Distain? I've got some ideas for more things, but I'd like to hear what you think so far.
Thanks!
-- torin
edit: Added the bit about the '[10]'