p5 for Processing users¶
p5 API borrows many core ideas from the Processing so most of the API looks similar. This document lists the major differences between Processing and the p5 API.
In addition to skimming through this document, you should also check the API reference for more details and take a look at complete working examples on the examples repository.
Naming conventions¶
- Most function names are now in
lowercase_separated_by_underscores
as opposed to thelowerCamelCase
in Processing. So, if a method was calledbezierPoint
in Processing it will be calledbezier_point
in p5. - Mathematical constants like \(\pi\) are still in
UPPPERCASE_SEPARATED_BY_UNDERSCORES
. Note thatwidth
,height
,mouse_x
, etc are not treated as constants. - The “P” prefix has been dropped from the class names. So,
PVector
becomesVector
,PImage
becomesImage
, etc.
We’ve also renamed a couple of things:
Processing’s
map()
method is now calledremap()
to avoid a namespace conflict with Python’s inbuiltmap()
function.All
get*()
andset*()
methods for objects have been removed and attributes can be set/read by directly accessing the objects.For instance, if we have a vector
vec
in Processing, we would use/* read the magnitude of the vector */ float m = vec.mag() /* set the magnitude of the vector */ vec.setMag(newMagnitude)
In p5, we can just use:
# read the magnitude of the vector m = vec.magnitude # set the magnitude of the vector vec.magnitude = new_magnitude
Processing’s
random()
method is now calledrandom_uniform()
to prevent confusion (and nasty errors!) while using Python’srandom
module.
Running Sketches¶
p5 doesn’t come with an IDE and p5 scripts are run as any other Python scripts/programs. You are free to use any text editor or Python IDE to run your programs.
Sketches must call the
run()
function to actually show the sketches. Sketches without a call torun()
will not work. So, a Processing sketch:void setup() { /* things to do in setup */ } void draw() { /* things to do in the draw loop */ } void mousePressed() { /* things to do when the mouse is pressed */ }
would look like this in p5:
from p5 import * def setup(): # Things to do in setup def draw(): # Things to do in the draw loop def mouse_pressed(): # Things to do when the mouse is pressed. run() # This is essential!
Drawing commands only work inside functions.
If you want to control the frame rate of the you need to pass in
frame_rate
asnan optional argument when you run your sketch.from p5 import * def setup(): # setup code def draw(): # draw code # run the sketch at 15 frames per second. run(frame_rate=15)
Processing’s
frameRate()
method is calledset_frame_rate()
in p5. To get the current frame rate in the sketch, use theframe_rate
global variable.
Shapes, etc¶
One of the major differences between the Processing and the p5 API is the way coördinate points are handled. With the exception of the point() functions, all drawing functions that allow the user to pass in coordinates use tuples.
Hence, to draw a line from \((100, 100)\) to \((180, 180)\), we would use:
start_point = (100, 100) end_point = (180, 180) line(start_point, end_point)
To draw a rectangle at \((90, 90)\) with width \(100\) and height \(45\), once would use:
location = (90, 90) rect(location, 100, 45)
Technically, any object that supports indexing (lists, p5 Vectors) could be used as the coordinates to the draw calls. Hence, the following code snippet is perfectly valid:
start_point = Vector(306, 72) control_point_1 = Vector(36, 36) control_point_2 = Vector(324, 324) end_point = Vector(54, 288) bezier(start_point, control_point_1, control_point_2, end_point)
Functions like bezier_point, bezier_tangent, curve_point, curve_tangent, etc also need the coordinates as iterables. Further, they also return special objects that have \(x, y, z\) coordinates.
start = Vector(306, 72) control_1 = Vector(36, 36) control_2 = Vector(324, 324) end = Vector(54, 288) bp = bezier_point(start, control_1, control, end, 0.5) # The x coordinate of the bezier point: print(bp.x) # The y coordinate of the bezier point: print(bp.y)
Unlike Processing, p5 doesn’t have special global constants for “modes”. Functions like
ellipse_mode()
andrect_mode()
take strings (in all caps) as inputs. The following are valid function calls:center = (width / 2, height / 2) rect_mode('RADIUS') square(center, 50) ellipse_mode('CENTER') circle(center, 100)
Processing’s
pushMatrix()
andpopMatrix()
have been replaced by a singlepush_matrix()
context manager that cleans up after itself. So, the following Procecssing code:pushMatrix() translate(width/2, height/2) point(0, 0) popMatrix()
Becomes:
with push_matrix(): translate(width / 2, height / 2) point(0, 0)
Like
push_matrix()
,push_style()
is a context manager and can be used with thewith
statement.
Event System¶
Processing’s
mousePressed
global boolean has been renamed tomouse_is_pressed
to avoid namespace conflicts with the user definedmouse_pressed
function.To check which mouse button was pressed, compare the
mouse_button
global variable to one of the strings'LEFT', 'RIGHT', 'CENTER', 'MIDDLE'
The
keyCode
variable has been removed. And Processing’s special “coded” keys can be compared just like other alpha numeric keys.def key_pressed(event): if event.key == 'A': # code to run when the <A> key is presesed. elif event.key == 'UP': # code to run when the <UP> key is presesed. elif event.key == 'SPACE': # code to run when the <SPACE> key is presesed. # ...etc
Math¶
Vector addition, subtraction, and equality testing are done using the usual mathematical operators and scalar multiplication is done using the usual
*
operator. The following are valid vector operations:# add two vectors `position` and `velocity` position = position + velocity # subtract the vector `offset` from `position` actual_location = position - offset # scale a vector by a factor of two scaled_vector = 2 * vec_1 # check if two vectors `player_location` # and `mouse_location` are equal if (player_location == mouse_location): end_game() # ...etc.
The mean and standard deviation value can be specified while calling
random_gaussian()
The distance function takes in two tuples as inputs. So, the following Processing call:
d = dist(x1, y1, z1, x2, y2, z2)
would become:
point_1 = (x1, y1, z1) point_2 = (x2, y2, z2) d = dist(point_1, point_2)
The
remap()
also takes tuples for ranges. The Processing call:n = map(mouseX, 0, width, 0, 10)
becomes:
source = (0, width) target = (0, 10) n = remap(mouse_x, source, target)
New Features¶
The
title()
method can be used to set the title for the sketch window.circle()
andsquare()
functions draw circles and squares.Colors can be converted to their proper grayscale values.
# if we have some color value... our_color = Color(255, 127, 0) # ...we can get its gray scale value # using its `gray` attribute gray_value = our_color.gray