We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › A bunch of simple (silly) questions
Page Index Toggle Pages: 1
A bunch of simple (silly?) questions (Read 1794 times)
A bunch of simple (silly?) questions
Apr 28th, 2005, 2:05am
 
All this code came from REAS' nonlinear motion example here on Processing.org.  I switched some of it around and got rid of a whole lot of pieces while I was trying to take it apart, but it is his code.  And I know I'm asking some stupid questions, but I'm new to programming in general, so bear with me.

int size = 8;
int length = 20;

int aSize;           // Height of the shape
float aPos;          // Position of shape
float aSpeed;        // Speed of the shape
int aDirection = 1;  // Left or Right

void setup()
{
 size(200, 200);
//  noStroke();
 framerate(60);
 aPos = width/2;
 
}

void draw()
{
 background(102);
 fill(255);

 aSpeed = hump(aPos/float(width-size));
 aPos = aPos + ((aSpeed+.5) * aDirection );
 if (aPos > width-length/2 || aPos < length/2) {
   aDirection *= -1; }
 ellipse(aPos, width/2, length, length);
}

float hump(float sa) {
 sa = (sa - 0.5) * 2; //scale from -2 to 2
 sa = sa*sa;
 if(sa > 1) { sa = 1; }
 return 1-sa;
}

I've been trying to understand why this works for a while, and I'm just not getting it.  Can someone describe to me what's happening with the "aSpeed=hump()" and float "hump(float sa)" lines?  I think hump() gets plugged in as "sa" and then the return function tells the program that it's done calculating aSpeed, but I'm confused as to what's actually being calculated.  What does the function "float hump(float sa)" actually do to the speed?  

Does (width-size) translate to the width of the display(200) and the previously defined size variable(8 )? My problem there is that the "size" function is also called to define the length and width of the display..

And why does the object simply run up against the side of the display and not go anywhere when i remove the +0.5 from ((aSpeed+0.5)*aDirection)?

The IF statement in void draw() also uses the operator *= which I've never seen before.  does it make sure only to assign an integer?

Yeah, it's a lot of questions, and yeah, it's a simple problem, but I'd appreciate any help you could give me.  Thanks - zaphod
Re: A bunch of simple (silly?) questions
Reply #1 - Apr 28th, 2005, 2:13am
 
here's part of an answer:
"a *= 5" is the same as "a = a * 5"
it's a way of condensing the code.
Re: A bunch of simple (silly?) questions
Reply #2 - Apr 28th, 2005, 2:20am
 
ok, thanks.  I also just confused myself a bunch more by trying to work through the process on paper.  If that first line of the behaviour: aSpeed=hump(aPos/float(width-size)) translates to hump((200/2)/float(200-8 )), and then the numbers get plugged into hump(float sa) as "sa", then the hump function works out to 0?!  Because sa ends up being less than one and the function returns 1-sa... so... why does this do anything at all?
Re: A bunch of simple (silly?) questions
Reply #3 - Apr 28th, 2005, 7:31am
 
Here's an exhaustive trace of the program. I hope this helps. Welcome to programming, by the way! Smiley

First, declare some globally accessible variables (variables that can be seen everywhere). This only happens once, before anything else.

Code:
// buffer... is this supposed to be 10?
int size = 8;

// Diameter of the shape
int length = 20;

// Height of the shape
int aSize;

// Position of shape
float aPos;

// Speed of the shape
float aSpeed;

// Left (-1) or Right (1)
int aDirection = 1;


Next, set up the environment. This only happens once automatically, before anything is drawn.

Code:
void setup() {

// Make the applet window 200px x 200px
size(200, 200);

// Set the desired framerate as 60fps (helps JAVA2D)
framerate(60);

// Place the shape in the middle of the window to start
aPos = width/2;
}


Finally, draw a frame. This happens repeatedly and can be considered your "main" method.

Code:
void draw() {
// Refresh the background (essentially paints over the last
// frame). Try removing this line to see what it's doing.
background(102);

// Make my "fill" color white
// Note: this line is redundant since it's white by default
fill(255);

// Calculate the speed of our shape for this frame.
// What's with the parameter? Well, consider that aPos will
// always be between 10 and 190 and watch what happens:
//
// When aPos is 10 the parameter will be 10/192 (almost zero)
// When aPos is 190 the parameter will be 190/192 (almost one)
//
// This means that the parameter is basically acting like a
// percentage
//
// Note, the intended parameter might be:
// (aPos - size) / float(width - size * 2)
//
// What does the hump function do?
// You have to look at the method to find out.
// Here, we're just interested in the fact that it returns _a_
// value.
aSpeed = hump(aPos/float(width-size);

// Calculate a new position based on the speed.
// The method used here is known as "forward Euler integration"
// The process is fairly simple to visualize:
//
// If I'm at position x now, traveling at v velocity,
// where will I be in t seconds?
// answer: x + v * t;
//
// what happens if t is always 1?
// answer: x + v
//
// Notice that x just represents our position in time so we get
// x = x + v (this is sometimes compacted to x += v)
//
// This code needs to turn speed into a velcity
// (we need to add direction to our magnitude)
//
// Looks like Casey also wanted to bump up the speed slightly
// (by 0.5). Perhaps to make sure we always have a minimum
// speed?
//
// Since hump always returns a value between 0 and 1,
// it may be more appropriate to multiply aSpeed to
// scale it instead of offsetting it.
aPos = aPos + ((aSpeed + 0.5) * aDirection);

// Simple collision detection...
// If the shape position exceeds the right border or the left
// border
// (with padding for the radius of the shape)
if (aPos > width - length/2 || aPos < length/2) {
// Change directions
aDirection *= -1;
}


// draw the shape
// Note, the second parameter should _probably_ be height/2
// instead
// The shape is a circle with diameter 20
// The shape is positioned at x: aPos, y: width/2
ellipse(aPos, width/2, length, length);
}


Establish the calculation of the nonlinear motion control, the "hump" function. This method will take a parameter (looks like a percentage from what we saw above) and return a value (looks like a speed from what we saw above).

Code:
float hump(float sa) {
// conform our percentage to a specific range of values
// here it will be -1 to 1
sa = (sa - 0.5) * 2;

// Square the result (this means that we get a nonlinear
// relationship)
// These values will also always be positive
sa = sa*sa;

// We should never get a result greater than one,
// but just in case, lets cap the result at one
// (this line isn't needed)
if (sa > 1) { sa = 1; }

// We perform the check above, because we want to find a
// complement
// (we want to move fast through the middle and slow at the
// edges, not slowly through the middle and fast at the edges)
return 1 - sa;
}


Final note:
Why is the nonlinear method called "hump"
Take a look at the speeds produced at the various x positions.
Re: A bunch of simple (silly?) questions
Reply #4 - Apr 28th, 2005, 11:24am
 
thanks very much for that explanation.  I realized what was going on in the program flow about three hours after I'd left the computer and was doing something totally different.  All the math is really simple, I just wasn't quite sure why some of that stuff was there but now i get it.
Page Index Toggle Pages: 1