Simple bird AI code
by Justin Knight · in Torque 3D Professional · 12/23/2009 (5:09 pm) · 3 replies
I'm trying to write a simple AI to control the birds in my level. I currently have a test bird staticShape and the following code to move it:
It's meant to circle but I'm getting strange behaviour with the rotation angle. Here's a bit of the console output:-
For some reason on the line I've bolded the axis of rotation shifts from the +ve to -ve Z axis and the angle changes itself. I've only been using T3D for 3 weeks so I've probably missed something obvious - can anyone help?
In case they're relevant here is the datablock and part of my mission file that creates the bird object...
Being new to torquescript and T3D I'd appreciate any other criticisms of my code - I may be doing things in long-winded or inappropriate ways.
Thanks,
Justin.
// Bird AI
// @TODO prevent going out of bounds
$bird = null;
$state = 0; // 1=fly 2=circle
$updateIntervalMS = 100; // How often to update position in ms
$flapping = false;
$flyDelta = 0.4;
$angleDelta = 0.0;
function startAI( %bird) {
$bird = %bird;
decideState(); // Decide initial state.
scheduleFlap();
}
// Decide what to do next
function decideState() {
// $state = getRandom( 1, 2);
$state = 2; // Just circle constantly while investigating bug
// Initialise chosen state.
switch( $state) {
case 1: // Fly
// nothing to initialise
case 2: // Circle
$angleDelta = getRandom( 1, 9) / 100.0;
}
// Schedule first update
scheduleNext();
// Schedule next decision
%decisionInterval = getRandom( 5000, 20000);
schedule( %decisionInterval,0, decideState);
}
function scheduleFlap() {
$flapping = ! $flapping;
if( $flapping)
$bird.playThread( 0, "flap");
else
$bird.stopThread( 0);
%flapInterval = getRandom( 5000, 20000);
schedule( %flapInterval, 0, scheduleFlap);
}
function scheduleNext() {
if( isObject($bird)) {
switch( $state) {
case 1:
schedule( $updateIntervalMS,0, updateBirdFly);
case 2:
schedule( $updateIntervalMS,0, updateBirdCircle);
}
}
}
// Flying
function updateBirdFly() {
if( isObject($bird) && $state==1) {
%forward = $bird.getForwardVector();
%tbird = $bird.getTransform();
%tbird.X += %forward.X * $flyDelta;
%tbird.Y += %forward.Y * $flyDelta;
$bird.setTransform( %tBird);
}
scheduleNext();
}
// Circling
function updateBirdCircle() {
if( isObject($bird) && $state==2) {
%tBird = $bird.getTransform();
%start = %tBird;
%forward = $bird.getForwardVector();
%tbird.X += %forward.X * $flyDelta;
%tbird.Y += %forward.Y * $flyDelta;
// adjust current heading by $angleDelta
%heading = getWord( %tBird, 6);
%heading += $angleDelta;
if( %heading>6.283) %heading=0;
%tBird = setWord( %tBird, 3, 0);
%tBird = setWord( %tBird, 4, 0);
%tBird = setWord( %tBird, 5, 1);
%tBird = setWord( %tBird, 6, %heading);
echo( %start @ " / " @ %tBird);
$bird.setTransform( %tBird);
}
scheduleNext();
}It's meant to circle but I'm getting strange behaviour with the rotation angle. Here's a bit of the console output:-
Quote:
-2.36893 -51.689 30.7601 0 0 1 3.82 / -2.61995 -52.0004 30.7601 0 0 1 3.89
-2.61995 -52.0004 30.7601 0 0 1 3.89 / -2.89214 -52.2935 30.7601 0 0 1 3.96
-2.89214 -52.2935 30.7601 0 0 1 3.96 / -3.18416 -52.5669 30.7601 0 0 1 4.03
-3.18416 -52.5669 30.7601 0 0 1 4.03 / -3.49459 -52.8192 30.7601 0 0 1 4.1
-3.49459 -52.8192 30.7601 0 0 1 4.1 / -3.8219 -53.0491 30.7601 0 0 1 4.17
-3.8219 -53.0491 30.7601 0 0 1 4.17 / -4.16449 -53.2556 30.7601 0 0 1 4.24
-4.16449 -53.2556 30.7601 0 0 -1 2.04319 / -4.52068 -53.4376 30.7601 0 0 1 2.11319
-4.52068 -53.4376 30.7601 0 0 1 2.11319 / -4.17809 -53.6441 30.7601 0 0 1 2.18319
-4.17809 -53.6441 30.7601 0 0 1 2.18319 / -3.85078 -53.874 30.7601 0 0 1 2.25319
-3.85078 -53.874 30.7601 0 0 1 2.25319 / -3.54035 -54.1263 30.7601 0 0 1 2.32319
For some reason on the line I've bolded the axis of rotation shifts from the +ve to -ve Z axis and the angle changes itself. I've only been using T3D for 3 weeks so I've probably missed something obvious - can anyone help?
In case they're relevant here is the datablock and part of my mission file that creates the bird object...
datablock StaticShapeData(BirdDB)
{
shapeFile = "art/shapes/chris_models/cranimation1.cached.dts";
category = "StaticShape";
};new StaticShape(crane) {
receiveSunLight = "1";
receiveLMLighting = "1";
useCustomAmbientLighting = "0";
customAmbientLighting = "0 0 0 1";
dataBlock = "BirdDB";
position = "-8.39808 1.70238 30.7601";
rotation = "0 0 1 0";
scale = "1 1 1";
isRenderEnabled = "true";
canSaveDynamicFields = "1";
};Being new to torquescript and T3D I'd appreciate any other criticisms of my code - I may be doing things in long-winded or inappropriate ways.
Thanks,
Justin.
About the author
#2
12/23/2009 (11:45 pm)
(ignore this post)
#3
Here's the fixed code in case it's of use to anyone else.
I've got a feeling using setVelocity() when it's flying straight would be more efficient but it didn't seem to work.
12/24/2009 (5:01 am)
@Dreamarvel thanks very much, all working now. Here's the fixed code in case it's of use to anyone else.
// Bird AI
// @TODO prevent going out of bounds
$bird = null;
$state = 0; // 1=fly 2=circle
$updateIntervalMS = 100; // How often to update position in ms
$flapping = false;
$flyDelta = 0.4;
$angleDelta = 0.0;
function startAI( %bird) {
$bird = %bird;
decideState(); // Decide initial state.
scheduleFlap();
}
// Decide what to do next
function decideState() {
$state = getRandom( 1, 2);
// Initialise chosen state.
switch( $state) {
case 1: // Fly
// nothing to initialise
case 2: // Circle
$angleDelta = getRandom( 1, 7) / 100.0;
}
// Schedule first update
scheduleNext();
// Schedule next decision
%decisionInterval = getRandom( 5000, 20000);
schedule( %decisionInterval,0, decideState);
}
function scheduleFlap() {
$flapping = ! $flapping;
if( $flapping)
$bird.playThread( 0, "flap");
else
$bird.stopThread( 0);
%flapInterval = getRandom( 5000, 20000);
schedule( %flapInterval, 0, scheduleFlap);
}
function scheduleNext() {
if( isObject($bird)) {
switch( $state) {
case 1:
schedule( $updateIntervalMS,0, updateBirdFly);
case 2:
schedule( $updateIntervalMS,0, updateBirdCircle);
}
}
}
// Flying
function updateBirdFly() {
if( isObject($bird) && $state==1) {
%forward = $bird.getForwardVector();
%tbird = $bird.getTransform();
%tbird.X += %forward.X * $flyDelta;
%tbird.Y += %forward.Y * $flyDelta;
$bird.setTransform( %tBird);
}
scheduleNext();
}
// Circling
function updateBirdCircle() {
if( isObject($bird) && $state==2) {
%tBird = $bird.getTransform();
// Move forward by $flyDelta
%forward = $bird.getForwardVector();
%tbird.X += %forward.X * $flyDelta;
%tbird.Y += %forward.Y * $flyDelta;
// Check axis of rotation is correct
if( getWord( %tBird, 3) != 0 || getWord( %tBird, 4) != 0) {
%tBird = setWord( %tBird, 3, 0);
%tBird = setWord( %tBird, 4, 0);
%tBird = setWord( %tBird, 5, 1);
}
// Adjust current heading by $angleDelta
%heading = getWord( %tBird, 6);
%zaxis = getWord( %tBird, 5);
if( %zaxis>0)
%heading += $angleDelta;
else
%heading -= $angleDelta;
if( %heading>6.283) %heading=0;
%tBird = setWord( %tBird, 6, %heading);
$bird.setTransform( %tBird);
}
scheduleNext();
}I've got a feeling using setVelocity() when it's flying straight would be more efficient but it didn't seem to work.
Torque 3D Owner Dreamarvel
0 0 1 a = 0 0 -1 2*PI-a