Help Wanted

collision problem – skynes

Skynes
Member

Posts: 202
From: Belfast, N Ireland
Registered: 01-18-2004
I posted this on the Reality community already, but it doesn't hurt to have extra thoughts.

I'm working on a simple AI to make enemy ships turn to face you and if you're so close, approach you. (shooting etc comes later)

Problem: When you have multiple ships near one another, when they turn, they actually turn INTO one another. They ignore their collision boxes and enter into one another. If they were ghost ships this would be fine, but they're not :|


This is what I use to make the enemy ship turn to face you

MVector direction is "location of player - location of enemy"


public float RotationSpeed = 1.0f;
protected MVector CurDirection = new MVector(0, 0, 1);

public void RotateToBoat(MVector direction)
{

newDirection = direction;
newDirection.y = 0;

newDirection.Normalize();


if (CurDirection.x < newDirection.x)
{

CurDirection.x += RotationSpeed;
if (CurDirection.x > newDirection.x)
{
CurDirection.x = newDirection.x;

}
}
else if (CurDirection.x > newDirection.x)
{

CurDirection.x -= RotationSpeed;
if (CurDirection.x < newDirection.x)
{
CurDirection.x = newDirection.x;

}
}

if (CurDirection.z < newDirection.z)
{

CurDirection.z += RotationSpeed;
if (CurDirection.z > newDirection.z)
{

CurDirection.z = newDirection.z;
}
}
else if (CurDirection.z > newDirection.z)
{

CurDirection.z -= RotationSpeed;
if (CurDirection.z < newDirection.z)
{

CurDirection.z = newDirection.z;
}
}


Rotation = MMatrix.LookTowards(CurDirection);



}

Moving forward is:


MVector dir = new MVector();

dir += Rotation.GetDir();
if (AIHelpers.GetDistance2D(theBoat.Instance.Location, Location) > 50 && AIHelpers.GetDistance2D(theBoat.Instance.Location, Location) < 1000)
{
Velocity = dir * MHelpers.DeltaTime * 10;

}
else
{

Velocity = new MVector(0,0,0);
}


Flags are:

 
CollisionFlags = COLLISION_FLAGS.CF_BBOX;
PhysicsFlags = PHYSICS_FLAGS.PHYS_PUSHABLE | PHYSICS_FLAGS.PHYS_ONBLOCK_CLIMBORSLIDE;


GUMP

Member

Posts: 1335
From: Melbourne, FL USA
Registered: 11-09-2002
RE comes with built in functions to check for actors within a specified radius. Also, you might be changing the Velocity variable of the actor itself (which it inherits from base classes) and not the variables attached to the PhysX object.

btw, I realize you're doing some sort of contest but is your group interested in the REC?

[This message has been edited by gump (edited July 05, 2007).]

Skynes
Member

Posts: 202
From: Belfast, N Ireland
Registered: 01-18-2004
quote:
Originally posted by gump:
RE comes with built in functions to check for actors within a specified radius.

I've been using the collision flags. Funny thing is that it picks up cannonball shots and my ship hitting it. But it seems to ignore enemy boats. They're all instances of the same class which shouldn't be a problem..

quote:
Also, you might be changing the Velocity variable of the actor itself (which it inherits from base classes) and not the variables attached to the PhysX object.

I found it odd that I had to do Location += Velocity; since it worked automatically everywhere else without me having to do that.

quote:
btw, I realize you're doing some sort of contest but is your group interested in the REC?

Not sure what REC is.

[This message has been edited by gump (edited July 05, 2007).][/QUOTE]

GUMP

Member

Posts: 1335
From: Melbourne, FL USA
Registered: 11-09-2002
REC = Reality Engine Community = Multiple companies merging all enhancements to RE for benefit of all.

I'll give an example of what I meant with Smite's projectile. Velocity is inherited since Smite extends Destroyable. But I don't use Velocity very much. When Smite is generated:

physicalSmite = MNxPhysics.CreateNxActor(desc, this);

physicalSmite.UserObject = this;
physicalSmite.RaiseBodyFlag(MNxBodyFlag.NX_BF_DISABLE_GRAVITY);
physicalSmite.AngularDamping = 0.5f;

physicalSmite.LinearVelocity = new MVector(Velocity);
physicalSmite.Orientation = new MMatrix(Rotation);
physicalSmite.Position = new MVector(Location);

Then during Tick I have some seeking code then:

if (FoundHit)
{
if (physicalSmite == null)
GenerateSmite();

if (physicalSmite != null)
{
MVector SmiteToLockOnPointDir = (LockOnPoint - Location).Normalized();
physicalSmite.AddTorque(Rotation.GetDir().cross(SmiteToLockOnPointDir) *
SeekStrength, MNxForceMode.NX_FORCE);

MVector Force = SmiteToLockOnPointDir * SeekStrength * 40.0f;
physicalSmite.AddForce(Force * GameCore.ForceMultiplier * 0.333f, MNxForceMode.NX_FORCE);
}
}

That code turns the Smite projectile in the direction of the object it's locked onto. Elsewhere Velocity, etc. are updated with the stuff from physicalSmite.

You can also use:

List<MNxActor> nxActorList = MNxPhysics.GetNxActorsSphere(Location, 8, true, true, true);
foreach (MNxActor actor in nxActorList) { blah }

We detect physx objects in order to project a blast wave behind the Smite projectile.

Skynes
Member

Posts: 202
From: Belfast, N Ireland
Registered: 01-18-2004
I looked up the REC on Rendernet, thanks for the invite but I doubt we'd have anything to offer to it.

I see how your code is working, but how could I implement that?

our enemy boat is an MActor.

Tell you what... time to suck up screen space. The full Badboat script.


Something is causing the boat models to overlap, as if they're ignoring collisions and go into one another. I'm 90% sure it's my code and not the model.

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using ScriptingSystem;
using AI;


[Browsable (true)]
class EvilBoat : MActor
{
private EvilCannonball cannonball;
private float FireTimer = 0.1f;

private static bool HasCached = false;
public static string ClassName = "EvilBoat";

public static void Precache()
{
if (!HasCached)
{
HasCached = MPrecacher.Precache(ClassName, HasCached);

}
}
private static float[] sin = new float[1080];
private static float[] cos = new float[1080];
//Load the boat mode;
static private MModel StaticModel = MPrecacher.PrecacheModel(ClassName, "BBoat.xml");
static float DemoPlayerBoxWidth = 1.5f;
static float DemoPlayerBoxHeight = 2.0f;

static public EvilBoat Instance;

public EvilBoat(MWorld world)
: base(world)
{
this.UserCollisionFlag = 2;
Precache();

MyModel = new MModel();
StaticModel.CreateNewInstance(MyModel);
//Declare Physics and Collision flags
CollisionFlags = COLLISION_FLAGS.CF_BBOX;
PhysicsFlags = PHYSICS_FLAGS.PHYS_PUSHABLE | PHYSICS_FLAGS.PHYS_ONBLOCK_CLIMBORSLIDE;

if (!MHelpers.EditorMode)
{

// set the player's collision box size
SetCollisionBox(new MVector(-DemoPlayerBoxWidth, -DemoPlayerBoxHeight / 2, -DemoPlayerBoxWidth),
new MVector(DemoPlayerBoxWidth, 0, DemoPlayerBoxWidth));

//SetCollisionModel(MyModel);
}

//Create the arrays for bobbing.
for (int i = 0; i < sin.Length; i++)
{
sin[i] = (float)Math.Sin(Math.PI / 540 * i) * -.2f;
cos[i] = (float)Math.Cos(Math.PI / 540 * i) * -2.2f;
}


Instance = this;


}

private float angle;
private MVector turn;
private MVector newDirection;
private MMatrix storeRotation;
public override void Tick()
{
//MHelpers.Printf("m1: " + Rotation.m2 + "cur: " + curDirection);
storeRotation = Rotation;

if (GameCore.Game.LocalAvatar != null)
{
if (!WillCollide())
Rotation = RotateToBoat(theBoat.Instance.Location - Location);
else
Rotation = storeRotation;

}

MVector dir = new MVector();

dir += Rotation.GetDir();
if (AIHelpers.GetDistance2D(theBoat.Instance.Location, Location) > 50 && AIHelpers.GetDistance2D(theBoat.Instance.Location, Location) < 1000)
{
this.Velocity = dir * MHelpers.DeltaTime * 10;

}
else
{

Velocity = new MVector(0,0,0);
}

Location += Velocity;
if (FireTimer > 0)
{
FireTimer -= MHelpers.DeltaTime;
}

if (AIHelpers.GetDistance2D(theBoat.Instance.Location, Location) < 150 && FireTimer <0)
{
FireTimer = 2;
Fire();
}
base.Tick();
}
int dir;

//FIIIIRE!
public void Fire()
{
dir = 2;
cannonball = new EvilCannonball(MyWorld, Location, dir, 0.5f, this);
}

public bool WillCollide()
{
//Get the collision info
MCollisionInfo info = new MCollisionInfo();



MMatrix check;

//Vector for current camera location
MVector evilNow = this.Location ;
MVector pos = evilNow;
pos += Velocity;


//Test if the camera has collided with the terrain
if (MyWorld.CollisionCheckRay(this, evilNow, pos, MCheckType.CHECK_EVERYTHING , info))
{

return true;
}


return false;
}


// TOUCHED

public float RotationSpeed = 1.0f;
protected MVector curDirection = new MVector(0, 0, 1);
MMatrix checkTurn;
private float yaw;
public MMatrix RotateToBoat(MVector direction)
{

newDirection = direction;
newDirection.y = 0;

newDirection.Normalize();


if (curDirection.x < newDirection.x)
{
yaw += RotationSpeed;
curDirection.x += RotationSpeed;
if (curDirection.x > newDirection.x)
{
curDirection.x = newDirection.x;

}
}
else if (curDirection.x > newDirection.x)
{
yaw += RotationSpeed;
curDirection.x -= RotationSpeed;
if (curDirection.x < newDirection.x)
{
curDirection.x = newDirection.x;

}
}

if (curDirection.z < newDirection.z)
{

curDirection.z += RotationSpeed;
if (curDirection.z > newDirection.z)
{

curDirection.z = newDirection.z;
}
}
else if (curDirection.z > newDirection.z)
{

curDirection.z -= RotationSpeed;
if (curDirection.z < newDirection.z)
{

curDirection.z = newDirection.z;
}
}


checkTurn = MMatrix.LookTowards(curDirection);
return checkTurn;


}

public MVector CurDirection
{
get {return curDirection;}
set { curDirection = value; }

}


public override void PreRender(MCamera camera)
{
Bob();

}

private float turnMotion = .0f;
MVector BobVector = new MVector();
int Index = 0;
public void Bob()
{
if (Index == sin.Length)
Index = 0;

MVector noYdir = Rotation.GetDir();
noYdir.y = 0;

MMatrix temp = MMatrix.LookTowards(noYdir.Normalized());


this.Location.y = sin[Index] + 1f; //Wave Simulation; Sin wave for up/down


temp.Rotate(cos[Index], 0, cos[Index] * this.turnMotion);
MyModel.SetTransform(temp, Location);

this.turnMotion = .0f;
Index++;

}
}

[This message has been edited by skynes (edited July 06, 2007).]

[This message has been edited by skynes (edited July 06, 2007).]

Skynes
Member

Posts: 202
From: Belfast, N Ireland
Registered: 01-18-2004
A mentor pointed out the flaw in my code.

Velocity =

should be

Velocity +=

that one character stopped all physics being applied to EvilBoat, forcing me to do Location += Velocity.

*beats himself on head*

curse my inexperience of games programming...

GUMP

Member

Posts: 1335
From: Melbourne, FL USA
Registered: 11-09-2002
heh, well, I didn't notice that myself in the code you posted. I had assumed you had a separate box mesh for collision and presumed it to be similar to Smite.

[This message has been edited by gump (edited July 06, 2007).]