Using Images
Prepare Images
- In many cases it makes sense to keep a larger resolution, layered .psd file for editing your assets.
- Don’t store the larger source files in your Processing sketch folder. That folder is for your code and assets.
- Use “Save for Web and Devices” to prepare your files for processing. PNG-24 is great for assets with transparency. JPG is great for photographic assets.
- Export a version of your asset at the size you need, add this version to your project.
Using PImage
- Declare your PImage variables globally (outside a function). This allows them to be used anywhere in your code.
- Global variables are easy to understand, but can make complex project more difficult to maintain. For, now using global variables for images makes sense.
- Load your image in setup(), that way you only load it one time. Once your image is loaded, you can draw it as often as you like.
- Loading an image in draw is almost always wrong. Loading images from the disk is much slower than drawing them and each time you load the image more memory will be used (at least temporarily). Accidentally loading the same image over and over is a common cause of memory and performance issues.
Code from http://processing.org/reference/image_.html, showing how to correctly handle loading and drawing images:
PImage img;
void setup() {
// Images must be in the "data" directory to load correctly
img = loadImage("laDefense.jpg");
}
void draw() {
image(img, 0, 0);
image(img, 0, 0, width/2, height/2);
}
Creating Navigation
If you are working on the Narrative project you will need to change what you draw, and how you respond to inputs, based on what “page” the viewer is on. Major state changes like this are common in many types of software and interactive projects: your book has multiple pages, games often have multiple levels, creative software often has modes like “edit” and “preview”.
Navigation.pde creates a simple example of one approach to breaking presenting multiple modes in one Processing sketch. This sketch has functions for each mode/page that handle drawing and responding to input. A variable is used to keep track of the current mode/page. Draw() and mouseReleased() don’t handle the drawing and interaction directly, instead they call the appropriate function for the current page.
Navigation.pde
// navigation.pde
// Demonstrates one way to create a more complex project that has multiple
// pages or screens that the user can navigate between.
String currentPage;
void setup() {
size(400, 400);
currentPage = "redPage";
}
/////////////////////////////////////////////////
// EVENT ROUTERS
void draw() {
if (currentPage == "redPage") {
drawRedPage();
}
else if (currentPage == "bluePage") {
drawBluePage();
}
}
void mouseReleased() {
if (currentPage == "redPage") {
mouseReleasedRedPage();
}
else if (currentPage == "bluePage") {
mouseReleasedBluePage();
}
}
/////////////////////////////////////////////////
// RED PAGE
void drawRedPage()
{
background(255, 0, 0);
fill(255, 255, 255);
rect(250, 150, 100, 100);
}
void mouseReleasedRedPage()
{
if (mouseInRect(250, 150, 100, 100)) {
currentPage = "bluePage";
}
}
/////////////////////////////////////////////////
// BLUE PAGE
void drawBluePage()
{
background(0, 0, 255);
fill(255, 255, 255);
rect(50, 150, 100, 100);
}
void mouseReleasedBluePage()
{
if (mouseInRect(50, 150, 100, 100)) {
currentPage = "redPage";
}
}
/////////////////////////////////////////////////
// UTILITY
boolean mouseInRect(float _x, float _y, float _w, float _h) {
if (mouseX > _x && mouseY > _y && mouseX < _x +_w && mouseY < _y + _h) {
return true;
}
return false;
}
With Changes from Class
// navigation.pde
// Demonstrates one way to create a more complex project that has multiple
// pages or screens that the user can navigate between.
String currentPage;
void setup() {
size(400, 400);
currentPage = "redPage";
}
/////////////////////////////////////////////////
// EVENT ROUTERS
void draw() {
if (currentPage == "redPage") {
drawRedPage();
}
else if (currentPage == "bluePage") {
drawBluePage();
}
else if (currentPage == "rainbowPage") {
drawRainbowPage();
}
}
void mouseReleased() {
if (currentPage == "redPage") {
mouseReleasedRedPage();
}
else if (currentPage == "bluePage") {
mouseReleasedBluePage();
}
else if (currentPage == "rainbowPage") {
mouseReleasedRainbowPage();
}
}
/////////////////////////////////////////////////
// RED PAGE
void drawRedPage()
{
background(255, 0, 0);
fill(255, 255, 255);
//right button
rect(50, 150, 100, 100);
//left button
rect(250, 150, 100, 100);
fill(0, 255, 0);
ellipse(mouseX, mouseY, 40, 40);
}
void mouseReleasedRedPage()
{
//left
if (mouseInRect(50, 150, 100, 100)) {
currentPage = "bluePage";
}
//right
if (mouseInRect(250, 150, 100, 100)) {
currentPage = "rainbowPage";
}
}
/////////////////////////////////////////////////
// BLUE PAGE
void drawBluePage()
{
background(0, 0, 255);
fill(255, 255, 255);
rect(50, 150, 100, 100);
}
void mouseReleasedBluePage()
{
if (mouseInRect(50, 150, 100, 100)) {
currentPage = "rainbowPage";
}
}
/////////////////////////////////////////////////
// Rainbow PAGE
void drawRainbowPage()
{
background(random(255), random(255), random(255));
fill(255, 255, 255);
rect(50, 150, 100, 100);
}
void mouseReleasedRainbowPage()
{
if (mouseInRect(50, 150, 100, 100) == true) {
currentPage = "bluePage";
}
}
/////////////////////////////////////////////////
// UTILITY
boolean mouseInRect(float _x, float _y, float _w, float _h) {
if (mouseX > _x && mouseY > _y && mouseX < _x +_w && mouseY < _y + _h) {
return true;
}
return false;
}
float boxX;
float boxY;
boolean boxDragging;
void setup()
{
size(400, 400);
boxX = 50;
boxY = 50;
boxDragging = false;
}
void mousePressed()
{
if (mouseInRect(boxX - 25, boxY - 25, 50, 50)) {
boxDragging = true;
}
}
void mouseReleased()
{
if (mouseInRect(300, 300, 50, 50)){
//do something
}
boxDragging = false;
boxX = 50;
boxY = 50;
}
void draw() {
background(0);
if (boxDragging) {
boxX = mouseX;
boxY = mouseY;
}
fill(255);
rect(boxX - 25, boxY - 25, 50, 50);
fill(120);
rect(300, 300, 50, 50);
}
//utility function form week 8 class example
boolean mouseInRect(float _x, float _y, float _w, float _h) {
if (mouseX > _x && mouseY > _y && mouseX < _x +_w && mouseY < _y + _h) {
return true;
}
return false;
}