Any idea why this Processing sketch runs so slow? - performance

I'm using processing 2.1.
Any idea why my simple sketch is running slow on my (powerful) machine?
I'm simply drawing some quads in a grid, and when pressing the mouse I was trying to animate them (via Ani library), but the animation is sloppy and superslow....Any hint?
import de.looksgood.ani.*;
import de.looksgood.ani.easing.*;
int quadSize = 30;
int spacing = 10;
int numRows = 11;
int numColumns = 22;
float angleRotationIncrease = 3;
void setup () {
size (900, 600, P3D);
background (0);
fill (255);
stroke (255);
Ani.init(this);
frameRate (60);
}
void draw () {
text(frameRate,20,20);
// println (angleRotationIncrease);
background (0);
int posX = 0;
int posY = 0;
int angleRotation = 0;
float scaleFactor = 1;
float scaleFactorIncrease = -0.045;
for (int i=0; i<numRows; i++) {
for (int j=0; j<numColumns; j++) {
pushMatrix();
translate (posX + quadSize/2, posY + quadSize/2);
// println (radians(angleRotation));
rotate(radians(angleRotation));
if (scaleFactor > 0) {
rect (-quadSize/2 * scaleFactor, -quadSize/2* scaleFactor, quadSize* scaleFactor, quadSize* scaleFactor);
}
popMatrix ();
posX += (quadSize + spacing);
angleRotation += angleRotationIncrease;
scaleFactor += scaleFactorIncrease;
}
// for each new line, reset or change params
scaleFactorIncrease -= 0.002;
scaleFactor = 1;
angleRotation = 0;
posX = 0;
posY += (quadSize + spacing);
}
}
void mousePressed() {
Ani.to(this, 20, "angleRotationIncrease", -3);
}

Solved. it was a casting problem. Anglerotation is an int, so when subtracting the value I'm animating via Ani, it gets rounded

Because you are animating low range of values over very long period of time
Ani.to(this, 20, "angleRotationIncrease", -3);
Your range is [3,-3] and time is 20 seconds. Just try to decrease time and increase range an you will see more fluent animation on your powerful machine :) like this:
Ani.to(this, 2, "angleRotationIncrease", -30);
But at the end of animation is some kind of slowing what should be specified by default by Ani library so for more information read documentation here

Related

How can I get the RGB/Greyscale value fro a single pixel

I'm creating a code in Processing that applies a filter to a photo by going over each pixel, extracting the RGB/Grayscale value and modifying the RGB values. The program would take the grayscale value and run it through a few if/else statements to determine how much to modify the RGB values. So far I have this for the code but I'm stumped on how to extract the RGB/Gray values of a pixel
PImage method(PImage image) {
loadPixels();
image.filter(GRAY);
for (int i = 0; i < image.width; i++) {
for (int j = 0; j < image.height; j++) {
//This part here is to store the RGB values
float R;
float G;
float B;
//Convert the RGB to Gray
float coordCol = (0.2989*R) + (0.5870*G) + (0.1140*B);
if (coordCol < 60) {
float rDark = R * 0.9;
float gDark = G * 0.9;
float bDark = B * 0.9;
} else if(60 <= coordCol && coordCol <= 190) {
float bTintBro = B * 0.7;
} else {
float bTintYel = B * 0.9;
}
}
}
return image; // change this to return a new PImage object
}
I've tried many methods, get(), pixel[], filter(GRAY), etc but so far I still can't get the RGB values for a pixel
It's a question many will ask themselves because processing encodes it's colors in a non-intuitive manner. But you're in luck, because they totally know about it being that way! The helpful folks that coded Processing made a couple methods that will get you exactly what you want. Here's the documentation for the one to get the R value, you should be able to track the others from there.
Also, here's a short proof of concept demonstrating how to get the ARGB values from your sketch:
int rr, gg, bb, aa;
PImage bg;
void setup() {
size(600, 400);
// now setting up random colors for a test background
bg = createImage(width, height, RGB);
bg.loadPixels();
for (int i=0; i<width*height; i++) {
bg.pixels[i] = color(random(200), random(200), random(200), random(200));
}
updatePixels();
}
void draw() {
background(bg);
// giving visual feedback
fill(255);
textSize(15);
text("R: " + rr, 10, 20);
text("G: " + gg, 10, 40);
text("B: " + bb, 10, 60);
text("A: " + aa, 10, 80);
}
// THIS IS WHERE THE INFO YOU WANT IS
void mouseClicked() {
loadPixels();
int index = mouseX*mouseY;
rr = (int)red(pixels[index]);
gg = (int)green(pixels[index]);
bb = (int)blue(pixels[index]);
aa = (int)alpha(pixels[index]);
}
I hope it helps. Have fun!

How can you write an algorithm to properly fill a circle using lines from the center?

Currently I try to write code for calculating the parts of the screen you can see and those who can't because of objects that block light in 2d, like in Among Us:
The code should run on a processor with very low specs (at least in 2020), the C64. On such a simple CPU it's not possible to do such complex math fast enough for a game, so I came up with an idea: First of all, I make everything tile based, that makes processing easier and also means that I can just change entire characters or their color cells. Then I just write code for the PC in Processing (that's a coding language similar to Java but easier to use) to calculate how rays of light would move (the following graphic should make that more understandable), first just with a rectangle (and a single quadrant):
Then I wrote some completely messy assembler code for using the recorded coordinates to just keep filling the tiles with an inverted character based on the number of the ray currently being drawn on the ray until they hit an object (/ the tile it wants to fill is not inverted and not a space) and then just go to the next ray. I reduced the radius to 7 so it just takes up 256 bytes, useful for ASM. And that totally worked, I was able to fix every single bug and the result was quite impressive, since I needed to add pause statements or everything ran so fast that you couldn't see anything.
After that worked, I tried it with a circle, setting the points using this code:
int pointNum = ceil(radius * PI * 2); // calculates the circumference
for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}
I previously used the Bresenham circle algorithm but that didn't quite work so I tried a more simple way. So ...
All the marked black tiles never get hit by any light, which is a pretty big issue, because it wouldn't make much sense in a game that you just can't see those tiles. The code I used, written in Processing, is:
float[] xPoints = new float[0];
float[] yPoints = new float[0];
float[] xPointsT;
float[] yPointsT;
float[] xPointsHad = new float[0];
float[] yPointsHad = new float[0];
int pos = 0;
float interpolPos = 0;
int radius = 12;
float tileSize = 800.0 / (2*radius+1);
String output = " !byte ";
int pointNum = ceil(radius * PI * 2);
void setup() {
size(800, 800);
frameRate(60);
xPointsT = new float[0];
yPointsT = new float[0];
/*for(int i = 0;i <= radius;i++){
setPixel(radius, i);
setPixel(i, radius);
}*/ //Uncomment this and comment the next 4 lines to get the rectangle version
for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}
xPoints = concat(xPoints, xPointsT);
yPoints = concat(yPoints, yPointsT);
}
void draw(){
if(interpolPos > radius){
pos++;
interpolPos = 0;
println(output);
output = " !byte ";
}
float x=0, y=0;
float interpolMul = interpolPos / radius;
x = xPoints[pos] * interpolMul;
y = yPoints[pos] * interpolMul;
interpolPos+=1;//sorta the resolution
background(0);
stroke(255);
for(int i = 0;i < 2*radius+1;i++){
for(int j = 0;j < 2*radius+1;j++){
if((round(x) + radius) == i && (round(y) + radius) == j){
fill(0, 255, 0);
if(output != " !byte ")
output += ", ";
output += i-radius;
output += ", ";
output += j-radius;
xPointsHad = append(xPointsHad, i);
yPointsHad = append(yPointsHad, j);
}
else{
int fillVal = 0;
for(int k = 0; k < xPoints.length;k++){
if(round(xPoints[k])+radius == i && round(yPoints[k])+radius == j){
fillVal += 64;
}
}
fill(0, 0, fillVal);
if(fillVal == 0){
for(int k = 0; k < xPointsHad.length;k++){
if(round(xPointsHad[k]) == i && round(yPointsHad[k]) == j){
fill(128, 0, 0);
}
}
}
}
rect(i * tileSize, j * tileSize, tileSize, tileSize);
}
}
strokeWeight(3);
stroke(0, 255, 255, 64);
for(int i = 0;i < xPoints.length;i++){
line((float(radius)+0.5) * tileSize, (float(radius)+0.5) * tileSize, (float(radius)+0.5+xPoints[i]) * tileSize, (float(radius)+0.5+yPoints[i]) * tileSize);
}
strokeWeight(1);
fill(255, 255, 0);
ellipse((x + radius + 0.5) * tileSize, (y + radius + 0.5) * tileSize, 10, 10);
}
void setPixel(float _x, float _y){
for(int i = 0; i < xPoints.length;i++){
if(_x == xPoints[i] && _y == yPoints[i]){
return;
}
}
for(int i = 0; i < xPointsT.length;i++){
if(_x == xPointsT[i] && _y == yPointsT[i]){
return;
}
}
xPointsT = append(xPointsT, _x);
yPointsT = append(yPointsT, _y);
}
(Instructions to get the rectangle are in the code)
Those mentioned tiles seem to be never hit because the rays on them just jump over them, but what can I do to prevent that? You can decrease interpolPos+=x; to hit more tiles because that way your steps are smaller, but that wastes quite some space, so I don't think that's a good solution. Ideally you could also just decrease the number of coordinates you draw to get a smaller vision. Has anyone a good idea how to do that?
You have chosen wrong method to find all touched cells - instead of point-based way you need cell(squares)-based approach - ray intersects rectangle rather than point.
There is article of Amanatides and Woo "A Fast Voxel Traversal Algorithm for Ray Tracing" for 2D.
Practical implementation.
Example:
Quick-made tracing example. Rays emitted from left top corner go to blue points. If ray meets black cell obstacle, it stops. Pink cells are lighted by rays, grey ones are not.
Okay, I found something that worked for me in my situation: I just used the part that totally works (the rectangle) and then just make that a circle by ignoring every tile hit that's further away from the light source then the radius + 0.5, because without + .5 the circle looks weird. You can try it yourself, here's the code:
float[] xPoints = new float[0];
float[] yPoints = new float[0];
float[] xPointsT;
float[] yPointsT;
float[] xPointsHad = new float[0];
float[] yPointsHad = new float[0];
int pos = 0;
float interpolPos = 0;
int radius = 7;
float tileSize = 800.0 / (2*radius+1);
int pointNum = ceil(radius * PI * 2);
String standardOutput = " !align 15,0\n !byte ";
void setup() {
size(800, 800);
frameRate(60);
xPointsT = new float[0];
yPointsT = new float[0];
for(int i = 0;i <= radius;i++){
setPixel(radius, i);
setPixel(i, radius);
} //Uncomment this and comment the next 4 lines to get the rectangle version
/*for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}*/
xPoints = concat(xPoints, xPointsT);
yPoints = concat(yPoints, yPointsT);
xPointsT = new float[0];
yPointsT = new float[0];
}
void draw(){
if(interpolPos > radius){
pos++;
interpolPos = 0;
String output = standardOutput;
for(int i = 0;i < radius + 1;i++){
int indexPos = floor(map(i, 0, radius + 1, 0, xPointsT.length));
output += round(xPointsT[indexPos]);
output += ",";
output += round(yPointsT[indexPos]);
if(i < radius){
output += ", ";
}
}
println(output);
xPointsT = new float[0];
yPointsT = new float[0];
}
float x=0, y=0;
float interpolMul = interpolPos / radius;
x = xPoints[pos] * interpolMul;
y = yPoints[pos] * interpolMul;
interpolPos+=1;//sorta the resolution
background(0);
stroke(255);
for(int i = 0;i < 2*radius+1;i++){
for(int j = 0;j < 2*radius+1;j++){
if((round(x) + radius) == i && (round(y) + radius) == j && sqrt(sq(round(x)) + sq(round(y))) < radius + 0.5){
fill(0, 255, 0);
xPointsT = append(xPointsT, i-radius);
yPointsT = append(yPointsT, j-radius);
xPointsHad = append(xPointsHad, i);
yPointsHad = append(yPointsHad, j);
}
else{
int fillVal = 0;
for(int k = 0; k < xPoints.length;k++){
if(round(xPoints[k])+radius == i && round(yPoints[k])+radius == j){
fillVal += 64;
}
}
fill(0, 0, fillVal);
if(fillVal == 0){
for(int k = 0; k < xPointsHad.length;k++){
if(round(xPointsHad[k]) == i && round(yPointsHad[k]) == j){
fill(128, 0, 0);
}
}
}
}
rect(i * tileSize, j * tileSize, tileSize, tileSize);
}
}
strokeWeight(3);
stroke(0, 255, 255, 64);
for(int i = 0;i < xPoints.length;i++){
line((float(radius)+0.5) * tileSize, (float(radius)+0.5) * tileSize, (float(radius)+0.5+xPoints[i]) * tileSize, (float(radius)+0.5+yPoints[i]) * tileSize);
}
strokeWeight(1);
fill(255, 255, 0);
ellipse((x + radius + 0.5) * tileSize, (y + radius + 0.5) * tileSize, 10, 10);
}
void setPixel(float _x, float _y){
for(int i = 0; i < xPoints.length;i++){
if(_x == xPoints[i] && _y == yPoints[i]){
return;
}
}
for(int i = 0; i < xPointsT.length;i++){
if(_x == xPointsT[i] && _y == yPointsT[i]){
return;
}
}
xPointsT = append(xPointsT, _x);
yPointsT = append(yPointsT, _y);
}
Besides the main difference to ignore tiles that are not in the circle, I also changed that I store the coordinates not in a String but in two arrays, because then I use code to stretch them when there are fewer then radius + 1 points, so I don't have to store multiple circles with different sizes in the C64's RAM, so it meets my main requirements: It should fill every tile and it should be downscalable by ignoring some points at the end of rays. And is if efficient? Uh ... there could be a better solution that fills the circle with fewer rays, but I don't care too much. Still, if you have an idea, it would be nice if you could tell me, but otherwise this question is solved.
Edit: I forgot to add a picture. Don't be confused, I modified the code after posting it so you can also see the blue tiles on the circle.

How to make an (moving) ellipse clickable? Processing

So I started learning processing since a week ago and I'm trying to get a moving ellipse clickable. I followed the processing API, but I can't figure it out. I removed all the code relating to the clickable ellipse because it was a mess.
In the section where I declare all my vars you can see me using:
int breedte = 600;
int hoogte = 600;
These are suppose to be:
int breedte = width;
int hoogte = height;
But for some reason the width and height don't output the width and height declared in:
size(600,600)
So what I'm asking is:
How can I make the (moving) ellipse clickable?
Why I can't use width and height on 'int hoogte' and 'int breedte'?
Thanks in advace.
Main file:
int x = 0;
int leftSide = 0;
int rightSide = width;
int bottomSide = height;
int totalHits = 0;
int totalMiss = 0;
boolean start = false;
int circelSize = 100;
int circelRings = 24;
int circelSpeed = 1;
int circelPositionY = 0;
int breedte = 600;
int hoogte = 600;
String[] buttonText = {"Start","Stop"};
String buttonTextActive = buttonText[0];
int[] buttonColor = {0,90};
int buttonColorActive = buttonColor[0];
int buttonHighlight = 50;
int buttonSize = 80;
int buttonY = breedte - (buttonSize /2);
int buttonX = hoogte / 2 - 40;
void setup() {
size(600, 600);
smooth();
noStroke();
}
void draw() {
if (start) {
circelPositionY = circelPositionY + circelSpeed;
drawCircel(circelPositionY);
if (circelPositionY == (width + circelSize)) {
circelPositionY = 0;
}
}
drawButton();
}
Events file:
void mousePressed() {
// Start or Stop button
if(mouseX > buttonX & mouseX < buttonX + buttonSize & mouseY > buttonY & mouseY < buttonY + (buttonSize / 2)){
if(start) {
start = false;
buttonColorActive = buttonColor[0];
buttonTextActive = buttonText[0];
println("Game stoped");
} else {
start = true;
buttonColorActive = buttonColor[1];
buttonTextActive = buttonText[1];
println("Game started");
}
}
//HERE SHOULD GO THE CLICKABLE ELLPISE
}
Functions file:
void drawCircel(int circelPositionY) {
background(204);
for (int i = 0; i < circelRings; i = i+1) {
int even = i % 2;
if (even == 0) {
fill(255,0,0);
ellipse(-(circelSize / 2) + circelPositionY, height / 2 - (circelSize / 2), circelSize - (i * (circelSize / circelRings)), circelSize - (i * (circelSize / circelRings)));
} else {
fill(255);
ellipse(-(circelSize / 2) + circelPositionY, height / 2 - (circelSize / 2), circelSize - (i * (circelSize / circelRings)), circelSize - (i * (circelSize / circelRings)));
}
}
}
void drawButton() {
fill(buttonColorActive);
rect(buttonX,buttonY, buttonSize, buttonSize / 2);
fill(255);
textAlign(CENTER, CENTER);
text(buttonTextActive, buttonX + (buttonSize / 2),buttonY + (buttonSize / 4));
}
In the future, please try to post a MCVE instead of a bunch of disconnected snippets or your whole project. Also please only ask one question per post.
To make your circle clickable, you're going to have to write code that checks whether the circle is being clicked. That's actually two separate checks. First you have to detect when the mouse is pressed. One way to do that is by defining a mousePressed() function:
void mousePressed(){
// mouse is pressed
}
Then you have to check whether the mouse is currently inside the circle. You can use the dist() function for that: if the distance between the mouse and the center of the circle is less than the radius of the circle, then the mouse is inside the circle. That might look like this:
void mousePressed(){
if(dist(mouseX, mouseY, circleX, circleY) < circleRadius){
// mouse is pressed inside the circle
}
}
Shameless self-promotion: I wrote a tutorial on collision detection in Processing, including point-circle collision, available here.
As for why you can't use width and height at the top of your sketch, that's because code at the top of your sketch is executed before the setup() function fires, and the width and height variables aren't set until after you call size() from the setup() function. So you have to move that code to after you call size().
If you have follow-up questions, please post an updated MCVE in a new question post, and we'll go from there. Good luck.
Processing does not provide an api for hit detection, so you need to implement this by yourself, which I think is a great learning exercise. You can explore the mathematics of an ellipse here.
But the general approach is to use a function like the one below to check that the point you clicked on was indeed inside the ellipse you provided.
boolean InsideEllipse(
float x, float y,
float xc, float yc,
float width, float height
) {
// First half the width and height to get the ellipse parameters
float a = width / 2;
float b = height / 2;
// Now calculate the deltas:
float xd = x - xc;
float yd = y - yd;
// Now the equation of an ellipse is given by
// x^2 / a ^ 2 + y^2 / b ^ 2 = 1
// So if we are inside the ellipse, we would expect the left hand
// side of this expression to be less than one
boolean inside = xd * xd / (a * a) + yd * yd / (b * b) <= 1.0
return inside
}

modification in the animation of vertical lines with processing

i have modified the code for the animation of vertical lines which was given by . In the recent code I need to change the value between the two arrays of lines which are generated by the code and also make the disappearing of lines gradual. All the lines leaving or coming should have the same spacing between them. Below is the code.
//float[] linePositions = new float[10];
ArrayList<Integer> linePositions = new ArrayList<Integer>();
int lineWidth = 50;
int lineSpacing = 25;
int lineSpeed = 1;
int totalwidth;
int pixelperframe = 0;
int arraySize = 0;
void setup() {
size(640, 360);
println("Setup");
totalwidth = lineWidth+lineSpacing;
for (int i = 0; i < width; i=i +totalwidth) {
//Float value = 0 + (lineWidth+lineSpacing)*i;
linePositions.add(i);
}
arraySize = linePositions.size();
}
Boolean drawn = false;
void draw() {
println("Draw");
background(51);
//loop through the lines
//println("before Draw ka forloop"+linePositions.size());\
pixelperframe = ((lineSpeed - 10) > 1) ? (lineSpeed-10) : 1;
for (int i = 0; i < arraySize; i++) {
//println("Draw ka forloop");
rect(linePositions.get(i), 0, lineWidth, width);
int newPosition = linePositions.get(i) - pixelperframe ;
linePositions.set(i, newPosition);
//linePositions[i] -= lineSpeed;
//wrap the line
if ( linePositions.get(i) < 0) {
println("Wrapping the line");
linePositions.set(i, width);
// drawn = true;
}
}
//int temp = (width - linePositions.get(arraySize - 1)) - totalwidth;
//println(temp);
}
For the spacing between the lines to always be the same, you have to make sure that the total line spacing adds up to the total width of your screen. Right now each line takes up 75 pixels (50 for the line itself and 25 for the space after it), but your width is 640. That will always leave you with extra space, which will mess up your spacing after the lines start over.
So the easiest thing to do is to simply make your window a multiple of the line spacing. Let's go with 600, which is enough room for exactly 8 lines.
However, since you want your lines to slide off the screen, you actually need 9 lines, since you'll often see half of one line going off the screen while half of another line enters the screen. Draw some pictures to see exactly what I'm talking about
If I understand what you mean by making the lines "gradually" restart, you just have to restart them when their right side goes off the screen. In other words, when their x position is negative enough to be off the screen.
Putting it all together, it looks like this:
float[] linePositions = new float[9];
float lineWidth = 50;
float lineSpacing = 25;
float lineSpeed = 1;
void setup() {
size(600, 360);
for (int i = 0; i < linePositions.length; i++) {
linePositions[i] = (lineWidth+lineSpacing)*i;
}
}
void draw() {
background(51);
for (int i = 0; i < linePositions.length; i++) {
linePositions[i] -= lineSpeed;
rect(linePositions[i], 0, lineWidth, height);
if ( linePositions[i] < -(lineWidth+lineSpacing)) {
linePositions[i] = width;
}
}
}

animation of vertical bars using processing

I am basically trying to make a animation of vertical bars across the screen which should be equally spaced and continue until some key is pressed etc.. in the processing.org tool for animation.
I was able to get a kind of animation, but with hard coded values and had to write the same code again and again to generate the animation of bars for the whole frame/screen. I need to make it generic, so that changing the screen width or the size of the bars would not make me change the whole code but just the variables which control the parameters. Below is my code. I have written the code for three vertical bars but that needs to be done for the whole screen..
int a;
int i;
int j;
void setup() {
size(640, 360);
a = width/2;
i = 0;
}
void draw() {
background(51);
//need to avoid these repetitions each time for each bar
rect(a , 0, 25, width);
a = a - 1;
if (a < 0) {
a = width;
}
rect(i= a+50, 0, 25, width);
i = i - 1;
if (i < 0) {
i = width + a;
}
rect(j = i + 50, 0, 25, width);
j = j - 1;
if (a < 0) {
j = width + i;
}
}
It sounds like you're looking for an array.
An array is like a variable, only it can hold multiple values in its indexes. You can then use a for loop to iterate over the array and do stuff based on the values in the array.
Here's an example that uses an array to keep track of the line positions:
float[] linePositions = new float[10];
float lineWidth = 25;
float lineSpacing = 25;
float lineSpeed = 1;
void setup() {
size(640, 360);
for (int i = 0; i < linePositions.length; i++) {
linePositions[i] = width/2 + (lineWidth+lineSpacing)*i;
}
}
void draw() {
background(51);
//loop through the lines
for (int i = 0; i < linePositions.length; i++) {
//draw the line
rect(linePositions[i], 0, lineWidth, width);
//move the line
linePositions[i] -= lineSpeed;
//wrap the line
if ( linePositions[i] < 0) {
linePositions[i] = width;
}
}
}
More info on arrays can be found in the Processing reference.

Resources