Programming question, pertaining to motion


#1

I have an item obeying the laws of “projectile throw” which travels expected.

If it lands on a ramph(opposite the launch), I want it’s trajectory to change–from the former path, projectile throw, to a normal path up the ramp.

  orangeBall_Vx = orange_initial_velocity * cos(orangeBallAngle);
  orangeBall_Vy = orange_initial_velocity * sin(orangeBallAngle);
  
  orangeBall_x = orangeBall_Vx * orangeBallTime; 
  orangeBall_y = orangeBall_Vy * orangeBallTime - (gravity*orangeBallTime*orangeBallTime/2);

if ((orangeBall_y * M + 105) < ((orangeBall_x*M - 885)*tan(rampAngle))+(orangeBallsize/2)*M) { 
      //would like ball path, along the y coordinates to change.
  }
  
  ellipse(c2ix(orangeBall_x*M), c2iy(orangeBall_y*M), orangeBallsize * M, orangeBallsize * M);
  
  println("x:   " + orangeBall_x*M + "   y:  "+ orangeBall_y*M);
  if ((orangeStart == true)) {
    if (orangeBallDirection) {
      orangeBallTime = orangeBallTime + dt*timeFactor;
    } else {
      orangeBallTime = orangeBallTime - dt*timeFactor;
    }
  }

I would somehow like to change orangeBall_y = current location of y * sin(rampAngle);

But, no matter how I try to change it, I keep getting the full calculation of y, even though I only want it’s last known location.

it’s simple programming, but I am still learning. =)

Thanks

EDIT: added more code. There are elements that deal with the more global setup of the program, which I have left out, namely the M (scaling), and ballDirection, which I will develop further.


#2

Hi! i don’t understand much of it, but it looks that you need a temporary variable to store the last value of your variable. like:

float lastValue;

void setup(){
//the setup function runs first and only once, so you initialize the last value variable according to what you want to calculate
lastValue = orangeBall_Vy * orangeBallTime - (gravity*orangeBallTime*orangeBallTime/2);
}

void draw(){

orangeBall_y = lastValue * sin(rampAngle);


lastValue = orangeBall_y;
}

#3

yeah that sounds like exactly like what I am looking for. Thanks, I will give it a try after supper! =)

big thanks.


#4

Ok, rewrote my code so it’s a notch more clear of how it’s setup.

//variables are all float
float orangeBall_Vx, orangeBall_Vy, orange_initial_velocity, orangeBallAngle, rampAngle, orangeBallsize, M;

setup() {
 //basic display settings, like buttons and scrollsbars, window setups, framerate.
}

draw() {
  orangeBall_Vx = orange_initial_velocity * cos(orangeBallAngle);
  orangeBall_Vy = orange_initial_velocity * sin(orangeBallAngle);
  
  orangeBall_x = orangeBall_Vx * orangeBallTime; 
  orangeBall_y = orangeBall_Vy * orangeBallTime - (gravity*orangeBallTime*orangeBallTime/2);

if ((orangeBall_y * M + 105) < ((orangeBall_x*M - 885)*tan(rampAngle))+(orangeBallsize/2)*M) { 
      //would like ball path, along the y coordinates to change.
  }
  
  ellipse(c2ix(orangeBall_x*M), c2iy(orangeBall_y*M), orangeBallsize * M, orangeBallsize * M);
  
  println("x:   " + orangeBall_x*M + "   y:  "+ orangeBall_y*M);
  if ((orangeStart == true)) {
    if (orangeBallDirection) {
      orangeBallTime = orangeBallTime + dt*timeFactor;
    } else {
      orangeBallTime = orangeBallTime - dt*timeFactor;
    }
  }
}

What you suggest Bryan, a “temporary variable” sounds like exactly what I need. My problem seems to be, I want to “save” the last step of “orangeBall_y” before switching to another formula. I tried, as you suggested, putting it into the setup, but it calculates 0, since when the game starts, that formula, is in fact zero. It can only be calculated as the game goes.

My problem seems to be, not only can I only calculate it within the draw routine, I also cannot save/extract this value–without continually including the full equation for orangeBall_y.

Thus, I get this behavior:

  1. launch the ball, get proper flight trajectory, following projectile throw mechanics.

  2. I can get the program to recognize, “oh, I am on the ramp”

So far, whatever I have tried, the ball flies as expected, hits the ramp, but for the life of me, I cannot get flight to cancel, and switch to a new equation–from the last point, when y came into contact with the ramp.

It sounds like I need a temporary variable, where I save the last known y, and use it with a new equation. I will keep playing with it, and see if I can get it to work.

Thanks again!


#5

You need to work with the concept of states: https://forum.processing.org/two/discussion/24867/make-the-typing-appear-after-the-mouse-click-and-stay-on-the-screen#latest

What you do is that you start in idle mode. When you click on the canvas, the projectile motion starts. When it hits the ramp, then you start applying the ramp equations instead.

Please notice that your example was not enough as we could not run it. Consider checking the following example for your reference.

Kf



final float gravity = 9.8;
final int IDLE=0;
final int PROJ_MOTION=1;
final int RAMP=2;

int state=0;

boolean orangeStart, orangeBallDirection;
float dt, timeFactor;
float c2ix, c2iy;

//variables are all float
float orangeBall_Vx, orangeBall_Vy, orangeBall_x, orangeBall_y, orange_initial_velocity, orangeBallAngle, rampAngle, orangeBallsize, M;
float orangeBallTime;

void setup() {
  size(400, 400);
  M=1;
  timeFactor=1;
  dt=1/60.0;
  //basic display settings, like buttons and scrollsbars, window setups, framerate.

  c2ix=1;
  c2iy=1;

  orangeBall_x=0;
  orangeBall_y=0;

  orange_initial_velocity=80;
  orangeBallAngle=radians(75);
  orangeBallsize=10;
  orangeBallDirection=true;

  rectMode(CENTER);

  //frameRate(10);
}

void draw() {
  background(0);

  //Invert axis to simulate cartesian coordinate system
  scale(1, -1);
  translate(0, -height);

  fill(0, 255, 0);
  ellipse(width/2, height/2, 5, 5); //Center reference
  ellipse(0, 0, 15, 15);            // Low left corner 

  if (state == IDLE)
    return; //Nothing to do

  fill(255);
  noStroke();

  drawRamp();

  orangeBall_Vx = orange_initial_velocity * cos(orangeBallAngle);
  orangeBall_Vy = orange_initial_velocity * sin(orangeBallAngle);

  orangeBall_x = M*(orangeBall_Vx * orangeBallTime); 
  orangeBall_y = M*(orangeBall_Vy * orangeBallTime - (gravity*orangeBallTime*orangeBallTime/2.0));

  if (dist(orangeBall_x, orangeBall_y,282.28, 142.75)<orangeBallsize) {
    //if ((orangeBall_y * M + 105) < ((orangeBall_x*M - 885)*tan(rampAngle))+(orangeBallsize/2.0)*M) { 
    //would like ball path, along the y coordinates to change.

    fill(255, 0, 0);
    }
  ellipse(c2ix*(orangeBall_x), c2iy*(orangeBall_y), orangeBallsize * M, orangeBallsize );

  println("x:   " + orangeBall_x*M + "   y:  "+ orangeBall_y*M);


  orangeBallTime = orangeBallTime + dt*timeFactor;
}

void mouseReleased() {
  state = (state+1)%3;

  if (state==IDLE)
    setup();
}

void drawRamp() {
  //Draws ramp
  pushMatrix();
  translate(282.28, 142.75-orangeBallsize/2.0);
  rotate(radians(55));
  rect(0, 0, 10, 100);
  popMatrix();
}

#6

Cools thanks for the help. Mostly got it to work, “state-wise.”

Now, I gotta double check the math.

Thanks for pointing that out, this concept of working with states. I have that firmly in mind now.


#7

Working with states is a good approach. Another approach is that you implement all the physics in your model and then you set your initial conditions. Then you let it run and allow your scenario to evolve based on the physics that you have defined. In other words:

  1. You implement your free flight formulas
  2. You implement the contact-force formulas.
  3. Then you set the projectile’s initial position, speed and angle as well as you set the ramp’s position, length and angle.
  4. Press play and let the physics do all the job, exactly as it would happen in real life. This is how physics engines work… like what you see in animations.

Processing and the community in general have implemented some of these engines and they are open source, in case you are interested to check them out.

Kf