I asked this question on Math.se a few days ago, and got the following answer in pseudocode:
Function RandomCircleInside(centerX, centerY, radius):
Let newRadius = radius * Random()
Let radians = 2.0 * 3.14159265358979323846 * Random()
Let deviation = (radius - newRadius) * Sqrt(Random())
Let newX = centerX + deviation * Cos(radians)
Let newY = centerY + deviation * Sin(radians)
Return (newX, newY, newRadius)
End Function
I changed the pseudocode to Java and added my own changes to fit my needs. The new code looks like this:
Circle createNewCircle(int centerX, int centerY, int radius, int newR, Color newColor) {
int newRadius = radius * Random();
double radians = 2.0 * 3.141592653589793 * Random();
double deviation = (radius - newRadius) * Math.sqrt(Random());
System.out.println(radius + " - " + newRadius + " * sqrt(0 or 1) = " + (radius-newRadius) + " * (0 or 1) = " + deviation);
double newX = centerX + deviation * Math.cos(radians);
System.out.println(centerX + " + " + deviation + " * cos(" + radians + ") = " + (centerX + deviation) + " * " + Math.cos(radians));
double newY = centerY + deviation * Math.sin(radians);
int newCirX = (int) newX;
int newCirY = (int) newY;
Circle newCir = new Circle(newCirX, newCirY, newR*2, newR*2, newR, newColor, true);
return newCir;
}
The code itself is supposed to create a new Circle inside of a preexisting one. I created a circle class that looks like this:
import java.awt.Color;
import java.awt.Graphics;
public class Circle {
public int X, Y, Width, Height, radius;
public Color color;
public boolean toFill;
public Circle(int x, int y, int width, int height, int radius, Color color, boolean fill) {
X = x;
Y = y;
Width = width;
Height = height;
this.radius = radius;
this.color = color;
toFill = fill;
}
public void render(Graphics g) {
g.setColor(color);
for(int i=-5; i<5; i++) {
if(toFill) {
g.fillOval(X+i, Y+i, Width-i, Height-i);
} else {
g.drawOval(X+i, Y+i, Width-i, Height-i);
}
}
}
public boolean contains(Circle pBound) {
int pBoundCenterX = pBound.X+pBound.radius;
int cirCenterX = X+radius;
int diffBetweenCentersX = Math.abs(pBoundCenterX-cirCenterX);
int pBoundCenterY = pBound.Y+pBound.radius;
int cirCenterY = Y+radius;
int diffBetweenCentersY = Math.abs(pBoundCenterY-cirCenterY);
if(diffBetweenCentersX<= (pBound.radius+radius) && diffBetweenCentersX>=Math.abs(pBound.radius-radius)) { // X
if(diffBetweenCentersY>=Math.abs(pBound.radius-radius)) { // Y
return true;
}
}
return false;
}
public int getX() {
return X;
}
public int getWidth() {
return Width;
}
public int getRadius() {
return radius;
}
public void setWidth(int width) {
Width = width;
}
public int getHeight() {
return Height;
}
public void setHeight(int height) {
Height = height;
}
public void setX(int x) {
X = x;
}
public int getY() {
return Y;
}
public void setY(int y) {
Y = y;
}
}
My way of creating the new circle is this:
if(secInGame==timesForCircle[X] && !hasChanged) { // circle 2
Circle cir1 = cir;
cir = createNewCircle(cir1.X+(cir1.Width/2), cir1.Y+(cir1.Height/2), cir1.getRadius(), 135, Color.cyan);
hasChanged = true;
circleOn++;
circ++;
}
Where cir1 is the preexisting Circle and cir is the new circle.
Is there anything I didn't code correctly? I've tried a few different variations, but they all give the same result.
Before I implemented the pseudocode, my circles looked like this:
but now it looks like this:
All of my code can be found on github at: link
I think there are several issues in your code.
1. First of all it is not clear why your Circle has radius, Width and Height. For a circle all 3 things should be the same. Also your render in case toFill is true looks strange. Here is a simplified version (note: I didn't compile it so there might be some bugs):
public class Circle {
public int X, Y, radius;
public Color color;
public boolean toFill;
public Circle(int x, int y, int radius, Color color, boolean fill) {
X = x;
Y = y;
this.radius = radius;
this.color = color;
toFill = fill;
}
public void render(Graphics g) {
g.setColor(color);
final int r2 = 2*radius;
if(toFill) {
g.fillOval(X, Y, r2, r2);
}
else {
for(int i=-5; i<5; i++) {
g.drawOval(X+i, Y+i, r2-i, r2-i);
}
}
}
public boolean contains(Circle pBound) {
int pBoundCenterX = pBound.X+pBound.radius;
int cirCenterX = X+radius;
int diffBetweenCentersX = Math.abs(pBoundCenterX-cirCenterX);
int pBoundCenterY = pBound.Y+pBound.radius;
int cirCenterY = Y+radius;
int diffBetweenCentersY = Math.abs(pBoundCenterY-cirCenterY);
if(diffBetweenCentersX<= (pBound.radius+radius) && diffBetweenCentersX>=Math.abs(pBound.radius-radius)) { // X
if(diffBetweenCentersY>=Math.abs(pBound.radius-radius)) { // Y
return true;
}
}
return false;
}
public int getX() {
return X;
}
public int getRadius() {
return radius;
}
public void setX(int x) {
X = x;
}
public int getY() {
return Y;
}
public void setY(int y) {
Y = y;
}
}
I didn't check your code, but I'd consider as a good practice:
renaming x and y into leftX and topY to avoid confusion with centerX/centerY meaning. Or change meaning to more typical center one.
declaring all your fields as private (see encapsulation);
declaring all your fields as final and remove all the setXyz methods (see immutability)
2. I don't understand why your createNewCircle has newR parameter and at the same time you generate a random newRadius in the first line. One of these definitely should be removed. Given that the parameter is always a constant 135 I think it should be removed.
3. Now I believe the main bug in your translation is in the lines
int newCirX = (int) newX;
int newCirY = (int) newY;
It probably should be something like
int newCirX = (int) newX - newRadius;
int newCirY = (int) newY - newRadius;
It looks like you messed with center vs top-left. Actually I think the fact that you made such a bug is an argument that supports renaming x and y I suggested in item #1.
Related
I am creating a Bullet projectile and giving it a Binding Circle with it. I am trying to set the circle to be at the front of the bullet so when it impacts it collides. Below is the bullet and a blue circle displaying the bounding circle location.
The bottom right example is what I am looking todo but with any rotation. Any thoughts on how I can offset the circle dynamically?
HitBox.java (This is the blue circle)
package com.icyrelic.game.object;
import com.icyrelic.game.object.entity.Entity;
import com.jogamp.opengl.math.VectorUtil;
import lombok.Getter;
import lombok.Setter;
public class HitBox {
#Getter
private GameObject object;
#Getter #Setter
private float width = 0, height = 0, xOffset = 0f, yOffset = 0f, radius = 0;
public HitBox(GameObject object, float width, float height) {
this.object = object;
this.width = width;
this.height = height;
}
public HitBox(GameObject entity, float radius) {
this.object = object;
this.radius = radius;
}
public boolean intersects(HitBox b) {
boolean collisionX = getMinX() <= b.getMaxX() && getMaxX() >= b.getMinX();
boolean collisionY = getMinY() <= b.getMaxY() && getMaxY() >= b.getMinY();
return collisionX && collisionY;
}
public boolean willCollide(HitBox b, float x, float y) {
//Circle vs Circle
if(radius != 0 && b.getRadius() != 0)
return circleCollide(x, y, b.getRadius(), b.getXOffset(), b.getYOffset());
//Circle vs AABB
if((radius != 0 && b.getRadius() == 0) || (radius == 0 && b.getRadius() != 0))
return circleAABBCollusion(b, x, y);
//AABB vs AABB
boolean collisionX = getMinX() <= x+b.getWidth()/2 && getMaxX() >= x-b.getWidth()/2;
boolean collisionY = getMinY() <= y+b.getHeight()/2 && getMaxY() >= y-b.getHeight()/2;
return collisionX && collisionY;
}
private boolean circleCollide(float x2, float y2, float radius2, float xOffset2, float yOffset2) {
double xDif = (object.getLocation().getX() + xOffset) - (x2 + xOffset2);
double yDif = (object.getLocation().getY() + yOffset) - (y2 + yOffset2);
double distanceSquared = xDif * xDif + yDif * yDif;
return distanceSquared < (radius + radius2) * (radius + radius2);
}
private boolean circleAABBCollusion(HitBox b, float x, float y) {
HitBox circle = radius == 0 ? b : this;
HitBox aabb = radius == 0 ? this : b;
float[] circleCenter = radius == 0 ? new float[] {x, y} : new float[] {object.getLocation().getX(), object.getLocation().getY()};
float[] aabbCenter = radius == 0 ? new float[] {object.getLocation().getX(), object.getLocation().getY()} : new float[] {x, y};
float closestX = circleCenter[0] + circle.getXOffset();
float closestY = circleCenter[1] + circle.getYOffset();
if(closestX < aabb.getMinX(aabbCenter[0])) closestX = aabb.getMinX(aabbCenter[0]);
else if (closestX > aabb.getMaxX(aabbCenter[0])) closestX = aabb.getMaxX(aabbCenter[0]);
if(closestY < aabb.getMinY(aabbCenter[1])) closestY = aabb.getMinY(aabbCenter[1]);
else if (closestY > aabb.getMaxY(aabbCenter[1])) closestY = aabb.getMaxY(aabbCenter[1]);
float dist = VectorUtil.distSquareVec3(new float[]{circleCenter[0]+circle.getXOffset(), circleCenter[1]+circle.getYOffset(), 1}, new float[]{closestX, closestY, 1});
return dist <= circle.getRadius() * circle.getRadius();
}
private float getMinX() { return object.getLocation().getX()+xOffset - width/2; }
private float getMaxX() { return object.getLocation().getX()+xOffset + width/2; }
private float getMinY() { return object.getLocation().getY()+yOffset - height/2; }
private float getMaxY() { return object.getLocation().getY()+yOffset + height/2;}
private float getMinX(float x) { return x+xOffset - width/2; }
private float getMaxX(float x) { return x+xOffset + width/2; }
private float getMinY(float y) { return y+yOffset - height/2; }
private float getMaxY(float y) { return y+yOffset + height/2;}
public void setSize(float width, float height) { this.width = width; this.height = height; }
public void setOffset(float x, float y) { this.xOffset = x; this.yOffset = y; }
}
Bullet.java
package com.icyrelic.game.object.projectile.type;
import com.icyrelic.game.Graphics.Animation;
import com.icyrelic.game.Graphics.ImageResource;
import com.icyrelic.game.object.projectile.Projectile;
public class Bullet extends Projectile {
public Bullet(float x, float y, float width, float height, float rotation, float rotationOffset) {
super(x,y,width, height, rotation, rotationOffset);
hitBox.setRadius(0.03f);
hitBox.setYOffset(-0.12f);
location.setRotationOffset(-0f);
animations = new Animation[1];
ImageResource[] a = new ImageResource[1];
a[0] = new ImageResource("/Projectile/Bullet.png");
animations[0] = new Animation(a, 1);
}
#Override
public void update() {
//location.setRotation(0);
}
}
Projectile.java
package com.icyrelic.game.object.projectile;
import com.icyrelic.game.Graphics.Graphics;
import com.icyrelic.game.object.GameObject;
import com.icyrelic.game.object.HitBox;
import lombok.Getter;
#Getter
public abstract class Projectile extends GameObject {
protected float speed = 1.0f;
protected HitBox hitBox;
public Projectile(float x, float y, float width, float height, float rotation, float rotationOffset) {
super(x, y, width, height, rotation, rotationOffset);
this.hitBox = new HitBox(this, width, height);
}
#Override
public void render() {
super.render();
Graphics.setColor(0,0, 1, 1);
if(hitBox.getRadius() == 0) {
Graphics.drawRect(location.getX() + hitBox.getXOffset(), location.getY() + hitBox.getYOffset(), hitBox.getWidth(), hitBox.getHeight(), false);
} else {
Graphics.drawHollowCircle(location.getX() + hitBox.getXOffset(), location.getY() + hitBox.getYOffset(), hitBox.getRadius());
}
Graphics.setColor(1,0, 0, 1);
//Graphics.drawRect(location.getX(), location.getY(), width/2, height/2, false);
Graphics.setColor(1,1, 1, 1);
Graphics.setColor(1,1, 1, 1);
}
}
GameObject.java
package com.icyrelic.game.object;
import com.icyrelic.game.Graphics.Animation;
import com.icyrelic.game.Graphics.Graphics;
import com.icyrelic.game.world.Location;
import lombok.Getter;
#Getter
public abstract class GameObject {
protected Location location;
protected float width = 1, height = 1;
protected float xImageOffset = 0, yImageOffset = 0;
protected Animation[] animations;
protected int currentAnimation = 0;
public GameObject(float x, float y, float width, float height, float rotation, float rotationOffset) {
this.location = new Location(x, y, rotation, rotationOffset);
this.width = width;
this.height = height;
}
public void render () {
animations[currentAnimation].play();
Graphics.setRotation(location.getRotation() + location.getRotationOffset());
Graphics.drawImage(animations[currentAnimation].getImage(), location.getX(), location.getY(), xImageOffset, yImageOffset, width, height);
Graphics.setRotation(0);
//Graphics.setRotation(-rotation);
}
public abstract void update ();
}
After trying to translate the information provided by Alberto I have the following result. its somewhat closer in the right direction but still not 100%
hitBox.setXOffset(((float) Math.sin(location.getRotationRadians()) ));
hitBox.setYOffset(((float) Math.cos(location.getRotationRadians()) ));
Since
Graphics.drawHollowCircle(location.getX() + hitBox.getXOffset(), location.getY() + hitBox.getYOffset(), hitBox.getRadius());
Is always drawing at the bottom, this
Graphics.drawHollowCircle(location.getX() + hitBox.getXOffset(), location.getY() + hitBox.getYOffset() / 2, hitBox.getRadius());
Should draw the circle in the center... then using some trigonometry, to get the center of the circle you will have to do something like this:
float offsetX = Math.sin(location.getRotation()) * (hitBox.getYOffset() / 2);
float offsetY = Math.cos(location.getRotation()) * (hitBox.getYOffset() / 2);
Graphics.drawHollowCircle(location.getX() + offsetX, location.getY() + offsetY, hitBox.getRadius());
assuming location.getRotation() will return the radiants to rotate
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
Well since you folks helped me a lot with my last project, I thought I might find some assistance with the current one :)
The project has us practicing recursion and objects (just started learning about the latter). So we first create a "BasicStar", later a "Snowflake", then comes the "SuperSnowflake" and finally the dreaded "KochCurve".
So I the "BasicStar" was quite easy, and now the idea of the "Snowflake" is to recursively draw "BasicStar"s with smaller radiuses. I have uploaded three images (basic star, which I did successfully, snowflake the way it should be, and my snowflake) so it's easy to understand what I mean. My recursive method draws something very different, and I have no idea what I'm doing wrong. Any help would be great.
Thanks!
(P.S. The Main and Painter classes were made by the university faculty so even if there are things to improve there it won't be relevant. The rest was written by myself)
Main:
package recursion;
import java.util.Scanner;
/*
* the class main get from the user the shape he wish to draw,
* and call the drew method of the desired shape .
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter the number of the shape you wish to draw:\n" +
" 1-example\n" +
" 2-BasicStar\n" +
" 3-Snowflake\n" +
" 4-SuperSnowflake\n" +
" 5-KochCurve\n" +
" 6-KochSnowflake\n");
int shape = sc.nextInt();
// chooses which shape to draw based on the number received
switch(shape){
/*
* An example given to you so you can see how the painted works.
* This example opens a frame, and draws a red line.
*/
case 1:
drawExample();
break;
case 2:
drawBasicStar();
break;
case 3:
drawSnowflake();
break;
case 4:
drawSuperSnowflake();
break;
case 5:
drawKochCurve();
break;
case 6:
drawKochSnowflake();
break;
default: System.out.println("invalid shape");
}
sc.close();
}
// Draw the example line
public static void drawExample(){
Painter.draw("example");
}
// Draw a BasicStar
public static void drawBasicStar(){
Painter.draw("BasicStar");
}
// Draw a Snowflake
public static void drawSnowflake(){
Painter.draw("Snowflake");
}
// Draw a SuperSnowflake
public static void drawSuperSnowflake(){
Painter.draw("SuperSnowflake");
}
// Draw a KochCurve
public static void drawKochCurve(){
Painter.draw("KochCurve");
}
// Draw a KochSnowflake
public static void drawKochSnowflake(){
Painter.draw("KochSnowflake");
}
}
Painter:
package recursion;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
/*
* open a frame named aShape and drew the given shape
*/
public class Painter extends Component {
private static final long serialVersionUID = 1L;
private static int SIZE = 600;
private static Painter painter;
private static Graphics g;
private static String shape = null;
// Create a frame and display it
public static void draw(String aShape) {
shape = aShape;
JFrame frame = new JFrame(shape);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
painter = new Painter();
frame.add(painter, null);
frame.pack();
frame.setVisible(true);
}
// returns the Frame's width
public static int getFrameWidth () {
return painter.getSize().width;
}
// returns the Frame's height
public static int getFrameHeight () {
return painter.getSize().height;
}
// changes the color of the lines to be drawn
public static void setColor (String color) {
if (color.equals("red")){
g.setColor(Color.red);
}
else if (color.equals("blue")){
g.setColor(Color.blue);
}
else if (color.equals("green")){
g.setColor(Color.green);
}
}
public static void drawLine (Pixel p1, Pixel p2) {
drawLine((int)Math.round(p1.getX()),(int)Math.round(p1.getY()),(int)Math.round(p2.getX()),(int)Math.round(p2.getY()));
}
// Draw a line on the frame
public static void drawLine (int x1, int y1, int x2, int y2) {
g.drawLine(x1, getFrameHeight()-y1, x2, getFrameHeight()-y2);
}
// Set the default size of the window frame to SIZE*SIZE pixels
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
// paint the frame - draw the shape given (call the draw method in that shape object)
public void paint(Graphics g) {
Painter.g = g;
try{
Object myShape = (Class.forName("recursion." + shape)).newInstance();
Object [] objs = null;
Class [] classes = null;
(Class.forName("recursion." + shape)).getMethod("draw", classes).invoke(myShape, objs);
}
catch(Exception e)
{
System.out.println("Can't handle shape " + shape);
System.out.println(e.toString());
System.out.println(e.getCause());
}
}
}
Pixel:
package recursion;
public class Pixel {
private double x;
private double y;
public Pixel(){
x = 0;
y = 0;
}
public Pixel(double x, double y){
this.x = x;
this.y = y;
}
public Pixel(Pixel center){
this();
if(center != null){
this.x = center.x;
this.y = center.y;
}
}
public double getX(){
return x;
}
public double getY(){
return y;
}
public void translate(Pixel p){
this.x = this.x + p.x;
this.y = this.y + p.y;
}
public void rotateRelativeToAxesOrigin(double theta){
double tempX = this.x;
double tempY = this.y;
this.x = ((tempX)*(Math.cos(theta)) - ((tempY)*(Math.sin(theta))));
this.y = ((tempX)*(Math.sin(theta)) - ((tempY)*(Math.cos(theta))));
}
public void rotateRelativeToPixel(Pixel p1, double theta){
double tempX = this.x;
double tempY = this.y;
Pixel translatedPixel = new Pixel(tempX-p1.getX(), tempY-p1.getY());
translatedPixel.rotateRelativeToAxesOrigin(theta);
this.x = translatedPixel.getX() + p1.getX();
this.y = translatedPixel.getY() + p1.getY();
}
}
BasicStar:
package recursion;
public class BasicStar {
private Pixel center;
private double radius;
public BasicStar(){
double height = Painter.getFrameHeight()/2;
double width = Painter.getFrameWidth()/2;
this.center = new Pixel (width, height);
double maxRadius = Math.min(width, height)/2;
this.radius = maxRadius/4;
}
public BasicStar(Pixel center, double radius){
this.center = new Pixel(center);
this.radius = radius;
}
public Pixel getCenter(){
return new Pixel(center);
}
public double getRadius(){
return this.radius;
}
public void draw(){
Pixel begin = new Pixel(this.center);
Pixel end = new Pixel(center.getX() + getRadius(), center.getY());
Painter.drawLine(begin, end);
end.rotateRelativeToPixel(center, (2*Math.PI)/6);
Painter.drawLine(begin, end);
end = new Pixel(center.getX() + getRadius(), center.getY());
end.rotateRelativeToPixel(center, (4*Math.PI)/6);
Painter.drawLine(begin, end);
end = new Pixel(center.getX() + getRadius(), center.getY());
end.rotateRelativeToPixel(center, (6*Math.PI)/6);
Painter.drawLine(begin, end);
end = new Pixel(center.getX() + getRadius(), center.getY());
end.rotateRelativeToPixel(center, (8*Math.PI)/6);
Painter.drawLine(begin, end);
end = new Pixel(center.getX() + getRadius(), center.getY());
end.rotateRelativeToPixel(center, (10*Math.PI)/6);
Painter.drawLine(begin, end);
}
}
Snowflake:
package recursion;
public class Snowflake {
private BasicStar basic;
private int depth;
public Snowflake(){
double height = Painter.getFrameHeight()/2;
double width = Painter.getFrameWidth()/2;
Pixel center = new Pixel (width, height);
double maxRadius = Math.min(width, height)/2;
double radius = maxRadius/4;
this.basic = new BasicStar(center, radius);
this.depth = 2;
}
public Snowflake(BasicStar basic, int depth){
this();
if(basic!=null){
this.basic = basic;
this.depth = depth;
}
}
public int getDepth(){
return this.depth;
}
public BasicStar getBasic(){
return this.basic;
}
public double getRadius(BasicStar basic){
return this.basic.getRadius();
}
public Pixel getBasicCenter(BasicStar basic){
return this.basic.getCenter();
}
public void draw(){
draw(this.depth, basic.getCenter(), basic.getRadius());
}
private void draw(int depth, Pixel center, double radius){
BasicStar basic = new BasicStar(center, radius);
if(depth==1){
basic.draw();
}
else{
Pixel p = new Pixel(center.getX() + radius, center.getY());
draw(depth - 1, p, (radius/3));
for(int i=0; i<6; i=i+1){
p.rotateRelativeToPixel(center, (2*Math.PI)/6);
BasicStar temp = new BasicStar(p, radius/3);
temp.draw();
}
}
}
}
This looks overly complicated to me. To be honest, I did not read all your code, but you can create a simple recursive function for drawing a snowflake just like this:
public void drawSnowflake(Graphics g, int x, int y, int size, int level) {
for (int a = 0; a < 360; a += 60) {
double rad = a * Math.PI / 180;
int x2 = (int) (x + Math.cos(rad) * size);
int y2 = (int) (y + Math.sin(rad) * size);
g.drawLine(x, y, x2, y2);
if (level > 0) {
drawSnowflake(g, x2, y2, size/3, level-1);
}
}
}
What this code does is: It draws the lines of a star using basic trigonometry (don't forget to convert angles to radians!), and then calls itself with a smaller size and level for the positions at the ends of the spikes. Embedding this into an actual GUI is left as an excercise to the reader.
I'm working on a lab for school and I have it almost completed, but there's one part that I can't get to work. The inheritance works except when I get to Cube. For some reason, it won't calculate the Area or Volume (it just comes up with 0). I'm thinking it's a problem with the way I have the inheritance from Square to Cube. Help would be awesome!
package InheritanceTest;
import javax.swing.JOptionPane;
public class InheritanceTest {
public static void main(String[] args) {
String input = "";
Point point = new Point();
input = getinput("Set variable X");
point.setx(input);
input = getinput("Set variable Y");
point.sety(input);
System.out.println("Point, x = " + point.getx() + " y = " + point.gety());
Square square = new Square();
input = getinput("Set variable Side Length");
square.setSideLength(input);
System.out.println("Square, x = " + point.getx() + " y = " + point.gety()
+ " Area = " + square.getAreaOfSquare() + " Perimeter = "
+ square.getPerimeterOfSquare());
Cube cube = new Cube();
input = getinput("Set variable depth");
cube.setDepth(input);
System.out.println("cube, x = " + point.getx() + " y = " + point.gety()
+ " Depth = " + cube.getDepth() + " Area = " + cube.getAreaOfCube()
+ " Volume = " + cube.getVolumeOfCube());
}
private static String getinput(String string) {
String x = JOptionPane.showInputDialog(string);
return x;
}
}
package InheritanceTest;
public class Cube extends Square {
private int depth;
Cube() {
super();
depth = 0;
}
Cube(int x, int y, int sideLength, int d) {
super(x, y, sideLength);
this.depth = d;
}
public int getAreaOfCube() {
return (6 * sideLength * sideLength);
}
public int getVolumeOfCube() {
return (sideLength * sideLength * sideLength);
}
public String getDepth() {
return Integer.toString(depth);
}
public void setDepth(String i) {
depth = Integer.parseInt(i);
}
}
package InheritanceTest;
public class Point {
private int x;
private int y;
Point() {
x = 0;
y = 0;
}
Point(int x, int y) {
this.x = x;
this.y = y;
}
public String getx() {
return Integer.toString(x);
}
public String gety() {
return Integer.toString(y);
}
public void setx(String input) {
x = Integer.parseInt(input);
}
public void sety(String input) {
y = Integer.parseInt(input);
}
}
package InheritanceTest;
public class Square extends Point {
protected int sideLength;
Square() {
super();
sideLength = 0;
}
Square(int x, int y, int l) {
super(x, y);
this.sideLength = l;
}
public int getAreaOfSquare() {
return sideLength * sideLength;
}
public int getPerimeterOfSquare() {
return sideLength + sideLength;
}
public String getSideLength() {
return Integer.toString(sideLength);
}
public void setSideLength(String input) {
sideLength = Integer.parseInt(input);
}
}
When you create cube (new Cube()) you aren't setting the side length (or x and y) for the Square Object it extends.
Cube(){
// This is the constructor called.
super();
depth = 0;
}
Cube(int x, int y, int sideLength, int d){
super(x, y, sideLength);
this.depth = d;
}
You probably want extract the x,y and length values into variables and use "new Cube(x, y, length, depth)"
Something like the following
String x = getinput("Set variable X");
String y = getinput("Set variable Y");
String sideLength = getinput("Set variable Side Length");
String depth getinput("Set variable depth");
Cube cube = new Cube(x, y, sideLength, depth);
Look at how you are defining getVolumeOfCube(). You are calculating volume with sideLength, but you never set sideLength to any non-zero value. Change sideLength to depth and you will get the value you are looking for.
I noticed that one of my methods is being very slow, with profiling I noticed it took up like 95% of the total execution time.
The class:
package gui;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
/**
*
* #author Frank
*/
public abstract class CustomRectangle {
protected final BufferedImage bufferedImage;
protected final int width;
protected final int height;
protected final int xOffset;
protected final int yOffset;
protected final int borderSize;
protected final boolean defaultOrientation;
protected Color color;
public CustomRectangle(final BufferedImage bufferedImage, final int width, final int height, final int xOffset, final int yOffset, final int borderSize, final boolean defaultOrientation) {
this.bufferedImage = bufferedImage;
this.width = width;
this.height = height;
if (defaultOrientation) {
this.xOffset = xOffset;
this.yOffset = yOffset;
}
else {
this.xOffset = bufferedImage.getWidth() - 1 - xOffset;
this.yOffset = bufferedImage.getHeight() - 1 - yOffset;
}
this.borderSize = borderSize;
this.defaultOrientation = defaultOrientation;
}
abstract public void inBorder(final int dx, final int dy);
abstract public void outBorder(final int dx, final int dy);
public void draw() {
if (defaultOrientation) {
drawDefaultOrientation();
}
else {
drawOppositeOrientation();
}
}
private void drawDefaultOrientation() {
int[] pixelArray = ((DataBufferInt)bufferedImage.getRaster().getDataBuffer()).getData();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int dx = Math.min(x, width - 1 - x);
int dy = Math.min(y, height - 1 - y);
if (dx < borderSize || dy < borderSize) {
inBorder(dx, dy);
}
else {
outBorder(dx, dy);
}
pixelArray[(xOffset + x) + ((yOffset + y) * bufferedImage.getWidth())] = color.getRGB();
}
}
}
private void drawOppositeOrientation() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int dx = Math.min(x, width - 1 - x);
int dy = Math.min(y, height - 1 - y);
if (dx < borderSize || dy < borderSize) {
inBorder(dx, dy);
}
else {
outBorder(dx, dy);
}
bufferedImage.setRGB(xOffset - x, yOffset - y, color.getRGB());
}
}
}
public void setColor(final Color color) {
this.color = color;
}
}
The slow method is the drawDefaultOrientation() method.
The scary part however is that even if I leave out all image-modifying code, then it is still slow.
The callee code:
new CustomRectangle(bufferedImage, 440, 180, 30, 490, 10, defaultOrientation) {
#Override
public void inBorder(final int dx, final int dy) {
setColor(new Color(red, green, blue, 255 - (int)Math.round(0.5 * Math.min(dx, dy))));
}
#Override
public void outBorder(final int dx, final int dy) {
setColor(new Color(red, green, blue, 128 - (int)Math.round(0.5 * Math.min(dx, dy))));
}
}.draw();
There must be something going on as in any way this code should not take this long, even if it loops over x and y coordinates.
Some thought I had was that it could have to do with the Anonymous inner class + Override...
But hopefully someone with more knowledge can answer the question.
Try this: If red, green, blue don't change, then stop using an anonymous class, and in your implemented subclass do: (note, this might not work, but the basic idea should, if you can avoid constantly calling new Color by caching all the colors you might need)
private final Color[] colors;
public ImplementedCustomRectangle(...) {
super(...); // ... is not real code, I just don't want to copy/paste
colors = new Color[256];
for (i = 0; i < 256; i++) {
colors[i] = new Color(red, green, blue, i);
}
}
#Override
public void inBorder(final int dx, final int dy) {
int value = 255 - (int)Math.round(0.5 * Math.min(dx, dy));
setColor(colors[value]);
}
#Override
public void outBorder(final int dx, final int dy) {
int value = 128 - (int)Math.round(0.5 * Math.min(dx, dy);
setColor(colors[value]);
}
I have a two image that moves in a random direction. Now, if that images would bump each other I want it to disappear and that is my problem about making a collision detection. Could someone help me about this problem?
Here is the code:
public class HumanBeing extends Sprite implements ImageObserver
{
private java.awt.Image humanImage;
private final World world;
private double x;
private double y;
private double speed;
private double direction = 1;
private java.util.List<Sprite> objects = new ArrayList<Sprite>();
private double angle;
public HumanBeing(World world, double x, double y, double speed)
{
this.world =world;
this.x = x;
this.y = y;
this.speed = convertToMeterPerSecond(speed);
URL iU = this.getClass().getResource("human.jpg");
ImageIcon icon = new ImageIcon(iU);
humanImage = icon.getImage();
objects.add(this);
}
public Image getImage()
{
return humanImage;
}
#Override
public void move(long dt)
{
double dt_s = dt / 1e9;
double dx_m = speed * dt_s * Math.sin(angle);
double dy_m = speed * dt_s * Math.cos(angle);
final double right_wall = world.x1_world;
final double up_wall = world.y1_world;
final double down_wall = 0.0;
final double left_wall = 0.0;
x += dx_m;
y += dy_m;
if (x >= right_wall)
{
setRandomDirection();
}
if (y > up_wall)
{
setRandomDirection();
}
if (x <= left_wall)
{
setRandomDirection();
}
if (y < down_wall)
{
setRandomDirection();
}
}
public void setRandomDirection()
{
HumanBeing humanbeing = this;
humanbeing.setAngle(Math.PI * 2 * Math.random());
}
#Override
public void render(Graphics2D g2d)
{
AffineTransform t = g2d.getTransform();
final double humanHeight = 1.6;// meter
final double humanWidth = 1.8; //meter
final double foot_position_y = humanHeight;
final double foot_position_x = humanWidth / 2;
int xx = world.convertToPixelX(x - foot_position_x); // to find the upper-left corner
int yy = world.convertToPixelY(y + foot_position_y); // to find the upper-left corner
g2d.translate(xx, yy);
// ratio for actual Image size
double x_expected_pixels = humanHeight * board.meter;
double y_expected_pixels = humanWidth * board.meter;
double w = ((ToolkitImage) humanImage).getWidth();
double h = ((ToolkitImage) humanImage).getHeight();
double x_s = x_expected_pixels / w;
double y_s = y_expected_pixels / h;
g2d.scale(x_s, y_s);
g2d.drawImage(getImage(), 0, 0, this); // upper left corner
g2d.setColor(Color.BLACK);
g2d.setTransform(t);
}
#Override
public void moveAt(double distance_x, double distance_y)
{
this.x = distance_x;
this.y = distance_y;
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
return false;
}
public void setAngle(double angle)
{
this.angle = angle;
}
}
this is my HumanBeing class
public class Chicken extends Sprite implements ImageObserver
{
private java.awt.Image chickenImage;
private final World world;
private double x;
private double y;
private double speed;
private double angle;
public Chicken(World world, double x, double y, double speed)
{
this.world = world;
this.x = x;
this.y = y;
this.speed = convertToMeterPerSecond(speed);
URL iU = this.getClass().getResource("chicken.gif");
ImageIcon icon = new ImageIcon(iU);
chickenImage = icon.getImage();
}
public Image getImage()
{
return chickenImage;
}
public void move(long dt)
{
double dt_s = dt / 1e9;
double dx_m = speed * dt_s * Math.sin(angle);
double dy_m = speed * dt_s * Math.cos(angle);
final double right_wall = world.x1_world;
final double up_wall = world.y1_world;
final double down_wall = 0.0;
final double left_wall = 0.0;
x += dx_m;
y += dy_m;
if (x >= right_wall)
{
x = right_wall;
setRandomDirection();
}
if (y > up_wall)
{
y = up_wall;
setRandomDirection();
}
if (x <= left_wall)
{
x = left_wall;
setRandomDirection();
}
if (y < down_wall)
{
y = down_wall;
setRandomDirection();
}
}
public void setRandomDirection()
{
Chicken chicken = this;
chicken.setAngle(Math.PI * 2 * Math.random());
}
#Override
public void render(Graphics2D g2d)
{
AffineTransform t = g2d.getTransform();
double height = 0.3; //meter
double width = 0.3; //meter
double chicken_footy = height;
double chicken_footx = width/2;
int xx = world.convertToPixelX(x - chicken_footx);
int yy = world.convertToPixelY(y + chicken_footy);
g2d.translate(xx, yy);
double x_expected_pixels = width * board.meter;
double y_expected_pixels = height * board.meter;
double x_s = x_expected_pixels / ((ToolkitImage) chickenImage).getWidth();
double y_s = y_expected_pixels / ((ToolkitImage) chickenImage).getHeight();
g2d.scale(x_s, y_s);
g2d.drawImage(getImage(), 0, 0, this);
g2d.setColor(Color.BLACK);
g2d.setTransform(t);
}
public void moveAt(double distance_x, double distance_y)
{
this.x = (int) distance_x;
this.y = (int) distance_y;
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
return true;
}
public void setAngle(double angle)
{
this.angle = angle;
}
}
this is my chicken class
Draw invisible Rectangle around your sprites as like Box's and than use below method to check whether they are intersecting or not :)
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Rectangle.html#intersects(java.awt.Rectangle)
if(rect.intersect(anotherRect))
{
disappear();
}
Good luck