We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi folks,
New to Processing and coding in general. Trying to put something together where a user (various users) input text which goes through a number of processes. I've created 3 screens/cases (?) Screen 0 = User inputs text via keyboard. Hitting control saves a file for print and advances to next screen. Screen 1 = User's text is animated - and here come the sticky part... I want it to animate for a certain amount of time, say 8 seconds, save a PNG and then advance automatically to the next screen. Screen 2 = is a work in progress.
I asked this before and got some great code to do this from screen 0 to screen 1, but the problems arise when I try to implement it from screen 1 to 2 (i.e. in the middle of the programme). After getting loads of different examples for timers and counters, using millis and frame-counts, I realise that the time or frame count is being measured from the start of the programme, not the start of Screen 1 - d'uh! Because some users will be inputting longer texts than others, I can't use an absolute measurement from the start of the programme.
So, I need a way to capture the time from when Screen 1 is called, and get it to advance 8 or so seconds after that. I've tried multiple ways, but there's obviously something wrong with my logic or my code. Any help gratefully accepted.
FYI: eventually (if I ever finish this bloody thing) screen 2 will go back to screen 0, and the whole cycle will start all over again for a new user with the last line of the previous user's text still visible - in other words it will be a sort of crowd-sourced chain narrative...hopefully.
//Code adapted from examples by Amnon available at: https://amnonp5.wordpress.com/2012/01/28/25-life-saving-tips-for-processing/
//and Daniel Shiffman available at: http://www.learningprocessing.com/examples/chapter-18/example-18-1/
//and John Park, University Oregon available at: http://pages.uoregon.edu/park/Processing/AdvancedSplit/applet/AdvancedSplit.pde
//and Kyuha Shim, available at: http://visualizing-data.org/index.php?/class-code/52-stringcharatascii-/
import java.util.Calendar;
int currentScreen;
String myText = "Your story..."; //for Screen 0
String yourText = ""; // Variable to store text currently being typed
String savedText = ""; // Variable to store saved text when Control is hit
//------------------
int x=0; //for Screen 1
float rotater = 0;
String [] rotateText = split (savedText, " "); // array of words contained in savedText
//------------------
int[] letterCounts = new int[26]; //for Screen 2
int maxCount = 0;
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ,.;:!? ";
int[] counters = new int[alphabet.length()];
boolean[] drawLetters = new boolean[alphabet.length()];
boolean drawText = true;
String joinedText;
float charSize; //for Screen 2
color charColor = 0;
int posX = 20;
int posY = 50;
float easing = 0.05;
int timer;
//------------------
PrintWriter textFile; //for Screen 0
// timestamp
String timestamp() {
Calendar now = Calendar.getInstance();
return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}
void setup() {
size(800, 600);
smooth();
PFont f = createFont("AGaramondPro-Regular", 140);
textFont(f);
smooth();
fill (0);
textAlign(CENTER, CENTER);
for (int t = 0; t < alphabet.length(); t++) {
drawLetters[t] = true;
}
countCharacters();
}
void draw() {
switch(currentScreen) {
case 0: drawScreenZero(); break;
case 1: drawScreenOne(); break;
case 2: drawScreenTwo(); break;
default: background(255); break;
}
}
void drawScreenZero() {
background(255);
textSize (30);
fill (0);
text (myText, 0, 0, width, height);
text (yourText, 0, 0, width, height);
}
void drawScreenOne() {
float r;
float g;
float b;
float a;
r = random(255);
g = random(150);
b = random(200);
a = 20;
String [] rotateText = split (savedText, " ");
textSize (140);
fill(r,g,b,a);
rotater += 1;
x++;
if(x> (rotateText.length-1)){
x=0;
}
translate(width/2, height/2);
rotate (rotater);
text(rotateText[x],0,0);
delay(40); // in milliseconds
// if (frameCount > 599) {
// saveFrame("rotate_images/"+timestamp()+".png"); //creates a PNG in the sketch directory
// }
//if(frameCount > 800) {
// currentScreen = 2;
//}
//if (millis() - timer >= 1799) {
// saveFrame("rotate_images/"+timestamp()+".png"); //creates a PNG in the sketch directory
// timer = millis();
//}
if (millis() - timer >= 18000) {
saveFrame("rotate_images/"+timestamp()+".png"); //creates a PNG in the sketch directory
currentScreen = 2;
timer = millis();
}
}
void drawScreenTwo() {
for (int t = 0; t < alphabet.length(); t++) {
drawLetters[t] = true;
}
background (0);
fill (255);
posX = 20;
posY = 200;
float oldX = 0;
float oldY = 0;
// go through all characters in the text to draw them
for (int t = 0; t < savedText.length(); t++) {
// find the index of the current letter in the alphabet
String u = str(savedText.charAt(t)).toUpperCase();
char uppercaseChar = u.charAt(0);
int index = alphabet.indexOf(uppercaseChar);
if (index < 0) continue;
textSize(20);
smooth ();
float sortY = index*20+40;
float newX = (frameCount*40) % width; //animates - increases x co-ordinate
float dx = newX - x; //easing
if(abs(dx) > 1) {
newX += dx * easing;
}
float m = map(newX, 50,width-50, 0,1); //alphabetises
m = constrain(m, 0, 1);
float interY = lerp(posY, sortY, m);
if (drawLetters[index]) {
oldX = posX;
oldY = interY;
}
/*
if (newX > 750) {
oldX = 750;
}
if (sortY > 600) {
oldY = 600;
}
*/
if (drawText) text(savedText.charAt(t), posX, interY);
else {
oldX = 0;
oldY = 0;
}
posX += textWidth(savedText.charAt(t));
if (posX >= width-200 && uppercaseChar == ' ') {
posY += 40;
posX = 20;
}
}
String[] list = splitTokens(savedText, ".?!"); //splits inputted text into lines.
colorMode(HSB);
translate(10, height/2);
//translates each character into an elipse colour coded by its ASCII number
for (int i=0; i<list.length; i++) {
for (int j=0; j<list[i].length(); j++) {
char num = list[i].charAt(j);
fill(map(int(num), 0, 128, 0, 255));
ellipse(j*15, i*15, 15, 15);
}
saveFrame("dot_images/"+timestamp()+".png"); //creates a PNG in the sketch directory
//noLoop();
}
}
void keyPressed() {
if (keyCode == BACKSPACE) {
if (yourText.length() > 0) {
yourText = yourText.substring(0, yourText.length()-1);
}
} else if (keyCode == DELETE) {
yourText = "";
} else if (keyCode != SHIFT && keyCode != CONTROL && keyCode != ALT) {
myText = "";
yourText = yourText + key;
}
// If the Control key is pressed save the String and write it to text file
if (key == CODED)
{
if (keyCode == CONTROL) {
savedText = yourText;
textFile = createWriter("stories/"+timestamp()+".txt");
textFile.println(savedText);
textFile.flush();
textFile.close();
rect (0,0,width, height); //PROBLEM sometimes visible when screen is switched.
noStroke ();
currentScreen++;
if (currentScreen > 2) { currentScreen = 0; } //switches to next screen
}
else {
// Otherwise, concatenate the String
// Each character typed by the user is added to the end of the String variable.
yourText = yourText + key;
}
}
}
void countCharacters(){
for (int t = 0; t < savedText.length(); t++) {
// get one char from the text, convert it to a string and turn it to uppercase
String u = str(savedText.charAt(t)).toUpperCase();
// convert it back to a char
char uppercaseChar = u.charAt(0);
// get the position of this char inside the alphabet string
int index = alphabet.indexOf(uppercaseChar);
// increase the respective counter
if (index >= 0) counters[index]++;
}
}
Answers
Just store current millis() (or frameCount) in a variable as the start of the new cycle! :-B