Print out an ASCII circle and axes with characters - java

I have to print a circle (taking as input it's radius, the coordinates of the center of the circle (cx and cy), and the character with which it has to be drawn).
I wrote a series of if-blocks for the axes and the circle. They work well if I use them separately, but when I put them in the same method (I have to have only one method) they overlap in an undesirable way.
Note: in case if the character overlaps the axes, the character has priority.
public static void drawCircle(int radius, int cx, int cy, char symbol) {
// this method verifies that there are no negative
// values involved (throws error/exception)
verifyInput(radius, cx, cy);
// set the values for extension of the axes
// (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
// set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax) {
System.out.println('|');
}
} else if (j == 0) {
if (i == xMax) {
System.out.println('>');
}
if (i != xMax) {
System.out.print('-');
}
}
// if block to print the circle
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print('*');
} else {
System.out.print(' ');
}
}
// I'm not sure if I need to use the print here V
// System.out.println()
}
}
Here is the onCircle method. It verifies for every i,j if it is on the outline of the circle to be drawn.
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
boolean isDrawn = false;
if (Math.pow(radius,2)<=(Math.pow((x-cx),2)+Math.pow((y-cy),2))
&& (Math.pow((x-cx),2)+Math.pow((y-cy),2))<=(Math.pow(radius,2)+1)) {
isDrawn = true;
}
return isDrawn;
}
Here is my output (without the last print statement):
^ |
*** |
* * |
* * |
* * + - - - - -*-*-*- >
Here is my output (with the last print statement):
^
|
***
|
* *
|
* *
|
* *
+ - - - - -*-*-*- >
Here is what I should get:

The general Equation of a circle:
In Java it can be implemented like this:
(x-a)*(x-a) + (y-b)*(y-b) == r*r
In the case of an integer coordinate system, it can be rounded like this:
(int) Math.sqrt((x-a)*(x-a) + (y-b)*(y-b)) == r
If the radius r=12 and the center of the circle a=5,b=1, then the circle and axes look like this:
r=12,a=5,b=1
^y
|
|
| * * * * * * * * *
* * * *
* * | * *
* * | * *
* * | * *
* | *
* | *
* | *
* | *
* | *
* | *
* | *
* | * *
------* ------------+---------------------------------* ---->x
* | *
* | *
* | *
* | *
* | *
* | *
* * | * *
* * | * *
* * | * *
* * * *
| * * * * * * * * *
|
|
|
Try it online!
// radius
int r = 12;
// center of the circle
int a = 5, b = 1;
// whitespace
int s = 3;
// print area
int xMin = a-r-s, xMax = a+r+s;
int yMin = b-r-s, yMax = b+r+s;
// output an ASCII circle and axes
System.out.println("r="+r+",a="+a+",b="+b);
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
if ((int) Math.sqrt((x-a)*(x-a) + (y-b)*(y-b)) == r) {
// circle
System.out.print("* ");
} else if (x == a && y == b) {
// center of the circle
System.out.print("* ");
} else if (x == 0 && y == 0) {
// origin of coordinates
System.out.print("+-");
} else if (x == 0) {
// ordinate axis - y
System.out.print(y == yMax ? "^y" : "| ");
} else if (y == 0) {
// abscissa axis - x
System.out.print(x == xMax ? ">x" : "--");
} else {
// whitespace
System.out.print(" ");
}
}
// new line
System.out.println();
}
See also:
• Print out an ASCII circle and axes
• Print out an ASCII circle of the specified width

It looks like the formatting issue is that you are sometimes using System.out.println where you should be using System.out.print. System.out.println will end the current line, so it should only be used once per output line. Thus you should just have the single empty System.out.printlnstatement at the end of the outer (j) loop, and use System.out.print throughout the rest of the program.
You will also need to fix the printing of the horizontal axis, as at the moment it will print both the axis and the circle, instead of just the circle.

jwaddell is right, your code needs only 5 minor updates like this (see comment like // <--):
public static void drawCircle(int radius, int cx, int cy, char symbol) {
// this method verifies that there are no negative
// values involved (throws error/exception)
verifyInput(radius, cx, cy);
// set the values for extension of the axes
// (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
// set of if-block to print the axes
if (onCircle(radius, cx, cy, i, j) == true) { // <-- draw circle first
System.out.print(symbol); // <-- use param 'symbol' here
} else if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax) {
System.out.print('|'); // <-- don't print new line here
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>'); // <-- don't print new line here
}
if (i != xMax) {
System.out.print('-');
}
} else {
System.out.print(' ');
}
}
System.out.println(); // <-- then add new line here
}
}
You can optimize onCircle like this:
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
double distance2 = Math.pow((x - cx), 2) + Math.pow((y - cy), 2);
double radius2 = Math.pow(radius, 2);
return radius2 <= distance2 && distance2 <= (radius2 + 1.0d);
}
The result with drawCircle(5, 10, 12, '&'); is as expected:
^
| &&&
| & &
| & &
|
| & &
| & &
| & &
|
| & &
| & &
| &&&
|
|
|
|
|
|
+--------------->

Related

How can i make the rendering process faster in JAVA?

I am making a software that has a screen filtering process. The code can already shift the colors and apply it to the frame the only problem is that It takes around 40-50 seconds for the filtered window to render. Is there any way I can make it faster? I would also like to ask which part of the code makes the process longer and time consuming. I will really appreciate the help. Thanks!
Here is my code.
public RedGreenFilter(int k1, int k2, int k3) {
this.k1 = k1;
this.k2 = k2;
this.k3 = k3;
}
#Override
public BufferedImage filter(final BufferedImage src, BufferedImage dst) {
if (dst == null) {
dst = this.createCompatibleDestImage(src, null);
}
// make sure the two images have the same size, color space, etc.
// MISSING !!! ???
DataBufferInt inBuffer = (DataBufferInt) src.getRaster().getDataBuffer();
DataBufferInt outBuffer = (DataBufferInt) dst.getRaster().getDataBuffer();
int[] inData = inBuffer.getData();
int[] outData = outBuffer.getData();
int simR = 0, simG = 0, simB = 0, mild = 10, moderate = 20, strong = 40;
float cIndex = MyDeficiency.cIndex;
float angle = MyDeficiency.angle;
float x = 0, y = 0, z = 0;
int prevIn = 0;
int prevOut = 0;
final int length = inData.length;
int corrG;
int corrR;
int corrB;
int SizeOfScreen = src.getHeight() * src.getWidth();
final int[] redArray = new int[SizeOfScreen];
final int[] blueArray = new int[SizeOfScreen];
final int[] greenArray = new int[SizeOfScreen];
for (int i = 0; i < SizeOfScreen; i++) {
final int in = inData[i];
if (in == prevIn) {
outData[i] = prevOut;
} else {
final int r = (0xff0000 & in) >> 16;
final int g = (0xff00 & in) >> 8;
final int b = 0xff & in;
// get linear rgb values in the range 0..2^15-1
final int r_lin = rgb2lin_red_LUT[r];
final int g_lin = rgb2lin_red_LUT[g];
final int b_lin = rgb2lin_red_LUT[b];
//http://publication.gunadarma.ac.id/bitstream/123456789/12232/1/Slide_Mahendra_54411250.pdf
float L = (17.8824f * r + 43.5161f * g + 4.11935f * b);
float M = (3.4565f * r + 27.1554f * g + 3.86714f * b);
float S = (0.02996f * r + 0.18431f * g + 1.46709f * b);
float dL = ( 0 * L + 2.02344f * M - 2.52581f * S);
float dM = ( 0 * L + 1 * M + 0 * S);
float dS = ( 0 * L + 0 * M + 1 * S);
float pL = ( 1 * L + 0 * M + 0 * S);
float pM = ( 0.494207f * L + 0 * M + 1.24827f * S);
float pS = ( 0 * L + 0 * M + 1 * S);
// simulated red and green are identical
// scale the matrix values to 0..2^15 for integer computations
// of the simulated protan values.
// divide after the computation by 2^15 to rescale.
// also divide by 2^15 asnd multiply by 2^8 to scale the linear rgb to 0..255
// total division is by 2^15 * 2^15 / 2^8 = 2^22
// shift the bits by 22 places instead of dividing
int r_blind = (int) (k1 * r_lin + k2 * g_lin) >> 22;
int b_blind = (int) (k3 * r_lin - k3 * g_lin + 32768 * b_lin) >> 22;
if (r_blind < 0) {
r_blind = 0;
} else if (r_blind > 255) {
r_blind = 255;
}
if (b_blind < 0) {
b_blind = 0;
} else if (b_blind > 255) {
b_blind = 255;
}
// convert reduced linear rgb to gamma corrected rgb
int red = lin2rgb_LUT[r_blind];
red = red >= 0 ? red : 256 + red; // from unsigned to signed
int blue = lin2rgb_LUT[b_blind];
blue = blue >= 0 ? blue : 256 + blue; // from unsigned to signed
if(k1 == 9591 && k2 == 23173){
x = dL;
y = dM;
z = dS;
}
if(k1 == 3683 && k2 == 29084){
x = pL;
y = pM;
z = pS;
}
//SEVERITY
//PROTAN
//normal to mild
if (angle > 0.70 && cIndex < 1.2){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z);
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z);
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//mild to moderate
else if (angle > 0.70 && cIndex < 3 && cIndex > 1.20){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z) + mild;
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z);
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//moderate to strong
else if (angle > 0.70 && cIndex < 4 && cIndex > 3){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z) + moderate;
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z);
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//strong to super strong
else if (angle > 0.70 && cIndex > 4){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z) + strong;
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z);
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//DEUTAN
//normal to mild
if (angle < 0.70 && angle > -65.00 && cIndex < 1.2){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z);
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z);
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//mild to moderate
else if (angle < 0.70 && angle > -65.00 && cIndex < 3 && cIndex > 1.20){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z);
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z) + mild;
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z);
}
//moderate to strong
else if (angle < 0.70 && angle > -65 && cIndex < 4 && cIndex > 3){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z);
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z) + moderate;
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z) ;
}
//strong to super strong
else if (angle < 0.7 && angle > -65 && cIndex > 4){
simR = (int)(0.0809533970341018f * x -0.1305188419612954f * y + 0.11673398252989027f * z);
simG = (int)(-0.01025222049871863f * x + 0.054025275314902886f * y -0.11362003603724172f * z) + strong;
simB = (int)(-0.0003651971010795924f * x -0.004121801653701777f * y + 0.693511617368688f * z) ;
}
int errR = r - simR;
int errG = g - simG;
int errB = b - simB;
float errModR = (0 * errR + 0 * errG + 0 * errB);
float errModG = (0.7f * errR + 1 * errG + 0 * errB);
float errModB = (0.7f * errR + 0 * errG + 1 * errB);
corrR = (int) errModR + r;
corrG = (int) errModG + g;
corrB = (int) errModB + b;
/*
int corrR = 0;
int corrG = 0;
int corrB = 0;
*/
//MyDeficiency my = new MyDeficiency();
if(r == 255 && g == 255 && b == 255){
corrR = corrG = corrB = 255;
}
if(r == 0 && g == 0 && b == 0){
corrR = corrG = corrB = 0;
}
final int out = 0xff000000 | (corrR << 16) | (corrG << 8) | corrB ;
redArray[i] = (out >> 16) & 0xFF;
greenArray[i] = (out >> 8) & 0xFF;
blueArray[i] = (out >> 0) & 0xFF;
//System.out.println("r: " +" " + redArray[i]+ " "+ " g:" +" " +greenArray[i] +" " +"b:"+" "+ blueArray[i] + " " +"i:"+ " "+i);
//System.out.println("sR: " + (red << 16) + "sG: " +(red <<8)+ " sB: " + blue);
//outData[i] = out;
//prevIn = in;
//prevOut = out;
}
}
//System.out.println(SizeOfScreen);
Window w = new Window(null);
w.add(new JComponent() {
public void paintComponent(Graphics g) {
int alpha = 190; // 50% transparent
int pixelcounter = 0;
for(int i = 0; i < src.getHeight(); i++){
for(int j = 0; j < src.getWidth(); j++){
Color myColour = new Color(redArray[pixelcounter],greenArray[pixelcounter],blueArray[pixelcounter], alpha);
g.setColor(myColour);
g.fillRect(j,i,1,1);
pixelcounter++;
}
}
}
public Dimension getPreferredSize() {
return new Dimension(src.getWidth(), src.getHeight());
}
});
w.pack();
w.setLocationRelativeTo(null);
w.setAlwaysOnTop(true);
/**
* This sets the background of the window to be transparent.
*/
AWTUtilities.setWindowOpaque(w, false);
setTransparent(w);
w.setVisible(true);
//w.setVisible(false);
return dst;
}
}

Print out an ASCII circle and axes

This program prints a circle in a Cartesian plane.
The inputs are: radius, coordinates of the center of the circle (cx,cy), and the character with which we want to print the circle.
If the points of the circle overlap with the axes, the points have priority. I wrote a condition for the printing of the axes in method drawCircle, but the image is distorted...
Something is eluding me... can someone help me to find my mistake?
Here is my entire program (the method that has issues is the last one, drawCircle):
public class Circle {
public static void main(String[] args) {
System.out.println(onCircle(1, 2, 3, 4, 5));
drawCircle(1, 3, 3, '*');
drawCircle(3, 3, 3, '*');
drawCircle(5, 10, 12, '*');
}
//Question 1A
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
//default answer is false, but if the
//inequality holds then it is set to true
boolean isDrawn = false;
if (Math.pow(radius,2)<=(Math.pow((x-cx),2)+Math.pow((y-cy),2))
&& (Math.pow((x-cx),2)+Math.pow((y-cy),2))<=(Math.pow(radius,2)+1)) {
isDrawn = true;
}
return isDrawn;
}
//Question 1B
public static void verifyInput(int radius, int cx, int cy) {
//if radius is negative, display error message
if (radius <= 0) {
throw new IllegalArgumentException(
"The radius of the circle must be a positive number.");
}
//if the center of the circle with radius 'radius' causes the circle
//to 'overflow' into other quadrants, display error message
if ((cx - radius) < 0 || (cy - radius) < 0) {
throw new IllegalArgumentException(
"the circle with requested parameters does not fit " +
"in the quadrant. Consider moving the center of the " +
"circle further from the axes.");
}
}
//Question 1C
public static void drawCircle(int radius, int cx, int cy, char symbol) {
verifyInput(radius, cx, cy);
//set the values for extension of the axes (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
//set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('|');
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>');
}
if (i != xMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('-');
}
}
//if block to print the circle
//verify for each coordinate (i,j)
//in the quadrant if they are on circle
//if =true print symbol, if =false print empty character
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print(symbol);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
}
Here is what I am getting:
false
^
| ***
| * *
| ***
|
+ - - - - >
^
| ***
|
* *
* *
* *
|
+ - ***- - >
^
| ***
| * *
| * *
|
| * *
| * *
| * *
|
| * *
| * *
| ***
|
|
|
|
|
|
+ - - - - - - - - - - - - - - - >
As you can see, the 1st and 3rd circles are fine, but the one that overlaps with the axes is distorted.
The general Equation of a circle centred at the origin:
In Java it can be implemented like this:
i*i + j*j == r*r
But in the case of an integer coordinate system, you have to round this equation somehow so that all the points of the circle are reflected in this coordinate system:
(int) Math.sqrt(i*i + j*j) == r
If r=8, then the circle and axes look like this:
r=8
* * * * * * * * *
* * * * *
* * *
* * *
* * * * *
* * *
* * *
* * *
* * * * * * * * * * * * * * * * *
* * *
* * *
* * *
* * * * *
* * *
* * *
* * * * *
* * * * * * * * *
Try it online!
int r = 8;
System.out.println("r=" + r);
IntStream.rangeClosed(-r, r)
.peek(i -> IntStream.rangeClosed(-r, r)
.mapToObj(j -> i == 0 || j == 0 ||
(int) Math.sqrt(i*i + j*j) == r ?
"* " : " ")
.forEach(System.out::print))
.forEach(i -> System.out.println());
See also: Print out an ASCII star in java
You're missing 3 continue statements.
Check out this revised version of your drawCircle method:
public static void drawCircle(int radius, int cx, int cy, char symbol) {
verifyInput(radius, cx, cy);
//set the values for extension of the axes (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
//set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
continue;
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('|');
continue;
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>');
}
if (i != xMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('-');
continue;
}
}
//if block to print the circle
//verify for each coordinate (i,j)
//in the quadrant if they are on circle
//if =true print symbol, if =false print empty character
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print(symbol);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
Actually when debugging, your onCircle methods gets for x=0 and y=4, cx=3, cy=3:
You have:
Math.pow(radius=3, 2) = 9
Math.pow((x - cx), 2) = 9
Math.pow((y - cy), 2) = 1
Hence
Math.pow(radius, 2) <= Math.pow((x - cx), 2) + Math.pow((y - cy), 2)
returns true
Then:
(Math.pow((x-cx),2) = 9
Math.pow((y-cy),2)) = 1
(Math.pow(radius,2)+1)) = 10
Thus
(Math.pow((x-cx),2)+Math.pow((y-cy),2)) <= (Math.pow(radius,2)+1))
returns also true
Thus onCircle(radius,cx,cy,i,j) returns true for this coordinate.
And that's why you get your symbol drawn. You need to improve your algorithm!

java unreachable code error (Render class game development)

i have been working on a java game engine but my render keeps getting the unreachable code error.The error appears at the setPixels method.
public class Renderer {
private int width, height;
private byte[] pixels;
public Renderer(GameContainer gc){
width = gc.getWidth();
height = gc.getHeight();
pixels = ((DataBufferByte)gc.getWindow().getImage().getRaster().getDataBuffer()).getData();
}
public void setPixel(int x, int y, float a, float r, float g, float b){
if((x < 0 || x>= width || y < 0 || y>= height) || a == 0){
return;
int index = (x + y * width) * 4;
pixels[index] = (byte)((a * 255f) + 0.5f);
pixels[index + 1] = (byte)((b * 255f) + 0.5f);
pixels[index + 2] = (byte)((g * 255f) + 0.5f);
pixels[index + 3] = (byte)((r * 255f) + 0.5f);
}
}
public void clear(){
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
setPixel(x,y,1,0,1,1);
}
}
}
}
I think this is what you are trying to do?
Your if statement should not be enclosing all the statements in your function.
public void setPixel(int x, int y, float a, float r, float g, float b){
// Check for invalid values
if((x < 0 || x>= width || y < 0 || y>= height) || a == 0){
// Break out of function if invalid values detected
return;
}
// Update pixel
int index = (x + y * width) * 4;
pixels[index] = (byte)((a * 255f) + 0.5f);
pixels[index + 1] = (byte)((b * 255f) + 0.5f);
pixels[index + 2] = (byte)((g * 255f) + 0.5f);
pixels[index + 3] = (byte)((r * 255f) + 0.5f);
}
The return statement ends the execution of a method. In the event that the if statement is run in the code below, the method will hit the return and end before doing all the other stuff. You don't seem to need a return statement in setPixel since there isn't a need to end the method prematurely.
public void setPixel(int x, int y, float a, float r, float g, float b) {
if((x < 0 || x>= width || y < 0 || y>= height) || a == 0){
//return;
int index = (x + y * width) * 4;
pixels[index] = (byte)((a * 255f) + 0.5f);
pixels[index + 1] = (byte)((b * 255f) + 0.5f);
pixels[index + 2] = (byte)((g * 255f) + 0.5f);
pixels[index + 3] = (byte)((r * 255f) + 0.5f);
}
}

Java Rect.intersects() not working sometimes

I currently loop through all my sprites checking if they intersect with each other like this:
for (Sprite s : sprites) {
if (s.dead) {
dead.add(s);
}
for (Sprite sprite : sprites) {
if (!sprite.equals(s)) {
s.collide(sprite, maxX, maxY);
}
}
s.run();
}
and the sprite checks using the Rect.intersects() method like so:
if (getRect().intersects(s.getRect()))
But sometimes it just completely ignores a collision, and the objects just pass through each other.
Any ideas?
You should try changing the code to
if(getRect().intersects(s.getRect()) || s.getRect().intersects(getRect()))
{
// They have intersected
}
The reason for this being, the intersection method check is unique for each rectangle. Performing an intersection check to see if rectangle a intersects rectangle b, is different than performing an intersection check to see if rectangle b intersects rectangle a.
Other than this, can you give me more information on your rectangles? Are they rotating? How fast are they moving? How large are they? Other information would be use full as well, I can try to think of other reasons for why they are not colliding.
I fixed it by making it create a rectangle for the area that it covers between frames like so:
private void checkForNextCollision() {
double boundsWidth = width + dX ;
if(dX < 0){
boundsWidth= width - dX ;
}
double boundsHeight = height + dY ;
if(dY < 0){
boundsHeight = height - dY ;
}
double boundx = xWorld + dX ;
double boundy = yWorld + dY ;
betweenRect = new Rectangle((int)(boundx),(int)(boundy),(int)(boundsWidth), (int)(boundsHeight));
}
This rectangle is then checked against the rectangle created in the other sprites to check if there should be a collision in the next frame:
public void collide(Sprite s, int maxX, int maxY) {
maxWX = maxX;
maxWY = maxY;
//check for collision with borders
if (xWorld <= 0) {
dX = -dX;
xWorld += 2;
if(xWorld < -1000){
dX = 0;
xWorld += 10;
}
}
if (yWorld <= 0) {
dY = -dY;
yWorld += 2;
if(yWorld < -1000){
dX = 0;
yWorld += 10;
}
}
if (xWorld + width >= maxX) {
dX = -dX;
xWorld -= 2;
if(xWorld+width > maxX + 1000){
dX = 0;
xWorld -= 10;
}
}
if (yWorld + height >= maxY) {
dY = -dY;
yWorld -= 2;
if(yWorld+height > maxY + 1000){
dY = 0;
yWorld -= 10;
}
}
//check for collision with borders
if(betweenRect.intersects(s.betweenRect)){
willIntersect = true;
}else{
willIntersect = false;
}
// Use all checks to see if they should collide
if (getRect().intersects(s.getRect()) || s.getRect().intersects(getRect()) || willIntersect || (xWorld + width > s.xWorld && xWorld < s.xWorld + s.width && yWorld < s.yWorld+s.height && yWorld + height > s.yWorld) ) {
double lastDy = dY;
double lastsDy = s.dY;
double lastDx = dX;
double lastsDx = s.dX;
dY = (((weight - s.weight) / (weight + s.weight)) * lastDy)
+ (((2.0 * s.weight) / (weight + s.weight)) * lastsDy);
s.dY = (((s.weight - weight) / (weight + s.weight)) * lastsDy)
+ (((2.0 * weight) / (weight + s.weight)) * lastDy);
dX = (((weight - s.weight) / (weight + s.weight)) * lastDx)
+ (((2.0 * s.weight) / (weight + s.weight)) * lastsDx);
s.dX = (((s.weight - weight) / (weight + s.weight)) * lastsDx)
+ (((2.0 * weight) / (weight + s.weight)) * lastDx);
if(willIntersect){
willIntersect = false;
//s.willIntersect = false;
}
}
}

Confusing Java syntax

I'm trying to convert the following code (from Wikipedia) from Java to JavaScript:
/*
* 3 June 2003, [[:en:User:Cyp]]:
* Maze, generated by my algorithm
* 24 October 2006, [[:en:User:quin]]:
* Source edited for clarity
* 25 January 2009, [[:en:User:DebateG]]:
* Source edited again for clarity and reusability
* 1 June 2009, [[:en:User:Nandhp]]:
* Source edited to produce SVG file when run from the command-line
*
* This program was originally written by [[:en:User:Cyp]], who
* attached it to the image description page for an image generated by
* it on en.wikipedia. The image was licensed under CC-BY-SA-3.0/GFDL.
*/
import java.awt.*;
import java.applet.*;
import java.util.Random;
/* Define the bit masks */
class Constants {
public static final int WALL_ABOVE = 1;
public static final int WALL_BELOW = 2;
public static final int WALL_LEFT = 4;
public static final int WALL_RIGHT = 8;
public static final int QUEUED = 16;
public static final int IN_MAZE = 32;
}
public class Maze extends java.applet.Applet {
/* The width and height (in cells) of the maze */
private int width;
private int height;
private int maze[][];
private static final Random rnd = new Random();
/* The width in pixels of each cell */
private int cell_width;
/* Construct a Maze with the default width, height, and cell_width */
public Maze() {
this(20,20,10);
}
/* Construct a Maze with specified width, height, and cell_width */
public Maze(int width, int height, int cell_width) {
this.width = width;
this.height = height;
this.cell_width = cell_width;
}
/* Initialization method that will be called when the program is
* run from the command-line. Maze will be written as SVG file. */
public static void main(String[] args) {
Maze m = new Maze();
m.createMaze();
m.printSVG();
}
/* Initialization method that will be called when the program is
* run as an applet. Maze will be displayed on-screen. */
public void init() {
createMaze();
}
/* The maze generation algorithm. */
private void createMaze(){
int x, y, n, d;
int dx[] = { 0, 0, -1, 1 };
int dy[] = { -1, 1, 0, 0 };
int todo[] = new int[height * width], todonum = 0;
/* We want to create a maze on a grid. */
maze = new int[width][height];
/* We start with a grid full of walls. */
for (x = 0; x < width; ++x) {
for (y = 0; y < height; ++y) {
if (x == 0 || x == width - 1 || y == 0 || y == height - 1) {
maze[x][y] = Constants.IN_MAZE;
} else {
maze[x][y] = 63;
}
}
}
/* Select any square of the grid, to start with. */
x = 1 + rnd.nextInt (width - 2);
y = 1 + rnd.nextInt (height - 2);
/* Mark this square as connected to the maze. */
maze[x][y] &= ~48;
/* Remember the surrounding squares, as we will */
for (d = 0; d < 4; ++d) {
if ((maze[][d][][d] & Constants.QUEUED) != 0) {
/* want to connect them to the maze. */
todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]);
maze[][d][][d] &= ~Constants.QUEUED;
}
}
/* We won't be finished until all is connected. */
while (todonum > 0) {
/* We select one of the squares next to the maze. */
n = rnd.nextInt (todonum);
x = todo[n] >> 16; /* the top 2 bytes of the data */
y = todo[n] & 65535; /* the bottom 2 bytes of the data */
/* We will connect it, so remove it from the queue. */
todo[n] = todo[--todonum];
/* Select a direction, which leads to the maze. */
do {
d = rnd.nextInt (4);
}
while ((maze[][d][][d] & Constants.IN_MAZE) != 0);
/* Connect this square to the maze. */
maze[x][y] &= ~((1 << d) | Constants.IN_MAZE);
maze[][d][][d] &= ~(1 << (d ^ 1));
/* Remember the surrounding squares, which aren't */
for (d = 0; d < 4; ++d) {
if ((maze[][d][][d] & Constants.QUEUED) != 0) {
/* connected to the maze, and aren't yet queued to be. */
todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]);
maze[][d][][d] &= ~Constants.QUEUED;
}
}
/* Repeat until finished. */
}
/* Add an entrance and exit. */
maze[1][1] &= ~Constants.WALL_ABOVE;
maze[width - 2][height - 2] &= ~Constants.WALL_BELOW;
}
/* Called by the applet infrastructure to display the maze on-screen. */
public void paint(Graphics g) {
drawMaze(g);
}
/* Called to write the maze to an SVG file. */
public void printSVG() {
System.out.format("<svg width=\"%d\" height=\"%d\" version=\"1.1\""
+ " xmlns=\"http://www.w3.org/2000/svg\">\n",
width*cell_width, height*cell_width);
System.out.println(" <g stroke=\"black\" stroke-width=\"1\""
+ " stroke-linecap=\"round\">");
drawMaze(null);
System.out.println(" </g>\n</svg>");
}
/* Main maze-drawing loop. */
public void drawMaze(Graphics g) {
int x, y;
for (x = 1; x < width - 1; ++x) {
for (y = 1; y < height - 1; ++y) {
if ((maze[x][y] & Constants.WALL_ABOVE) != 0)
drawLine( x * cell_width, y * cell_width,
(x + 1) * cell_width, y * cell_width, g);
if ((maze[x][y] & Constants.WALL_BELOW) != 0)
drawLine( x * cell_width, (y + 1) * cell_width,
(x + 1) * cell_width, (y + 1) * cell_width, g);
if ((maze[x][y] & Constants.WALL_LEFT) != 0)
drawLine( x * cell_width, y * cell_width,
x * cell_width, (y + 1) * cell_width, g);
if ((maze[x][y] & Constants.WALL_RIGHT) != 0)
drawLine((x + 1) * cell_width, y * cell_width,
(x + 1) * cell_width, (y + 1) * cell_width, g);
}
}
}
/* Draw a line, either in the SVG file or on the screen. */
public void drawLine(int x1, int y1, int x2, int y2, Graphics g) {
if ( g != null ) g.drawLine(x1, y1, x2, y2);
else System.out.format(" <line x1=\"%d\" y1=\"%d\""
+ " x2=\"%d\" y2=\"%d\" />\n", x1, y1, x2, y2);
}
}
Anyway, I was chugging along fairly quickly when I came to a bit that I just don't understand:
/* Remember the surrounding squares, as we will */
for (var d = 0; d < 4; ++d) {
if ((maze[][d][][d] & Constants.QUEUED) != 0) {
/* want to connect them to the maze. */
todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]);
maze[][d][][d] &= ~Constants.QUEUED;
}
}
What I don't get is why there are four sets of brackets following the "maze" parameter instead of just two, since "maze" is a two dimensional array, not a four dimensional array.
I'm sure there's a good reason for this. Problem is, I just don't get it.
Thanks!
To simply correct the syntax, this answer is as good as any. However to fix the algorithm, Leon's has more insight there.
Looks to me like the code is wrong having two too many sets of square brackets. maze is declared and initialized as a 2-dimensional int array. There's no reason it should have more than that. Perhaps the result of a misinformed or buggy code generator?
Just remove the preceding, empty square brackets [] (or ][) from the array accesses and you'll be set.
My educated guess would be that there is some code missing. Removing the extra [] makes the code compile but it does not generate a maze but is stuck in an infinite loop
I think [][d][][d] are supposed to be maze[x+dx[d]][y+dy[d]].
It is clear that d is supposed to index into dx and dy arrays, which are offsets into the neighbours of the current cell, as is is always iterated 4 times. Also todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]); indexes the maze array using dx[d] and dy[y] as offsets to the neighbours.
I am not sure whether this is the best way thou, as when x=0 and dx offset is -1 you will have and OutOfBoundsException. You may have to handle those cases explicitly.
OK, here's the JavaScript version:
/*
* 3 June 2003, [[:en:User:Cyp]]:
* Maze, generated by my algorithm
* 24 October 2006, [[:en:User:quin]]:
* Source edited for clarity
* 25 January 2009, [[:en:User:DebateG]]:
* Source edited again for clarity and reusability
* 1 June 2009, [[:en:User:Nandhp]]:
* Source edited to produce SVG file when run from the command-line
* 7 January, 2011 [[:en:User:SharkD]]:
* Source converted to JavaScript
*
* This program was originally written by [[:en:User:Cyp]], who
* attached it to the image description page for an image generated by
* it on en.wikipedia. The image was licensed under CC-BY-SA-3.0/GFDL.
*/
/* Recreate a math function that exists in Java but not JavaScript. */
Math.nextInt = function (number) {
return Math.floor(Math.random() * number)
}
/* Recreate a system function that exists in Java but not JavaScript.
* Uncomment either WScript.Echo() or alert() depending on whether you are
* running the script from the Windows command-line or a Web page.
*/
function println(string)
{
// if inside Windows Scripting Host
// WScript.Echo(string)
// if inside a Web page
alert(string)
}
/* Define the bit masks */
var Constants =
{
WALL_ABOVE : 1,
WALL_BELOW : 2,
WALL_LEFT : 4,
WALL_RIGHT : 8,
QUEUED : 16,
IN_MAZE : 32
}
/* Construct a Maze with specified width, height, and cell_width */
function Maze(width, height, cell_width) {
if (width)
this.width = width;
else
this.width = 20;
if (height)
this.height = height;
else
this.height = 20;
if (cell_width)
this.cell_width = cell_width;
else
this.cell_width = 10;
this.maze = []
/* The maze generation algorithm. */
this.createMaze = function() {
var width = this.width
var height = this.height
var maze = this.maze
var x, y, n, d;
var dx = [ 0, 0, -1, 1 ];
var dy = [ -1, 1, 0, 0 ];
var todo = new Array(height * width);
var todonum = 0;
/* We want to create a maze on a grid. */
/* We start with a grid full of walls. */
for (x = 0; x < width; ++x) {
maze[x] = []
for (y = 0; y < height; ++y) {
if (x == 0 || x == width - 1 || y == 0 || y == height - 1) {
maze[x][y] = Constants.IN_MAZE;
}
else {
maze[x][y] = 63;
}
}
}
/* Select any square of the grid, to start with. */
x = 1 + Math.nextInt(width - 2);
y = 1 + Math.nextInt(height - 2);
/* Mark this square as connected to the maze. */
maze[x][y] &= ~48;
/* Remember the surrounding squares, as we will */
for (d = 0; d < 4; ++d) {
if ((maze[x + dx[d]][y + dy[d]] & Constants.QUEUED) != 0) {
/* want to connect them to the maze. */
todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]);
maze[x + dx[d]][y + dy[d]] &= ~Constants.QUEUED;
}
}
/* We won't be finished until all is connected. */
while (todonum > 0) {
/* We select one of the squares next to the maze. */
n = Math.nextInt(todonum);
x = todo[n] >> 16; /* the top 2 bytes of the data */
y = todo[n] & 65535; /* the bottom 2 bytes of the data */
/* We will connect it, so remove it from the queue. */
todo[n] = todo[--todonum];
/* Select a direction, which leads to the maze. */
do {
d = Math.nextInt(4);
}
while ((maze[x + dx[d]][y + dy[d]] & Constants.IN_MAZE) != 0);
/* Connect this square to the maze. */
maze[x][y] &= ~((1 << d) | Constants.IN_MAZE);
maze[x + dx[d]][y + dy[d]] &= ~(1 << (d ^ 1));
/* Remember the surrounding squares, which aren't */
for (d = 0; d < 4; ++d) {
if ((maze[x + dx[d]][y + dy[d]] & Constants.QUEUED) != 0) {
/* connected to the maze, and aren't yet queued to be. */
todo[todonum++] = ((x + dx[d]) << Constants.QUEUED) | (y + dy[d]);
maze[x + dx[d]][y + dy[d]] &= ~Constants.QUEUED;
}
}
/* Repeat until finished. */
}
/* Add an entrance and exit. */
maze[1][1] &= ~Constants.WALL_ABOVE;
maze[width - 2][height - 2] &= ~Constants.WALL_BELOW;
}
/* Called to write the maze to an SVG file. */
this.printSVG = function () {
var outstring = "<svg width=\"" + (width * cell_width) + "\" height=\"" + (height*cell_width) + "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"
+ " <g stroke=\"black\" stroke-width=\"1\" stroke-linecap=\"round\">\n"
+ this.drawMaze()
+ " </g>\n</svg>\n";
println(outstring)
}
/* Main maze-drawing loop. */
this.drawMaze = function () {
var x, y;
var width = this.width;
var height = this.height;
var cell_width = this.cell_width
var outstring = ""
for (x = 1; x < width - 1; ++x) {
for (y = 1; y < height - 1; ++y) {
if ((this.maze[x][y] & Constants.WALL_ABOVE) != 0)
outstring += this.drawLine( x * cell_width, y * cell_width, (x + 1) * cell_width, y * cell_width);
if ((this.maze[x][y] & Constants.WALL_BELOW) != 0)
outstring += this.drawLine( x * cell_width, (y + 1) * cell_width, (x + 1) * cell_width, (y + 1) * cell_width);
if ((this.maze[x][y] & Constants.WALL_LEFT) != 0)
outstring += this.drawLine( x * cell_width, y * cell_width, x * cell_width, (y + 1) * cell_width);
if ((this.maze[x][y] & Constants.WALL_RIGHT) != 0)
outstring += this.drawLine((x + 1) * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width);
}
}
return outstring
}
/* Draw a line, either in the SVG file or on the screen. */
this.drawLine = function (x1, y1, x2, y2) {
return " <line x1=\"" + x1 + "\" y1=\"" + y1 + "\" x2=\"" + x2 + "\" y2=\"" + y2 + "\" />\n";
}
}
/* Initialization method that will be called when the program is
* run from the command-line. Maze will be written as SVG file. */
function main(args) {
var m = new Maze();
m.createMaze();
m.printSVG();
}
/* execute the program */
main()
Next step is to turn it into a six axis 3D maze and convert to Lua, which is my actual target platform. :)
PS - I'm trying to vote on answers, but it's telling me I need to login or register, wtf?

Categories

Resources