We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › 3D chase...
Page Index Toggle Pages: 1
3D chase... (Read 1798 times)
3D chase...
Dec 26th, 2009, 7:26pm
 
Hi there, i'm trying to make a small game in 3D.
There is a target and a chaser.
The target moves in space, and the chaser just moves towards the target with a given speed.
I have done the same in 2D, and the code is like that:
/////////
//xpos = position x
//ypos = position y
//tx = target x
//ty = target y
//direction = angle measured on the  X-Y plane.
direction = atan2((ty-ypos),(tx-xpos));
stepx = cos(direction)*speed;
stepy = sin(direction)*speed;
xpos += stepx;
ypos += stepy;
/////////
In 2D it works just fine.
I am currently quite frustrated with the mathematics needed to do the same thing in 3d (which is split the speed in stepx, stepy, stepz according to two angles, one on the X-Y plane, and one on the X-Z or Y-Z plane.). Any assistance would be greatly appreciated.
Re: 3D chase...
Reply #1 - Dec 27th, 2009, 3:08am
 
Use PVector! It has very helpful built-in maths...

Code:
PVector pos = new PVector(x, y, z); 

Re: 3D chase...
Reply #2 - Dec 27th, 2009, 4:01am
 
In 2D, you don't need to work out what the "angle" is to the target. All you need is the vector, scaled to your speed.

This extends easily to 3D.

I was going to write a few lines to show the method, then got carried away making an example (to make sure it works!).

Quote:
Chaser chaser;

// Flag to determine how chaser speed is determined
boolean useLimit = false;

// Use Z dimension?
boolean useZ = true;

void setup()
{
  size(400, 400, P3D);
  frameRate(10);  // slowed down to see motion detail

  chaser = new Chaser();
  chaser.pos = new PVector(width/2, height/2);
}

void draw()
{
  // Chase the mouse
  PVector target = new PVector(mouseX, mouseY);
  
  if (useZ)
    target.z = -300 + 200 * sin(millis() * 0.001);
  
  chaser.chase(target);
  
  // Update display
  background(0);
  
  // Show the target
  pushMatrix();
  
  if (useZ)
  {
    stroke(255);
    line(target.x, target.y, -100, target.x, target.y, -500);
  }
  
  translate(target.x, target.y, target.z);
  noStroke();
  fill(255, 0, 0, 255);
  sphere(10);
  popMatrix();

  // Show the chaser
  chaser.draw();
}

void keyPressed()
{
  switch(key)
  {
    case 'l': case 'L': useLimit = !useLimit; break;
    case 'z': case 'Z': useZ     = !useZ;     break;
  }
}

public class Chaser
{
  PVector pos;
  float speed = 15; // Default speed
  float size = 20;  // Default size
  
  public void chase(PVector target)
  {
    // Get direction (difference between target and
    // current chaser position)
    PVector chaserToTarget = PVector.sub(target, pos);
  
    // We could use normalize() then mult(chaserSpeed), but
    // if the chaser is close to the target then it will keep
    // jumping past the target instead of just arricving at it!
    // limit() will instead limit to magnitude to at most the
    // speed we want in the direction to the target.  
  
    if (useLimit)
    {
      chaserToTarget.limit(speed);
    }
    else
    {
      chaserToTarget.normalize();
      chaserToTarget.mult(speed);
    }
    
    // Move towards the target
    pos.add(chaserToTarget);
  }
  
  public void draw()
  {
    pushMatrix();
    noStroke();
    fill(200, 200, 0, 50);
    translate(pos.x, pos.y, pos.z);
    sphere(size);
    popMatrix();
  }
}


Use the Z key to enable/disable use of the Z dimension.
Use the L key to enable/disable use of the limit() function to stop the chaser overshooting the target

-spxl
Re: 3D chase...
Reply #3 - Dec 27th, 2009, 5:38pm
 
Thanks a lot!
I just run the code and it works just fine...
Didn't get to look at it closely yet, though.
Suppose I 'll be back later with further comments or questions.
Re: 3D chase...
Reply #4 - Dec 28th, 2009, 3:13pm
 
Well, everything seems to work!
Thanks alot, guys! PVector RULES!
I will try to post the code as soon as it is quite readable and commented. I actually used the "chase" idea to make a more complex project. There are many chasers, one target. The chasers are attracted to the target, but also they are negatively attracted to each other. There is a key to make more chasers. The thing works fine up to 200-300 chasers at 60 fps. from there on it starts lagging, but this is no problem for me.
Cya later.
Re: 3D chase...
Reply #5 - Dec 28th, 2009, 10:32pm
 
...and here is the code.
you need to include the font in the folder.
it is one of the standard fonts included in the processing examples
Quote:
//////////////////////////////////////////////
//"Static chaser"
//use TAB to generate chasers
//use WASDQE to move the target
///////////////////////////////////////////////

import processing.opengl.*;

//class init
target tg = new target(-100,-1,0);
grid gr = new grid(0,0,0);
ArrayList balls;
float cntz=0;

void setup() {
 size(640, 480, OPENGL);
 PFont font;
 font = loadFont("CourierNew36.vlw");
 textFont(font);
 frameRate(60);
 PVector Ppos = new PVector(10,10,10);
 balls = new ArrayList();
 balls.add(new ball(Ppos));
}

void draw() {

 lights();
 background(0);
 text(balls.size(), 15, 60);
 cntz++;
 camera(250*sin(radians(cntz/10)), -150+mouseY, 250.0*cos(radians(cntz/10)), // eyeX, eyeY, eyeZ
        0.0, 0.0, 0.0, // centerX, centerY, centerZ
        0.0, 1.0, 0.0); // upX, upY, upZ
 gr.update();
 tg.update();
 PVector Ptarget = new PVector(tg.x,tg.y,tg.z);
 //dual "for loop"
 //move every chaser closer to target
 //move every chaser away from every other chaser
 for(int i = balls.size() -1; i>=0; i--){
   ball bo = (ball) balls.get(i);
   bo.updatetarget(Ptarget);
   for (int j = balls.size()-1; j>=0; j--){
     if (i!=j){
       ball bi = (ball) balls.get(j);
       PVector Pother = new PVector(bi.pos.x,bi.pos.y,bi.pos.z);
       bo.updateother(Pother);
       /*stroke(80,80,158,10);
       line(bo.pos.x,bo.pos.y,bo.pos.z,bi.pos.x,bi.pos.y,bi.pos.z);*/
     }
   }
   bo.display();
 }
}

public class ball{
 PVector pos;
 PVector target;
 PVector other;
 float pspeed;
 float nspeed;
 float csize = 3;
 ball (PVector inpos){
   pos = inpos;
 }
 void updatetarget(PVector intarget){
   target = intarget;
   PVector chaserToTarget = PVector.sub(target, pos);
   //chaserToTarget.limit(pspeed);
   pspeed = chaserToTarget.mag()/55;
   chaserToTarget.normalize();
   chaserToTarget.mult(pspeed);
   pos.add(chaserToTarget);
 }
 void updateother(PVector inother){
   other = inother;
   PVector chaserToOther = PVector.sub(other, pos);
   //chaserToOther.limit(nspeed);
   nspeed = .2-20/chaserToOther.mag();
   chaserToOther.normalize();
   chaserToOther.mult(nspeed);
   pos.add(chaserToOther);
 }
 void display(){
   pushMatrix();
   noStroke();
   fill(255);
   translate(pos.x,pos.y,pos.z);
   box(csize);

   popMatrix();
 }
}

public class grid{
 float x,y,z;
 int i=0; //counter
 int c = 0; //colorizer
 grid(float inx, float iny, float inz) {
   x = inx;
   y = iny;
   z = inz;
 }
 void update(){
   for (i=-100; i<=100; i+=5){ //x-y
     if (i<0) c = i/2;
     else if (i>0) c = -i/2;
     else c = 50;
     stroke (255,255,255,50+c);
     line(-100,i,0,100,i,0);
     line(i,-100,0,i,100,0);
     line(-100,0,i,100,0,i);
     line(i,0,-100,i,0,100);
     line(0,-100,i,0,100,i);
     line(0,i,-100,0,i,100);
   }
 }
}

void keyPressed(){
 if(key == TAB){
   PVector Ppos = new PVector(0,0,0);
   balls.add(new ball(Ppos));
 }
}

public class target{
 float x,y,z;
 target(float inx, float iny, float inz) {
   x = inx;
   y = iny;
   z = inz;
 }
 void update(){
   if (keyPressed){
     if ((key == 'W' )||( key == 'w')){
       y-=5;
       if (y<-100) y = -100;
     }
     if ((key == 'S' )||( key == 's')){
       y+=5;
       if (y>100) y = 100;
     }
     if ((key == 'A' )||( key == 'a')){
       x-=5;
       if (x<-100) x = -100;
     }
     if ((key == 'D' )||( key == 'd')){
       x+=5;
       if (x>100) x = 100;
     }
     if ((key == 'Q' )||( key == 'q')){
       z+=5;
       if (z>100) z = 100;
     }
     if ((key == 'E' )||( key == 'e')){
       z-=5;
       if (z<-100) z = -100;
     }
   }
   pushMatrix();
   noStroke();
   fill(255,0,0,random(255));
   translate(x,y,z);
   box(3);
   popMatrix();
   /*stroke(255,0,0,80);
   line(x,-100,0,x,100,0);//
   line(-100,y,0,100,y,0);//
   line(x,0,-100,x,0,100);//
   line(-100,0,z,100,0,z);//
   line(0,y,-100,0,y,100);//
   line(0,-100,z,0,100,z);//
   stroke(255,0,0,250);
   line(x,y,z,x,y,0);
   line(x,y,z,x,0,z);
   line(x,y,z,0,y,z);*/
 }
}
Re: 3D chase...
Reply #6 - Dec 28th, 2009, 11:22pm
 
The grid is rad - I like it!

I had in mind the idea of having multiple chasers. You can see the project I made after I posted code here on my website. The graphics are a bit ugly (why doesn't OpenGL render this nicely?), but you can mostly see what is going on.

http://subpixels.com/processing/spxlChaser2D3D/
Re: 3D chase...
Reply #7 - Dec 29th, 2009, 8:10am
 
subpixel wrote on Dec 28th, 2009, 11:22pm:
The grid is rad - I like it!

I had in mind the idea of having multiple chasers. You can see the project I made after I posted code here on my website. The graphics are a bit ugly (why doesn't OpenGL render this nicely), but you can mostly see what is going on.

http://subpixels.com/processing/spxlChaser2D3D/


Cool polygon - tail. I might steal your idea.

does anyone have any idea about multiple simultaneous key stroke handling in processing
(for example WASD --> W=up S=down A=left D=right and W+D=up-right etc.)
The standard keyPressed function ony works for interface handling, and not for in-game control so much.
Im not sure in which topic to post that, but it is also useful for this project.
Re: 3D chase...
Reply #8 - Dec 29th, 2009, 8:26am
 
Try a search: this question comes up often enough (e.g. here.  The short answer is use booleans to store the state of the keys and adjust movement based on the value of the booleans.
Re: 3D chase...
Reply #9 - Dec 29th, 2009, 3:52pm
 
blindfish wrote on Dec 29th, 2009, 8:26am:
Try a search: this question comes up often enough (e.g. here.  The short answer is use booleans to store the state of the keys and adjust movement based on the value of the booleans.


Problem solved!
I was using keyPressed inside the class.
With booleans outside it works just fine.
Page Index Toggle Pages: 1