Вы находитесь на странице: 1из 24

Dr. J.

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

Function void setup() { }


Statement

Function void draw() { }


Statement
Try this Processing program:
final int DIAMETER= 50; //the size of the circles
void setup(){
size(500,500); //The usual canvas size
}
void draw(){
//Draw a circle at the mouse cursor's location
ellipse(mouseX, mouseY, DIAMETER, DIAMETER);
}
Statements within the setup() function are done only once, at
the beginning, then..
Statements within the draw() function are done over and over
again, 60 times per second.
See the example file FollowTheMouse.pde
The previous example draws a new circle
each frame, on top of all the old ones.
In some animations, you want to erase all the
old stuff, and draw a fresh frame each time.
To erase a frame and start fresh:
Use background(...);
This draws the whole frame to that colour.
In the FollowTheMouse program
Try adding background(128); before ellipse
What happens if you put it after ellipse?
What happens if you put it in setup() instead?
Try this one:
void setup(){
size(500,500); //The usual canvas size
}
void draw(){
//Draw a line from the previous mouse location
//to the current mouse location
line(pmouseX,pmouseY,mouseX,mouseY);
}
Simple, isn't it?
This one doesn't have any declarations at the start.
Use the formatting style shown, with indentation.
See the example file PenDrawing.pde
Make the circle grow slowly as we draw:
Try to add DIAMETER = DIAMETER + 1; to the draw function.
This wont work. Why?
Fix it.
That gets too big. Let's keep it smaller. How?
The result of x%50 is always from 0 to 49 (for x0).
In general, x%N is something that will always be in the
range 0 to N-1 (for positive numbers).
This can be very useful.
It's one of the main uses of the mod (%) operation.
To get values that go 0,1,2,...,n-2, n-1,0,1,2,...etc. just use
%n like this:
x=(x+1)%4; makes x go 0,1,2,3,0,1,2,3,0,1,2,3,0,...
The % operator is good for anything that goes in cycles!
So if we want the circles to grow to only 60 pixels
in diameter, we could use:
diameter = (diameter + 1)%60;
See MouseCones.pde
Student challenge:
Use colours, and make them slowly change, too.
Make red, green, and blue change at different rates.
Find other things to do. Be creative!
The scope of a variable is the portion of
the program where it can be used. int a=50;
...
Variables declared here are
global variables they're permanent void setup(){
Their scope is the whole program int b;
after their declaration, of course b=a;
Variables declared in a { } block are }
local variables, which are temporary
Their scope is that { } block only! void draw(){
and after the declaration itself int c;
When the } is reached, they vanish c=a;
A fresh variable is created every time! }
What happens in Braces, STAYS in Braces!
The scope of variable a
int a=50;
...
int x=a*2;

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

Hey! That looks familiar. Lets do something with


that!
Write a program to make a pac-man chase the
mouse around the screen. Animate the mouth,
too.
But that sounds complicated! How can we do it?
Use functions to break up the problem and do one small
piece at a time:
void setup(){
size(500,500);
}

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.

Вам также может понравиться