'Spin the bottle' - 360 degrees with PVector

Can someone please tell me what I’m missing here to make this spin 360 degrees. I was able to do it without using PVectors but it doesn’t seem to work when I alter with code with PVectors. I’m still just getting the hang of them.

In the end, I want to produce a ‘spin the bottle’ type of loop but for now, this much would do - have it spin.

Thanks!


PVector radius; 
PVector angle; 
PVector aVel; 
PVector aAccel; 

void setup () {
  size (600, 600);
}

void draw () {
  background (255); 

  PVector location = new PVector (0.0, 0.0);
  PVector aVel = new PVector (0.0, 0.0); 
  PVector aAccel = new PVector (0.0, 0.0); 
  PVector radius = new PVector (150.0, 0.0);
  PVector angle = new PVector (0.0, 0.0); 

  translate (width/2, height/2); 

  location.x= radius.x * cos(angle.x); 
  location.y = radius.x * sin(angle.x); 
  fill (0); 
  stroke (0); 
  line (0, 0, location.x, location.y); 
  ellipse (location.x, location.y, 50, 50); 

  angle.add(aVel); 
  aVel.add(aAccel); 
}

My initial code is a copy from Daniel Schiffman’s video youtube video. It works.



float r = 150; 
float a = 0.0;

float aVel = 0.0; 
float aAccel = 0.001; 

void setup () {
  size (600,600); 
}

void draw () {
  background (255); 
  
  translate (width/2, height/2); 
  float x = r * cos(a); 
  float y = r * sin(a); 
  
  fill (0); 
  stroke (0); 
  line (0,0, x,y); 
  ellipse (x,y,50,50); 
  
  
  a += aVel; 
  aVel += aAccel; 
  aVel = constrain(aVel, 0,0.35); 

  
}



Hi @acousticer,

Issue is here …

You need to declare it outside of draw an modify only the values in draw, otherwise it will be always set to the declared values and the code below …

…has no effect.

Cheers
— mnse

PS: s.th like this should work…

PVector radius; 
PVector angle; 
PVector aVel; 
PVector aAccel; 
PVector location;

void setup () {
  size (600, 600);
  location = new PVector (0.0, 0.0);
  aVel = new PVector (0.0, 0.0); 
  aAccel = new PVector (0.0, 0.0); 
  radius = new PVector (150.0, 0.0);
  angle = new PVector (0.0, 0.0); 
}

void draw () {
  background (255); 
  translate (width/2, height/2); 

  location.x= radius.x * cos(angle.x); 
  location.y = radius.x * sin(angle.x); 
  fill (0); 
  stroke (0); 
  line (0, 0, location.x, location.y); 
  ellipse (location.x, location.y, 50, 50); 

  angle.add(aVel); 
  aVel.add(aAccel); 
}

PPS: also your velocity and acceleration is 0 now (0+0=0). Fill with proper values …

It worked @mnse. Thanks a lot! In hindsight, I should’ve noticed this. Glad that you spotted it.

Could you give me advice on this next part too? I am hoping to have the background change colour to different colours each time the ball overlaps with another ball. The balls are from the same class and I have an ‘overlap’ function. It worked in an earlier iteration but no longer works now that I’ve implemented PVector.

The issue seems to be that everything happens at the start of the sketch and then never happens again.

This is my main sketch.

// MAIN SKETCH
PVector radius; 
PVector angle; 
PVector aVel; 
PVector aAccel; 
PVector location;

myObject movingBall; 
myObject a1;
myObject a10; 

void setup () {
  size (600, 600);
  background (255); 
  fill (0); 
  stroke (0); 

  location = new PVector (0.0, 0.0);
  aVel = new PVector (0.01, 0.0); 
  aAccel = new PVector (0.1, 0.0); 
  radius = new PVector (150.0, 0.0);
  angle = new PVector (0.0, 0.0); 

  movingBall = new myObject(0, 0, 30);
  a1 = new myObject (0, 0, 30);
  a10 = new myObject (0, 0, 30);
}

void draw () {


  // WHEN MOVING BALL OVERLAPS ANOTHER BALL, CHANGE BACKGROUND
  if (movingBall.overlaps(a1)) {
    background (255);
  } else if (movingBall.overlaps(a10)) {
    background (100);
  } else {
    background (180);
  }


  translate (width/2, height/2); 

  // ADDING FORCE 
  //PVector f = new PVector (0,0.1); 
  //aVel.add(f); 


  // Moving line 
  location.x= radius.x * cos(angle.x); 
  location.y = radius.x * sin(angle.x); 
  line (0, 0, location.x, location.y); 


  // Moving Ball 
  movingBall.location.x= radius.x * cos(angle.x); 
  movingBall.location.y = radius.x * sin(angle.x); 
  ellipse (movingBall.location.x, movingBall.location.y, movingBall.mass*movingBall.diameter, movingBall.mass*movingBall.diameter); 


  // Static balls 
  ellipse (a1.location.x+100, a1.location.y-100, 50, 50); 
  ellipse (a10.location.x-110, a10.location.y+110, 50, 50); 


  // ADDING FRICTION 
  //PVector friction = aVel.get(); 
  //friction.normalize(); 
  //friction.mult(-1); 
  //float c = -0.01; 
  //friction.mult(c); 
  //m.applyForce (c);  


  movingBall.display(); 
  a1.display();
  a10.display();


  angle.add(aVel); 
  //aVel.add(aAccel);
  //aVel.limit(0.2);
}

And, this is my class:

class myObject {


  float diameter; // So declare your variable
  float c1 = 180; 
  float c2 = 0; 

  PVector location; 
  PVector aVel; 
  PVector aAccel; 

  float mass; 

// CONSTRUCTOR
  myObject (float xPosit, float yPosit, float tempD) {

    location = new PVector (0, 0); 
    aVel = new PVector (0, 0); // Start at 0
    aAccel = new PVector (0, 0); // Start at 0

    location.x = xPosit; 
    location.y = yPosit;
    diameter = tempD; //

    mass = 1; //
    fill (0); 
  }


// OVERLAP FUNCTION 
  boolean overlaps (myObject other) {
    float d = dist(location.x, location.y, other.location.x, other.location.y); 
    if (d < diameter/2 + other.diameter/2) {
      return true;
    } else {
      return false;
    }
  }


  void display () {
    
    aVel.add(aAccel); 
    location.add(aVel); 
   
    aAccel.mult(0); // Clear out at end of every frame 
  }


  void applyForce (PVector force) {

    aAccel.add(force);
  }
} // END

Hello @acousticer ,

You need to compare the two locations directly.

You are adding values to the location when displaying the ellipse and this will not work because the ellipse that is displayed is not at the location that you are comparing to.

Example with just PVectors:

PVector v0, v1;

void setup () 
  {
  size (500, 200);
  background(255); 
  fill(0); 
  noStroke(); 

  v0 = new PVector(0, height/2);
  v1 = new PVector (width/2, height/2);
  }

void draw () 
  { 
  if (v0.dist(v1) < 35)
    background(128, 255, 255);
  else
    background(255, 228, 255);
  
  // Moving
  circle (v0.x, v0.y, 20); 

  // Static balls 
  circle (v1.x, v1.y, 50);
  
  v0.x += 2;
  
  if (v0.x > width) 
    v0.x = 0;
  }

:)

@mnse @glv Thanks for helping me! Could you please take a look over the code again? I’ve made some changes and have realised that I won’t need to implement forces, but I am still having trouble with this overlap function since I restarted. I know that it should work but I can’t figure it out why it’s not. I hope that you don’t mind. Thanks in advance!

The background should change to a different colour when the mover hits a ‘bob’.

bob a1; 
bob a2; 
bob a3; 
bob a4; 
bob a5; 
bob a6; 
bob a7; 
bob a8; 
bob a9; 
bob a10; 
bob a11; 
bob a12; 

bob mover; 


void setup () {
  size(600, 600); 

  a1 = new bob(0, 0, 0, 0); 
  a2 = new bob(0, 0, 30, 0); 
  a3 = new bob(0, 0, 60, 0); 
  a4 = new bob(0, 0, 90, 0); 
  a5 = new bob(0, 0, 120, 0); 
  a6 = new bob(0, 0, 150, 0); 
  a7 = new bob(0, 0, 180, 0); 
  a8 = new bob(0, 0, 210, 0); 
  a9 = new bob(0, 0, 240, 0); 
  a10 = new bob(0, 0, 270, 0); 
  a11= new bob(0, 0, 300, 0); 
  a12 = new bob(0, 0, 330, 0);

  mover = new bob(0, 0, 0, color(255, 255, 0));
}


void draw() {

  background (255); 
  mover.rot += 1; 


  if (mover.overlaps(a1)) {
    background (180);
  } else  if 
    (mover.overlaps(a2)) {
    background (40);
  } else  if 
    (mover.overlaps(a3)) {
    background (20);
  }

  a1.display(); 
  a2.display();
  a3.display(); 
  a4.display(); 
  a5.display();
  a6.display(); 
  a7.display(); 
  a8.display();
  a9.display(); 
  a10.display(); 
  a11.display();
  a12.display(); 

  mover.display();

}

And my class:

class bob {

  PVector loc; //location 
  float l = 100; // length
  float rot;  // rotate
  float r=40; // radius
  color c = color(0, 0, 0); 
  float a = 0; 

  bob (float tempX, float tempY, float tempRot, color tempC) {

    loc=new PVector(0, 0); 

    loc.x = tempX; 
    loc.y = tempY; 

    rot = tempRot; 
    c = tempC; 



    loc.x = loc.x+l*sin(a); 
    loc.y = loc.x+l*cos(a);
  }


  boolean overlaps (bob other) {
    float d = dist (loc.x, loc.y, other.loc.x, other.loc.y); 
    if (d < 35) {
      return true;
    } else {
      return false;
    }
  }

  void display() {


    fill (c); 

    pushMatrix();
    translate (width/2, height/2); 
    rotate(radians(rot)); 
   ellipse (loc.x,loc.y,r,r); 

    popMatrix();
  }
}

Hello @acousticer,

A transformation does not change the value of variables and only transforms them:

image

Changes made to get this working:

// draw()
 translate (width/2, height/2); 
 mover.a += radians(1);
// class
  void display() 
    {
    fill (c); 
    loc.x = l*sin(a); 
    loc.y = l*cos(a);
    ellipse (loc.x,loc.y, r, r); 
    }

You can complete the missing code.

References:

:)