FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Topics & Contributions
   Responsive Form, Games
(Moderator: REAS)
   Rotation-calculating.
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: Rotation-calculating.  (Read 1903 times)
sinkblot

sinkblot
Rotation-calculating.
« on: May 3rd, 2004, 8:56am »

I have a simple game-type thing which I've been using to learn various behaviors -  but I'm gummed down on what I think is a very simple operation.  Each object has a current rotation [ r1 ] and a target rotation [ r2 ] - at the moment, the target rotation is the atan2 of the mouse position, but of course now I can't figure out how to aim the current rotation towards the target at a set speed.    Meaning, it does that fine, but if the r2 passes TWO_PI it resets and the object rotates all the way around the opposite direction to match.
 
I don't like to post such simple questions, but after an hour of searching the threads I get frustrated.
 
Thanks a million.
 
 
/*_gm03 for behaviors and interfacing
 
STRIPPED FOR POSTING
*/
 
float rvel=.2;
int tlength=135;
int w,h;
int shiptrack=12;
int shipcount=2;
Ship[] ships;
float gfriction=-.05;
float turnrange=.1;
int dr1=130;
void setup(){
  size(300,200);
 
  ships = new Ship[shipcount];
  for (int j=0;j<shipcount;j++)ships[j]=new Ship( j , "Barthes" );
  w=width;
  h=height;
  rectMode(CENTER_DIAMETER);
  ellipseMode(CENTER_DIAMETER);
  fill(255,255,255,100);
 
}
 
void loop(){
  background(155);
 
  for(int j=0;j<shipcount;j++)ships[j].updateship(mouseX,mouseY);
}
 
class Ship{
  int shipnum;
  String shipname;
  int dimx,dimy;
  int behavior;
  float x,y,z,fx,fy,velr,velt,vel1;
  float r1,r2,r3;
  int[] tx= new int[tlength];
  int[] ty= new int[tlength];
 
  float thr;
  Ship(int _shipnum,String _shipname){
    this.shipname=_shipname;
    this.r1=0;  //actual rotation
    this.r2=0;  //targ rotation
    this.x=random(0,width);
    this.y=random(0,height);
    this.shipnum=_shipnum;
    this.dimx=20;
    this.dimy=20;
    this.behavior=1;
    this.vel1=0;
    this.velr=0;
    this.thr=0;
    this.tx=new int[tlength+1];
    this.ty=new int[tlength+1];
  }
 
  void updateship( float newx, float newy){
    //stroke(255,255,0);
    for(int i=0;i<tlength;i++){
 stroke(0,0,0,50);
 
 line(this.tx[i],this.ty[i],this.tx[i+1],this.ty[i+1]);
 //   ellipse(this.tx[i],this.ty[i],10,10);
 this.tx[i]=this.tx[i+1];
 this.ty[i]=this.ty[i+1];
    }
    this.tx[tlength]=int(this.x);
    this.ty[tlength]=int(this.y);
 
    if(this.behavior==1){
 
 float dx=mouseX-this.x;
 float dy=mouseY-this.y;
 this.r2=float(Math.atan2(-dy,-dx));
 
 if(this.r1<this.r2+turnrange&&this.r1>this.r2-turnrange){
   rvel=0;
 }else{
   rvel=.1;
 
   //here is the faulty method
   if(this.r1<this.r2)this.r1+=rvel;
   if(this.r1>this.r2)this.r1-=rvel;
 
   if(mousePressed){
     println("currrotation:" +this.r1);
     println("targrotation:" +  this.r2);
 
   }
 }
 
 if (this.r1>=TWO_PI)this.r1=-TWO_PI;
 if (this.r1<=-TWO_PI)this.r1=TWO_PI;
 
 if (this.r2>=TWO_PI)this.r2=-TWO_PI;
 if (this.r2<=-TWO_PI)this.r2=TWO_PI;
 
 fill(255,255,255,100);
 
 noFill();
 ellipse(this.x,this.y,2*dr1,2*dr1);
 fill(255,255,255,100);
 ellipse(this.x,this.y,20,20);
 line(this.x,this.y,mouseX,mouseY);
 
 
 if(dist(this.x,this.y,mouseX,mouseY)>dr1){
   this.thr+=.1;
 }else{
   if(this.thr>0)this.thr-=.1;
 }
 
 this.vel1+=this.thr;
 
 this.vel1*=.6;
 //this.vel1+=gfriction;
 this.x+=this.vel1*sin(-1*r1-HALF_PI);
 this.y+=this.vel1*cos(-1*r1-HALF_PI);
    }
 
    //wrap
    if(this.x<0)this.x=w;
    if(this.x>w)this.x=0;
    if(this.y<0)this.y=h;
    if(this.y>h)this.y=0;
 
    this.drawship();
  }
 
  void drawship() {
    push();
    translate(this.x,this.y,this.z);
    rotateZ(r1+HALF_PI);
    stroke(0);
    //rect(0,0,10,10);
 
    beginShape(POLYGON);
    vertex(0,dimy);
    vertex(.5*dimx,-.5*dimy);
    vertex(0,0);
    vertex(-.5*dimx,-.5*dimy);
    endShape();
 
    pop();
  }
}
 
mflux

fluxhavoc WWW
Re: Rotation-calculating.
« Reply #1 on: May 3rd, 2004, 10:24am »

Have a function return the normalized angle (0-360) even after your values have become over 360 or even negative.
 
So... let your variable keep your angle the same (any value) so that it could be continuously added or subtracted, but before you use it, convert that number into a normalized value.
 
Here's my normalize function, which works on degrees only:
 
float normalizeHeading(float ang)    //normalizes a heading between 0 and 360
{
  while(ang > 360)ang -= 360;
  while(ang < 0)ang += 360;
  return ang;
}
 
Glen Murphy

WWW Email
Re: Rotation-calculating.
« Reply #2 on: May 3rd, 2004, 3:04pm »

Wouldn't 'ang = ang % 360' be faster?
 
mflux

fluxhavoc WWW
Re: Rotation-calculating.
« Reply #3 on: May 3rd, 2004, 6:10pm »

hmmmmmmmmm you're right... there was some reason I resorted to while loops.  
 
*thinks*
 
narain


Re: Rotation-calculating.
« Reply #4 on: May 4th, 2004, 6:34am »

I'm not sure that'll work, mflux... The function will do what it's supposed to do, but it won't solve the problem.
 
The problem is that when you're at angle 340', and you want to get to 30', you shouldn't decrease the angle but increase it; you should go via 340' -> 360'/0' -> 30'. You should pass Go, and you should collect $200.
 
So you need to find the direction of turn which will take you through the smallest turning angle.
 
This function will do it:
 
Code:
float turnAngle (float current, float target) {
  // assuming current and target are both between 0 and TWO_PI
  float angle = target - current;
  if (angle > PI) angle -= TWO_PI;
  if (angle < -PI) angle += TWO_PI;
  return angle;
}

This will tell you both how much to turn and in what direction. You can call this and check if it is greater than or less than zero in your "faulty method".
 
mflux

fluxhavoc WWW
Re: Rotation-calculating.
« Reply #5 on: May 4th, 2004, 7:38am »

my way actually works, just not terribly efficient. your way is much much better, but I didn't think about it back then when I ran into this same problem
 
thanks for sharing
 
sinkblot

sinkblot
Re: Rotation-calculating.
« Reply #6 on: May 5th, 2004, 8:20pm »

They all work beautifully - thanks so much!
 
Markavian

Markavian+iTX WWW
Re: Rotation-calculating.
« Reply #7 on: May 20th, 2004, 11:35am »

I was dealing with a similar problem. I had 24 photos of a model being rotated on a turn table. The viewer (which I wrote in flash) turned to different points on the model based on buttons (front - back - left - right). I wanted it to turn to the point through the shortest distance.
 
The shortest distance is the direction to turn in. So, calculate the distance in both directions, pick the closest, and then turn in that direction.
 
The problem I had was working out the closest. The way I solved it was to first balance the distance to  
the target within my range, so:
 
Code:
range = 24;   // total frames/angle
current = 10; //(angle/value/frame)
target = 22;  // target to get to
 
if(target >= current ) {
  balanced_target = target - current;  
} else {
  balanced_target = target - current + range;
}

 
so:
 
Code:
0 <= balanced_target < range;

 
Then, I could make a decision based on the balanced value:
 
Code:
if(balanced_target <= (range/2)) {
  current++; // Turn one way
} else {
  current--; // Turn the other way
}

 
..and so, the animation would turn towards the target in the closest direction. This code was in a loop, and was ran until current == target, then it stopped.
 
 
This is the same as narain said, but he used 2PI as his range (360 degrees), I'm using a variable range. Either way, you can easily convert the value across depending on if you need an exact angle, or need a precise animation frame.
 
Pages: 1 

« Previous topic | Next topic »