The field component.x is not visible - java

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
}

Related

Objects sharing another object (Processing 3.3.7)

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.

How to update a canvas in SWT every 100 milliseconds inside a KeyListener Java

I'm writing a program which updates a canvas after every key press by regenerating a data structure (cube) and then painting this onto the canvas. If the user enters 'S' I want the canvas to display the cube after every turn (turn = one character of the solution string generated by the program) every 100ms and redraw this to the screen, have tried several different approaches but can't get it to work. This is my KeyListener code:
canvas.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
GC gc = new GC(canvas);
Rectangle rect = canvas.getClientArea();
String alg = ""+e.character;
cube.performAlgorithm(alg, false);
drawCube(rect,gc);
if(e.character=='S'){
Cube cube2 = new Cube(cube);
String solution = Solutions.longsolve(cube2, "Fridrich", false);
String[] moves = new String[solution.length()];
moves = solution.split("(?!^)");
for(String move : moves){
cube.performAlgorithm(move, false);
try {
drawCube(rect,gc);
canvas.redraw();
canvas.update();
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//System.out.println(solution);
}
gc.dispose();
}
});
and my drawFace and drawCube code, appreciate this may not be a very nice way of solving my problem but I'm very new to using SWT.
private static void drawFace(GC gc, int startwidth, int startdepth, int celldim, Color[] colour, byte[][] Face){
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
//draw face of the cube
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
Rectangle rect = new Rectangle(x, y, celldim, celldim);
gc.setBackground(colour[Face[i][j]]);
gc.fillRectangle(rect);
gc.drawRectangle(rect);
x += celldim;
//only draw a box
}
x = startwidth;
y+=celldim;
}
}
private static void drawCube(Rectangle clientArea, GC gc){
int startdepth = 10;
int celldim = (((clientArea.height)-(startdepth*2))/12);
int startwidth = (int) ((int)(clientArea.width/2)-(1.5*celldim));
Color[] colours = {gc.getDevice().getSystemColor(SWT.COLOR_GREEN),gc.getDevice().getSystemColor(SWT.COLOR_RED),
gc.getDevice().getSystemColor(SWT.COLOR_BLUE),gc.getDevice().getSystemColor(SWT.COLOR_GRAY),
gc.getDevice().getSystemColor(SWT.COLOR_BLACK),gc.getDevice().getSystemColor(SWT.COLOR_YELLOW)};
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
drawFace(gc, x, y, celldim,colours,cube.Uface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Fface);
x -= (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Lface);
x += (6*celldim);
drawFace(gc, x, y, celldim,colours,cube.Rface);
x -= (3*celldim);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Dface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Bface);
}
You can't do updates in a loop like that because you must let the main SWT Display.readAndDispatch loop run since this is what actually updates the screen.
Instead use Display.timerExec to execute one step of the loop every 100ms:
Display.getDefault().timerExec(100, new Runnable() {
#Override
public void run() {
canvas.redraw();
// Run again - TODO add logic to stop after correct number of moves
Display.getDefault().timerExec(100, this);
}
});
You should just call redraw in this routine, all the actual drawing should be in a paint listener on the control.

How To Turn Main Code Into A Class (Snowfall)

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!

Processing in Java - drawn clearing rectangle breaks after calling a method

I am using Processing in Java to perpetually draw a line graph. This requires a clearing rectangle to draw over drawn lines to make room for the new part of the graph. Everything works fine, but when I call a method, the clearing stops working as it did before. Basically the clearing works by drawing a rectangle in front of where the line is currently at
Below are the two main methods involved. The drawGraph function works fine until I call the redrawGraph which redraws the graph based on the zoom. I think the center variable is the cause of the problem but I cannot figure out why.
public void drawGraph()
{
checkZoom();
int currentValue = seismograph.getCurrentValue();
int lastValue = seismograph.getLastValue();
step = step + zoom;
if(step>offset){
if(restartDraw == true)
{
drawOnGraphics(step-zoom, lastY2, step, currentValue);
image(graphGraphics, 0, 0);
restartDraw = false;
}else{
drawOnGraphics(step-zoom, lastValue, step, currentValue);
image(graphGraphics, 0, 0);
}
} // draw graph (connect last to current point // increase step - x axis
float xClear = step+10; // being clearing area in front of current graph
if (xClear>width - 231) {
xClear = offset - 10; // adjust for far side of the screen
}
graphGraphics.beginDraw();
if (step>graphSizeX+offset) { // draw two clearing rectangles when graph isn't split
// left = bg.get(0, 0, Math.round(step-graphSizeX), height - 200); // capture clearing rectangle from the left side of the background image
// graphGraphics.image(left, 0, 0); // print left clearing rectangle
// if (step+10<width) {
// right = bg.get(Math.round(step+10), 0, width, height - 200); // capture clearing rectangle from the right side of the background image
// // print right clearing rectangle
// }
} else { // draw one clearing rectangle when graph is split
center = bg.get(Math.round(xClear), lastY2, offset, height - 200); // capture clearing rectangle from the center of the background image
graphGraphics.image(center, xClear - 5, 0);// print center clearing rectangle
}
if (step > graphSizeX+offset) { // reset set when graph reaches the end
step = 0+offset;
}
graphGraphics.endDraw();
image(graphGraphics, 0 , 0);
System.out.println("step: " + step + " zoom: " + zoom + " currentValue: "+ currentValue + " lastValue: " + lastValue);
}
private void redrawGraph() //resizes graph when zooming
{
checkZoom();
Object[] data = seismograph.theData.toArray();
clearGraph();
step = offset;
int y2, y1 = 0;
int zoomSize = (int)((width - offset) / zoom);
int tempCount = 0;
graphGraphics.beginDraw();
graphGraphics.strokeWeight(2); // line thickness
graphGraphics.stroke(242,100,66);
graphGraphics.smooth();
while(tempCount < data.length)
{
try
{
y2 = (int)data[tempCount];
step = step + zoom;
if(step > offset && y1 > 0 && step < graphSizeX+offset){
graphGraphics.line(step-zoom, y1, step, y2);
}
y1 = y2;
tempCount++;
lastY2 = y2;
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
graphGraphics.endDraw();
image(graphGraphics, 0, 0);
restartDraw = true;
}
Any help and criticisms are welcome. Thank you for your valuable time.
I'm not sure if that approach is the best. You can try something as simple as this:
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example: a graph of random numbers
float[] vals;
void setup() {
size(400,200);
smooth();
// An array of random values
vals = new float[width];
for (int i = 0; i < vals.length; i++) {
vals[i] = random(height);
}
}
void draw() {
background(255);
// Draw lines connecting all points
for (int i = 0; i < vals.length-1; i++) {
stroke(0);
strokeWeight(2);
line(i,vals[i],i+1,vals[i+1]);
}
// Slide everything down in the array
for (int i = 0; i < vals.length-1; i++) {
vals[i] = vals[i+1];
}
// Add a new random value
vals[vals.length-1] = random(height);//use seismograph.getCurrentValue(); here instead
}
You can easily do the same using a PGraphics buffer as your code suggests:
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example: a graph of random numbers
float[] vals;
PGraphics graph;
void setup() {
size(400,200);
graph = createGraphics(width,height);
// An array of random values
vals = new float[width];
for (int i = 0; i < vals.length; i++) {
vals[i] = random(height);
}
}
void draw() {
graph.beginDraw();
graph.background(255);
// Draw lines connecting all points
for (int i = 0; i < vals.length-1; i++) {
graph.stroke(0);
graph.strokeWeight(2);
graph.line(i,vals[i],i+1,vals[i+1]);
}
graph.endDraw();
image(graph,0,0);
// Slide everything down in the array
for (int i = 0; i < vals.length-1; i++) {
vals[i] = vals[i+1];
}
// Add a new random value
vals[vals.length-1] = random(height);//use seismograph.getCurrentValue(); here instead
}
The main idea is to cycle the newest data in an array and simply draw the values from this shifting array. As long as you clear the previous frame (background()) the graph should look ok.

Method not recognizing the call this in JavaFX application

I'm working on a program that displays circles colliding with the wall and with themselves.
I'm having trouble with the method that will compensate for collisions.
public class bouncyFX extends Application {
public ArrayList<Ball> arr = new ArrayList<Ball>();
public static void main(String[] args) {
launch(args);
}
static Pane pane;
#Override
public void start(final Stage primaryStage) {
pane = new Pane();
final Scene scene = new Scene(pane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
pane.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(final MouseEvent event) {
final Ball ball = new Ball(event.getX(), event.getY(), 40, Color.AQUA);
ball.circle.relocate(event.getX(), event.getY());
pane.getChildren().addAll(ball.circle);
arr.add(ball);
final Bounds bounds = pane.getBoundsInLocal();
final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {
double deltaX = ball.ballDeltaX;
double deltaY = ball.ballDeltaY;
public void handle(final ActionEvent event) {
ball.circle.setLayoutX(ball.circle.getLayoutX() + deltaX);
ball.circle.setLayoutY(ball.circle.getLayoutY() + deltaY);
final boolean atRightBorder = ball.circle.getLayoutX() >= (bounds.getMaxX()-ball.circle.getRadius());
final boolean atLeftBorder = ball.circle.getLayoutX() <= (bounds.getMinX()+ball.circle.getRadius());
final boolean atBottomBorder = ball.circle.getLayoutY() >= (bounds.getMaxY()-ball.circle.getRadius());
final boolean atTopBorder = ball.circle.getLayoutY() <= (bounds.getMinY()+ball.circle.getRadius());
if(atRightBorder || atLeftBorder)
deltaX *= -1;
if(atBottomBorder || atTopBorder)
deltaY *= -1;
for(int i = 0; i<arr.size(); i++){
for(int j = i+1; j<arr.size()-1; j++){
arr.get(i).collisionMagnitued(arr.get(j));
}
}
}
}));
loop.setCycleCount(Timeline.INDEFINITE);
loop.play();
}
});
}
class Ball{
public Circle circle;
public double ballDeltaX = 3;
public double ballDeltaY = 3;
public void AddBall(Ball b){
arr.add(b);
}
public Ball(double X, double Y, double Rad, Color color) {
circle = new Circle(X, Y, Rad);
circle.setFill(color);
}
private boolean defineCollision(Ball b){
double xd = this.circle.getLayoutX() - b.circle.getLayoutX();
double yd = this.circle.getLayoutY() - b.circle.getLayoutY();
double sumRad = this.circle.getRadius() + b.circle.getRadius();
double squareRad = Math.pow(sumRad, 2);
double distSquare = Math.pow(xd, 2) + Math.pow(yd, 2);
if(distSquare <= squareRad){
return true;
}return false;
}
public void collisionMagnitued(Ball b){
if(this.defineCollision(b)){
double tempDeltaX = ballDeltaX;
double tempDeltaY = ballDeltaY;
if((this.ballDeltaX < 0 && b.ballDeltaX > 0) || (this.ballDeltaX >0 && b.ballDeltaX <0)){
this.ballDeltaX *= -this.ballDeltaX;
b.ballDeltaX *= -b.ballDeltaX;
System.out.println("tredje");
}
if((this.ballDeltaY < 0 && b.ballDeltaY > 0) || (this.ballDeltaY > 0 && b.ballDeltaY < 0)){
this.ballDeltaY *= -this.ballDeltaY;
b.ballDeltaY *= -b.ballDeltaY;
System.out.println("fjärde");
}
else{
System.out.println("Knull");
this.ballDeltaX *= -1;
b.ballDeltaX *= -1;
}
}
}
}
}
The Balls (or circles) are created and are bouncing against the Bounds as expected.
The Collision detection method works as I'm getting print statements inside the last method. However, it seems that there's something wrong with either my ArrayList not being filled with objects or the method trying to compare the parameter Ball and the Ball that calls the method.
Am I way off? Not sure how I'm suppossed to go forth from here.
I see a few issues with your logic:
The first problem is that when the balls "bounce" off the boundaries of the pane, you don't change their ballDeltaX or ballDeltaY values (you just change a local value in the animation loop and use the local value to update the position). So the first time two balls collide, both of their ballDeltaX and ballDeltaY values are equal to +3 (the initial value), which may not represent the actual direction the animation loop is moving them in. In fact, you never actually use any updated values of ballDeltaX or ballDeltaY to compute the new positions; you get the initial values of those variables, copy them into deltaX and deltaY, and then just compute the new positions using deltaX and deltaY. So if you change ballDeltaX and ballDeltaY, the animation loop never sees the change.
The for loops look wrong to me; I don't think they compare the last two elements of the list. (When i = arr.size()-2 in the penultimate iteration of the outer loop, your inner loop is for (int j = arr.size() - 1; j < arr.size() -1; j++) {...} which of course never iterates.) I think you want the bounding conditions to be i < arr.size() - 1 and j < arr.size(), i.e. the other way around.
And then your if/else structure in collisionMagnitued(...) is probably not exactly what you want. I'm not sure what you're trying to implement there, but the else clause only kicks in if the second if is false, and no matter what happens in the first if.
Finally, you are starting a new animation on each mouse click. So, for example, if you have three balls bouncing around, you have three animation loops running, each of which is updating values when the balls collide. You need to start just one loop; it shouldn't do any harm if it refers to an empty list.

Categories

Resources