Active Programming Notes
Active Programming Notes
Bate
Week 3
Adding the keyword final before a declaration
Makes it a constant not a variable
Promises that its value will never change
You can set it once, before it's ever used
Requests an error if you ever try to change it again
I won't do a new syntax diagram for this.
Convention: Use ALL_UPPER_CASE for constants.
int currentSize; //This is a variable
final int SCALE_X = 3; //This is a constant
That constant may be used 100 times in the program
If the X scale factor changes, change this one declaration
Not the 100 other places
Use constants for all non-trivial literals in your
programs. (No "magic numbers".)
Especially for anything that could conceivably need to
be changed in the future.
positionX * 6; //BAD!! ("magic number")
positionX * X_SCALE_FACTOR; //GOOD!!
Increases both readability and reliability.
Well-named constants are self-commenting
Cant change 99 out of 100 places it appears, and
forget the last one, leading to a bug.
Ease of change! Reliability of change! Readability!
See Robot_Head_V5
Weird rule: The size(w,h) command should use
numbers not variables.
This is for unusual implementation issues.
Good: size(500,500);
Better but not allowed (unfortunately):
final int CANVAS_SIZE=500;
size(CANVAS_SIZE, CANVAS_SIZE);
But after the size command, you have pre-
defined variables width and height.
Example: Draw the biggest ellipse possible
size(400,600);
//Now you automatically have int width=400;
//and int height=600;
ellipse(width/2,height/2,width,height);
There are some variables declared for you:
int mouseX, mouseY; // the location of the cursor
Only valid when the mouse cursor is within the canvas
(the window)
If the mouse isn't in the canvas, they remain frozen.
At the start, if the mouse isn't in the canvas at all, they'll
both be 0.
int pmouseX, pmouseY; //the previous location
But how would you use mouseX and mouseY??
We need...
Processing can very easily do animations
This is known as "active" Processing.
It can perform a new set of drawing commands 60 times
per second.
Each of these draws a new "frame".
A new program syntax:
Program
Declaration Function
void setup(){
int b;
b=a;
}
void draw(){
int c;
c=a;
}
The scopes of the variables b and c. int a=50;
In the MouseCones program: ...
Try changing the position of the int x=a*2;
declaration of diameter
As a global void setup(){
int b;
In the setup block
b=a;
In the draw block
}
If you want to
keep a variable's value from one "frame" to void draw(){
the next, or
int c;
use it in both setup and draw,
c=a;
then it should be global
}
All others should be local.
Locals are usually good, globals are bad unless you NEED them.
(except for final constants those are OK as globals)
In Processing, we use global variables to keep
track of the state of the program.
Whats happening? Whats the diameter? Wheres the
ball? Whats the score? Is the game over? How many
enemies are there? Etc. etc. etc.
The variable diameter was a state variable in the
previous examples.
The important thing is that global variables retain their
values from one frame to the next (from one execution
of the draw function to the next).
The draw function will
Use the state variables to find out whats happening
Change the state variables to make something different
happen in the future
Make a ball move across the canvas.
State information needed: Wheres the ball?
Two variables: positionX, positionY
Use this information to: draw the ball
Change this information by: adding some small
amount every frame to these positions
Make the ball wrap around so that if it goes off the
bottom/right edge, it re-appears at the top/left edge.
That sounds like a job for the % operation!
Tricky: What if the speed is negative? How do you
make that work?
Use println or the debug tool to see whats happening.
See SimpleBall.pde
You can provide your own functions using
exactly the same syntax as setup() and draw():
void setup( ) { }
void draw( ) { }
void doMyOwnThing( ) { }
void drawComplexObject( ) { }
The syntax is:
function void Identifier ()
{ }
Statement
To use (call) your own functions the
commands look like this:
doMyOwnThing( );
drawComplexObject( );
With the simple syntax:
Statement Identifier ();
Example:
void draw( ){
clearTheScreen();
}
void clearTheScreen(){
background(128);
}
When you call a function
Execution pauses at the call statement. The spot is noted.
Then the statements in the function are executed.
Execution returns to the noted spot and continues.
You can call a function many times from any place.
void draw(){ void drawThing(){
fill();
drawThing(); ellipse();
stroke();
drawThing(); line();
rect();
}
oneMoreTime(); void oneMoreTime(){
} //Call a function from another
drawThing();
}
To re-use common code in many places.
Never write the same code twice if you can avoid it!
If a job needs to be done in several places
Write it once, in a function.
Call the function in several places.
This improves reliability
If that code needs changing, the changes are made to one
place only.
To greatly improve readability
Each function should do one specific small job
It must be well-defined (what data it uses, what
variables it changes, what it draws or does, etc.).
Keeps code local and reasonably small.
To make it easier to write complex programs
Write one small independent section at a time.
This code draws a random line radiating from the
mouse: (Well officially meet random() next week.)
void randomLine(){
stroke(random(255),random(255),random(255));
strokeWeight(random(3));
line(mouseX,mouseY,
random(mouseX-50,mouseX+50),random(mouseY-50,mouseY+50));
}
Now its easy to draw many such lines without
duplicating any code:
void draw(){
background(128);
randomLine();
randomLine();
randomLine();
randomLine();
}
The arc command can be used to draw arcs
or pie slices:
arc(x,y,wide,high, //same as an ellipse
startAngle,endAngle, //These are in radians
PIE); //Gives a pie slice
The angles are in radians:
Built-in constants:
TWO_PI gives 2 (same as 360 degrees)
Also PI (180), HALF_PI (90), QUARTER_PI (45).
The angle 0 is to the right (positive x axis).
You really need fractions for this. The int data type
has no fractions, but the float data type does. Well
cover this data type fully next week.
Heres a sample arc command
arc(250,250,75,75,
QUARTER_PI,TWO_PI-QUARTER_PI,PIE);
Which draws
void draw(){
background(128); //draw a fresh frame each time
movePacman(); //Move the pacman toward the mouse
turnPacman(); //Turn it to face the mouse
animateMouth(); //Make the mouth open and close
drawPacman(); //And draw it
}
Now write the 4 small pieces one at a time, testing them
as theyre written. Soon you have a complete program.
This will be done live in class.
Well use a few things like float from next weeks notes, and come
back and look at them again next week.
See PacmanChase.pde for the final result.