[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scripting

Gregor Mueckl wrote:

> > I've written a real simple parser to translate a C subset into a very
> > simple bytecode - it's not especially fast - but it seems good enough
> > for my needs.
> That's the drawback: I don't know of any open implmentation of a
> bytecode interpreter that allows you to specify how many instructions it
> should execute from which script. So you would have to take it into your
> own hands - with all the problems involved in reinventing the wheel once
> again (I don't think that I have to go into detail here).
Mine is OpenSourced - but you'll have to extract it from the guts of
TuxAQFH.  I should probably make a separate package out of it sometime.

> > The main problem (as far as I'm concerned) is that you kill any hope of
> > portability if you generate machine-code.  That's why I use a simple
> > byte-code.  It's slower - but not unacceptably so for the relatively
> > simple things I expect interpreted code to do in my games.
> Well... how many platforms do you want to support with your code? My
> guess is that at least 80-90% of the players will have Intel-compatible
> hardware, maybe even more. The rest is far from being an uniform
> environment: UNIX Workstations, Macs, PS(/2), etc.

I believe that portability is important.  I don't want an x86 monopoly
any more than I want a Microsoft monopoly.  I often run my code on other
CPU's though - so whilst 90% of people may not care, I'm one of the other
10% and when I'm the one writing the code - I get to choose!

I've done several projects on MIPS CPU's.
> > I don't anticipate interpreting thousands of lines of code per
> > frame for each script - I rather expect to execute just a few
> > dozen bytecodes for each one.
> Wouldn't it be better to revert to an event handler system then? If the
> scripts are that simple (I'm refering to your emamples below now) it
> could be far better to do it this way than letting your scripts loop
> within a virtual thread and thereby wasting time *every* frame instead
> of wasting time only when really needed.

They don't have to run every frame - they have a 'Wait until...' bytecode
that puts them on a list of processes that are stalled waiting to run.

> The overhead required to
> determine whether and / or which event handler should be called can be
> neglected in these examples.
> But again, your approach makes perfectly sense if at least some of your
> scripts are a *lot* more complex than in your examples.

That is indeed the case.
> OK. Two notes here:
> 1. It's OK to call compiled helper code in scripts (although that might
> depend on one's taste).

Absolutely - definitely - CRITICALLY!

The script is (in my way of thinking) just a convenient way to tie together
a bunch of pre-designed building blocks that are each written in C++.

> I believe, however, that the design of such
> helper code could become very difficult to get right. It should be
> lightweight but at the same time flexible enough to support different
> behaviour models, at least different enough so that scripting isn't lead
> ad absurdum, because if it's too specific to the creature you're
> designing the AI for you could easily have left out the interpreter
> entirely. It's difficult to ge this right.

Yes.  But at least if the game programmer gets it right, life will be easy
for non-programmers such as the level designers and artists - the pre-built
modules will work and be efficient.  All they should have to do is to plug
them together using the scripting language.
> 2. If you execute only a certain segment of the code in each game cycle
> you end up having yet another problem (it would be one for me if I ever
> took that approach in my current project): It's hard to write frame-rate
> independent scripting code, i.e. code that does calculations based on
> the elapsed time. Consider the following (pseudo-)code that could be in
> the AI of a racing simulation:
> int time, lasttime;
> Pos lastpos, pos; // the car's position
> while(some_condition) {
>    lasttime=time;
>    lastpos=pos;
>    time=get_time_since_start();
>    if(distance(lastpos,pos)/(time-lasttime)<desired_speed) {
>      accelerate(current_acceleration()+1);
>    } else {
>      accelerator(current_acceleration()-1);
>    }
> }
> Admittedly it would not be a good driver, but it shows up a problem when
> it is interrupted for too long. Asume it's execution is paused for some
>   10 msecs just after having fetched the time and the physics simulation
> of the game calculates another cycle. The result is that the calculated
> velocity of the car is out of date and it's likely that the script takes
> the wrong action when the car's speed is near desired_speed. This leads
> to a somewhat unstable driving behaviour with at worst somewhat random
> behaviour from time to time.

That code isn't right though.  You shouldn't increase or decrease the
accelleration by the same amount regardless of the elapsed time - that's
why this code is unstable.

But at any rate, I'm not suggesting that you execute a fixed number
of byte-codes per frame.  Instead there should be some kind of 'wait until...'
command built into the scripting language that would tell the byte-code
execution unit when to cease executing - and what the conditions are to
restart it.

In this case, one might toss in a line inside the 'while' loop that says:

   wait_until ( ELAPSED_TIME_AT_LEAST, 0.1 seconds ) ;
----------------------------- Steve Baker -------------------------------
Mail : <sjbaker1@airmail.net>   WorkMail: <sjbaker@link.com>
URLs : http://www.sjbaker.org
       http://plib.sf.net http://tuxaqfh.sf.net http://tuxkart.sf.net
       http://prettypoly.sf.net http://freeglut.sf.net
       http://toobular.sf.net   http://lodestone.sf.net