How to make code into a class with processing - processing

I am taking a coding class, and I am struggling to do the following:
Rewrite the following code into an object-oriented fashion with a Snake class, and use an array to make a second snake appear.
This is what I have so far.
THIS IS NOT HOMEWORK, DO NOT WORRY. THIS IS A CLASS I AM TAKING ONLINE
int[] xpos = new int[50];
int[] ypos = new int[50];
void setup() {
size(800,600);
// Initialize
for (int i = 0; i < xpos.length; i++){
xpos[i] = 0;
ypos[i] = 0;
}
}
void draw() {
background(255);
// Shift Array Values
for (int i = 0; i < xpos.length - 1; i++){
xpos[i] = xpos[i + 1];
ypos[i] = ypos[i + 1];
}
// New location
xpos[xpos.length - 1] = mouseX;
ypos[ypos.length - 1] = mouseY;
// Draw Everything
for (int i = 0; i < xpos.length - 1; i++){
noStroke();
fill(255 - i*5);
ellipse(xpos[i], ypos[i], i, i);
}
}

So I don't know how much you already know about objects is Processing, so I hope you will understand this.
A object is just an instance of a class.
A class can include variables and functions.
When you create an object from a class you can set the variables of the object, so that two different objects can have two different values for the same variable.
When you run a function of an object it will perform the function only on the variables from that object (not from the others).
So to create a class you just wrap the code in class [class name here] { [your code here] }.
You can cut out stuf that you don't want to be executed multible times like background(255); and paste it back into draw function.
Now you have to rename the functions: for the setup function you can use a constructer which is just a function without a return type (like void) and with the same name as the class. This will automatically run when you create the object later. The draw function you can just name how you want (I named it update).
So at that point you should have this:
class Snake{
private int[] xpos = new int[50];
private int[] ypos = new int[50];
Snake(){
for (int i = 0; i < xpos.length; i++){
xpos[i] = 0;
ypos[i] = 0;
}
}
void update(){
// Shift Array Values
for (int i = 0; i < xpos.length - 1; i++){
xpos[i] = xpos[i + 1];
ypos[i] = ypos[i + 1];
}
// New location
xpos[xpos.length - 1] = mouseX;
ypos[ypos.length - 1] = mouseY;
// Draw Everything
for (int i = 0; i < xpos.length - 1; i++){
noStroke();
fill(255 - i*5);
ellipse(xpos[i], ypos[i], i, i);
}
}
}
so now you can create an array of snakes and run the update function (or what ever you named it) on all of them (of cause I would do that with a loop, but I think this way it's more obvious)
Snake[] snakes = {new Snake(), new Snake()};
void setup() {
size(800,600);
// Initialize
}
void draw() {
background(255);
snakes[0].update();
snakes[1].update();
}
Now you have two snakes, but you can't see both of them because they are on top of each other. That's why I added a variable offset, that will offset the two snakes and r, g, b variables for the color of the snake.
of cause you have to pass the variables to the object when you create it and recieve it in the constructor.
So when you're done you should have something like that:
Snake[] snakes = {new Snake(0,0,255, 0), new Snake(255,0,0, 50)};
void setup() {
size(800,600);
// Initialize
}
void draw() {
background(255);
snakes[0].update();
snakes[1].update();
}
class Snake{
private int[] xpos = new int[50];
private int[] ypos = new int[50];
private int r;
private int g;
private int b;
private int offset;
Snake(int r, int g, int b, int offset){
this.r = r;
this.g = g;
this.b = b;
this.offset = offset;
for (int i = 0; i < xpos.length; i++){
xpos[i] = 0;
ypos[i] = 0;
}
}
void update(){
// Shift Array Values
for (int i = 0; i < xpos.length - 1; i++){
xpos[i] = xpos[i + 1];
ypos[i] = ypos[i + 1];
}
// New location
xpos[xpos.length - 1] = mouseX +offset;
ypos[ypos.length - 1] = mouseY +offset;
// Draw Everything
for (int i = 0; i < xpos.length - 1; i++){
noStroke();
fill(r - i*5, g - i*5, b - i*5);
ellipse(xpos[i], ypos[i], i, i);
}
}
}
So finally it should look like this:
two snakes in red and blue
I hope I could help you with this!

Related

Processing String splitting and loops to form a facade

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

Delete leftmost circle on the canvas

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 !

How to write this processing code in an alternative (beginner) way?

How do I write the code (below) in an alternative (beginner) way? I don't wish to use createShape, setFill and addChild. Instead, any other way to perform the same thing?
grid = createShape(GROUP)
for i in range(C*R):
self.cell = createShape(RECT, (i%C)*S, (i//C)*S, S, S)
self.cell.setFill(colors[i] if i in filled else 210)
grid.addChild(self.cell)
Assuming that you're try to create a rectangle grid:
final int _numRows = 5;
final int _numCols = 7;
int l = 20;
int t = 20;
int w = 90;
int h = 60;
int hg = 10;
int vg = 10;
int left;
int top;
void rectGrid() {
for(int k = 0; k < _numRows; k++) {
for(int j = 0; j < _numCols; j++){
left = l + j*(w+vg);
top = t + k*(h+hg);
stroke(255);
strokeWeight(2);
fill(118);
rect( left, top, w, h);
}
}
}
void setup() {
size(800,500);
background(0,0,245);
rectGrid();
}
void draw() {
}
Adds a color array:
/*
Adds color array to rectangle grid.
*/
final int _numRows = 5;
final int _numCols = 7;
int l = 20;
int t = 20;
int w = 90;
int h = 60;
int hg = 10;
int vg = 10;
int left;
int top;
int count = 0;
color[] c;
void colorArray(){
for(int x=0; x< _numRows*_numCols; x++){
c[x] = color(random(255),random(255),random(255))
}
}
void rectGrid() {
for(int k = 0; k < _numRows; k++) {
for(int j = 0; j < _numCols; j++){
left = l + j*(w+vg);
top = t + k*(h+hg);
stroke(255);
strokeWeight(2);
fill(c[count]);
rect( left, top, w, h);
count++;
}
}
}
void setup() {
size(800,500);
background(0,0,245);
c = new color[_numCols*_numRows];
colorArray();
// Make sure the color array is filled first
rectGrid();
}
void draw() {
}

Array index out of bounds exception: 100

//----------------------------------------------\\
float x = 300;
float y = 300;
float direction = 0;
float increment = 1;
float speed = 5;
boolean toggle = true; // - For spaceship reversal
float wormX = random(0, 600); // - For wormHole v
float wormY = random(0, 600);
float wormGrowth = 0;
boolean growthSwitch = true; // - for wormHole ^
float[] starXpos = new float[100]; //starsRandom
float[] starYpos = new float[100]; //starsRandom
float d = dist(x, y, wormX, wormY);
int score = 0;
//----------------------------------------------\\
//----------------------------------------------\\ Setup
void setup (){
size (600, 600);
starsP1();
}
//----------------------------------------------\\ Draw
void draw (){
background (0);
spaceShip();
starsP2();
wormHole ();
score();
warpInitial();
blackHoleAt(100, 40);
blackHoleAt(400, 500);
}
//----------------------------------------------\\
//----------------------------------------------\\ starsRandom
void starsP1(){
int i = 0;
while (i < 100){
starXpos[i] = random(0, width);
starYpos[i] = random(0, height);
i = i + 1;
}
}
void starsP2(){
stroke(255);
strokeWeight(5);
int i = 0;
while (i < 100){
point(starXpos[i], starYpos[i]);
i = i + 1;
}
if (key == 'w'){
starYpos[i] = starYpos[i] + 1;
}
}
I'm trying to create a form of parallax for the stars in my code. When the user presses w,a,s,d the array of stars should correspond to the direction. I don't understand how this should work as I keep getting this error.
Try formatting your code to better see what's going on:
void starsP2(){
stroke(255);
strokeWeight(5);
int i = 0;
while (i < 100){
point(starXpos[i], starYpos[i]);
i = i + 1;
}
if (key == 'w'){
starYpos[i] = starYpos[i] + 1;
}
}
Your while loop executes until i == 100. Then after the while loop exits, you use that i variable again. Since i is 100, and your starYpos array only has up to index 99, you get an error.
The fix is to either move that if statement to inside the while loop, or to refactor your code so i doesn't go outside the bounds of the array.

How to draw two different matrices in Processing

I'm new to Processing. Why don't I see the first matrix drawn? I seem to only see the matrix after the delay, and not the one before. My ultimate goal is to watch how a matrix changes over time steps.
// Number of columns and rows in the grid
int[][] myArray = { {0, 1, 2, 3},
{3, 2, 1, 0},
{3, 5, 6, 1},
{3, 8, 3, 4} };
void setup() {
size(200,200);
}
void draw() {
background(204);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
rect(20+30*j,30+30*i,3,3);
}
}
delay(2500);
background(204);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
rect(40+30*j,50+30*i,7,7);
}
}
}
Your myArray variable is misleading, it doesn't seem to be used anywhere.
Basically you want to animate/interpolate between values.
Your code does this in the draw loop:
clear the background
draw 16 squares
wait 2500 ms
clear the background
draw 16 squares
which you'll tiny squares and after 2500 ms larger squares and that's it.
What want to do can be achieved in many ways, from the simpler to the more complex. Luckily Processing offers a lot of handy functions.
You want to store a property (like x position of a box) in a variable which you'll update over time and use the updated value to redraw on screen:
int x = 20;
int y = 30;
int w = 3;
int h = 3;
void setup() {
size(200,200);
}
void draw() {
//update
if(x <= 40) x++;
if(y <= 50) y++;
if(w <= 7) w++;
if(h <= 7) h++;
//draw
background(204);
for (int i = 0; i < 4 ; i++) {
for (int j = 0; j < 4; j++) {
rect(x+30*j,y+30*i,w,h);
}
}
}
You could also map() your values to a variable changing over time:
int x,y,s;
int xmin = 20,xmax = 40;
int ymin = 30,ymax = 50;
int smin = 3,smax = 7;
void setup() {
size(200,200);
}
void draw() {
//update
x = (int)map(mouseX,0,width,xmin,xmax);
y = (int)map(mouseX,0,width,ymin,ymax);
s = (int)map(mouseX,0,width,smin,smax);
//draw
background(204);
for (int i = 0; i < 4 ; i++) {
for (int j = 0; j < 4; j++) {
rect(x+30*j,y+30*i,s,s);
}
}
}
Or use linear interpolation (already implemented as lerp()):
int xmin = 20,xmax = 40;
int ymin = 30,ymax = 50;
int smin = 3,smax = 7;
void setup() {
size(200,200);
}
void draw() {
//update
float t = (float)mouseX/width;
//draw
background(204);
for (int i = 0; i < 4 ; i++) {
for (int j = 0; j < 4; j++) {
rect(lerp(xmin,xmax,t)+30*j,
lerp(ymin,ymax,t)+30*i,
lerp(smin,smax,t) ,
lerp(smin,smax,t) );
}
}
}
and you could alter your interpolation amount based on any variable you like:
int xmin = 20,xmax = 40;
int ymin = 30,ymax = 50;
int smin = 3,smax = 7;
void setup() {
size(200,200);
}
void draw() {
//update
float t = abs(sin(frameCount * .01));
//draw
background(204);
for (int i = 0; i < 4 ; i++) {
for (int j = 0; j < 4; j++) {
rect(lerp(xmin,xmax,t)+30*j,
lerp(ymin,ymax,t)+30*i,
lerp(smin,smax,t) ,
lerp(smin,smax,t) );
}
}
}
HTH

Resources