24. September 2013
Wie bereits im Beitrag "Lessons+" angekündigt, wurde auch in den Lektionen die Klasse PVector behandelt. Die Aufgabe dazu war der PingPongBall auf einer Linie hin und her zu animieren. Das ganze sieht so aus: Animation Live Zum Code. Wahrscheinlich ist die Sache nicht allzu elegant gelöst, aber es funktioniert. Als Erstes habe ich einen clickcount eingebaut, der mir schaut, ob ich das erste oder das zweite Mal geklickt habe. Je nachdem wird die start oder die endPosition gesetzt. Darauf wird das drawFlag auf true gesetzt und die Linie mitsamt Kugel werden gezeichnet. Dabei verwende ich ein Boolean 'reverse', welches mir sagt ob der Ball in die eine oder die andere Richtung schwebt. Anfänglich ist das auf false gesetzt und die curTime berechnet sich aus Additionen von animSpeed. Falls die animTime erreicht ist, wird die Richtung umgestellt; sprich reverse wird auf true gesetzt. Ab diesem Punkt berechnet sich die curTime aus animTime - animSpeed*verstrichene Frames. So wird hier im Beispiel von 2000 auf 0 abgezählt. So geht der Ball rückwärts. Sobald er bei 0 angelangt ist, wird reverse wieder auf false gesetzt und die Kugel kann wieder wie anfänglich in die Ursprungsrichtung schweben. Auch hier, gäbe es vielleicht eine hübschere Variante, das ist jedoch grad das einzige, was mir einfällt und auch umzusetzen war. Der Code
PVector startPos = new PVector();
PVector endPos = new PVector();
int curTime = 0;
int animSpeed = 20;
int animTime = 2000;
boolean drawFlag=false;
boolean reverse = false;
int clickcount = 0;
void setup()
{
size(640, 480);
smooth();
}
void draw()
{
background(51);
if (!reverse) {
// calc. the anim time
curTime += animSpeed; //in diesem Beispiel; 0 + 20; in 20er Schritten dazu
println("NORMAL " + curTime);
if (curTime >= animTime) { //wenn 2000, umkehren
reverse = true; //umkehren
}
}
else if (reverse) {
curTime -= animSpeed;
println("REVERSE " + curTime);
if (curTime <= 0) {
reverse = false;
}
}
// calc. the current time in the animation
float normTime = curTime * 1.0 / animTime;
if (drawFlag)
{
stroke(255);
line(startPos.x, startPos.y,
endPos.x, endPos.y);
// calculate the position of the circle on the line
PVector dir = PVector.sub(endPos, startPos);
PVector pos = PVector.add( startPos, PVector.mult(dir, normTime));
ellipse(pos.x, pos.y, 20, 20);
}
}
void mousePressed()
{
if (clickcount == 0) {
curTime = 0;
startPos.set(mouseX, mouseY, 0);
endPos = startPos.get();
clickcount = 1; //zähler wieviele clicks
}
else if (clickcount == 1) {
drawFlag = true;
endPos.set(mouseX, mouseY, 0);
println("draw, dammit!");
clickcount = 0; //
}
}
---------------
Ein Blick nach links zu Jon zeigt mir eine wahrlich einfachere und schönere Variante was das hin- und her betrifft:
Einfach den animSpeed ändern. -> animSpeed = -animSpeed.
Dann noch der Check, falls curTime = 0; wird wieder animSpeed = -animSpeed gesetzt – also wieder umgekehrt.
Ebenfalls habe ich noch einen kleinen SChönheitsfehler ausgemerzt:
Nun wird nicht beim ersten Click die curTime auf 0 zurückgesetzt (wenn der zweite Click nämlich lange danach fällt, startet der Ball in der Mitte) sondern erst beim zweiten Click.
Der neue Code:
PVector startPos = new PVector();
PVector endPos = new PVector();
int curTime = 0;
int animSpeed = 20;
int animTime = 2000;
boolean drawFlag=false;
int clickcount = 0;
void setup()
{
size(640, 480);
smooth();
}
void draw()
{
background(51);
// calc. the anim time
curTime += animSpeed;
if(curTime >= animTime){
animSpeed = -animSpeed;
}
if(curTime <= 0 ){
animSpeed = -animSpeed;
}
// calc. the current time in the animation
float normTime = curTime * 1.0 / animTime;
if (drawFlag)
{
stroke(255);
line(startPos.x, startPos.y,
endPos.x, endPos.y);
// calculate the position of the circle on the line
PVector dir = PVector.sub(endPos, startPos);
PVector pos = PVector.add( startPos, PVector.mult(dir, normTime));
ellipse(pos.x, pos.y, 20, 20);
}
}
void mousePressed()
{
if (clickcount == 0) {
startPos.set(mouseX, mouseY, 0);
endPos = startPos.get();
clickcount = 1; //zähler wieviele clicks
}
else if (clickcount == 1) {
drawFlag = true;
curTime = 0;
endPos.set(mouseX, mouseY, 0);
println("draw, dammit!");
clickcount = 0; //
}
}