Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > New Scripting Engine (GS2)
FAQ Members List Calendar Today's Posts

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 07-10-2006, 04:27 AM
Celarion Celarion is offline
void cel() {awesome++;}
Celarion's Avatar
Join Date: Feb 2006
Location: Australia
Posts: 40
Celarion is on a distinguished road
Variables in arrays not unique across multiple instances.

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?

Quote:
// 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
Reply With Quote
  #2  
Old 07-10-2006, 06:28 PM
upsilon upsilon is offline
Shmoo
upsilon's Avatar
Join Date: Dec 2005
Location: Birmingham, Alabama
Posts: 58
upsilon is on a distinguished road
I think you should qualify the object-local variables with 'this.'. I dont really know the default scope of unqualified variable in the body of functions/events, but i think it either makes them class local, or even global variables.
NPC Code:

this.acceleration = 1;
this.granularity = 0.05;
... etc



and i think the general convention for function local-variable, is to just make them members of the temp object, like:

NPC Code:

function foo(x,y) {
temp.baz = x*y;
this.bar = temp.baz * 11;
}


to avoid unintentionally over writing global variables with the same name.
__________________
Health nuts are going to feel really stupid someday, lying in hospitals dying of nothing. - Redd Foxx

Last edited by upsilon; 07-10-2006 at 06:46 PM..
Reply With Quote
  #3  
Old 07-12-2006, 02:03 AM
ApothiX ApothiX is offline
Okiesmokie
Join Date: May 2004
Posts: 1,447
ApothiX is on a distinguished road
@upsilon: The default scope for un-prefixed is global. They can be accessed by any script that is currently running.
__________________


[06:24:19] * Parts: Skyld (i=silent@unaffiliated/skyld) ("Perhaps Okiesmokie did not realise that I like the boys. ")
Reply With Quote
  #4  
Old 07-12-2006, 02:51 PM
Celarion Celarion is offline
void cel() {awesome++;}
Celarion's Avatar
Join Date: Feb 2006
Location: Australia
Posts: 40
Celarion is on a distinguished road
I tried prefixing the variables with "this.". The entire thing stopped working. Perhaps I missed something.
*shrugs*
Reply With Quote
  #5  
Old 07-12-2006, 05:51 PM
upsilon upsilon is offline
Shmoo
upsilon's Avatar
Join Date: Dec 2005
Location: Birmingham, Alabama
Posts: 58
upsilon is on a distinguished road
Quote:
Originally Posted by ApothiX
The default scope for un-prefixed is global. They can be accessed by any script that is currently running.
07-10-2006 11:28 AM
gotcha

Quote:
Originally Posted by Celarion
I tried prefixing the variables with "this.". The entire thing stopped working. Perhaps I missed something.
Im guessing they just arent moving? or are they not even drawing? if you could, just paste what you have now, maybe something will stick out.

without seeing the code, all i can think of, is that maybe you qualified the variables x and y wrong when you were prefixing things. If it worked before without those prefixed, i would leave those two as they were originally.
__________________
Health nuts are going to feel really stupid someday, lying in hospitals dying of nothing. - Redd Foxx
Reply With Quote
  #6  
Old 07-13-2006, 08:39 PM
jake13jake jake13jake is offline
Former Classic Staff
jake13jake's Avatar
Join Date: Dec 2002
Location: Northwest Vermont
Posts: 1,452
jake13jake will become famous soon enough
the scope of non-prefixed vars:
An NPC's static variables - local to the NPC (can be written x= or this.x=).
Any other vars that are built-in (ex. players, npcs arrays)
A function parameter- local to the function.
Otherwise, it's a global variable that all scripts share.

If you're using a variable temporarily, like send some data into a function and simply returning a value, I'd use a temp.var.
Reply With Quote
  #7  
Old 08-21-2006, 02:58 AM
Celarion Celarion is offline
void cel() {awesome++;}
Celarion's Avatar
Join Date: Feb 2006
Location: Australia
Posts: 40
Celarion is on a distinguished road
Okay, so I've scoped the vars properly with this. now, and that works fine for individually spawned NPC objects.

There is, however, still the same problem when instantiating instances of this code as a class - despite this.name attribute being unique for each instance. I believe that there may be an issue with the compiler/interpreter for the scripting language w/r/t classes: Perhaps only copying array header/reference when instantiating objects (thus leaving the reference to the start of the first array, rather than creating a new array for each object)?

Awesome if it could be fixed, anyway.

Cheers,
Cel

PHP Code:
// 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.Celarion
// 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
  
this.= -1;
  
this.dist = {0,0};
  
this.uv = {0,0};
 
//  viewRadius = 7;
//  personalSpaceRadius = 3;
  
this.acceleration 1;
  
this.maxVelocity 3;
  
this.granularity 0.05;
  
this.distanceThreshold 3
  
this.owner "Celarion";
  
showcharacter();
  
this.headimg "head3.png";
  
this.bodyimg "body13.png";
  
setcharani("sit"" ");
//  setimg("era_hachibluering.png");
  
setshape(1,0,0);
  
message(" ");
  
// Set timer to start behavioural thread
  
setTimer(this.granularity);
}

function 
getUnitVector(vec) {
  
temp.angle getangle(vec[0], vec[1]);
  
temp.calcVec = {cos(temp.angle), -sin(temp.angle)};
  return 
temp.calcVec;
}
function 
onPlayerEnters() {
  
onTimeout();
}
function 
onTimeOut() {
// DEPRECATED
  // Calculate desired movement vector
//  findplayer("Celarion").chat = "Owner: " @ this.target.name @ ", " @ "Targets: x=" @ this.targets[0] SPC "y=" @ this.targets[1] @ ", Distances: x=" @ this.dist[0] @ ", y=" @ this.dist[1];
  
this.target findplayer(this.owner);
  if (
this.target != "")
  {
    
this.targets = {this.target.xthis.target.y};
    if (
this.level.name != target.level.name) {
      
warpto(target.level.namethis.targets[0], this.targets[1]);
    }
  } else {
    
this.velocity = {0,0};
    
setTimer(0);
    return;
  }
  
this.dist = {this.targets[0] - this.xthis.targets[1] - this.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
  
this.uv getUnitVector(this.dist);
  
this.velocity[0] += this.acceleration this.uv[0];
  
this.velocity[1] += this.acceleration this.uv[1];

  
// Check resultant velocity vector amplitude against max velocity
  
if ((this.velocity[0]^this.velocity[1]^2)^(1/2) > this.maxVelocity) {
    
this.uv getUnitVector(this.velocity);
    
this.velocity = {this.maxVelocity this.uv[0], this.maxVelocity this.uv[1]};
  }
  
  
// Apply resultant movement vector
  
this.this.this.velocity[0];
  
this.this.this.velocity[1];

  
// Set timer to start next behavioural thread
  
setTimer(this.granularity);
}

function 
onPlayerChats()
{
  if (
player.chat.starts("/"))
  {
    
temp.toks player.chat.tokenize();
    if (
temp.toks[0] == "/destroy")
    {
      if (
this.owner == temp.toks[1])
      {
        
destroy();
      }
    }
  }

EDIT:: Thanks Skyld.

Last edited by Celarion; 08-21-2006 at 02:27 PM.. Reason: Edited to PHP tags
Reply With Quote
  #8  
Old 08-21-2006, 06:04 AM
ApothiX ApothiX is offline
Okiesmokie
Join Date: May 2004
Posts: 1,447
ApothiX is on a distinguished road
Use code tags to post code, not quote tags. That is extremely hard to read in the state that it's in.
__________________


[06:24:19] * Parts: Skyld (i=silent@unaffiliated/skyld) ("Perhaps Okiesmokie did not realise that I like the boys. ")
Reply With Quote
  #9  
Old 08-21-2006, 12:55 PM
xXziroXx xXziroXx is offline
Master of Puppets
xXziroXx's Avatar
Join Date: May 2004
Location: Sweden
Posts: 5,288
xXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant future
Send a message via AIM to xXziroXx Send a message via MSN to xXziroXx
Or even better, PHP tags.
__________________

"A delayed game is eventually good, but a rushed game is forever bad." - Shigeru Miyamoto
Reply With Quote
  #10  
Old 08-21-2006, 02:28 PM
Celarion Celarion is offline
void cel() {awesome++;}
Celarion's Avatar
Join Date: Feb 2006
Location: Australia
Posts: 40
Celarion is on a distinguished road
Thanks for that tip.
Is my code faulty, or is the engine lacking that functionality. If the latter is so, do you know of any workarounds I could implement?
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 12:14 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.