Turing Diffusion in JavaFX - user-interface

I was trying to translate a Turing Diffusion model from JavaScript to JavaFX as seen here:
CODE
VIDEO
... but my code is not behaving properly. I believe is a combination of bad logic and the way I am updating the UI. Any help would be greatly appreciated. Code compiles and runs.
package application;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class Main extends Application {
private double dA = 1;
private double dB = 0.5;
private double feed = 0.055;
private double k = 0.062;
// Concentrate [x][y][t]
private double[][][] A = new double[100][100][100];
private double[][][] B = new double[100][100][100];
final NumberAxis xAxis = new NumberAxis(0, 100, 10);
final NumberAxis yAxis = new NumberAxis(0, 100, 10);
final ScatterChart<Number,Number> sc = new ScatterChart<Number,Number>(xAxis,yAxis);
Slider slider = new Slider(0,99,1);
VBox root = new VBox();
#SuppressWarnings("rawtypes")
XYChart.Series vizualize_A = new XYChart.Series();
#SuppressWarnings("rawtypes")
XYChart.Series vizualize_B = new XYChart.Series();
#SuppressWarnings("rawtypes")
XYChart.Data data_A;
#SuppressWarnings("rawtypes")
XYChart.Data data_B;
#SuppressWarnings("unchecked")
#Override
public void start(Stage primaryStage) {
try {
xAxis.setLabel("x");
yAxis.setLabel("y");
sc.setTitle("Turing Diffusion");
initArray();
update();
draw(0);
sc.getData().setAll(vizualize_A, vizualize_B);
sc.setLegendVisible(false);
sc.setAnimated(false);
sc.setPrefSize(500, 500);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(10f);
slider.setBlockIncrement(1f);
slider.setValue(0);
root.getChildren().addAll(sc, slider);
Scene scene = new Scene(root,700,550);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
slider.valueProperty().addListener((obs, oldval, newVal) -> {
draw(newVal.intValue());
Platform.runLater(new Runnable() {
#Override
public void run() {
sc.getData().setAll(vizualize_A, vizualize_B);
}
});
});
}
private void initArray(){
for (int m = 0; m <= (100-1); m++ ){
// y: j
for (int j = 0; j <= (100-1); j++){
// x: i
for (int i = 0; i <= (100-1); i++){
A[i][j][m] = 1;
// B[i][j][m] = 1;
if (i >= 20 && i<= 35 && j >= 35 && j <= 75 && m == 0) {
B[i][j][m] = 1;
} else {
B[i][j][m] = 0;
}
}
}
}
}
Rectangle rect_A[][][] = new Rectangle[100][100][100];
Rectangle rect_B[][][] = new Rectangle[100][100][100];
#SuppressWarnings({ "rawtypes", "unchecked" })
public void draw(int time){
vizualize_A.getData().clear();
vizualize_B.getData().clear();
sc.getData().remove(vizualize_A);
sc.getData().remove(vizualize_B);
// y: j
for (int j = 0; j <= (100-1); j++){
// x: i
for (int i = 0; i <= (100-1); i++){
int m = time;
data_A = new XYChart.Data(i, j);
data_B = new XYChart.Data(i, j);
// Type A
rect_A[i][j][m] = new Rectangle(5, 5);
rect_A[i][j][m].setFill(Color.RED);
data_A.setNode(rect_A[i][j][m]);
data_A.getNode().setOpacity(A[i][j][m]);
vizualize_A.getData().add(data_A);
// Type B
rect_B[i][j][m] = new Rectangle(5, 5);
rect_B[i][j][m].setFill(Color.BLACK);
data_B.setNode(rect_B[i][j][m]);
data_B.getNode().setOpacity(B[i][j][m]);
vizualize_B.getData().add(data_B);
}
}
}
public void update(){
for (int m = 1; m <= (100-2); m++ ){
// y: j
for (int j = 1; j <= (100-2); j++){
// x: i
for (int i = 1; i <= (100-2); i++){
A[i][j][m+1] = A[i][j][m] + (dA * laplace(A, i, j, m)) - (A[i][j][m] * Math.pow(B[i][j][m] ,2)) + (feed * (1 - A[i][j][m]));
B[i][j][m+1] = B[i][j][m] + (dB * laplace(B, i, j, m)) + (A[i][j][m] * Math.pow(B[i][j][m] ,2)) - (( k + feed) + B[i][j][m]);
A[i][j][m+1] = Math.min(Math.max(A[i][j][m+1], (double) 0), (double) 1);
B[i][j][m+1] = Math.min(Math.max(B[i][j][m+1], (double) 0), (double) 1);
}
}
}
}
public double laplace(double[][][] xArray, int x, int y, int time){
double laValue = 0;
laValue = laValue + xArray[x][y][time] * -1;
laValue = laValue + xArray[x - 1][y][time] * 0.2;
laValue = laValue + xArray[x + 1][y][time] * 0.2;
laValue = laValue + xArray[x][y + 1][time] * 0.2;
laValue = laValue + xArray[x][y - 1][time] * 0.2;
laValue = laValue + xArray[x - 1][y - 1][time] * 0.05;
laValue = laValue + xArray[x + 1][y - 1][time] * 0.05;
laValue = laValue + xArray[x + 1][y + 1][time] * 0.05;
laValue = laValue + xArray[x - 1][y + 1][time] * 0.05;
return laValue;
}
public static void main(String[] args) {
launch(args);
}
}
Update: Fixed one error in the update equations.

The issue:
You start update at "time" m=1. However m is the time of the state you read from, which means you start reading from the second state, not the initial state:
public void update(){
for (int m = 0; m <= (100-2); m++){ // fix here
Note that the following code contains a few modifications, like displaying the code in a Canvas (a chart seems to be a sorry choice to display the data) only doing the necessary initialisations and changing the index order (using "time" first allows you to pass the data for one "frame" around as double[][]):
private static final double dA = 1;
private static final double dB = 0.5;
private static final double feed = 0.055;
private static final double k = 0.062;
private static final int FRAMES = 200;
private static final int WIDTH = 100;
private static final int HEIGHT = 100;
private double[][][] A = new double[FRAMES][WIDTH][HEIGHT];
private double[][][] B = new double[FRAMES][WIDTH][HEIGHT];
Slider slider = new Slider(0, FRAMES - 1, 1);
VBox root = new VBox();
PixelWriter writer;
#Override
public void start(Stage primaryStage) {
Canvas canvas = new Canvas(WIDTH, HEIGHT);
writer = canvas.getGraphicsContext2D().getPixelWriter();
try {
initArray();
update();
draw(0);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(10f);
slider.setBlockIncrement(1f);
slider.setValue(0);
root.getChildren().addAll(canvas, slider);
Scene scene = new Scene(root, 700, 550);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
slider.valueProperty().addListener((obs, oldval, newVal) -> {
draw(newVal.intValue());
});
}
private void initArray() {
double[][] state = A[0];
for (int j = 0; j < WIDTH; j++) {
Arrays.fill(state[j], 1);
}
// fill border
for (double[][] s : A) {
Arrays.fill(s[0], 1);
Arrays.fill(s[WIDTH - 1], 1);
for (int i = 1; i < (WIDTH - 1); i++) {
double[] line = s[i];
line[0] = 1;
line[HEIGHT - 1] = 1;
}
}
state = B[0];
for (int i = 20; i <= 35; i++) {
Arrays.fill(state[i], 35, 75 + 1, 1);
}
}
public void draw(int time) {
double[][] stateA = A[time];
double[][] stateB = B[time];
for (int i = 0; i < WIDTH; i++) {
double[] lineA = stateA[i];
double[] lineB = stateB[i];
for (int j = 0; j < HEIGHT; j++) {
double a = lineA[j];
double b = lineB[j];
double result = Math.max(0, a - b);
writer.setArgb(i, j,
0xff000000
| (((int) (0xff * result)) << 16));
}
}
}
public void update() {
for (int m = 0; m < (FRAMES - 1); m++) {
double[][] sourceA = A[m];
double[][] sourceB = B[m];
double[][] targetA = A[m + 1];
double[][] targetB = B[m + 1];
for (int i = 1; i <= (WIDTH - 2); i++) {
double[] sourceLineA = sourceA[i];
double[] sourceLineB = sourceB[i];
double[] targetLineA = targetA[i];
double[] targetLineB = targetB[i];
for (int j = 1; j <= (HEIGHT - 2); j++) {
double a = sourceLineA[j];
double b = sourceLineB[j];
targetLineA[j] = Math.max(0, Math.min(1, a
+ dA * laplace(sourceA, i, j)
- a * b * b
+ (feed * (1 - a))));
targetLineB[j] = Math.max(0, Math.min(1, b
+ dB * laplace(sourceB, i, j)
+ (a * b * b)
- ((k + feed) * b)));
}
}
}
}
public double laplace(double[][] xArray, int x, int y) {
return 0.2 * (xArray[x - 1][y] + xArray[x + 1][y] + xArray[x][y + 1] + xArray[x][y - 1])
+ 0.05 * (xArray[x + 1][y + 1] + xArray[x + 1][y - 1] + xArray[x - 1][y + 1] + xArray[x - 1][y - 1])
- xArray[x][y];
}
public static void main(String[] args) {
launch(args);
}

Related

Change variable in array coded with processing

Help!
I'm drawing a sketch with randomized letters that fill the screen. The code issue is with my
for (int i = 0; i < I1; i++) {
targets = tX + i * ts;
targets2 = tY;
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets = random(ts, width - ts);
targets2 = random(ts, height - ts);`
** I need to update i within the for loop to denote the array letters' locations. The error returns a type mismatch, "float" does not match with int[]
How do I update the i within the for loop?/ (the targets= and targets2=)
Here is the code**
String message = "a,b,c,d,e,f";
int []positions = new int [0];
int[]positions2= new int[1];
int []targets = new int [0] ;
int [] targets2= new int[1];
int I1= message.length();
boolean runTowards = true;
float runSpeed = 100;
float restSpeed = 1;
float currentSpeed = restSpeed;
float ts = 64;
boolean thisHasReached;
float bk;
float elapsedTime;
boolean allHaveReached;
float pauseTime = 1000;
float distX;
float distY;
float changeX;
float changeY;
float tX;
float tY;
float reachedTargetAt = 0;
boolean hasReachedTarget = true;
void setup() {
size (600,600);
background(255);
if ((I1 > targets.length) && (I1 > positions.length)){
pickNewTarget();
}
}
void draw() {
elapsedTime = millis() - reachedTargetAt;
if (elapsedTime > pauseTime) {
pickNewTarget();
}
drawChars();
updatePositions();
updateCurrentSpeed();
}
void drawChars() {
for (int i = 0; i < I1; i++) {
text(message.charAt(i),positions[i], positions[i]);
}
}
void updatePositions() {
allHaveReached = true;
thisHasReached = false;
for (int i = 0; i < I1; i++) {
distX = abs(positions[i] - targets[i]);
distY = abs(positions2[i] - targets2[i]);
changeX = random(currentSpeed);
changeY = random(currentSpeed);
thisHasReached = changeX > distX && changeY > distY;
if (positions[i] > targets[i]) {
changeX = -changeX;
}
if (positions2[i] > targets2[i]) {
changeY = -changeY;
}
positions[i] += changeX;
positions2[i] += changeY;
allHaveReached = allHaveReached && thisHasReached;
}
if ((!hasReachedTarget) && (allHaveReached)) {
hasReachedTarget = true;
reachedTargetAt = millis();
}
}
void updateCurrentSpeed() {
if (hasReachedTarget) {
if (currentSpeed >= restSpeed) {
currentSpeed -= (currentSpeed - restSpeed) * 9;
} else {
currentSpeed += 1;
}
} else {
if (currentSpeed <= runSpeed) {
currentSpeed += (runSpeed - currentSpeed) * 0.25;
} else {
currentSpeed -= 1;
}
}
}
void pickNewTarget() {
if (!runTowards && random(1) > 0.75) {
runTowards = true;
tX = random(ts, width - 3 * ts);
tY = random(ts, height - ts);
for (int i = 0; i < I1; i++) {
targets = tX + i * ts;
targets2 = tY;
}
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets = random(ts, width - ts);
targets2 = random(ts, height - ts);
}
}
hasReachedTarget = false;
}
Please look at this reference for random(): https://processing.org/reference/random_.html. Note that it states "If two parameters are specified, the function will return a float with a value between the two values." You got the error message because you tried to mix ints and floats. You can correct it by changing the array types from int to float, eg.
float[] targets = new float[80] ;
float[] targets2= new float[80];
You'll also need to make those arrays large enough to handle the size of your data or you'll wind up with another error that the array length has been overrun. Then change the loop to reflect that you are adding data to the arrays ([i]):
void pickNewTarget() {
if (!runTowards && random(1) > 0.75) {
runTowards = true;
tX = random(ts, width - 3 * ts);
tY = random(ts, height - ts);
for (int i = 0; i < I1; i++) {
targets[i] = tX + i * ts;
targets2[i] = tY;
}
} else {
runTowards = false;
for (int i = 0; i < I1; i++) {
targets[i] = random(ts, width - ts);
targets2[i] = random(ts, height - ts);
}
}
hasReachedTarget = false;
}
Also need to add a fill() for the text characters or you will see a blank screen.

Simulation stops after certain UI elements are used

Im working on a project in processing, and I'm having some difficulty with this super annoying bug. All the code is pasted below, 4 class files.
Whenever the "Simulation speed" slider is moved up and then moved back down, the simulation will stop giving no errors. Same thing with the "Auto" button. I have no idea why this is occurring and I've gone through my code following the variables and I don't see anything wrong.
Help!
noisedemo file
int tableHeight = 20;
int tableWidth = 20;
float prismWidth = 10;
float tableTopx = 260;
float tableTopy = 200;
int k = 0;
int simulationSpeed;
int frameCounter;
Prism[][] prisms = new Prism[tableWidth][tableHeight];
//Declare the sliders
Slider simulationSpeedSlider = new Slider(10, 20, 100, 30, "Simulation Speed");
Slider noiseOctaveSlider = new Slider(10, 50, 100, 4, "Noise Ocatave");
Slider noiseScaleSlider = new Slider(10, 80, 100, 10, 10, "Noise Scale", true);
//Declare the buttons
Button autoScrollButton = new Button(400, 100, "Auto");
void setup(){
size(500, 500);
smooth();
pixelDensity(2);
frameRate(30);
noiseDetail((int)noiseOctaveSlider.sliderValue, noiseScaleSlider.sliderValue);
for(int i = 0; i < 20; i++){
for(int j = 0; j < 20; j++){
prisms[i][j] = new Prism(noise(i, j)*30+10, prismWidth);
prisms[i][j].setHeight(noise(i, j)*30+10);
}
}
}
float[] convertCoordinate(int xcoord, int ycoord, float xtop, float ytop, float pwidth){
float[] coord = new float[2];
coord[0] = (xtop + xcoord*cos(radians(40))*prismWidth - ycoord * cos(radians(40))*prismWidth)*0.95;
coord[1] = (ytop + ycoord*sin(radians(40))*prismWidth + xcoord * sin(radians(40))*prismWidth)*0.95;
return coord;
}
void updateHeight(){
for(int i = 0; i < tableWidth; i++){
for(int j = 0; j < tableHeight; j++){
prisms[i][j].drawPrism(convertCoordinate(i, j, tableTopx, tableTopy, prismWidth)[0], convertCoordinate(i, j, tableTopx, tableTopy, prismWidth)[1]);
}
}
}
void setHeight(){
for(int i = 0; i < tableWidth; i++){
for(int j = 0; j < tableHeight; j++){
prisms[i][j].setHeight(noise(i+k, j+k)*30+10);
}
}
}
void mouseClicked(){
if(autoScrollButton.isInRange()){
autoScrollButton.buttonActive = !autoScrollButton.buttonActive;
}
}
void draw(){
background(0, 150, 0);
noiseDetail((int)noiseScaleSlider.sliderValue, noiseScaleSlider.sliderValue);
simulationSpeedSlider.drawSlider();
simulationSpeed = (int)simulationSpeedSlider.sliderValue;
noiseOctaveSlider.drawSlider();
noiseScaleSlider.drawSlider();
autoScrollButton.drawButton();
if(frameCounter == simulationSpeed && autoScrollButton.buttonActive){
k++;
frameCounter = 0;
setHeight();
}
updateHeight();
frameCounter++;
}
button file
class Button{
boolean buttonActive = true;
float buttonX;
float buttonY;
float buttonWidth = 30;
float buttonHeight = 15;
String buttonLabel;
Button(float x, float y, String label){
buttonX = x;
buttonY = y;
buttonLabel = label;
}
void drawButton(){
if(!buttonActive){
fill(100);
rect(buttonX, buttonY, buttonWidth, buttonHeight, 5);
fill(255);
text(buttonLabel, buttonX + 4, buttonY + 10);
}else{
fill(200);
rect(buttonX, buttonY, buttonWidth, buttonHeight, 5);
fill(0);
text(buttonLabel, buttonX + 4, buttonY + 10);
}
}
boolean isInRange(){
if(mouseX > buttonX && mouseX < buttonX + buttonWidth && mouseY > buttonY && mouseY < buttonY + buttonHeight){
return true;
}
else{
return false;
}
}
}
prism file
class Prism{
float pheight;
float pwidth;
Prism(float tempheight, float tempwidth){
pheight = tempheight;
pwidth = tempwidth;
}
Prism(){
pheight = 10;
pwidth = 5;
}
void drawPrism(float x, float y){
noStroke();
fill(175);
quad(x, y, x - cos(radians(40))*pwidth, y - sin(radians(40))*pwidth, x - cos(radians(40))*pwidth, y - sin(radians(40))*pwidth - pheight, x, y - pheight);
fill(100);
quad(x, y, x + cos(radians(40))*pwidth, y - sin(radians(40))*pwidth, x + cos(radians(40))*pwidth, y - sin(radians(40))*pwidth - pheight, x, y - pheight);
fill(225);
quad(x, y - pheight, x - cos(radians(40))*pwidth, y - sin(radians(40))*pwidth - pheight, x, y - 2*sin(radians(40))*pwidth - pheight, x + cos(radians(40))*pwidth, y - sin(radians(40))*pwidth - pheight);
}
void setHeight(float tempheight){
pheight = tempheight;
}
}
slider file
class Slider{
float sliderLength;
float sliderX;
float sliderY;
float sliderWidth;
float handleWidth;
float sliderValue;
float sliderPos;
int sliderTotal;
boolean handleActive;
boolean isPrecise;
String sliderLabel;
//provide x and y position, length and the max value, the least amount of info
Slider(float x, float y, float slength, int total){
sliderX = x;
sliderY = y;
sliderLength = slength;
sliderWidth = 10;
handleWidth = sliderWidth*1.5;
sliderTotal = total;
sliderPos = sliderX + sliderWidth/2;
sliderLabel = "";
}
//provide x and y position, length and the max value AND a label
Slider(float x, float y, float slength, int total, String label){
sliderX = x;
sliderY = y;
sliderLength = slength;
sliderWidth = 10;
handleWidth = sliderWidth*1.5;
sliderTotal = total;
sliderPos = sliderX + sliderWidth/2;
sliderLabel = label;
}
//provide default values AND a label AND a width AND whether its precise
Slider(float x, float y, float slength, float swidth, int total, String label, boolean p){
sliderX = x;
sliderY = y;
sliderLength = slength;
sliderWidth = swidth;
handleWidth = sliderWidth*1.5;
sliderTotal = total;
sliderPos = sliderX + sliderWidth/2;
sliderLabel = label;
isPrecise = p;
}
void drawSlider(){
fill(255);
textSize(10);
text(sliderLabel, sliderX, sliderY - 5);
text(sliderValue, sliderX + sliderLength + 7, sliderY + sliderWidth/1.1);
fill(100);
rect(sliderX-1, sliderY, sliderLength+1, sliderWidth, 5);
fill(255);
ellipse(sliderPos, sliderY + (sliderWidth/2), handleWidth, handleWidth);
if(!isPrecise){
sliderValue = (int)((sliderPos - sliderX)/(sliderLength/sliderTotal));
}else if(isPrecise){
sliderValue = (sliderPos - sliderX)/(sliderLength/sliderTotal);
}
if(mouseX >= sliderX && mouseX <= sliderX+sliderLength + sliderX && mouseY >= sliderY - (handleWidth/2) && mouseY <= sliderY + (handleWidth/2) && mousePressed){
handleActive = true;
}
if(!mousePressed){
handleActive = false;
}
if(handleActive && sliderPos <= sliderX + sliderLength && sliderPos >= sliderX){
sliderPos = mouseX;
}
if(sliderPos > sliderX + sliderLength){
sliderPos = sliderX + sliderLength;
}
if(sliderPos < sliderX){
sliderPos = sliderX + 1;
}
}
}
Thank you! Sorry if the code is a little messy :)
In your main file, this block relies on the values of those two controls:
if(frameCounter == simulationSpeed && autoScrollButton.buttonActive){
k++;
frameCounter = 0;
setHeight();
}
When that gets skipped (because you changed simulationSpeed or buttonActive), your frameCounter gets out of sync with simulationSpeed so the block continues to get skipped.

Buggy bouncing balls

I was making a colliding ball sketch in Processing, and I encountered a weird bug. Despite having a condition for bouncing off of the walls, some balls get stuck to it. I can't find the source of error here. Can someone help? I also realise that there maybe few (a lot) bad coding practices, but I apologise beforehand.
I am posting the codes below.
1) Main : https://pastebin.com/hv0H14gZ
particle[] elec = new particle[5];
boolean record = false;
void setup(){
float x=0,y=0;
int i,j;
float diam = 100;
size(800,400);
//Initialising the particle objects
for (int k = 0; k < elec.length; k++){
x = random(width/10, width/1.2);
y = random(height/10, height/1.2);
elec[k] = new particle(x,y);
}
//Spawning at random places
for ( i = 0; i < elec.length; i++){
if (i!=0){
for ( j = 0; j < elec.length; j ++){
if (dist(x,y,elec[j].getX(),elec[j].getY()) <= diam){
x = random(width/10, width/1.2);
y = random(height/10, height/1.2);
j = -1;
}
}
}
elec[i] = new particle(x,y,diam,4,4,2);
}
}
void draw(){
background(0);
for (int i = 0; i < elec.length; i++){
elec[i].update(elec);
elec[i].move();
elec[i].bounce();
if(record){
saveFrame("collide_#####.png");
fill(255,0,0);
} else {
fill(0,255,0);
}
ellipse(width/1.01, height/1.01,5,5);
}
}
void keyPressed(){
if (key =='r' || key =='R'){
record = !record;
}
}
2) Classes : https://pastebin.com/Rt49sN9c
public class velocity{
float delx, dely;
//Constructor 1
public velocity(){}
//Constructor 2
public velocity(float delx, float dely){
this.delx = delx;
this.dely = dely;
}
//Mutators for xvelocity and y velocity
public float getdelx(){
return this.delx;
}
public float getdely(){
return this.dely;
}
//Accessors for xvelocity and y velocity
public void setdelx(float delx){
this.delx = delx;
}
public void setdely(float dely){
this.dely = dely;
}
}
public class particle{
private float xpos , ypos, delx , dely,size, decay, mass;
color colour;
//constructor 1
public particle(float x, float y){
this.xpos = x;
this.ypos = y;
}
//constructor 2
public particle(float xpos, float ypos, float size, float delx, float dely, float mass){
this.xpos = xpos;
this.ypos = ypos;
this.size = size;
this.delx = delx;
this.dely = dely;
this.mass = mass;
}
//Mutators for size, x velocity y velocity and velocity vector
public void setsize(float size){
this.size = size;
}
public void setDX(float delx){
this.delx = delx;
}
public void setDY(float dely){
this.dely = dely;
}
//Accessors for size, x position, y position, x velocity and y velocity
public float getsize(){
return this.size;
}
public float getX(){
return this.xpos;
}
public float getY(){
return this.ypos;
}
public float getDX(){
return this.delx;
}
public float getDY(){
return this.dely;
}
public float getmass(){
return this.mass;
}
public velocity getvel(){
velocity v = new velocity(this.getDX(), this.getDY());
return v;
}
//Functionality. Moving around, Bouncing off of walls, and basic display updates
public void move(){
this.xpos += this.delx;
this.ypos += this.dely;
}
public void bounce(){
if((this.xpos - this.size/2.0) < 0 || (this.xpos + this.size/2.0) > width){
this.setDX(this.getDX()*-1);
}
if((this.ypos - this.size/2.0) < 0 || (this.ypos + this.size/2.0) > height){
this.setDY(this.getDY()*-1);
}
}
public void update(particle[] elec){
for(int i =0; i< elec.length; i++){
if(this == elec[i]) continue;
if(dist(this.getX(),this.getY(),elec[i].getX(),elec[i].getY()) - this.getsize() <0){
collision(this, elec[i]);
//println(dist(this.getX(),this.getY(),elec[i].getX(),elec[i].getY()) - this.getsize()/2);
}
}
display();
}
public void display(){
stroke(0);
fill(119,240,153);
ellipse(this.xpos, this.ypos, this.size ,this.size);
}
}
velocity rotate(velocity v, float angle){
float x = v.getdelx()*cos(angle) - v.getdely()*sin(angle);
float y = v.getdelx()*sin(angle) + v.getdely()*cos(angle);
velocity vel = new velocity(x,y);
return vel;
}
void collision(particle p1, particle p2){
float xveldiff = p1.getDX()-p2.getDX();
float yveldiff = p1.getDY()-p2.getDY();
float xdist = p2.getX() - p1.getX();
float ydist = p2.getY() - p1.getY();
//Check for accidental overlaps of particles
if(xveldiff*xdist + yveldiff*ydist > 0){
float angle = -atan2(p2.getY() - p1.getY(), p2.getX() - p1.getY());
float m1 = p1.getmass();
float m2 = p2.getmass();
velocity u1 = rotate(p1.getvel(),angle);
velocity u2 = rotate(p2.getvel(),angle);
velocity v1 = new velocity(u1.getdelx() * (m1 - m2) / (m1 + m2) + u2.getdelx() * 2 * m2 / (m1 + m2), u1.getdely());
velocity v2 = new velocity(u2.getdelx() * (m1 - m2) / (m1 + m2) + u1.getdelx() * 2 * m2 / (m1 + m2), u2.getdely());
velocity vf1 = rotate(v1, -angle);
velocity vf2 = rotate(v2, -angle);
p1.setDX(vf1.getdelx());
p1.setDY(vf1.getdely());
p2.setDX(vf2.getdelx());
p2.setDY(vf2.getdely());
}
}
Nice animation, the issue is cased by the method bounce of class particle:
When the "ball" doesn't leave the wall in one step, then it sticks.
Note, if e.g the condition (this.xpos - this.size/2.0) < 0 is fulfilled twice, the the direction is inverted twice (this.getDX()*-1). This causes that the ball bounce into the wall continuously and leads to a trembling movement along the wall.
public void bounce(){
if((this.xpos - this.size/2.0) < 0 || (this.xpos + this.size/2.0) > width){
this.setDX(this.getDX()*-1);
}
if((this.ypos - this.size/2.0) < 0 || (this.ypos + this.size/2.0) > height){
this.setDY(this.getDY()*-1);
}
}
You have to ensure, the the direction (delx, dely) always points away from the wall, if the ball is to near to it:
public void bounce(){
if( this.xpos - this.size/2.0 < 0 ) {
this.setDX( Math.abs(this.getDX()) );
} else if( this.xpos + this.size/2.0 > width ) {
this.setDX( -Math.abs(this.getDX()) );
}
if( this.ypos - this.size/2.0 < 0 ) {
this.setDY( Math.abs(this.getDY()) );
} else if( this.ypos + this.size/2.0 > height ) {
this.setDY( -Math.abs(this.getDY()) );
}
}

Processing Image Load Error

I've added a background image to my processing file which works fine when I run it in Processing locally, however, I'm receiving this error in console when I host the file:
Uncaught Error using image in background(): PImage not loaded.
I can't find anywhere why this may be happening. Please see my code below:
Particle p = new Particle();
final int LIGHT_FORCE_RATIO = 70; final int LIGHT_DISTANCE= 70 * 50; final int BORDER = 100; float baseRed, baseGreen, baseBlue; float baseRedAdd, baseGreenAdd, baseBlueAdd; final float RED_ADD =
3.2; final float GREEN_ADD = 1.7; final float BLUE_ADD = 4.3; float boxX, boxY; float widthSize = width;
int rectWidth = 915; int rectHeight = 197;
PImage img;
void setup() { img = loadImage("https://s3.amazonaws.com/zcom-media/sites/a0iE000000QK9yZIAT/media/mediamanager/bannerbg.jpg");
background(img); size(1840, 400); // surface.setResizable(true); noCursor(); //img = loadImage("flowtoy.jpg"); baseRed = 0; baseRedAdd = RED_ADD;
baseGreen = 0; baseGreenAdd = GREEN_ADD;
baseBlue = 0; baseBlueAdd = BLUE_ADD;
boxX = width/2; boxY = height/2;
img.loadPixels(); for (int i = 0; i < img.pixels.length; i++) { img.pixels[i] = color(0, 90, 102); } img.updatePixels(); }
void draw() { //image(img, 400, 100, img.width/2, img.height/2); if (mouseX>boxX-rectWidth && mouseX<boxX+rectWidth &&
mouseY>boxY-rectHeight && mouseY<boxY+rectHeight) {
//saveFrame("output/LightDrawing_####.png");
baseRed += baseRedAdd;
baseGreen += baseGreenAdd;
baseBlue += baseBlueAdd;
colorOutCheck();
p.move(mouseX, mouseY);
int tRed = (int)baseRed;
int tGreen = (int)baseGreen;
int tBlue = (int)baseBlue;
tRed *= tRed;
tGreen *= tGreen;
tBlue *= tBlue;
loadPixels();
int left = max(0, p.x - BORDER);
int right = min(width, p.x + BORDER);
int top = max(0, p.y - BORDER);
int bottom = min(height, p.y + BORDER);
for (int y = top; y < bottom; y++) {
for (int x = left; x < right; x++) {
int pixelIndex = x + y * width;
int r = pixels[pixelIndex] >>16 & 0xFF;
int g = pixels[pixelIndex] >> 8 & 0xFF;
int b = pixels[pixelIndex] & 0xFF;
int dx = x - p.x;
int dy = y - p.y;
int distance = (dx *dx ) + (dy* dy);
if (distance < LIGHT_DISTANCE) {
int fixFistance = distance * LIGHT_FORCE_RATIO;
if (fixFistance == 0) {
fixFistance = 1;
}
r = r + tRed / fixFistance;
g = g + tGreen / fixFistance;
b = b + tBlue / fixFistance;
}
pixels[x + y * width] = color(r, g, b);
}
}
updatePixels(); } else {
setup(); }
//updatePixels(); }
void colorOutCheck() { if (baseRed < 10) {
baseRed = 10;
baseRedAdd *= -1; } else if (baseRed > 255) {
baseRed = 255;
baseRedAdd *= -1; }
if (baseGreen < 10) {
baseGreen = 10;
baseGreenAdd *= -1; } else if (baseGreen > 255) {
baseGreen = 255;
baseGreenAdd *= -1; }
if (baseBlue < 10) {
baseBlue = 10;
baseBlueAdd *= -1; } else if (baseBlue > 255) {
baseBlue = 255;
baseBlueAdd *= -1; } }
void mousePressed() { setup(); }
class Particle { int x, y; float vx, vy; //float slowLevel;
Particle() {
x = (int)3;
y = (int)2; // slowLevel = random(100) + 1; }
void move(float targetX, float targetY) {
vx = (targetX - x) ;
vy = (targetY - y) ;
x = (int)(x + vx);
y = (int)(y + vy); } }
Can anybody explain why this may be happening? It's much appreciated, thank you.
I assume by 'hosting the file' you mean running the sketch at www.openprocessing.org.
There are two problem with your code:
Using background() inside setup. This will not work, you will get the error you mentioned. You can try moving that to draw().
Using an image which is hosted in another server. You should host your own images.
A workaround to problem 2 is to store the image as a base64 encoded string.
String uriBase64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgA";
img = loadImage(uriBase64);
Full example here: https://www.openprocessing.org/sketch/511424

Array is only displaying 1 object instead of the full amount of variables

I'm new to coding (as I'm sure you might be able to tell). The program runs and generates 1 Tubble, but the additional objects don't show.
Here's my class:
class Tubble {
float x;
float y;
float diameter;
float yspeed;
float tempD = random(2,86);
Tubble() {
x = random(width);
y = height-60;
diameter = tempD;
yspeed = random(0.1, 3);
}
void ascend() {
y -= yspeed;
x = x + random(-2, 2);
}
void dis() {
stroke(0);
fill(127, 100);
ellipse(x, y, diameter, diameter);
}
void top() {
if (y < -diameter/2) {
y = height+diameter/2;
}
}
}
Class
class Particle {
float x, y;
float r;
float speed = 2.2;
int direction = 1;
PImage pbubbles;
Particle(float x_, float y_, float r_) {
x = x_;
y = y_;
r = r_;
}
void display() {
stroke(#F5D7D7);
strokeWeight(2.2);
noFill();
ellipse(x, y, r*2, r*2);
}
boolean overlaps(Particle other) {
float d = dist(x, y, other.x, other.y);
if (d < r + other.r) {
return true;
} else {
return false;
}
}
void move() { //testing
x += (speed * direction);
if ((x > (width - r)) || (x < r)) {
direction *= -1;
}
}
void updown() {
y += (speed * direction);
if ((y > (height - r)) || (y < r)) {
direction *= -1;
}
}
}
Main sketch:
Tubble[] tubbles = new Tubble [126];
PImage bubbles;
Particle p1;
Particle p2;
Particle p3;
Particle p4;
Particle p5;
float x,y;
float speed;
int total = 0;
int i;
//int direction = 1;
void setup() {
size(800, 925);
bubbles = loadImage("purple_bubbles.png");
p1 = new Particle (100, 100, 50);
p2 = new Particle (500, 200, 100);
p3 = new Particle (600, 600, 82);
p4 = new Particle (height/2, width/2, 200);
p5 = new Particle ((height/3), (width/3), 20);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i] = new Tubble();
}
}
void mousePressed() {
total = total + 1;
}
void keyPressed() {
total = total - 1;
}
void draw() {
image(bubbles, 0, 0, 800, 925);
//background(0);
for (int i = 0; i < tubbles.length; i++); {
tubbles[i].ascend();
tubbles[i].dis();
tubbles[i].top();
}
if ((p2.overlaps(p1)) && (p2.overlaps(p4))) {
background(#BF55AB, 25);
}
if ((p3.overlaps(p2)) && (p3.overlaps(p4))) {
background(#506381, 80);
}
p2.x = mouseX;
p3.y = mouseY;
p1.display();
p2.display();
p3.display();
p4.display();
p5.display();
p4.move();
p5.updown();
// for (int i = 0; i < tubbles.length; i++); {
// tubbles[i].dis();
// tubbles[i].ascend();
// tubbles[i].top();
// }
}
There are extra semicolons in the lines
for (int i = 0; i < tubbles.length; i++); {
for (int i = 0; i < tubbles.length; i++); {
// for (int i = 0; i < tubbles.length; i++); {
It make the for loop do virtually nothing.
Then the block after the for loop will read the global variable i and do the action only once.
Remove the semicolons like this to put the block in the loop.
for (int i = 0; i < tubbles.length; i++) {
for (int i = 0; i < tubbles.length; i++) {
// for (int i = 0; i < tubbles.length; i++) {

Resources