Movable doors/trunk in Onyx

Ruud

RACER Developer
I've been playing a bit with Stereo's Simca Aronde and the scripts in there. These things are nice to get into Onyx at some point, since that will be a more mature language (looking very much like C++). I've added some Onyx functions for v0.8.41 (not out yet) to make at least the Simca trunk/door opening possible.

The code looks like this (all based on Stereo's QScript code, although now enhanced with a common class to do the animation).

Issues:
- Onyx uses handles to hook the car inside Racer's engine, and also to get the generic models. Handles can be assigned to eachother, which is very dangerous for a scripting language. No solution yet (perhaps make handle assignments forbidden?). Onyx also knows the 'pointer' type, which is a bit the same but a different base type, so 'handle h; pointer p; h=p; ' is not allowed. Still, it kinda s*cks to expose this kind of flexibility, as it makes crashes quite easy.
- No constructors yet, so class creation is a bit hardcoded.
- An Onyx bug with variable offsets, the following does not work because of compiling issues:

Code:
void OnFrame()
{
  float t=123.0f;
  echo(t);
 
  if(1)
  {
    echo(t);
    float v;
    v=2;
    echo(t);    // Prints 2, not 123 (bug!)
  }
}

Now for the Onyx code for the Simca (I added scripts.load in car.ini, setting it to car.oxs; this is v0.8.41 functionality though).

Code:
/*
* Car script, handling any added logic
* 08-06-2012: Created (based on Stereo's variant for the Simca Aronde in QScript)
* NOTES:
* - No constructors exist yet in Onyx; would be handy
*/
 
#include "racer.oxs"
 
// Objects
Car    car;          // The car we control
 
// Angle animation
class AngleAnimator
{
  handle  gm;                // The generic model
  Vector3 pos,                // Position of model
          rotMask;            // Mask to define rotation (i.e. 0,1,0)
  int    open;              // Desired state
  float  angle;              // Current angle
 
  void UpdateAngle(float incRate,float decRate,float minAngle,float maxAngle,float interval)
  // Angle handler for a generic model.
  //
  // incRate: angular change (per ms) in radians when opening.
  // decRate: angular change (per ms) in radians when closing. note: both should be positive.
  // minAngle: min value for the angle
  // maxAngle: max value for the angle
  // 'interval' is the delta time since the last frame
  //
  // Returns the updated angle
  {
    float targetState=open;
    // Figure out where we want to go
    float targetAngle=targetState*(maxAngle-minAngle)+minAngle;
   
    // Move towards target angle
    if(targetAngle>angle)
      angle=angle+incRate*interval;
    if(targetAngle<angle)
      angle=angle-decRate*interval;
     
    // Clamp angle within a valid range
    if(angle<minAngle)    angle=minAngle;
    else if(angle>maxAngle)angle=maxAngle;
 
    // display the object correctly
    GenModSetPosition(gm,pos);
    GenModSetRotation(gm,angle*rotMask.x,angle*rotMask.y,angle*rotMask.z);
  }
};
 
AngleAnimator trunkAnim,leftAnim,rightAnim;
 
// Generic
int    keyPressed;
 
// Frame interval
float lastT;
 
void OnInit(handle h)
// Called when the car is created
{
  echo("OnInit of car");
 
  // This next line should change in the future
  car.h=h;
 
  // Trunk animation setup
  trunkAnim.gm=car.GetGenericModel(8);
  trunkAnim.pos.x=0;
  trunkAnim.pos.y=0.35;
  trunkAnim.pos.z=-1.31;
  trunkAnim.rotMask.x=0; trunkAnim.rotMask.y=1; trunkAnim.rotMask.z=0;
 
  // Doors
  leftAnim.gm=car.GetGenericModel(9);
  leftAnim.pos.x=0.739;
  leftAnim.pos.y=-0.58;
  leftAnim.pos.z=0.628;
  leftAnim.rotMask.x=-1; leftAnim.rotMask.y=0; leftAnim.rotMask.z=0;
 
  rightAnim.gm=car.GetGenericModel(10);
  rightAnim.pos.x=-0.739;
  rightAnim.pos.y=-0.58;
  rightAnim.pos.z=0.628;
  rightAnim.rotMask.x=1; rightAnim.rotMask.y=0; rightAnim.rotMask.z=0;
}
 
 
void OnFrame()
{
  float t=GetSimTime();    // Milliseconds
  t=t*0.001;                // Time in seconds
  float yaw,pitch,roll;
 
  // Time since last frame
  float dt=t-lastT;
  lastT=t;
 
  if(IsKeyPressed(KEY_T))
  {
    if(keyPressed==false)
    {
      echo("T pressed! Toggle trunk");
      keyPressed=true;
      if(trunkAnim.open)trunkAnim.open=false; else trunkAnim.open=true;
    }
  } else if(IsKeyPressed(37))
  {
    if(keyPressed==false)
    {
      echo("Left pressed! Toggle door");
      keyPressed=true;
      if(leftAnim.open)leftAnim.open=false; else leftAnim.open=true;
    }
  } else if(IsKeyPressed(39))
  {
    if(keyPressed==false)
    {
      keyPressed=true;
      if(rightAnim.open)rightAnim.open=false; else rightAnim.open=true;
    }
  } else
  {
    keyPressed=false;
  }
 
  // Animate
  trunkAnim.UpdateAngle(3.0,3.0, 0,1.2, dt);
  leftAnim.UpdateAngle(2.0,2.0, 0,1.1, dt);
  rightAnim.UpdateAngle(2.0,2.0, 0,1.0, dt);
}
 
Stuff like this is a bit beyond me (from scratch), but it's great to see stuff that we can interpret and adapt in Onyx format!

Can Onyx also do things like make changes in the car.ini, so if the door is open the frontal area of the car is changed (ie, more drag)??

Cheers

Dave
 
Hmm, since you're putting together a new language, may as well say what my top 3 wishes are for scripts:
1) apply forces to cars (direction+position vector, magnitude) that the physics engine can integrate. This one has many possible uses, from active downforce (fan cars) or jet engines, to putting a load on the back of a truck.
2) transform world coordinates to screen coordinates text/image display can use. Head up display info benefits from this, like providing more info about another driver than just their name. It would also make debugging&tuning things that aren't displayed by 'show carpoints' easier.
3) collision detection of some sort. I don't know what's easiest - provide world x,y and get track elevation, or ask how far along a direction vector it hits something, or maybe a point's proximity to any collision box, or ask Newton whether 2 particular objects are touching. Really this is less important, but there are certainly some things it enables depending what's doable - make sure movables don't hit anything when a script moves them outside the car's bound box, give drivers penalties for touching (although determining who's at fault is trickier for a script), playing 'cops and robbers' or 'tag' type games where one driver has to hit a specific other driver, etc. Some of these can be done without collision detection, others can't.
 
Sorry for the big bump but this thread it's similar to the question i have... I want to know how to assign or where to see what keys move doors and similars... reading for hours and can't find the answer! thanks ;)
 
Iirc, check the scripts/paint/unused folder of the Lambo Gallardo that I recently updated.

In there is a script that Stereo wrote (iirc) that will tell you which key you are pressing!

Just drop it in the scripts/paint folder!


Cheers

Dave
 
Sorry but i can't see that folder :D

Maybe it's the "dev" one? There are a keys file inside :)

Thanks for the support Dave!

10xbotj.jpg
 

Latest News

How long have you been simracing

  • < 1 year

    Votes: 352 15.6%
  • < 2 years

    Votes: 247 10.9%
  • < 3 years

    Votes: 242 10.7%
  • < 4 years

    Votes: 177 7.8%
  • < 5 years

    Votes: 301 13.3%
  • < 10 years

    Votes: 259 11.5%
  • < 15 years

    Votes: 166 7.3%
  • < 20 years

    Votes: 126 5.6%
  • < 25 years

    Votes: 99 4.4%
  • Ok, I am a dinosaur

    Votes: 291 12.9%
Back
Top