Jump to content
A 2021 backup has been restored. Forums are closed and work in progress. Join our Discord server for more updates! ×
SoaH City Message Board

ProSonic Scripting Trial & Error


saxman

Recommended Posts

I've been playing with a possible ProSonic scripting prototype. This is what I have:

DOC format:

http://www.comprosoftware.com/saxman/object%20Ring.doc

RTF format:

http://www.comprosoftware.com/saxman/object%20Ring.rtf

Here's what I'm interested in from anyone viewing this topic:

- Do you know any C, C++, or Java?

- Does this scripting language look easy understand?

Also if you have any suggestions on how I could dumb down the language to make it even easier for people who have no clue how to even begin programming, please let me know!

Link to comment
Share on other sites

It seems more than ok for me, as I'm really used to C programming. However, I would design it in a more event based style, somewhere along the lines of:

object Ring
{
     bit Hit;

     event Creation(x, y)
     {
           Hit = false;
     }

     event Destruction()
     {
           if (Hit == false) return;
           SoundPlay(sndRing);
           ObjectCreateAt(x, y, RingSpark);
     }

     event Step()
     {
            // Animate...
     }

     event Draw()
     {
            RenderSpriteMasked(Ring, CurrentFrame, Layer, x, y);
     }

     event Collision(Object)
     {
           if (ObjectType(Object) == Sonic) { Hit = true; Destroy(self); }
     }
}

Link to comment
Share on other sites

If you want to "dumb it down" then I would like to make the following suggestions:

First, Create a library of generic object behaviors and allow multiple behaviors to be assigned to an object in combination.

For example, the "Ring" object is almost guaranted to be in any game, so a generic behavior for this would be "Player touches me, I add FOO to stat QUXX, play a sound effect and remove myself from the game". This behavior could then be applied to any object that can be collected by touching. Playing the sound in alternate left/right audio channels should be part of this behavior as set by a variable.

behavior(collect_on_touch, alternate_sound);

Another (possible) behavior for a ring would be to bounce and vanish after some time. This behavior could then be applied to, say, the segments of a Caterkiller after being hit.

behavior(random_bounce_timeout, 24);

Simplify as many things as possible. Instead of having the scripter call blit functions, let them define animation sequences.

animation_sequence 1 (
// frame framenumber, ticks, xoffset, yoffset, image_id, flipx, flipy
frame 1, 3, -8, -8, 1, 0, 0
frame 2, 3, -8, -8, 2, 0, 0
frame 3, 3, -8, -8, 3, 0, 0
frame 4, 3, -8, -8, 2, 1, 0
frame 5, 3, -8, -8, 1, 1, 0
);

Edit: PREVIEW not POST... dammit...

Anyway, you could even remove the framenumber if you want, since that's implied by the sequence. Nothice how I started at 1, since it's more "natural" to count from 1 than 0 (unless you're a programmer!)

The above code defines "animation sequence #1", which has 5 frames. All frames have a "ticks" value of 3, meaning 3 ticks of the behavior's internal counter would advance to the next frame (Whatever a "tick" is would be internally defined...). -8 for the offsets means to draw the image up and to the left by 8 pixels from the object's current position. there are 3 images for this animation: flat "O" shape, rotated "()" shape, edge-on "|" shape. The two remaining animation frames are made from flipping the first two images on the "X" axis.

your ring object code would then boil down to:

object Ring
{

 // Define animation sequences used by this object. Images are assumed to be
 // associated with this object and enumerated by some other mechanism?
 animation_sequence 1 (
  autoloop = TRUE; // Automaticallt loop for first frame at sequence end
  usemasks = TRUE; // Use a mask for transpareny/alpha channel
  frame 1, 3, -8, -8, 1, 0, 0
  frame 2, 3, -8, -8, 2, 0, 0
  frame 3, 3, -8, -8, 3, 0, 0
  frame 4, 3, -8, -8, 2, 1, 0
  frame 5, 3, -8, -8, 1, 1, 0
 );

 // Object_State is internally defined by the behavior.
 switch (Object_State)
 {

  case 0: // Just sitting there, also the default case
   // For this state, use the generic "add FOO to QUXX" behavior, with
   // left/right audio channel SFX toggle.
   behavior(collect_on_touch, alternate_sound);

   animation 1; // use animation sequence #1 for this state
   break;

  case 1: // Dropped from a player that was hit

   // Behavior for state=1 is to bounce and die after 24 "clicks" *AND*
   // allow collect-on-touch
   behavior(collect_on_touch, alternate_sound);
   behavior(random_bounce_timeout, 24);

   animation 1; // use animation sequence #1 for this state
   break;
 }

  // Set some variables. Behavior definitions should expect certain variables
  // to be set as parameters. In this case, random_bounce_timeout does not
  // need any params, but collect_on_touch would need to know both FOO
  // and QUXX values to work right. I also added "spawn_object" since part
  // of that behavior is to remove itself from the game, it might want to
  // create a new object.
  //
  // It shouldn't matter where these are set, since they are the same for
  // all states. If they were different for different states, they woudl have
  // to be defined in the switch() statement above.

  stat_add = "rings";  // The stat to add to on collect is "Rings" (QUXX)
  stat_qty = 1;  // The quantity to add to on collect is 1 (FOO)
  spawn_object = "Sparkle";

// Done with object definition
}


object Sparkle
{
 // Should be obvious how this works...

 animation_sequence 1 (
  autoloop = FALSE;
  usemasks = TRUE;
  frame 1, 3, -8, -8, 1, 0, 0
  frame 2, 3, -8, -8, 2, 0, 0
  frame 3, 3, -8, -8, 1, 0, 0
  frame 4, 3, -8, -8, 2, 0, 0
 );

 switch (Object_State)
 {
  case 0:
   behavior(die_on_timeout, 12);
   animation 1;
 }
}

As you can see, the object is GREATLY simplified from the scripter's point of view. Drawing, state tracking, collision detection and preset behaviors are all "internal" to the program and do not need to be coded explicitly into the each object unless absolutely necessary.

=Smidge=

Link to comment
Share on other sites

It seems more than ok for me, as I'm really used to C programming. However, I would design it in a more event based style, somewhere along the lines of:

object Ring
{
     bit Hit;

     event Creation(x, y)
     {
           Hit = false;
     }

     event Destruction()
     {
           if (Hit == false) return;
           SoundPlay(sndRing);
           ObjectCreateAt(x, y, RingSpark);
     }

     event Step()
     {
            // Animate...
     }

     event Draw()
     {
            RenderSpriteMasked(Ring, CurrentFrame, Layer, x, y);
     }

     event Collision(Object)
     {
           if (ObjectType(Object) == Sonic) { Hit = true; Destroy(self); }
     }
}

Lol, GM promotion. xD

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...