Parabolic projectile launch


#1

I,m trying to change the value of vi using left&rigth arrows and the theta value with up&down arrows, but i don’t know exactlu how to do it.

The code is the following

// based on Projectile Simulation by Hugo Meiring
// Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
// https://www.openprocessing.org/sketch/147483

Ball cannonball = new Ball(140, 0, 0, 20);
float time = 0;
boolean stop;


void setup() {
  size(1400, 550);
  background(0);
  fill(255, 90);
  stroke(255);
  //noStroke();
  smooth();
  frameRate(100);
  //textAlign(CENTER);
  stop = false;
  
  /*cannon = createShape();
  cannon.beginShape();
  cannon.fill(70, 70, 255);
  cannon. */
}

void draw() {
  background(0);
  cannonball.update(time);
  if (stop != true) {
    time += 0.01;  
  }
  displayData();
}

void displayData() {
  int pos1 = 20;
  int pos2 = 180;
  int pos3 = 350;
  int pos4 = 530;
  int line1 = 20;
  int line2 = 43;
  int line3 = 66;
  fill(255, 128, 0);
  textSize(20);
  text("R(t) - Position", pos1, line1);
  text("x: " + round(cannonball.getX()) + " m", pos1, line2); 
  text("y: " + round(cannonball.getY()) + " m", pos1, line3); 
  
  text("Projectile info", pos2, line1);
  text("Vi = " + cannonball.getVi() + " m/s", pos2, line2);
  text("Theta = " + cannonball.getTheta() + " °", pos2, line3);
  
  text("Velocity info", pos3, line1);
  text("Vx = " + round(cannonball.getVx()) + " m/s", pos3, line2);
  text("Vy = " + round(cannonball.getVy()) + " m/s", pos3, line3);
  
  text("Other data", pos4, line1);
  text("Time = " + time + " s", pos4, line2);
  fill(255, 90);
}

class Ball {
  float vi, xi, yi;
  float x;
  float y;
  float theta;
  float time;
  
  Ball(float _vi, float _xi, float _yi, float _theta){
    vi = _vi;
    xi = _xi;
    yi = _yi;
    theta = _theta;  
  }
  
  void update(float t){
    if (x >= 0 && x <= width && y >= 0 && y <= height) {
      int radius = 200;
      x = vi * t * cos(radians(theta));
      y = vi * t * sin(radians(theta)) - 4.9 * pow(t, 2);
      ellipse(x + xi, mY(y + yi), 13, 13);
      time = t;
    }
    else { stop = true; }
  }
  
  float getVx() {
    return vi * cos(radians(theta));
  }
  
  float getVy() {
    return vi * sin(radians(theta)) - 9.8 * time;
  }
    
  float getX () { return x; }
  float getY () { return y; }
  float getVi () { return vi; }
  float getTheta() { return theta; }
  float getXi () { return xi; }
  float getYi () { return yi; }
  
}

float mX (float _value) {
  return map(_value, 0, width, width, 0);
}

float mY (float _value) {
  return map(_value, 0, height, height, 0);
}

My intention is replace

Ball cannonball = new Ball(140, 0, 0, 20);

with

Ball cannonball = new Ball(vi, 0, 0, theta);

changed with the arrow keys

I’m a beginner and I have some difficulties.

Thanks a lot


#2

hi,
you describe your wanted operation,
but in the code i not even see
that you start about that coding.

so i must wonder where your above code comes from?
can you give a link??

basically need the key operation

float my_vi = 140, my_theta = 20;

void setup() {
  size(200,200);
  println("use: key arrow UP DOWN for THETA, LEFT RIGHT for VI");
}

void draw() {
  background(200,200,0);
  fill(0);
  text("setpoint: THETA: "+my_theta+" VI "+my_vi,10,height-20);
}

void keyPressed() {
 if ( keyCode == UP )    my_theta++;
 if ( keyCode == DOWN )  my_theta--;
 if ( keyCode == LEFT )  my_vi--;
 if ( keyCode == RIGHT ) my_vi++;
}

#3

Hi, thanks for your reply

Codes come from https://www.openprocessing.org/sketch/147483, but has v0 and theta fixed.

My idea is to use up&down arrows to change theta and left&right arrows to change v0.

Thanks again


#4

thanks for the info:

so legally you steal it!

that code is from Hugo Meiring
from 8.5.2014
and has lic. Creative Commons Attribution ShareAlike
what means in short form you can use it…
but must keep a link to the source in it.


#5

Of course, author will be mentioned as CC BY SA


#6

That’s fine – just include the cc reference when you post. I’ve edited the top post to include it.

About your question: when you say “changed with the arrow keys” what do you mean?


#7

The problem is that this string is run only once as you start the sketch, and after that anything inside the
new Ball(... part of the line is not used, since it doesn’t spawn any new balls.

Do you want to change vi and theta of the already existing ball in the middle of its flight? Or do you want to be able to spawn new balls with custom vi and theta? Or maybe you want to be able to restart the simulation with new vi and theta without actually restarting the whole sketch?

First variant would at least make the simulation less accurate, as it’s rare for balls to change their properties while flying.
Second variant makes more sense, but that means that the sketch would need to have a little rewrite, and all of these numbers on top would have to be worked on, as they can only show info about a single ball - not of multiple at once.
Third variant makes most sense, and doesn’t seem like a huge amount of job. For this, I guess you could just add this to the sketch at the end:

void mousePressed(){
  cannonball = new Ball(mouseX/10, 0, 0, mouseY/10);
  time = 0;
  stop = false;
}

So by pressing left mouse button it restarts the simulation, and uses your mouseX and mouseY coordinates to determine both parameters.


#9

gaah i’m messy with forums sometimes

I’ll triple-post here, as I’ve modified the sketch to use arrows to change vi and theta values as long as you hold them, and pressing ENTER restarts the simulation with the new values:

// based on Projectile Simulation by Hugo Meiring
// Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
// https://www.openprocessing.org/sketch/147483

float defaultVi = 140;
float defaultTheta = 20;

Ball cannonball = new Ball(defaultVi, 0, 0, defaultTheta);
float time = 0;
boolean stop;


boolean pressingUp = false;
boolean pressingDown = false;
boolean pressingLeft = false;
boolean pressingRight = false;


void setup() {
  size(1400, 550);
  background(0);
  fill(255, 90);
  stroke(255);
  //noStroke();
  smooth();
  frameRate(100);
  //textAlign(CENTER);
  stop = false;
  
  /*cannon = createShape();
  cannon.beginShape();
  cannon.fill(70, 70, 255);
  cannon. */
}

void draw() {
  background(0);
  cannonball.update(time);
  if (stop != true) {
    time += 0.01;  
  }
  displayData();
  updateParameters();
}

void displayData() {
  int pos1 = 20;
  int pos2 = 180;
  int pos3 = 350;
  int pos4 = 530;
  int pos5 = 700;
  int line1 = 20;
  int line2 = 43;
  int line3 = 66;
  fill(255, 128, 0);
  textSize(20);
  text("R(t) - Position", pos1, line1);
  text("x: " + round(cannonball.getX()) + " m", pos1, line2); 
  text("y: " + round(cannonball.getY()) + " m", pos1, line3); 
  
  text("Projectile info", pos2, line1);
  text("Vi = " + nf(cannonball.getVi(),0,1) + " m/s", pos2, line2);
  text("Theta = " + nf(cannonball.getTheta(),0,1) + " °", pos2, line3);
  
  text("Velocity info", pos3, line1);
  text("Vx = " + round(cannonball.getVx()) + " m/s", pos3, line2);
  text("Vy = " + round(cannonball.getVy()) + " m/s", pos3, line3);
  
  text("Start params", pos4, line1);
  text("Vi = " + nf(defaultVi,0,1) + " m/s", pos4, line2);
  text("Theta = " + nf(defaultTheta,0,1) + " °", pos4, line3);
  
  text("Other data", pos5, line1);
  text("Time = " + time + " s", pos5, line2);
  fill(255, 90);
}

class Ball {
  float vi, xi, yi;
  float x;
  float y;
  float theta;
  float time;
  
  Ball(float _vi, float _xi, float _yi, float _theta){
    vi = _vi;
    xi = _xi;
    yi = _yi;
    theta = _theta;  
  }
  
  void update(float t){
    if (x >= 0 && x <= width && y >= 0 && y <= height) {
      int radius = 200;
      x = vi * t * cos(radians(theta));
      y = vi * t * sin(radians(theta)) - 4.9 * pow(t, 2);
      ellipse(x + xi, mY(y + yi), 13, 13);
      time = t;
    }
    else { stop = true; }
  }
  
  float getVx() {
    return vi * cos(radians(theta));
  }
  
  float getVy() {
    return vi * sin(radians(theta)) - 9.8 * time;
  }
    
  float getX () { return x; }
  float getY () { return y; }
  float getVi () { return vi; }
  float getTheta() { return theta; }
  float getXi () { return xi; }
  float getYi () { return yi; }
  
}

float mX (float _value) {
  return map(_value, 0, width, width, 0);
}

float mY (float _value) {
  return map(_value, 0, height, height, 0);
}

void keyPressed() {
  if( keyCode == UP ){ pressingUp = true; }
  if( keyCode == DOWN ){ pressingDown = true; }
  if( keyCode == LEFT ){ pressingLeft = true; }
  if( keyCode == RIGHT ){ pressingRight = true; }
  if( keyCode == ENTER ){ restartSimulation(); }
}

void keyReleased() {
  if( keyCode == UP ){ pressingUp = false; }
  if( keyCode == DOWN ){ pressingDown = false; }
  if( keyCode == LEFT ){ pressingLeft = false; }
  if( keyCode == RIGHT ){ pressingRight = false; }
}

void updateParameters() {
  if(pressingUp)   {defaultVi+= 0.4; }
  if(pressingDown) {defaultVi-= 0.4; }
  if(pressingLeft) {defaultTheta+= 0.1; }
  if(pressingRight){defaultTheta-= 0.1; }
}

void restartSimulation() {
  cannonball = new Ball(defaultVi, 0, 0, defaultTheta);
  time = 0;
  stop = false;
}

Long story short, I made myself 4 boolean values, each for every arrow key. Every time you press the key, it gets detected by the keyPressed() function, which turns the corresponding value to true, and as long as it is true, updateParameters() function keeps on changing the parameter until keyReleased() function is triggered.

I agree that it might get tedious to keep on adding new booleans for every single key when you need it, I’ve done it myself at one point. But unless you are interested in using complex solutions(which, considering you are a beginner, you might not get along with), as far as I know, that’s the best way to go.