not sure what you mean
- this reads easing from an
ArrayList
of draggable points (the y of the points is mapped to easing) - points are made with a
sin()
formula
I would be far more happy with it if when we could get ALL the points from curveVertex(pv.x, pv.y).
- But I don’t know how.
- See what I mean when you press and hold any key and watch the CAR going not on the black line (which would be cool) but from point to point
// see https://discourse.processing.org/t/dont-understand-what-this-code-means-easing/38588/3
// see https://discourse.processing.org/t/bezier-curve-move-weight-points/8872/3
// graph:
// holding the curveVertex points in 2D - the core data. Here you add and edit your points.
ArrayList<PointGraph> listPointsGraph = new ArrayList();
int step=1;
boolean goodtogo=true;
boolean firstTimeKeyPressed=true;
//----
// move a sphere along the curve (Rollercoaster) optional
boolean showRollercoasterFlag = false;
int showRollercoaster_i; // current number of sphere on track for the Rollercoaster CAR
int i2=0; // counter for the taken steps between 2 single points of track for rollercoaster
//----
// for drag
boolean hold=false;
int hold_i = 0;
//----
float easing = 0.05;
float targetX, targetY;
float followingX, followingY;
// ---------------------------------------------------------------------
// CORE functions
void setup() {
size(1850, 880);
background(255);
makeArrayList(); // the graph
}// func
void draw() {
drawForNormal();
}//draw
//------------------------------------------------------------------------------
// called by draw()
void drawForNormal() {
background(255);
fill(0); // black
text("A black curve (curveVertex() command) composed of red points of an ArrayList, mouse drag to move points. Red points control the easing. \nA small car is giong on the graph like on a Rollercoaster, \n"
+"but unfortunately it doesn't follow the black line (how to get data from curveVertex() command?) but goes directly between the red points."
+"\nTry the sketch also with holding a key down and mouse drag (this is without the target/follower and in makeArrayList() a step of 90 for the for loop)",
17, 17,
width-100, 900);
// show ArrayList
showArrayList();
// drag?
if (hold) {
listPointsGraph.get(hold_i).pv.x=mouseX;
listPointsGraph.get(hold_i).pv.y=mouseY;
}
if (true) {
rollerCoaster();
}//if
if (keyPressed)
return;
if (goodtogo) {
showTargetAndFollower();
}
}// func
void showTargetAndFollower() {
// needs to have ALL points without any gaps (in makeArrayList())
PointGraph pm = listPointsGraph.get(frameCount*10%width);
float value = pm.getY();
// we calculate the easing based on the graph:
// * the lower the graph (nearer to height) the slower (0.0001)
// * the higher the graph (nearer to 150) the faster (0.9)
easing = map(value, height, 150, 0.001, 0.59 );
// manage x
targetX = frameCount*10%width; // get the mouseX as target x coord
float dx = targetX - followingX; // calc delta between the current x and target x
followingX += dx * easing; // move the current x a bit closer to the target x by adding delta BUT NOT the full delta but a value that is a smaller fraction
// Do the same with Y
targetY = 100; // get the mouseY as target y coord
// float dy = targetY - y; // delta between the current y and target y
// y += dy * easing; // move the current y a bit closer to the target y
followingY = targetY;
stroke(255, 0, 0);
line(targetX-17, targetY,
targetX+17, targetY);
noFill();
stroke(0);
rect(followingX, followingY,
12, 12);
}
// -------------------------------------------------------------------------
// INPUTS
void keyPressed() {
if (firstTimeKeyPressed) {
firstTimeKeyPressed=false;
step=90;
listPointsGraph.clear();
makeArrayList(); // the graph
step=1;
goodtogo=false;
}
}
void keyReleased() {
if (!keyPressed) {
step=1;
listPointsGraph.clear();
makeArrayList(); // the graph
goodtogo=true;
firstTimeKeyPressed=true;
showRollercoaster_i=0;
}
}
void mouseReleased() {
// end drag
hold = false;
}
// -------------------------------------------------------------------------
void makeArrayList() {
// make Graph, called from setup()
//
//float radiusX=300;
float radiusY=110;
// float centerX=width/2;
float centerY=height-130;
// start and end of graph and density
for (int angleStar = 0; angleStar <= width+100; angleStar += step) {
float starX =angleStar; // centerX + (cos (radians(angleStar)) * radiusX);
float starY = centerY + (sin (radians(angleStar)) * radiusY);
// the part gets elevated
if (starX>220 &&
starX<777) {
// starY+=map(starX-220, 0, 310, -10, -42);
starY=200;
}
PVector newPVector = new PVector(starX, starY);
listPointsGraph.add ( new PointGraph ( newPVector, false) ); // 2D
}//for
// futher
// listPointMy.get(65).pv.y -= 155;
}//func
void showArrayList() {
// show graph
// show the curve with beginShape and endShape
noFill();
stroke(0);
beginShape();
int i=0;
if (listPointsGraph.size()>0) {
listPointsGraph.get(i).useAsCurveVertexPVector();
for ( i = 0; i < listPointsGraph.size(); i++) {
listPointsGraph.get(i).useAsCurveVertexPVector();
}
i=listPointsGraph.size()-1;
listPointsGraph.get(i).useAsCurveVertexPVector();
}//if
endShape();
//show the points (additionally) green OR Red
noStroke();
float rad=3;
boolean firstTimeShowingGreen=true;
for ( i = 0; i < listPointsGraph.size(); i++) {
PointGraph pm = listPointsGraph.get(i);
PVector pv=pm.pv;
pm.selected=false;
// if we are close to the mouse, color green, else red
if (dist(mouseX, mouseY, pv.x, pv.y)<11 && firstTimeShowingGreen) {
// near mouse
fill( 0, 255, 0); // green
rad=3;
firstTimeShowingGreen=false;
if (mousePressed&&!hold) {
pm.selected=true;
hold=true;
hold_i= i;
}
} else {
// normal
pm.selected=false;
fill(255, 0, 0); // red
rad=3;
}
pm.showAsRect(rad);
}//for
//
}//func
// ------------------------------------------------------------------------
void rollerCoaster() {
// interprete the graph as a rollercoaster track with a CAR on it
ellipseMode(CENTER);
if (showRollercoaster_i > listPointsGraph.size()) {
showRollercoaster_i=0;
}
// get two points between which the CAR currently is running
PointGraph pm1=listPointsGraph.get( showRollercoaster_i );
PointGraph pm2=listPointsGraph.get( showRollercoaster_i+1 );
// get dist between 2 points
float dist1 = pm1.pv.dist(pm2.pv);
// calculate the steps between the 2 points depending on dist1 between them (smooth running)
float steps; // = 9;
steps = (dist1 / 2.0);
// calc t (can be seen as amt in lerp() / curvePoint)
float t = i2 / (float) steps;
// similar to lerp() wth amt:
float x = curvePoint(pm1.pv.x, pm1.pv.x, pm2.pv.x, pm2.pv.x, t);
float y = curvePoint(pm1.pv.y, pm1.pv.y, pm2.pv.y, pm2.pv.y, t);
// different camera view for rollercoaster view
// setRollerCoasterCamera(x, y, z, t);
// show ball&box [the rollercoaster car]
if (true) {
fill(255, 2, 244);
noStroke();
pushMatrix();
translate(x, y);
rect(0, 0, 9, 9);
translate(4, -3);
ellipse(0, 0, 7, 7);
popMatrix();
}
i2++;
if (i2>steps) {
showRollercoaster_i++;
if (showRollercoaster_i>listPointsGraph.size()-2) { // little rough management at the end of arraylist... ???
showRollercoaster_i=0;
}//if
i2=0;
}//if
}//func
// ==================================================================
class PointGraph {
// one point one the track
PVector pv; // position
boolean selected=false; // selected y/n for mouse drag
// constructor
PointGraph( PVector pv_, boolean selected_ ) {
pv = pv_.copy();
selected = selected_;
} // constructor
// -------------------------------------------------
void showAsRect( float rad ) {
pushMatrix();
translate(pv.x, pv.y);
rect(0, 0, rad, rad);
popMatrix();
} // method
float getY() {
// used for easing
return
pv.y;
}
void useAsCurveVertexPVector() {
// use curveVertex with PVector as input
curveVertex(pv.x, pv.y);
} // method
//
}//class
//