I have tried many methods, and can't seem to grasp the idea of extracting an index from my array of strings to help me generate my desired number of building with a desired height, please help, here is my example
edit: Hi, i saw your feedback and posted my code below, hopefully it helps with the idea overall, as much as it is just creating rects, its more complicated as i need to involve arrays and string splitting along with loops. i more or less got that covered but i as i said above, i cannot extract the values from my array of string and create my facades at my own desired number and height
String buffer = " ";
String bh = "9,4,6,8,12,2";
int[] b = int(split(bh, ","));
int buildingheight = b.length;
void setup () {
size(1200, 800);
background(0);
}
void draw () {
}
void Textbox() {
textSize(30);
text(buffer, 5, height-10);
}
void keyTyped() {
if (key == BACKSPACE) {
if (buffer.length() > 0) {
buffer = buffer.substring(0, buffer.length() - 1);
}
} else if (key == ENTER) {
background(0);
stroke(0);
GenerateFacade();
println(buffer);
}
else {
buffer = buffer + key;
Textbox();
}
}
void GenerateFacade() {
fill(128);
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length; j++) {
if (int(b[j]) > buildingheight) {
buildingheight = int(b[j]);
}
}
rect(i*width/b.length, height - (int(b[i])*height/buildingheight), width/b.length, int(b[i])*height/buildingheight);
}
}
For the next time it would be great if you provide us with some code so we know what you tried and maybe can point you to the problem you have.
You need just the keyPressed function and some variables
int x = 0;
int buildingWidth = 50;
int buildingHeight = height / 6;
void setup(){
size(1000, 500);
background(255);
}
void draw(){
}
void keyPressed(){
if(key >= '0' && key <= '9'){
int numberPressed = key - '0' ;
fill(0);
rect(x, height - buildingHeight * numberPressed,
buildingWidth, buildingHeight * numberPressed);
x += buildingWidth;
}
}
This is my result
Related
I was able to write a code that draws different circles on a canvas and i need to find a way i could delete the leftmost circle when any key is pressed. i've been at this for hours and i feel like i am close to the answer. i am most klikely going to look for the array whenever a key is pressed and delete the array position.
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPointsX = 0;
int numPointsY = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
boolean start = false;
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i<numPointsX; i++) {
circle(xPos[i], yPos[i], DIAM);
}
println(xPos[0]);
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPointsX] = x;
yPos[numPointsY] = y;
numPointsX += 1;
numPointsY += 1;
start = true;
}
void printArrays() {
println("X Positions");
for (int i = 0; i < 20; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
}
You are on the right track.
In broad terms you'd need two steps:
find the smallest X
delete the data associated with the smallest X
The 1st part is trivial:
use a variable to keep track of the currently smallest value (initialised with a bigger than than your data has)
iterate through each value
compare each value with the current smallest:
if it's bigger ignore
if it's smallest: update the currently smallest value (and remember the index)
at the end of the iteration the currently smallest value is the smallest possible value and index can be used to associate between x,y arrays (which are incremented in sync)
Here's a slightly modified version of your code to illustrate this:
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPoints = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i < numPoints; i++) {
circle(xPos[i], yPos[i], DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPoints] = x;
yPos[numPoints] = y;
numPoints++;
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
int smallestX = width;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < numPoints; i++){
// if xPos[i] is smaller than the smallest value so far...
if (xPos[i] < smallestX){
// ...remember it's value and index
smallestX = xPos[i];
smallestXIndex = i;
}
}
// delete the item at this index: fake it for now: move coordinates offscreen (to the right so left search still works)
xPos[smallestXIndex] = width * 2;
}
void printArrays() {
println("X Positions");
for (int i = 0; i < 20; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
I've made a few of other minor adjustments:
deleted start since it was assigned but not used (when debugging delete anything that isn't necessary)
renamed numPointsX to numPoints and deleted numPointsY: you are using two arrays indeed, however there is only one index for each point that could be re-used to access each array
numPoints++ is shorthand for numPoints = numPoints + 1;
Also, I've used a hacky placeholder for the remove a point just visually.
This means in terms of memory the xPos/yPos for deleted points will still be allocated.
To actually delete the array is a bit tricker since the array datatype does not change size, however you could manually put something together using subset() and concat(). You can achieve a similar effect to deleting an element by concatenating two subset array: from the start to the index to delete and from the index next to the one to delete to the end of the array.
Something like this:
void setup(){
println(deleteIndex(new int[]{1,2,3,4,5,6},-1));
println(deleteIndex(new int[]{1,2,3,4,5,6},2));
println(deleteIndex(new int[]{1,2,3,4,5,6},6));
}
int[] deleteIndex(int[] sourceArray, int indexToDelete){
if(sourceArray == null){
System.err.println("can't process null array");
return null;
}
if(indexToDelete < 0){
System.err.println("invalid index " + indexToDelete + "\nit's < 0");
return null;
}
if(indexToDelete >= sourceArray.length){
System.err.println("invalid index " + indexToDelete + "\nmax index = " + sourceArray.length);
return null;
}
return concat(subset(sourceArray, 0, indexToDelete),
subset(sourceArray, indexToDelete + 1, sourceArray.length - indexToDelete - 1));
}
It's a good idea to check arguments to a method to ensure they are valid and test with at least a few edge cases.
Here's a version of the above sketch using this delete method:
float colour = random(256);
final int DIAM = 20;
final int MAX_NUM = 1000;
int numPoints = 0;
int [] xPos = new int[MAX_NUM];
int [] yPos = new int [MAX_NUM];
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (int i=0; i < numPoints; i++) {
circle(xPos[i], yPos[i], DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
int x = mouseX;
int y = mouseY;
xPos[numPoints] = x;
yPos[numPoints] = y;
numPoints++;
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
int smallestX = width;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < numPoints; i++){
// if xPos[i] is smaller than the smallest value so far...
if (xPos[i] < smallestX){
// ...remember it's value and index
smallestX = xPos[i];
smallestXIndex = i;
}
}
// delete xPos item at this index
xPos = deleteIndex(xPos, smallestXIndex);
// delete yPos as well
yPos = deleteIndex(yPos, smallestXIndex);
// update size counter
numPoints--;
}
int[] deleteIndex(int[] sourceArray, int indexToDelete){
if(sourceArray == null){
System.err.println("can't process null array");
return null;
}
if(indexToDelete < 0){
System.err.println("invalid index " + indexToDelete + "\nit's < 0");
return null;
}
if(indexToDelete >= sourceArray.length){
System.err.println("invalid index " + indexToDelete + "\nmax index = " + sourceArray.length);
return null;
}
return concat(subset(sourceArray, 0, indexToDelete),
subset(sourceArray, indexToDelete + 1, sourceArray.length - indexToDelete - 1));
}
void printArrays() {
println("X Positions");
for (int i = 0; i < xPos.length; i++) {
println("\t" + xPos[i]);
}
}
void keyPressed() {
if (key == 'p') {
printArrays();
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
If manually deleting an item from an array looks tedious it's because it is :)
Array is meant to be fixed size: deleting an item actually allocates 3 arrays: two subset arrays and one for concatenation.
A better option is to use a dynamic sized array data structure like ArrayList. Speaking of data structures, to represent a point you can use the PVector class (which has x,y properties, but can also do much more).
You might have not encountered ArrayList and PVector yet, but there are plenty of resources out there (including CodingTrain/NatureOfCode videos).
Here's an example using these:
final int DIAM = 20;
final int MAX_NUM = 1000;
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size (500, 500);
}
void draw() {
background(150);
fill(random(256), random(256), random(256));
for (PVector point : points) {
circle(point.x, point.y, DIAM);
}
}
void mouseClicked() {
insertXandY();
}
void insertXandY() {
if(points.size() < MAX_NUM){
points.add(new PVector(mouseX, mouseY));
}
}
void deleteLeftMost(){
// find leftmost index
// start with a large X value
float smallestX = Float.MAX_VALUE;
int smallestXIndex = -1;
// iterate through each X
for(int i = 0 ; i < points.size(); i++){
PVector point = points.get(i);
// if xPos[i] is smaller than the smallest value so far...
if (point.x < smallestX){
// ...remember it's value and index
smallestX = point.x;
smallestXIndex = i;
}
}
// remove item from list
points.remove(smallestXIndex);
}
void keyPressed() {
if (key == 'p') {
println(points);
}
if (keyCode == DELETE || keyCode == BACKSPACE){
deleteLeftMost();
}
}
Hopefully this step by step approach is easy to follow.
Have fun learning !
I wrote this code on Processing 3.3.7, it creates a ball that bounces around.
Ball b;
int n = 0;
void setup() {
size(600, 400);
b = new BallBuilder()
.buildRadius(20)
.buildXSpeed(5)
.buildYSpeed(5)
.buildYAcceleration(1)
.toBall();
}
void draw() {
background(0);
n++;
print("n: " + n + " | ");
print("xSpeed: " + b.getXSpeed() + " | ");
println("ySpeed: " + b.getYSpeed());
b.display();
b.move();
}
There is also a Ball class, which has these methods:
void display() {
fill(255);
stroke(255);
ellipse(xPosition, yPosition, radius * 2, radius * 2);
}
void move() {
this.moveX();
this.moveY();
}
private void moveX() {
for(float i = 0; i <= abs(this.xSpeed); i += abs(this.xSpeed) / 10) {
this.bounceX();
this.xPosition += this.xSpeed / 10;
}
}
private void moveY() {
for(float i = 0; i <= abs(this.ySpeed); i += abs(this.ySpeed) / 10) {
this.bounceY();
this.yPosition += this.ySpeed / 10;
}
this.ySpeed += this.yAcceleration;
}
void bounceX() {
if(!this.canMoveX()) {
this.xSpeed = -this.xSpeed;
}
}
void bounceY() {
if(!this.canMoveY()) {
this.ySpeed = -this.ySpeed;
}
}
boolean canMoveX() {
if(this.xPosition < radius || this.xPosition >= width - this.radius) {
return false;
}
return true;
}
boolean canMoveY() {
if(this.yPosition < radius || this.yPosition >= height - this.radius) {
return false;
}
return true;
}
}
And there's also a builder and two getters for the Ball(not posted here, as they're pretty straight forward). The problem is, neither the xSpeed nor the ySpeed can be set to 0, otherwise the code stops running. That means that I need to give it both speeds when instantiating and if I set the acceleration makes the speed go to 0, the program stops running (the n variable is used to count the number of times the draw() loops, when the speed hits 0, it stops increasing). What am I missing?
Have you tried debugging your code to figure out where the code differs from what you expected?
You have two loops like this:
for(float i = 0; i <= abs(this.xSpeed); i += abs(this.xSpeed) / 10) {
You might add a print statement inside these loops, like this:
println("i: " + i);
If you did this, you'd discover that i is always 0. Why is that?
Think about what happens if this.xSpeed is 0: when will this loop exit?
I'm currently working on a school project and I'm trying to make a game similar to galaga. My problem is that whenever the bullet hits the enemy, another enemy would disappear. I believe this is because of the fact that I'm using a for loop and the enemies are being deleted in sequential order. Another problem I am having is with the bullets, I do not know why it slows down and eventually disappears as the number of the enemies decreases. Any help is appreciated.
ArrayList<enemy> e = new ArrayList<enemy>();
ArrayList<bullet> b = new ArrayList<bullet>();
boolean shoot = false;
void setup() {
fullScreen();
//enemy
for (int i = 0; i<5; i++) {
e.add(new enemy(50, 50));
}
//bullet
for (int i = 0; i<5; i++) {
b.add(new bullet(mouseX, mouseY));
}
}
void draw() {
background(255);
for (int p = 0; p<e.size(); p++) {
for (int i = 0; i<b.size(); i++) {
bullet a = b.get(i);
enemy o = e.get(p);
if (a.update()) {
b.remove(i);
}
if (o.col()) {
b.remove(i);
e.remove(i);
}
}
}
//enemy
for (int i = 0; i<e.size(); i++) {
enemy a = e.get(i);
a.display();
}
}
void mouseReleased() {
shoot = true;
b.add(new bullet(mouseX, mouseY));
}
class enemy {
int x, y, w, h;
int enemyX = int(random(width));
int enemyY = int(random(200));
public enemy(int tempenemyW, int tempenemyH) {
int tempenemyX = enemyX;
int tempenemyY = enemyY;
this.x = tempenemyX;
this.y = tempenemyY;
this.w = tempenemyW;
this.h = tempenemyH;
}
void display() {
fill(255, 0, 0);
rect(this.x, this.y, this.w, this.h);
}
boolean col() {
for (int i = 0; i<b.size(); i++) {
bullet a = b.get(i);
if (a.x+a.w>this.x && a.x<this.x+this.w && a.y+a.h+a.bulletSpeed>this.y && a.y+a.bulletSpeed<this.y+this.h) {
return true;
}
}
return false;
}
}
class bullet {
int x, y, w, h;
int bulletSpeed = 10;
public bullet(int tempx, int tempy) {
int tempw = 3;
int temph = 20;
this.x = tempx;
this.y = tempy;
this.w = tempw;
this.h = temph;
}
boolean update() {
this.y -= bulletSpeed;
fill(0, 255, 0);
rect(this.x, this.y, this.w, this.h, 100, 100, 100, 100);
if (x<0 || x>width || y<0 || y>height) {
return true;
} else {
return false;
}
}
}
Your removing the enemy that lives at the index of the bullet instead of the enemy at the index of the enemy. To fix this, try changing the line
e.remove(i);
to
e.remove(p);
I also recommend that you give better variable names. The reason that this was confusing for you is because "i" and "p" aren't very descriptive or helpful. It would have been easier to spot the mistake if the middle of the draw function looked like this:
for (int enemyIndex = 0; enemyIndex<e.size(); enemyIndex++) {
for (int bulletIndex = 0; bulletIndex<b.size(); bulletIndex++) {
bullet currentBullet = b.get(bulletIndex);
enemy currentEnemy = e.get(enemyIndex);
if (a.update()) {
b.remove(bulletIndex);
}
if (currentEnemy.col()) {
b.remove(bulletIndex);
e.remove(bulletIndex); // Clearly the wrong index!
}
}
}
Then you could go further by changing the names of your lists to "bullets" and "enemies" instead of just "b" and "e" :p
Teddy's answer is half the story. The other half of the story is that you're removing items from the list as you loop over it.
Let's say you have a loop like this:
for(int index = 0; index < list.size(); index++){
if(list.get(index).contains("remove me")){
list.remove(index);
}
}
And let's say your list looks like this:
0: "keep"
1: "remove me one"
2: "remove me two"
3: "keep"
Go through the loop with this list in mind. When index is 0, it sees "keep" and doesn't do anything. Now index is 1 and it sees "remove me one" so it removes the item at index 1 and every index after that shifts down one, making the list this:
0: "keep"
1: "remove me two"
2: "keep"
But index is still 1 at the end of the loop, so it increases to 2, and the next iteration sees "keep".
In other words, we skip over "remove me two" because we never check that index when it's shifted down by one.
The solution to this problem is to either use an Iterator or to loop backwards over the list.
Shameless self-promotion: I wrote a tutorial on using ArrayLists in Processing available here. See the section on removing items from an ArrayList.
I am currently using a processing sketch to work through a large number of images I have in a folder. I have set an onClick command to advance to the next image in the string. It is quite time consuming and I would like to automate the action that once the sketch is completed the sketch would repeat it's self selecting the next image from the string. The onClick command also save the image the export folder but each time saves with the same file name, I've tried to set up sequential numbering but it hasn't worked so far. Any help would be greatly appreciated.
String[] imgNames = {"1.jpg", "2.jpg", "3.jpg"};
PImage img;
int imgIndex = 0;
void nextImage() {
background(255);
frameRate(10000);
loop();
frameCount = 0;
img = loadImage(imgNames[imgIndex]);
img.loadPixels();
imgIndex += 1;
if (imgIndex >= imgNames.length) {
imgIndex = 0;
}
}
void paintStroke(float strokeLength, color strokeColor, int strokeThickness) {
float stepLength = strokeLength/4.0;
// Determines if the stroke is curved. A straight line is 0.
float tangent1 = 0;
float tangent2 = 0;
float odds = random(1.0);
if (odds < 0.7) {
tangent1 = random(-strokeLength, strokeLength);
tangent2 = random(-strokeLength, strokeLength);
}
// Draw a big stroke
noFill();
stroke(strokeColor);
strokeWeight(strokeThickness);
curve(tangent1, -stepLength*2, 0, -stepLength, 0, stepLength, tangent2, stepLength*2);
int z = 1;
// Draw stroke's details
for (int num = strokeThickness; num > 0; num --) {
float offset = random(-50, 25);
color newColor = color(red(strokeColor)+offset, green(strokeColor)+offset, blue(strokeColor)+offset, random(100, 255));
stroke(newColor);
strokeWeight((int)random(0, 3));
curve(tangent1, -stepLength*2, z-strokeThickness/2, -stepLength*random(0.9, 1.1), z-strokeThickness/2, stepLength*random(0.9, 1.1), tangent2, stepLength*2);
z += 1;
}
}
void setup() {
size(1600, 700);
nextImage();
}
void draw() {
translate(width/2, height/2);
int index = 0;
for (int y = 0; y < img.height; y+=1) {
for (int x = 0; x < img.width; x+=1) {
int odds = (int)random(20000);
if (odds < 1) {
color pixelColor = img.pixels[index];
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor), 100);
pushMatrix();
translate(x-img.width/2, y-img.height/2);
rotate(radians(random(-90, 90)));
// Paint by layers from rough strokes to finer details
if (frameCount < 20) {
// Big rough strokes
paintStroke(random(150, 250), pixelColor, (int)random(20, 40));
} else if (frameCount < 1000) {
// Thick strokes
paintStroke(random(75, 125), pixelColor, (int)random(8, 12));
} else if (frameCount < 1500) {
// Small strokes
paintStroke(random(20, 30), pixelColor, (int)random(1, 4));
} else if (frameCount < 10000) {
// Big dots
paintStroke(random(5, 10), pixelColor, (int)random(5, 8));
} else if (frameCount < 10000) {
// Small dots
paintStroke(random(1, 2), pixelColor, (int)random(1, 3));
}
popMatrix();
}
index += 1;
}
}
if (frameCount > 10000) {
noLoop();
}
// if(key == 's'){
// println("Saving...");
// saveFrame("screen-####.jpg");
// println("Done saving.");
// }
}
void mousePressed() {
save("001.tif");
nextImage();
}
Can't you just call the nextImage() function from inside this if statement?
if (frameCount > 10000) {
noLoop();
}
Would be:
if (frameCount > 10000) {
nextImage();
}
As for using different filenames, just use an int that you increment whenever you save the file, and use that value in the save() function. Or you could use the frameCount variable:
save("img" + frameCount + ".tif");
If you have follow-up questions, please post a MCVE instead of your whole project. Try to isolate one problem at a time in a small example program that only does that one thing. Good luck.
I am trying to create 100 frames where the numbers 0-100 are "printed" in the center of every frame. If I try the code below I get the error "It looks like you're mixing "active" and "static" modes".
size(1440,900);
font = loadFont("Arial-Black-96.vlw");
textFont(font,96);
int x = 0;
void draw() {
background(204);
y=0;
if (x < 100) {
text(y, 10, 50);
x = x + 1;
y=y+1;
} else {
noLoop();
}
// Saves each frame as screen-0001.tif, screen-0002.tif, etc.
saveFrame();
}
You need to wrap the first 3 lines in the setup() function.
Like:
void setup(){
size(1440,900);
font = loadFont("Arial-Black-96.vlw");
textFont(font,96);
}
I answered this without running the code, there were others issues, here a version of your code:
PFont font;
int x = 0;
int size = 96;
void setup() {
size(1440, 900);
font = createFont("Arial-Black", size);
textFont(font);
}
void draw() {
background(204);
if (x <= 100) {
String number = nf(x, 2);
text(number, width/2 - textWidth(number)/2, height/2);
x++;
saveFrame();
}
else {
exit();
}
}