I'm trying to get my code to recreate a random x and y value if there is already another object occupying the chosen value. But for some reason, the loop just keeps giving me the same float value causing it to loop forever instead of creating new value and then checking that one against previous x and y variables. Here's the code. Let me know if you need anymore.
static int numberOfDots = 5;
static int windowSize = 400;
float[] pos = new float[2];
float[] vel = new float[2];
float[] acc = new float[2];
float dotSize = 0;
float dotMass = 0;
float dotWidth = 0;
float dotRadius = 0;
float[] centrePos = new float[2];
float[][] dots = new float[numberOfDots][10];
//for making dots
boolean first = true;
boolean creationCollision = false;
boolean dotCollision = false;
// pos means x and y positions
// vel means x and y velocity
// centrePos means centre of the dot x and y
// dotMass isnt implemented yet
public boolean collisionOnCreate() {
//compare all dots
for (int i = 0; i < dots.length; i++) {
//against any dots later in the array
// since they will already have compared themselves to dots previous in the array
// - dont need to loop over them again
for (int a = i + 1; a < dots.length; a++) {
if (dots[a][0] != 0) {
creationCollision = dots[i][1] + dots[i][8] > dots[a][1] && dots[i][1] + dots[i][8] < dots[a][1] + dots[a][8] || dots[i][1] > dots[a][1] && dots[i][1] < dots[a][1] + dots[a][8] || dots[i][0] > dots[a][0] && dots[i][0] < dots[a][0] + dots[a][8] || dots[i][0] + dots[i][8] > dots[a][0] && dots[i][0] + dots[i][8] < dots[a][0] + dots[a][8];
System.out.println(dots[a][0] + " " + dots[a][1]);
}
//check if the left-most part of the dot is anywhere between the leftmost and right most part of another dot
//check if the rightmost part of the dot is anywhere between the left most and right most part of another dot
//check if the top part of the dot is anywhere between the top and bottom part of another dot
//check if the bottom of the dot is anywhere between the top and bottom part of another dot
// I know its long but its easier then running a bunch of if statements to do the same task
}
}
return creationCollision;
}
public void createDots(int i) {
pos[0] = r.nextFloat() * 300;
pos[1] = r.nextFloat() * 300;
dotWidth = r.nextFloat() * 30;
if (dotWidth < 5) {
dotWidth *= 10;
}
dotRadius = dotWidth / 2;
dotMass = r.nextFloat() / 10;
centrePos[0] = centrePos[0] + dotRadius;
centrePos[1] = pos[1] + dotRadius;
vel[0] = r.nextFloat() / 10;
vel[1] = r.nextFloat() / 10;
check(i);
}
public void check(int i) {
collisionOnCreate();
if (creationCollision) {
createDots(i);
System.out.println("collision on creation");
} else {
setValues(i);
System.out.println("dot number " + i + " is created");
}
}
public void setValues(int i) {
dots[i][0] = pos[0];
dots[i][1] = pos[1];
dots[i][2] = vel[0];
dots[i][3] = vel[1];
dots[i][4] = dotRadius;
dots[i][5] = centrePos[0];
dots[i][6] = centrePos[1];
dots[i][7] = dotMass;
dots[i][8] = dotWidth;
}
//create an array of dots and assign them values for x, y, radius, etc.
public float[][] Dots() {
if (first == true) {
for (int i = 0; i < numberOfDots; i++) {
createDots(i);
}
first = false;
} else {
for (int i = 0; i < numberOfDots; i++) {
// update values
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
centrePos[0] = dots[i][0] + dots[i][4];
centrePos[1] = dots[i][1] + dots[i][4];
dots[i][5] = centrePos[0];
dots[i][6] = centrePos[1];
collisionOnWall(i);
}
}
repaint();
return dots;
}
I don't think the problem is with random number generation. Instead there is something wrong with the logic of creation / checking.
It seems that first, inside of createDots(), you assign values to some variables that are meant to represent a new dot (why don't make a dedicated class for that?). Then you don't add that new dot to dots array but instead you go straight to checking if there are any collisions.
However, you only check the values that are already present in the dots array, without taking into account the newly created one.
Another thing, that creationCollision condition is really unreadable to me. You should use some parentheses just for the clarity. Plus make sure it is actually doing what you want it to.
You don't appear to ever set dots[i] to your new values here:
public void createDots(int i) {
pos[0] = r.nextFloat() * 300;
pos[1] = r.nextFloat() * 300;
dotWidth = r.nextFloat() * 30;
if (dotWidth < 5) {
dotWidth *= 10;
}
dotRadius = dotWidth / 2;
dotMass = r.nextFloat() / 10;
centrePos[0] = centrePos[0] + dotRadius;
centrePos[1] = pos[1] + dotRadius;
vel[0] = r.nextFloat() / 10;
vel[1] = r.nextFloat() / 10;
check(i);
}
Looks like you want to call setValues(i) at the end, just before check(i).
Related
I was beginning with coding in Processing when I encountered an error which I can't find a solution for.
**DISCLAIMER: I'm new to coding, so I'm having trouble understanding how it works lol
I was attempting to use processing to write a code for a kinect program that would create a ripple effect, but I can't figure out how to define two variables.
Code:
// A simple ripple effect. Click on the image to produce a ripple
// Author: radio79
// Code adapted from http://www.neilwallis.com/java/water.html
// Code adapted from https://forum.processing.org/two/discussion/25348/can-i-apply-ripple-effect-to-kinect
import org.openkinect.processing.*;
Kinect kinect;
PImage img;
Ripple ripple;
void setup() {
size(1920, 1080);
kinect = new Kinect(this);
kinect.initVideo();
img = new PImage(kinect.colorWidth, kinect.colorHeight);
ripple = new Ripple();
//frameRate(60);
}
void draw() {
image(kinect.getVideoImage(), 0, 0);
img.loadPixels();
for (int loc = 0; loc < Kinect.colorWidth * Kinect.colorHeight; loc++) {
img.pixels[loc] = ripple.col[loc];
}
img.updatePixels();
ripple.newframe();
}
class Ripple {
int i, a, b;
int oldind, newind, mapind;
short ripplemap[]; // the height map
int col[]; // the actual pixels
int riprad;
int rwidth, rheight;
int ttexture[];
int ssize;
Ripple() {
// constructor
riprad = 3;
rwidth = width >> 1;
rheight = height >> 1;
ssize = width * (height + 2) * 2;
ripplemap = new short[ssize];
col = new int[width * height];
ttexture = new int[width * height];
oldind = width;
newind = width * (height + 3);
}
void newframe() {
// update the height map and the image
i = oldind;
oldind = newind;
newind = i;
i = 0;
mapind = oldind;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
short data = (short)((ripplemap[mapind - width] + ripplemap[mapind + width] +
ripplemap[mapind - 1] + ripplemap[mapind + 1]) >> 1);
data -= ripplemap[newind + i];
data -= data >> 5;
if (x == 0 || y == 0) // avoid the wraparound effect
ripplemap[newind + i] = 0;
else
ripplemap[newind + i] = data;
// where data = 0 then still, where data > 0 then wave
data = (short)(1024 - data);
// offsets
a = ((x - rwidth) * data / 1024) + rwidth;
b = ((y - rheight) * data / 1024) + rheight;
//bounds check
if (a >= width)
a = width - 1;
if (a < 0)
a = 0;
if (b >= height)
b = height-1;
if (b < 0)
b=0;
col[i] = img.pixels[a + (b * width)];
mapind++;
i++;
}
}
}
}
void mouseDragged() {
for (int j = mouseY - ripple.riprad; j < mouseY + ripple.riprad; j++) {
for (int k = mouseX - ripple.riprad; k < mouseX + ripple.riprad; k++) {
if (j >= 0 && j < height && k>= 0 && k < width) {
ripple.ripplemap[ripple.oldind + (j * width) + k] += 512;
}
}
}
}
The error is: 'The global variable "x" does not exist', 'The global variable "y" does not exist' and so forth. Please help.
The variables I need help defining appear on line 18 for the first time, they are colorWidth and colorHeight
The line reads:
img = new PImage(kinect.colorWidth, kinect.colorHeight);
The colorWidth and colorHeight are underlined in red.
I have tried using this method:
public
float colorWidth;
float colorHeight;
But, only the second line appears to be defined properly. The first line emits the message "colorWidth cannot be resolved or is not a field" when the program runs, or "illegal modifier for parameter colorWidth; only final is permitted" when the underline is clicked.
Picture of what the program shows after the public code
PLEASE HELP!!! Thank you!
The keyword public here just means nothing, it must be said of a function or variable. And you just don't need it. So removing it should fix the problem!
I am currently just messing around with some code and I keep running into an issue. I want to create ten circles and simply have them bounce around the window. I've had a couple of problems (like when I want the circles to bounce off the wall, for some reason the 400,400 window isn't actually that size. I have the circles collide on the right by checking if x + width >= 400, but it bounces outside the screen unless I change the 400 to 380?), but my main issue is that when I create the circles, I want them to be in different locations (so they aren't colliding before they can even move). I am trying to get it so that if a circle is going to be 'inside' another circle then instead create random x and y coordinates again until it isn't inside another circle. But for some reason, if I put r.nextInt() inside the while loop it keeps giving me the same values. Can anyone help?
p.s. I wouldn't mind advice on any other mistakes I have made.
package practicedots;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PracticeDots extends JPanel {
float dots[][] = new float[10][7];
Random r = new Random();
boolean first = true;
float x = 0;
float y = 0;
float xAccel = 0;
float yAccel = 0;
int wall = 380;
int width = 50;
float radius = 0;
float centreX = 0;
float centreY = 0;
boolean collision;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new PracticeDots());
f.setPreferredSize(new Dimension(400, 400));
f.setResizable(true);
f.pack();
f.setVisible(true);
}
/**
*
* #return
*/
public float[][] CreateDots() {
if (first == true) {
for (int i = 0; i < 10; i++) {
while(collision == true){
x = r.nextInt(300);
y = r.nextInt(300);
xAccel = r.nextFloat() / 2;
yAccel = r.nextFloat() / 2;
radius = width/2;
centreX = x + radius;
centreY = y + radius;
dots[i][0] = x;
dots[i][1] = y;
dots[i][2] = xAccel;
dots[i][3] = yAccel;
dots[i][4] = radius;
dots[i][5] = centreX;
dots[i][6] = centreY;
bounce();
}
}
first = false;
} else if (first == false) {
for (int i = 0; i < 10; i++) {
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
if (dots[i][0] >= wall - width) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] >= wall - 20 - width) {
dots[i][3] = -dots[i][3];
}
if (dots[i][0] < 0) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] < 0) {
dots[i][3] = -dots[i][3];
}
bounce();
}
}
repaint();
return dots;
}
//(x2-x1)^2 + (y1-y2)^2 <= (r1+r2)^2
public void bounce() {
for (int i = 0; i < 10; i++) {
for (int a = 0; a < 10; a++) {
if (a != i) {
System.out.println((dots[i][0] - dots[a][0])*(dots[i][0] - dots[a][0]) + (dots[i][1] - dots[a][1])*(dots[i][1] - dots[a][1]) <= (dots[i][4] + dots[a][4]) * (dots[i][4] + dots[a][4]));
collision = (dots[i][0] - dots[a][0])*(dots[i][0] - dots[a][0]) + (dots[i][1] - dots[a][1])*(dots[i][1] - dots[a][1]) <= (dots[i][4] + dots[a][4]) * (dots[i][4] + dots[a][4]);
}
}
}
}
/**
*
* #param g
*/
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 10; i++) {
CreateDots();
g.drawOval((int) dots[i][0], (int) dots[i][1], width, width);
g.fillOval((int) dots[i][0], (int) dots[i][1], width, width);
}
}
}
<!-- end snippet -->
There were a couple of problems:
During bounce you should return the first time you find a collision, otherwise the collision will be set to true, but then could be set back to false on the next iteration in the for-loop.
In the first == true condition, you should initialize collision to true or it will never do the while loop at all. Either that or change it to a do-while.
During paintComponent you should not call CreateDots within the for-loop since it loops over all dots itself. Just call it before.
The code seems to work with these changes (including width of 400 not 380):
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PracticeDots extends JPanel {
float dots[][] = new float[10][7];
Random r = new Random();
boolean first = true;
float x = 0;
float y = 0;
float xAccel = 0;
float yAccel = 0;
int wall = 400;
int width = 50;
float radius = 0;
float centreX = 0;
float centreY = 0;
boolean collision;
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new PracticeDots());
f.setPreferredSize(new Dimension(400, 400));
f.setResizable(true);
f.pack();
f.setVisible(true);
}
public float[][] CreateDots() {
if (first == true) {
for (int i = 0; i < 10; i++) {
do {
x = r.nextInt(300);
y = r.nextInt(300);
xAccel = r.nextFloat() / 2;
yAccel = r.nextFloat() / 2;
radius = width / 2;
centreX = x + radius;
centreY = y + radius;
dots[i][0] = x;
dots[i][1] = y;
dots[i][2] = xAccel;
dots[i][3] = yAccel;
dots[i][4] = radius;
dots[i][5] = centreX;
dots[i][6] = centreY;
bounce();
} while (collision == true);
}
first = false;
} else {
for (int i = 0; i < 10; i++) {
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
if (dots[i][0] >= wall - width) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] >= wall - 20 - width) {
dots[i][3] = -dots[i][3];
}
if (dots[i][0] < 0) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] < 0) {
dots[i][3] = -dots[i][3];
}
bounce();
}
}
repaint();
return dots;
}
public void bounce() {
collision = false;
for (int i = 0; i < 10; i++) {
for (int a = 0; a < 10; a++) {
if (a != i && !(dots[a][0] == 0 && dots[a][1] == 0)) {
boolean thisCollision = (dots[i][0] - dots[a][0]) * (dots[i][0] - dots[a][0]) + (dots[i][1] - dots[a][1]) * (dots[i][1] - dots[a][1]) <= (dots[i][4] + dots[a][4]) * (dots[i][4] + dots[a][4]);
// System.out.println("collision: "+collision+" i="+i+" a="+a);
if (thisCollision) {
collision = true;
return;
}
}
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
CreateDots();
for (int i = 0; i < 10; i++) {
g.drawOval((int) dots[i][0], (int) dots[i][1], width, width);
g.fillOval((int) dots[i][0], (int) dots[i][1], width, width);
}
}
}
can anyone tell me what i'm doing wrong? i'm trying to get the circles to bounce off each other but they don't seem to be working.i keep making changes to fix the issue but that only makes more issues, whilst the main issue isn't resolved. have i used the wrong math's algorithm to check for collisions? or is it right and i have just made an error i cant seem to find? any help would be appreciated.
public float[][] CreateDots() {
if (first == true) {
for (int i = 0; i < dotNumber; i++) {
do{
dotX = r.nextInt(300);
dotY = r.nextInt(300);
dotWidth = r.nextFloat() * 50;
dotRadius = dotWidth / 2;
dotMass = r.nextFloat() / 10;
dotCentreX = dotX + dotRadius;
dotCentreY = dotY + dotRadius;
dotVelocityX = r.nextFloat();
dotVelocityY = r.nextFloat();
dots[i][0] = dotX;
dots[i][1] = dotY;
dots[i][2] = dotVelocityX;
dots[i][3] = dotVelocityY;
dots[i][4] = dotRadius;
dots[i][5] = dotCentreX;
dots[i][6] = dotCentreY;
dots[i][7] = dotMass;
dots[i][8] = dotWidth;
}while(collision == true);
}
first = false;
} else {
for (int i = 0; i < dotNumber; i++) {
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
if (dots[i][0] + dots[i][8] >= wallX) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] + dots[i][8] >= wallY) {
dots[i][3] = -dots[i][3];
}
if (dots[i][0] < 0) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] < 0) {
dots[i][3] = -dots[i][3];
}
}
}
repaint();
return dots;
}
public void bounce() {
collisionDot = false;
for (int i = 0; i < dotNumber; i++) {
for (int a = i + 1; a < dotNumber; a++) {
// difference between the x and y velocity of two dots
float xVelDiff = dots[i][2] - dots[a][2];
float yVelDiff = dots[i][3] - dots[a][3];
//difference between the centre x and y of two dots
float xDist = dots[i][5] - dots[a][5];
float yDist = dots[i][6] - dots[a][6];
System.out.println(xVelDiff + " * " + xDist + " + " + yVelDiff + " * " + yDist + " = "+ (xVelDiff * xDist + yVelDiff * yDist));
//not quite sure yet
if (xVelDiff * xDist + yVelDiff * yDist <= 0) {
angleCollision = (float) -Math.atan2(dots[a][0] - dots[i][0], dots[a][1] - dots[i][1]);
float mass = (dots[i][7] + dots[a][7]);
float mass2 = (dots[i][7] - dots[a][7]);
// x and y velocity and angle of collision for the two dots
float[] u1 = rotate(dots[i][2], dots[i][3], (float) angleCollision);
float[] u2 = rotate(dots[a][2], dots[a][3], (float) angleCollision);
//Velocity of dot 1
float[] v1 = new float[2];
v1[0] = u1[0] * mass2 / mass + u2[0] * 2 * dots[a][7] / (mass);
v1[1] = u1[1];
// velocity of dot 2
float[] v2 = new float[2];
v2[0] = u2[0] * mass2 / mass + u1[0] * 2 * dots[a][7] / (mass);
v2[1] = u2[1];
// final velocity of two colliding dots is:
float[] vFinal1 = rotate(v1[0], v1[1], (float) -angleCollision);;
float[] vFinal2 = rotate(v2[0], v2[1], (float) -angleCollision);;
if (a != i && !(dots[a][0] == 0 && dots[a][1] == 0)) {
// if the x and y distance between the two dots centres is less than their radii combined then the dots have collided
boolean thisCollision = Math.pow(xDist, 2) + Math.pow(yDist, 2) <= Math.pow((dots[a][4] + dots[i][4]), 2);
//if the dots collided, create new final velocity's from the angle of collision and the x and y velocitys at collision
if (thisCollision) {
collisionDot = true;
dots[i][2] = vFinal1[0];
dots[i][3] = vFinal1[1];
dots[a][2] = vFinal2[0];
dots[a][3] = vFinal2[1];
return;
}
}
}
}
}
}
public float[] rotate(float velocityX, float velocityY, float angle) {
float x1 = (float) (velocityX * Math.cos(angle) - velocityY * Math.sin(angle));
float y1 = (float) (velocityX * Math.sin(angle) - velocityY * Math.cos(angle));
float vel[] = new float[2];
vel[0] = x1;
vel[1] = y1;
return vel;
}
I have this array
Ball[] balls = new Ball[7]; // 7 just being an example
In my Ball class, I have getters and setters for x and y values.
I'm trying to compare the x and y values to make sure that they don't intersect.
My first thought was to make a loop looking like
for(Ball b1 : balls) {
for(Ball b2 : balls) {
if(b1.intersects(b1, b2)) {. . .} // I made intersects, not my issue
}
}
But this is no good, as it compares:
balls 0 to balls 0
balls 1 to balls 1
etc.
for(int i = 0; i < balls.length; i++) {
System.out.println(f.getContentPane().getWidth() + "\n" + f.getContentPane().getHeight());
int radius = 10 + rand.nextInt(20);
balls[i] = new Ball(360, radius,
rand.nextInt(f.getContentPane().getWidth() - 4 * radius - 5) + radius + 5,
rand.nextInt(f.getContentPane().getHeight() - 4 * radius - 5) + radius + 5
);
}
for(Ball b1 : balls) {
for (Ball b2 : balls) {
while (b1.intersects(b1, b2)) {
System.out.println("Ball started out inside of another, replacing now.");
b1.setX(rand.nextInt(f.getContentPane().getWidth() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
b1.setY(rand.nextInt(f.getContentPane().getHeight() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
}
}
}
////////////// class change //////////////////
class Ball {
private int direction;
private int radius;
private int x,y;
Ball(int direction, int radius, int x, int y) {
this.direction = direction;
this.radius = radius;
this.x = x;
this.y = y;
}
// Getters + Setters here
boolean intersects(Ball b1, Ball b2) {
double x = Math.pow((b2.getX() - b1.getX()), 2); // Distance formula
double y = Math.pow((b2.getY() - b1.getY()), 2); // Distance formula
double r = b1.getRadius() + b2.getRadius();
//System.out.println(x + " + " + y + " <= " + r );
return x + y <= r;
}
}
(Ignore that I didn't put my first hunk of code in a method and class, I've done that in my actual code.)
I, for whatever reason, can't think of a way to do this without a whole lot of if statements
(So I'm asking for the best way to do this)
One way to compare every distinct (i.e., no ball with itself) pair of Balls, without comparing any pair more than once would be:
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
// ...
}
}
}
Detecting new collisions introduced in the process of resolving previous ones just means making multiple passes over balls until you no longer have any collisions. A simple, perhaps naive, way of doing this would be something like this:
boolean foundCollision;
int numTries = 0;
int maxTries = 1000000;
do {
foundCollision = false;
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
foundCollision = true;
// resolve collision...
}
}
++numTries;
} while (foundCollision && numTries < maxTries);
if (numTries >= maxTries)
System.err.println("Couldn't sort out balls after " + maxTries + "tries: what now?");
For this class, I have to generate the SierpinskiTriangle by using loop and arraylist. This is what I have done so far; however, I don't know how to do the loop. Does anyone have any ideas? Thank you.
public ArrayList<Oval> createASierpinskiTriangle() {
int no_points = new Input().readIntDialog("Please enter number of points");
if(no_points<1||no_points>MAXIMUM_NUMBER_OF_POINTS){
JOptionPane.showMessageDialog(null, "Invalid value entered. Please enter from 1 to "+MAXIMUM_NUMBER_OF_ROWS);
}
ArrayList<Oval> list = new ArrayList<Oval>();
int x1 = 250, y1 = 50;
int x2 = 100, y2 = 350;
int x3 = 350, y3 = 350;
Random rand = new Random();
// start point
int x = x1, y = y1;
// loop
// Select randomly one of the vertices
int v = rand.nextInt(3) + 1; // 1, 2, or 3
// next point
// half way between the current point and the selected vertex
if (v == 1) {
x = (x + x1)/2;
y = (y + y1)/2;
} else if (v == 2) { //...
x = (x + x2)/2;
y = (y + y2)/2;
} else { // v is 3
x = (x + x3)/2;
y = (y + y3)/2;
}
Oval oval = new Oval(x-2,y-2,4,4,Color.BLUE,true);
list.add(oval);
// end of the loop
return list;
}