Celarion

07-10-2006, 05:27 AM

Hey guys, I've created the following code in preparation for a flocking AI system for Era. There is a problem, however, that when I spawn multiple instances (or even create separate autonomous NPCs), their variables become entangled (they move in exactly the same manner at exactly the same time). Is there any way to ensure that the variables are unique for every instance of the class?

// Created by Frans N Henskens (*Celarion)

// Last Modified 10/07/06 15:22

// Boid NPC

// Uses attraction, repulsion avoidance and

// guidance rules to simulate flocking

// and targetseeking/avoiding behaviour.

//

// Currently reduces a base desired movement vector to

// a desired movement angle, applies trigonometric

// functions to retrieve a unit vector,

// applies acceleration then adds this to current

// velocity vector.

// This is checked against and constrained by a

// maximum velocity vector.

//

// To Do:

// Implement boid rules of separation, alignment and cohesion

// Assign appropriate biases to each of the resultant vectors

// Replace target point with sum of weighted rule vectors to

// achieve desired movement angle.

// Possibly implement breaking, "perching"

//

// Long Term:

// Implement advanced rules: predators, pathways, prey/food.

//

// Algorithm Complexity (On^2)

//

// NOTE: In Graal, the y-axis is inverted (counting up in a

// downwards direction from the top-left of the screen)

// Thus, all calculations to do with the y-axis have to be

// negated.

function onCreated()

{

// DEPRECATED

targets = {23,17};

// Initialise variables

z = -1;

velocity = {0,0};

// viewRadius = 7;

// personalSpaceRadius = 3;

acceleration = 1;

maxVelocity = 3;

granularity = 0.05;

distanceThreshold = 3;

// owner = "Celarion";

showcharacter();

headimg = "head3.png";

bodyimg = "body13.png";

setcharani("sit", " ");

// setimg("era_hachibluering.png");

setshape(1,0,0);

message(" ");

// Set timer to start behavioural thread

setTimer(granularity);

}

function getUnitVector(vec) {

angle = getangle(vec[0], vec[1]);

calcVec[0] = cos(angle);

calcVec[1] = -sin(angle);

return calcVec;

}

function onPlayerEnters() {

onTimeout();

}

function onTimeOut() {

// DEPRECATED

// Calculate desired movement vector

found = 0;

spl = findplayer(owner);

if (spl != "")

{

found = 1;

targets[0] = spl.x;

targets[1] = spl.y;

if (level.name != spl.level.name) {

this.warpto(spl.level.name, targets[0], targets[1]);

}

}

if (found == 0) {

velocity = {0,0};

setTimer(3);

return;

}

dist[0] = targets[0] - x;

dist[1] = targets[1] - y;

// Locate boids

// Calculate rule 1 :: Separation

// Calculate rule 2 :: Cohesion

// Calculate rule 3 :: Alignment

// Calculate resultant rule vector

// Calculate unit vector for resultant velocity

uv = getUnitVector(dist);

velocity[0] += acceleration * uv[0];

velocity[1] += acceleration * uv[1];

// Check resultant velocity vector amplitude against max velocity

if ((velocity[0]^2 + velocity[1]^2)^(1/2) > maxVelocity) {

uv = getUnitVector(velocity);

velocity[0] = maxVelocity * uv[0];

velocity[1] = maxVelocity * uv[1];

}

// Apply resultant movement vector

x = x + velocity[0];

y = y + velocity[1];

// Set timer to start next behavioural thread

setTimer(granularity);

}

function onPlayerChats()

{

if (player.chat.starts("/"))

{

toks = player.chat.tokenize();

if (toks[0] == "/destroy")

{

if (owner == toks[1])

{

destroy();

}

}

}

}

Thanks!

Frans

// Created by Frans N Henskens (*Celarion)

// Last Modified 10/07/06 15:22

// Boid NPC

// Uses attraction, repulsion avoidance and

// guidance rules to simulate flocking

// and targetseeking/avoiding behaviour.

//

// Currently reduces a base desired movement vector to

// a desired movement angle, applies trigonometric

// functions to retrieve a unit vector,

// applies acceleration then adds this to current

// velocity vector.

// This is checked against and constrained by a

// maximum velocity vector.

//

// To Do:

// Implement boid rules of separation, alignment and cohesion

// Assign appropriate biases to each of the resultant vectors

// Replace target point with sum of weighted rule vectors to

// achieve desired movement angle.

// Possibly implement breaking, "perching"

//

// Long Term:

// Implement advanced rules: predators, pathways, prey/food.

//

// Algorithm Complexity (On^2)

//

// NOTE: In Graal, the y-axis is inverted (counting up in a

// downwards direction from the top-left of the screen)

// Thus, all calculations to do with the y-axis have to be

// negated.

function onCreated()

{

// DEPRECATED

targets = {23,17};

// Initialise variables

z = -1;

velocity = {0,0};

// viewRadius = 7;

// personalSpaceRadius = 3;

acceleration = 1;

maxVelocity = 3;

granularity = 0.05;

distanceThreshold = 3;

// owner = "Celarion";

showcharacter();

headimg = "head3.png";

bodyimg = "body13.png";

setcharani("sit", " ");

// setimg("era_hachibluering.png");

setshape(1,0,0);

message(" ");

// Set timer to start behavioural thread

setTimer(granularity);

}

function getUnitVector(vec) {

angle = getangle(vec[0], vec[1]);

calcVec[0] = cos(angle);

calcVec[1] = -sin(angle);

return calcVec;

}

function onPlayerEnters() {

onTimeout();

}

function onTimeOut() {

// DEPRECATED

// Calculate desired movement vector

found = 0;

spl = findplayer(owner);

if (spl != "")

{

found = 1;

targets[0] = spl.x;

targets[1] = spl.y;

if (level.name != spl.level.name) {

this.warpto(spl.level.name, targets[0], targets[1]);

}

}

if (found == 0) {

velocity = {0,0};

setTimer(3);

return;

}

dist[0] = targets[0] - x;

dist[1] = targets[1] - y;

// Locate boids

// Calculate rule 1 :: Separation

// Calculate rule 2 :: Cohesion

// Calculate rule 3 :: Alignment

// Calculate resultant rule vector

// Calculate unit vector for resultant velocity

uv = getUnitVector(dist);

velocity[0] += acceleration * uv[0];

velocity[1] += acceleration * uv[1];

// Check resultant velocity vector amplitude against max velocity

if ((velocity[0]^2 + velocity[1]^2)^(1/2) > maxVelocity) {

uv = getUnitVector(velocity);

velocity[0] = maxVelocity * uv[0];

velocity[1] = maxVelocity * uv[1];

}

// Apply resultant movement vector

x = x + velocity[0];

y = y + velocity[1];

// Set timer to start next behavioural thread

setTimer(granularity);

}

function onPlayerChats()

{

if (player.chat.starts("/"))

{

toks = player.chat.tokenize();

if (toks[0] == "/destroy")

{

if (owner == toks[1])

{

destroy();

}

}

}

}

Thanks!

Frans