We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi,
I am quite new to processing and I have been playing with it the last couple of weeks. I am working on a tiny project. The idea is to make a simple sequential animation. it is basically a few images, shapes, and text that appear in sequence. I have written the pde code (see below) and all works fine using the IDE. Now I want to port this on a website using processing.js (simply using processing.min.js and a canvas element).
It all works fine in the browser (chrome), but here is the problem the animation looks fine on a desktop, but on a tablet (a lenovo quad core) or Smasung Galaxy S3, the animation is all jerky (looks like the frame rate is dropping to unacceptable levels). So my question is: Is this a normal behavior, is my animation simply too complex, or may be I am doing something wrong in my code that is making the animation so heavy for non-desktop devices (although for example I don't think I have too long for loops )?
Also, does anyone has any best practice and tips when trying to set up simple sequential animation like below?
In btw, the images are each around 20-30KB. may be this is also slowing down things !!
I will appreciate any help, thank you.
Michel.
PS: I could not find a place (such as jsfiddle) to put the code along with the images somewhere for people to visualize the animation :(.
PImage main,cloud,phone,send,hand,alert;
PFont f;
String message1 = "Hello there, this";
String message2 = "is a message.";
String message3 = "See you.";
int c;
float typeSpeed = 12;
float speedDot = 3.0;
float x;
float y;
float xCloud,yCloud,xPhone,yPhone;
int fr = 24;
float angle,anglePhone,scaleCloud,scaleSend,angleSend,scaleAlert,angleAlert;
float xDot,xDot2,yDot; // Dot2 is used on the right side of the cloud
float cloudWidth = 150;
int ringingDuration,sendDuration,clickDuration,alertDuration,inBtwLoops;
int diam=50;
boolean finishedTextDisplay;
int myFrameCount;
void setup() {
size(1000,400);
frameRate(fr);
/* @pjs preload="data/main.png"; */
/* @pjs preload="data/cloud.png"; */
/* @pjs preload="data/phone.png"; */
/* @pjs preload="data/send.png"; */
/* @pjs preload="data/hand.png"; */
/* @pjs preload="data/alert.png"; */
main = loadImage("data/main.png");
cloud = loadImage("data/cloud.png");
phone = loadImage("data/phone.png");
send = loadImage("data/send.png");
hand = loadImage("data/hand.png");
alert = loadImage("data/alert.png");
f = createFont("Arial",14,true); textFont(f);
resetValues();
}
void draw() {
myFrameCount++; // each trip thry draw is 1 frame count
imageMode(CORNERS);image(main,0,0);
displayCloud(0);
displayPhone(0);
if (alertDuration == 0 || alertDuration > fr) {displayAlert(0,false);} // displayAlert(scale,tinted)
if (finishedTextDisplay == false) {
x = 195;
y = 170;
for (int i = 0; i < message1.length(); i++) { // show letters 1 sec interval
//println("for loop");
if (fr*i/typeSpeed <= myFrameCount) {
c = 0; // show
}
else {
c = 255; // don't show
}
fill(c);
text(message1.charAt(i),x,y);
x += textWidth(message1.charAt(i));
// println(textWidth(message3.charAt(i)));
}
x = 190;
y = 170 + textAscent()+textDescent();
for (int i = 0; i < message2.length(); i++) { // show letters 1 sec interval
//println("for loop");
if (fr*i/typeSpeed <= myFrameCount - ((fr/typeSpeed)*(message1.length()))) {
c = 0; // show
}
else {
c = 255; // don't show
}
fill(c);
text(message2.charAt(i),x,y);
x += textWidth(message2.charAt(i));
}
x = 185;
y = 170 + 2*(textAscent()+textDescent());
for (int i = 0; i < message3.length(); i++) { // show letters 1 sec interval
// println("for loop");
if (fr*i/typeSpeed <= myFrameCount - ((fr/typeSpeed)*(message1.length()+message2.length()))) {
c = 0; // show
if (i == message3.length()-1) { // last character shown --> click button
finishedTextDisplay = true;
}
}
else {
c = 255; // don't show
}
fill(c);
text(message3.charAt(i),x,y);
x += textWidth(message3.charAt(i));
} // end for loop
} // if finishedTextDisplay
else // characters are all dislayed
{
// display strings
// println("NO for loop");
fill(0);
x = 195;y = 170; text(message1,x,y);
x = 190;y = 170+textAscent()+textDescent(); text(message2,x,y);
x = 185;y = 170+2*(textAscent()+textDescent()); text(message3,x,y);
// display hand
if (clickDuration <= 0.5*fr) {
// display bigger send button
/*
if (angle <= PI) {
scaleSend = map(sin(angleSend), 0, 1, 0, 0.15);
displaySend(scaleSend);
angleSend += 5*PI/100;
}
*/
if (clickDuration < 0.5*0.5*fr ) {scaleSend = clickDuration;}
else {scaleSend = 0.5*fr - clickDuration;}
// println(scaleSend);
scaleSend = map(scaleSend, 0, 0.5*0.5*fr, 0, 0.15);
displaySend(scaleSend);
clickDuration++;
tint(255,180);imageMode(CORNERS);image(hand,265,205);tint(255,255);
}
else
{
displaySend(0);
// move on with simualtion
if (xDot < xCloud - cloudWidth/2) { // not reached cloud yet
displayDot();
// println("dot");
}
else
{ // dot reached the cloud --> no dot and grow cloud
// put the dot on the other side of the cloud
if (angle <= PI) { // once inflate and deflates once, cloud stops moving
// println(scaleCloud);
scaleCloud = map(sin(angle), 0, 1, 0, 0.15);
displayCloud(scaleCloud);
angle += 5*PI/100;
// println("cloud");
}
else
{ // dot on the other side
if (xDot2 < xCloud + 165) { // not reached the arrow
displayDot2();
// println("dot 2");
}
else { // dot reached the phone --> no dot , phone shakes
if (ringingDuration < 4.5*fr) {
// println("ringing");
// displayPhone(random(-0.06,0.06)); // phone shakes
displayPhone(map(sin(anglePhone), -1, 1, -(PI/50), +(PI/50)));
anglePhone += (PI/2);
// rings
if ( (0 < ringingDuration && ringingDuration <= 0.5*fr) || (ringingDuration > 2.5*fr && ringingDuration <= 3*fr)) {
displayRing(0);
}
if ( (0.5*fr < ringingDuration && ringingDuration <= fr) || (ringingDuration > 3*fr && ringingDuration <= 3.5*fr) ) {
displayRing(0);
displayRing(20);
}
if ( (fr < ringingDuration && ringingDuration <= 1.5*fr) || (ringingDuration > 3.5*fr && ringingDuration <= 4*fr)) {
displayRing(0);
displayRing(20);
displayRing(40);
}
if ( (ringingDuration > 1.5*fr && ringingDuration <= 2.0*fr) || (ringingDuration > 4*fr && ringingDuration <= 4.5*fr)) {
displayRing(0);
displayRing(20);
displayRing(40);
// displayRing(60);
}
ringingDuration++;
}
else {
if (alertDuration <= fr) {
// alert beeps 2 times
if (alertDuration >= 0 && alertDuration < fr/4 ) {scaleAlert = alertDuration;}
if (alertDuration >= fr/4 && alertDuration < 2*fr/4) {scaleAlert = 2*fr/4 - alertDuration;}
if (alertDuration >= 2*fr/4 && alertDuration < 3*fr/4) {scaleAlert = alertDuration - 2*fr/4;}
if (alertDuration >= 3*fr/4 && alertDuration <= fr) {scaleAlert = fr - alertDuration;}
// else {scaleAlert = 0.5*fr - alertDuration;}
// println(scaleAlert);
scaleAlert = map(scaleAlert, 0, 0.5*0.5*fr, 0, 0.15);
displayAlert(scaleAlert,true);
alertDuration=alertDuration+1;
}
else
{
// alertDuration = 0;
// wait for a second a so before starting the animation again
if (inBtwLoops <= 2*fr) {
inBtwLoops ++;
}
else {
resetValues();
}
}
}
}
}
}
}
}
}
void displayAlert(float scaleAlert, boolean tinted){
pushMatrix();
translate(222,386);
imageMode(CENTER);
scale(1+scaleAlert);
if (tinted) {tint(217, 83, 79);}
image(alert,0,0);
tint(255,255);
popMatrix();
}
void resetValues(){
angle=anglePhone=scaleCloud=scaleSend=angleSend=scaleAlert=angleAlert=0;
xCloud = width/2+85;
yCloud = height/2-10;
xDot = xCloud - 170;
yDot = height/2;
xDot2 = xCloud + cloudWidth/2;
xPhone = xDot2 + 170 + 50;
yPhone = height/2;
ringingDuration = sendDuration = clickDuration = alertDuration = inBtwLoops = 0;
finishedTextDisplay = false;
myFrameCount = 0;
}
void displayRing(int diamExtra){
int alpha = round(map(diamExtra,0,40,255,50));
strokeWeight(5.5);
strokeCap(ROUND);
noFill();
stroke(24, 188, 156, alpha);
// arc(xPhone+10, yPhone - 69, diam+diamExtra, diam+diamExtra, -HALF_PI,0);
arc(xPhone+10, yPhone - 69, diam+diamExtra, diam+diamExtra, -HALF_PI+(HALF_PI/7),0-(HALF_PI/7));
}
void displayCloud(float scaleCloud){
pushMatrix();
translate(xCloud,yCloud);
imageMode(CENTER);
scale(1+scaleCloud);
image(cloud,0,0,150,150);
popMatrix();
}
void displayPhone(float anglePhone){
pushMatrix();
translate(xPhone,yPhone);
rotate(anglePhone);
imageMode(CENTER);
// scale(1+scaleCloud);
image(phone,0,0,55,161);
popMatrix();
}
void displayDot(){
xDot+=speedDot;
fill(21, 158, 130);
stroke(21, 158, 130);
ellipse(xDot,yDot,15,15);
}
void displayDot2(){
xDot2+=speedDot;
fill(21, 158, 130);
stroke(21, 158, 130);
ellipse(xDot2,yDot,15,15);
}
void displaySend(float scaleSend){
pushMatrix();
translate(275,215);
imageMode(CENTER);
scale(1+scaleSend);
image(send,0,0,48,26);
popMatrix();
/*
pushMatrix();
imageMode(CORNERS);
tint(255,alpha); // alpha=0: tranparent
image(send,250,205);
tint(255,255); // 255: normal
popMatrix();
*/
}
Answers
https://forum.Processing.org/two/discussion/15473/readme-how-to-format-code-and-text
https://www.OpenProcessing.org/sketch/create
http://studio.SketchPad.cc/
https://thimble.Mozilla.org/en-US/
Thank you for the pointers @GoToLoop. The code is now formatted and available here: http://studio.sketchpad.cc/CKavONHCZ8
Anyone can explain why this animation:
http://studio.sketchpad.cc/CKavONHCZ8
is running fine on a desktop but very slow on a tablet?
It looks like the image main.png (backgorund) seems to be the big factor slowing the animation. When I do not display it the animation is "almost" acceptable on a tablet. But it is only 40KB though. is this already too big for processing to handle? looks like I am alone on this forum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :(
If you wanna use "main.png" as your background, use set() instead of image():
http://ProcessingJS.org/reference/set_/
At least in Processing Java, both set() & background() are better performant for JAVA2D renderer.
Be aware that only the 1st
/** @pjs */
directive found is processed.The others are completely ignored! :-SS
You're gonna need to use the syntax for multiple images for
preload=""
:http://ProcessingJS.org/reference/pjs directive/
http://ProcessingJS.org/reference/preload/
Ah! In order to avoid all-green code posts in this forum, never use
/*
but/**
instead! :-\"tried both set and background. did not help much :(.
http://studio.sketchpad.cc/CKavONHCZ8
Here's an online example w/ createGraphics():
http://studio.SketchPad.cc/sp/pad/view/ro.9ozYNbweyOpjT/latest
I have removed the tints. Wow, it is pretty much running normally on the tablet now. So indeed the tinting is a real animation slow down. Thanks a lot @GoToLoop for the hint.