flipCode - Tech File - Henry Robinson [an error occurred while processing this directive]
Henry Robinson
Click the name for some bio info

E-Mail: hr109@york.ac.uk



   08/25/1999, Scripting Ideas


So, once more it's been a long time since my last update. I've been continuing with my research, and my engine framework, a bit since I last talked here. However, being the lazy swine I am, I decided to put graphics coding on hold until I get my new machine (PII 400, ATI Rage Pro etc). This is because I currently use a P100 with about 20Mb free HD space, and not enough room to manoeuvre. In these times of 3d acceleration, I really didn't want to be messing around with DOS based software rasterizers. Anyway, the new machine arrives in parts tomorrow, so all being well it should be functional by Thursday or Friday. Woohoo!

So what have I been doing? My current attention is focused on a debate raging around the Crystal Space mailing list about scripting. It's been an education listening to everybody's point of view, but also a problem. You see, there are about as many ways to do scripting as there are to skin a cat. Some people wanted the scripting language to just call the CS API explicitly. In this implementation a scripting language is just something that can be either interpreted or byte-compiled. The actual application resides in the domain of the scripting language, which controls the flow of execution. To my mind, this is a bare-bones approach, but it depends on exactly what you want to use the language for.

My ideal scripting system would look a lot like Unreal's. I have great admiration for the Unreal content-control system, for it's flexibility, power and ease-of-use. Given infinite time, I would start from scratch and design a language like UnrealScript, with support for latent functions, game states and other stuff. I would then create an object management system, that understood the distinction between class and object (class is the type of an object), had support for persistent instances of objects, and could generally organise everything as needed. A necessary feature of this system would be to synchronise game objects with Crystal Space engine objects. For instance, a ScriptedLight object might have a member variable Brightness. This might directly correspond to a csLight.Brightness variable. If one was updated, then the other should be also. This is not hard to do with dedicated variable update functions in the object management layer, as long as one key assumption is made: that the CS engine will not update any variables that could be updated by the scripting language. Although on the surface this seems easy to do with checking for disparity between the variables, there are some tricky issues involved. For instance, if both engines update the member variable to different values, whose value is correct? I think it is easier just to say only the scripting language can update variables. I struggle to think of a case where this will not be acceptable. Any variables that the engine might be updating are probably too low-level concepts to be exposed to a scripting language.

Then there is the question of things like meshes, and sounds. Who is responsible for holding the data for these things? Certainly meshes and sounds need to be part of the scripting language, but the internal engine will be the one that needs to actually get at the data. My solution would be to implement a different kind of object, aside from the normal GameObject, in the object management layer. This object, with a base class of DataHandle, would know about loading data and saving it, while still functioning like a normal GameObject. Thus the data would be hidden from the scripting language, but control of it wouldn't. Unfortunately this approach requires a new DataHandle kind of object for every kind of data object that people might want to import. However, this really doesn't stretch beyond meshes, textures, sounds and geometry. Textures will mainly not need to be scripted, so a texture library object might be in order instead. With this approach, the application can just load in the world file, which will contain a bunch of objects which will automatically load any data associated with them and tell CS about it.

At this point, the issue of how and when to pass control to the scripting language rears its ugly head. For games, you can perform a tick operation which updates every object, telling it how much time has passed since the last update. Other events need to be raised as well, like collision detection, and hearing sounds. Unfortunately, there is no nice and precise way to define an event in a general way: how do you create a system that can say: if my bounding box touches somebody else's, or there is a sound played within 2 feet of me, then tell me about it, otherwise don't talk to me. This is only possible if the underlying engine knows about the concept of sounds, bounding boxes and ranges. These would have to be hardcoded into the C++ code for the object system, which is a fudge I don't like. I suppose you could have a scripting language feature Event, which would be checked every tick. In fact, that's not a bad idea, let me think that through now....

So you could possibly do something like:

 Event HearSound
 { 
  
     ActorList AffectedActor;
     Sound currentsound;
 Check()
 { 
 for (currentsound = firstsound;currentsound == lastsound,currentsound = currentsound.next)
 { 
  
     for (i=0;i<num_affectedactors;i++)
     {
     if (DistanceBetween(AffectedActor[i],currentsound.origin) < 10*currentsound.Volume)
         AffectedActor[i].RaiseEvent(HearSound,currentsound);    
   }
  
 } 
 }
  
 RegisterObject(Actor toregister)
 { 
     AffectedActor.Add(toregister);
 } 
  
 UnregisterObject(Actor unreg)
 { 
     AffectedActor,Remove(unreg);
 } 
  
 } 
and in an actor's definition you could have:

 Actor Monster
 { 
  
     // Event registration
  
     EventRegister SoundRegister()
     {
         HearSound.RegisterObject(self);
     }
  
     EventUnRegister SoundUnRegister()
     {
         HearSound.UnregisterObject(self);
     }
  
     // Event handlers
  
     EventHandler HearSound(Sound)
     {
         SetState('Awake');
     }
  
 } 
Hmm, this might just work....

I'll have a play with this, and see what I come up with. Next update, I'll tell you what the Crystal Space project decided on, a tale of Python and COM......

Till next time

Henry





  • 06/21/2001 - Tech File Update
  • 06/07/2000 - Tech File Update
  • 08/25/1999 - Scripting Ideas
  • 07/18/1999 - No Subject
  • 05/13/1999 - No Subject
  • 04/26/1999 - On Scripting...
  • 04/24/1999 - Hi!

  • This document may not be reproduced in any way without explicit permission from the author and flipCode. All Rights Reserved. Best viewed at a high resolution. The views expressed in this document are the views of the author and NOT neccesarily of anyone else associated with flipCode.

    [an error occurred while processing this directive]