I'm working on trying to use this free source code I found (http://solemone.de/demos/snow-effect-processing/) into a class that I can utilize within a larger, more complex "game" code. It's a pretty basic snow fall code:
int quantity = 15;
float [] xPosition = new float[quantity];
float [] yPosition = new float[quantity];
int [] flakeSize = new int[quantity];
int [] direction = new int[quantity];
int minFlakeSize = 10;
int maxFlakeSize = 20;
void setup() {
size(800, 350);
frameRate(30);
noStroke();
smooth();
for(int i = 0; i < quantity; i++) {
flakeSize[i] = round(random(minFlakeSize, maxFlakeSize));
xPosition[i] = random(0, width);
yPosition[i] = random(0, height);
direction[i] = round(random(0, 1));
}
}
void draw() {
background(0);
for(int i = 0; i < xPosition.length; i++) {
ellipse(xPosition[i], yPosition[i], flakeSize[i], flakeSize[i]);
if(direction[i] == 0) {
xPosition[i] += map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
} else {
xPosition[i] -= map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
}
yPosition[i] += flakeSize[i] + direction[i];
if(xPosition[i] > width + flakeSize[i] || xPosition[i] < -flakeSize[i] || yPosition[i] > height + flakeSize[i]) {
xPosition[i] = random(0, width);
yPosition[i] = -flakeSize[i];
}
}
}
I just haven't quite grasped on how to separate the for() loops, integers, and arrays into functions I can put into a separate class that I've titled Snow so that I can easily move it and manipulate it within the greater code. Here's one of my (many) attempts so far:
Class Tab:
class Snow{
int quantity = 15;
float [] xPosition = new float[quantity];
float [] yPosition = new float[quantity];
int [] flakeSize = new int[quantity];
int [] direction = new int[quantity];
int minFlakeSize = 10;
int maxFlakeSize = 20;
Snow(){
frameRate(30);
noStroke();
smooth();
}
void display() {
flakeSize = round(random(minFlakeSize, maxFlakeSize));
xPosition = random(0, width);
yPosition = random(0, height);
direction = round(random(0, 1));
}
void update() {
for(int i = 0; i < xPosition.length; i++) {
ellipse(xPosition[i], yPosition[i], flakeSize[i], flakeSize[i]);
if(direction[i] == 0) {
xPosition[i] += map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
} else {
xPosition[i] -= map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
}
yPosition[i] += flakeSize[i] + direction[i];
if(xPosition[i] > width + flakeSize[i] || xPosition[i] < -flakeSize[i] || yPosition[i] > height + flakeSize[i]) {
xPosition[i] = random(0, width);
yPosition[i] = -flakeSize[i];
}
}
}
}
Main Tab:
//Ice
Snow [] flakes = new Snow[15];
int quantity = 15;
void setup(){
size(600,800);
flakes = new Snow[15];
}
void draw(){
background(0);
for(int i = 0; i < quantity; i++){
flakes[i].display();
flakes[i].update();
}
}
I'm sure it's a really simple method of breaking down the code and separating them into the proper places, but I can't seem to grasp it.
If anyone could help me with this process, I would really appreciate it.
This code doesn't make sense, because the Snow class seems to be keeping track of every snowflake, but you then have multiple instances of Snow.
Instead of trying to copy-paste random code into your sketch, you'll have much better luck if you take a step back, start a little smaller, try to understand what the code does, and then write your own code.
Step 1: Can you create a class that encapsulates the data and behavior for a single snowflake?
Don't worry about multiple snowflakes yet. Just get something very basic working. Here's a simple example class:
class SnowFlake{
float x = random(width);
float y = random(height);
float r = random(10);
void draw(){
ellipse(x, y, r, r);
y++;
if(y > height){
y = 0;
x = random(width);
}
}
}
Step 2: Can you use that class in a single variable to draw a single snowflake?
You might create a little example sketch like this:
SnowFlake snowFlake;
void setup(){
size(500, 500);
snowFlake = new SnowFlake();
}
void draw(){
background(0);
snowFlake.draw();
}
Get this single snowflake working perfectly before moving on.
Step 3: Now that you have the single snowflake working, can you use an array or ArrayList to create multiple snowflakes?
If you work in small steps, it will be easy to add one thing at a time:
ArrayList<SnowFlake> snowFlakes = new ArrayList<SnowFlake>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
snowFlakes.add(new SnowFlake());
}
}
void draw() {
background(0);
for (SnowFlake snowFlake : snowFlakes) {
snowFlake.draw();
}
}
You can't program by trying to blindly copy-paste code into your sketch. You have to really understand what it's doing, and you're usually better off just writing your own code based on that understanding. Good luck!
Related
Hello Stack Overflow people :)
I'm a huge newbie when it comes to coding, and I've just ran into a problem that my brain just won't get over...
Before I start blabbering about this issue, I'll paste my code so as to give a little bit of context (sorry in advance if looking at it makes you wanna puke). The main focus of the issue is commented and should therefore be fairly visible :
Main
ArrayList<Individual> individuals = new ArrayList<Individual>();
void setup()
{
size(500,500);
for(int i = 0; i < 2; i++)
{
individuals.add(new Individual());
}
println(frameRate);
}
void draw()
{
background(230);
for(int i = 0; i < individuals.size(); i++)
{
individuals.get(i).move();
individuals.get(i).increaseTimers();
individuals.get(i).display();
}
}
Individual
class Individual
{
float x;
float y;
int size = 5;
Timer rdyBreed; /* Here is the object that appears to be shared
between individuals of the ArrayList */
float breedRate;
float breedLimit;
Individual()
{
x = random(0, width);
y = random(0, height);
rdyBreed = new Timer("rdyBreed", 0);
breedRate = random(.2, 3);
breedLimit = random(10, 20);
}
void move()
{
int i = (int)random(0, 1.999);
int j = (int)random(0, 1.999);
if (i == 0)
{
x = x + 1;
} else
{
x = x - 1;
}
if (j == 0)
{
y = y + 1;
} else
{
y = y - 1;
}
checkWalls();
}
void checkWalls()
{
if (x < size/2)
{
x = width - size/2;
}
if (x > width - size/2)
{
x = size/2;
}
if (y < size/2)
{
y = width - size/2;
}
if (y > width - size/2)
{
y = size/2;
}
}
void display()
{
noStroke();
if (!rdyBreed.finished)
{
fill(255, 0, 0);
} else
{
fill(0, 255, 0);
}
rect(x - size/2, y - size/2, size, size);
}
void increaseTimers()
{
updateBreedTimer();
}
void updateBreedTimer()
{
rdyBreed.increase(frameRate/1000);
rdyBreed.checkLimit(breedLimit);
rdyBreed.display(x, y);
}
}
Timer
class Timer
{
float t;
String name;
boolean finished = false;
Timer(String name, float t)
{
this.t = t;
this.name = name;
}
void increase(float step)
{
if (!finished)
{
t = t + step;
}
}
void checkLimit(float limit)
{
if (t >= limit)
{
t = 0;
finished = true;
}
}
void display(float x, float y)
{
textAlign(RIGHT);
textSize(12);
text(nf(t, 2, 1), x - 2, y - 2);
}
}
Now that that's done, let's get to my question.
Basically, I'm trying to create some sort of a personal Conway's Game of Life, and I'm encountering a lot of issues right off the bat.
Now my idea when writing this piece of code was that every individual making up the small simulated "society" would have different timers and values for different life events, like mating to have children for example.
Problem is, I'm not a huge pro at object-oriented programming, and I'm therefore quite clueless as to why the objects are not having each their own Timer but both a reference to the same timer.
I would guess making an ArrayList of timers and using polymorphism to my advantage could make a change, but I'm not really certain of it or really how to do it so... yeah, I need help.
Thanks in advance :)
EDIT : Here is a screenshot of the debugger. The values keep being the same with each iteration of the updates.
Screenshot
What makes you think they reference the same Timer object? The values of t displayed in the debugger are going to be the same until one of them reaches the breedLimit and gets set to 0, because they're being initialized at the same time.
Try this and see that the values of t are different.
void setup() {
size(500,500);
}
void mouseClicked() {
individuals.add(new Individual());
}
I'd recommend setting the breakpoint somewhere around here:
t = 0;
finished = true;
They do not share the same timer, you create a new Timer object for each Individual.
class Individual {
// ...
Timer rdyBreed;
Individual() {
// ...
rdyBreed = new Timer("rdyBreed", 0);
//...
The only way they could be sharing the same Timer is if you were setting rdyBreed elsewhere, but since you don't want that I recommend making it final.
If you did want to share the same Timer instance across all individuals then you could declare it static.
I am doing this in processing which is essentially java and I have never attempted anything like this before. Can't find any examples of collision detection using arrays to map the pixels.
I am not really trying to make them realistic collisions. I was thinking it would have the same response as if it hit a wall which is just for it to change directions in whatever axis is appropriate for the wall it hit.
I have tried checking if the x and y position are the same but can't seem to make that work. I'd appreciate any input on this.
import java.util.Arrays;
int numOfParticles = 10;
float[] x = new float[numOfParticles]; //initial position of y only matters
float[] px = new float[numOfParticles];
float[] y = new float[numOfParticles];
float[] py = new float[numOfParticles];
int speed = 10;//inversly related to speed
float[] xIncrement = new float[numOfParticles]; //the ratio of increments determines the pattern
float[] yIncrement = new float[numOfParticles]; // it is the slope of the line
//float xIncrement = 10/speed; //the ratio of increments determines the pattern
//float yIncrement = 11/speed; // it is the slope of the line
color currentColor;
int alpha = 100;//range of 0-255
//radius of ball
int radius = 1;
//thickness of line behind ball
int thickness = 5;
int rateOfColor = 5; //this is inversely related to rate but also changes the range of colors
int maxColor = 255;
int minColor = 0;
void setup(){
size(500,500);
background(0);
colorMode(HSB);
strokeWeight(thickness);
frameRate(60);
//initialize particles
for(int i = 0;i<numOfParticles;i++){
xIncrement[i] = random(0,100)/speed; //the ratio of increments determines the pattern
yIncrement[i] = random(0,100)/speed; // it is the slope of the line
x[i] = random(0,width);
px[i] = x[i];
y[i] = random(0,height);
py[i] = y[i];
}
//you can either initialize all of them individually or do a random one
//x[0] = 0;
//px[0] = x[0];
//y[0] = 450;
//py[0] = y[0];
//x[1] = width;
//px[1] = x[1];
//y[1] = 450;
//py[1] = y[1];
}
void draw(){
background(0); //comment out for criss cross
for(int i = 0; i < numOfParticles; i++){
particle(i);
}
}
void particle(int particleNum){
currentColor = color(minColor + (x[particleNum]/rateOfColor)%maxColor,255,255,alpha);
stroke(currentColor);
fill(currentColor);
ellipse(x[particleNum],y[particleNum],radius,radius);
line(px[particleNum],py[particleNum],x[particleNum],y[particleNum]);
px[particleNum] = x[particleNum];
py[particleNum] = y[particleNum];
y[particleNum]+= yIncrement[particleNum];
x[particleNum]+= xIncrement[particleNum];
if(x[particleNum] > width + 1 || x[particleNum] < 0){
x[particleNum] -= 2*xIncrement[particleNum];
xIncrement[particleNum]*=-1;
}
if( y[particleNum] > height + 1 || y[particleNum] < 0){
y[particleNum] -= 2*yIncrement[particleNum];
yIncrement[particleNum]*=-1;
}
//if(Arrays.binarySearch(x,x[particleNum]) >= 0 && Arrays.binarySearch(y,y[particleNum]) >= 0){
// xIncrement[particleNum]*=-1;
// yIncrement[particleNum]*=-1;
// print("*\n");
// stop();
//}
print("x[0] = " + x[0] + "\n");
print("x[1] = " + x[1] + "\n");
print("y[0] = " + y[0] + "\n");
print("y[1] = " + y[1] + "\n");
}
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. But I'll try to help in a general sense:
You need to break your problem down into smaller pieces and then take those pieces on one at a time. Don't worry about the whole particle system. Make it work for a single particle. Do some research on collision detection.
Then if you get stuck, you can post a more specific question along with a MCVE. Good luck.
So, I have been working on this program for drawing a star from a circle created using g.fillPolygon(int, int, int). I was intially having issues with creating an entire circle, but changed double angle = (i * 360) to (i * 720) to fix that (may be a band-aid fix, not sure yet). Now I'm in the process of attempting to connect all the points together (as shown in the "Target Output" section).
Note: I believe that the labeling of the points shown in the modification section was not done wih Java.
My Code: (Where I'm at right now)
import java.awt.*;
public class StarSampler {
public static void main(String[] args)
{
DrawingPanel panel = new DrawingPanel(500, 500);
Graphics2D g = panel.getGraphics();
g.setColor(Color.YELLOW);
fillStar(g, 250, 250, 150, 50, .7);
}
public static void fillStar(Graphics2D g, int ctrX, int ctrY, int radius, int nPoints, double spikiness)
{
double xDouble[] = new double[2*nPoints];
double yDouble[] = new double[2*nPoints];
int xPoint[] = new int[100];
int yPoint[] = new int[100];
for (int i = 0; i < 2*nPoints; i++)
{
double iRadius = (i % 2 == 0) ? radius : (radius * spikiness);
double angle = (i * 720.0) / (2*nPoints);
xDouble[i] = ctrX + iRadius * Math.cos(Math.toRadians(angle));
yDouble[i] = ctrY + iRadius * Math.sin(Math.toRadians(angle));
for (int j = 0; j < nPoints; j++) // Casts for ints and doubles
{
xPoint[j] = (int) xDouble[j];
yPoint[j] = (int) yDouble[j];
}
}
g.fillPolygon(xPoint, yPoint, nPoints); // Creates polygon but
}
}
My Code's Output:
Target Output (What I'm generally aiming for, not both together):
I'm trying to run this code:
import TUIO.*;
TuioProcessing tuioClient;
// Grid
int cols = 6, rows = 6;
boolean[][] states = new boolean[cols][rows];
int videoScale = 100;
// these are some helper variables which are used
// to create scalable graphical feedback
float cursor_size = 15;
float object_size = 60;
float table_size = 760;
float scale_factor = 1;
PFont font;
boolean verbose = false; // print console debug messages
boolean callback = true; // updates only after callbacks
void setup(){
size(600,600);
noCursor();
noStroke();
fill(0);
// periodic updates
if (!callback) {
frameRate(60); //<>//
loop();
} else noLoop(); // or callback updates
font = createFont("Arial", 18);
scale_factor = height/table_size;
// finally we create an instance of the TuioProcessing client
// since we add "this" class as an argument the TuioProcessing class expects
// an implementation of the TUIO callback methods in this class (see below)
tuioClient = new TuioProcessing(this);
}
void draw()
{
// Begin loop for columns
for (int i = 0; i < cols; i++) {
// Begin loop for rows
for (int j = 0; j < rows; j++) {
// Scaling up to draw a rectangle at (x,y)
int x = i*videoScale;
int y = j*videoScale;
fill(255);
stroke(0);
//check if coordinates are within a box (these are mouse x,y but could be fiducial x,y)
//simply look for bounds (left,right,top,bottom)
rect(x,y,videoScale,videoScale);
}
}
textFont(font,18*scale_factor);
float obj_size = object_size*scale_factor;
float cur_size = cursor_size*scale_factor;
ArrayList<TuioObject> tuioObjectList = tuioClient.getTuioObjectList();
for (int i=0;i<tuioObjectList.size();i++) {
TuioObject tobj = tuioObjectList.get(i);
stroke(0);
fill(0,0,0);
pushMatrix();
translate(tobj.getScreenX(width),tobj.getScreenY(height));
rotate(tobj.getAngle());
rect(-obj_size/2,-obj_size/2,obj_size,obj_size);
popMatrix();
fill(255);
text(""+tobj.getSymbolID(), tobj.getScreenX(width), tobj.getScreenY(height));
}
ArrayList<TuioCursor> tuioCursorList = tuioClient.getTuioCursorList();
for (int i=0;i<tuioCursorList.size();i++) {
TuioCursor tcur = tuioCursorList.get(i);
ArrayList<TuioPoint> pointList = tcur.getPath();
if (pointList.size()>0) {
stroke(0,0,255);
TuioPoint start_point = pointList.get(0);
for (int j=0;j<pointList.size();j++) {
TuioPoint end_point = pointList.get(j);
line(start_point.getScreenX(width),start_point.getScreenY(height),end_point.getScreenX(width),end_point.getScreenY(height));
start_point = end_point;
}
stroke(192,192,192);
fill(192,192,192);
ellipse( tcur.getScreenX(width), tcur.getScreenY(height),cur_size,cur_size);
fill(0);
text(""+ tcur.getCursorID(), tcur.getScreenX(width)-5, tcur.getScreenY(height)+5);
}
}
ArrayList<TuioBlob> tuioBlobList = tuioClient.getTuioBlobList();
for (int i=0;i<tuioBlobList.size();i++) {
TuioBlob tblb = tuioBlobList.get(i);
stroke(0);
fill(0);
pushMatrix();
translate(tblb.getScreenX(width),tblb.getScreenY(height));
rotate(tblb.getAngle());
ellipse(-1*tblb.getScreenWidth(width)/2,-1*tblb.getScreenHeight(height)/2, tblb.getScreenWidth(width), tblb.getScreenWidth(width));
popMatrix();
fill(255);
text(""+tblb.getBlobID(), tblb.getScreenX(width), tblb.getScreenX(width));
}
}
// --------------------------------------------------------------
// these callback methods are called whenever a TUIO event occurs
// there are three callbacks for add/set/del events for each object/cursor/blob type
// the final refresh callback marks the end of each TUIO frame
// called when an object is added to the scene
void addTuioObject(TuioObject tobj) {
if (verbose) println("add obj "+tobj.getSymbolID()+" ("+tobj.getSessionID()+") "+tobj.getX()+" "+tobj.getY()+" "+tobj.getAngle());
double fx = tobj.getX();
double fy = tobj.getY();
println (fx + " " + fy);
if( (fx >= x && fx <= x + videoScale) && //check horzontal
(fy >= y && fy <= y + videoScale)){
//coordinates are within a box, do something about it
fill(0);
stroke(255);
//you can keep track of the boxes states (contains x,y or not)
states[i][j] = true;
}
}
But I get the error "The field component.x is not visible" regarding the last if statement. I tried to make x and y public when I declared them in the draw method but I get the error "illegal modifier for the variable x; only final is permitted".
How could I fix this ?
Thanks for taking the time to read and for your help !
You never declare x and y outside of your draw() method, so they are not visible to addTuioObject(). If you need values from inside the draw method, you could declare class fields instead like you did with cursor_size or object_size. Use
int x, y;
outside of any methods and then assign accordingly, or add parameters to your addTuioObject() method:
void addTuioObject(TuioObject tobj, int x, int y) {
// Your code
}
I am trying to figure out why is my Array not showing any lines, I am trying to make it draw 10 different lines, now println of x and z does show 10 coordinates but they are identical and it seems as if they are being passed down to the object line itself but not drawn. It seems quite simple but I know I've made a mistake somewhere but not sure where.
lines[] mylinesArray = new lines[10];
void setup() {
size(1028, 768, P3D);
translate(width/2, height/2, 0);
rotateX(radians(180));
float prp = -2000;
float vrp = 50;
float z = random(prp, 2000);
float x = random(vrp, 500);
for (int i = 0; i<mylinesArray.length; i++) {
mylinesArray[i] = new lines(z, 0, x);
println(z);
println(x);
}
}
void draw() {
background(255);
for (int i=0; i<mylinesArray.length; i++) {
// println(i);
mylinesArray[i].drawlines();
//println("still doing it");
}
}
class lines {
color fillColor;
color strokeColor;
PVector dot1;
PVector dot2;
lines(float xpos, float ypos, float zpos) {
dot1 = new PVector(500+xpos, 200, 700+zpos);
dot2 = new PVector(500+xpos, -400, 700+zpos);
fillColor = strokeColor = color(random(255), random(255), random(255));
}
void drawlines() {
pushMatrix();
line (dot1.x, dot1.y, dot1.z, dot2.x, dot2.y, dot2.z);
stroke(0);
// println("new");
popMatrix();
}
void whatever() {
// println("please");
}
}