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
Related
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.
I am making a 2D top-down shooter in Java (uni project) but hit a problem with bullet aiming - I am unsure why the angle is incorrect, and how to correct it.
The player shoots bullets at the cursor location on mousedown. I am using dx/y = (x/ytarget - x/yorigin), normalising and incrementing the bullets x/y pos with dx each tick.
When the cursor is moved, the firing angle tracks the cursor - but the angle is off by 45 degrees or so The white circle is player, red is cursor and bullets the yellow dots.
I dont have rep to post images (first post), here is a link that shows the error of the angle.
http://i.imgur.com/xbUh2fX
Here is the bullet class:
note - update() is called by the main game loop
import java.awt.*;
import java.awt.MouseInfo;
public class Bullet {
private double x;
private double y;
private int r;
private double dx;
private double dy;
private double speed;
private double angle;
private Point c;
private Color color1;
public Bullet(int x, int y) {
this.x = x;
this.y = y;
r = 3;
speed = 30;
color1 = Color.YELLOW;
c = MouseInfo.getPointerInfo().getLocation();
// getting direction
dx = c.x - x;
dy = c.y - y;
double distance = Math.sqrt(dx*dx + dy*dy);
dx /= distance;
dy /= distance;
}
public boolean update() {
x += dx*speed;
y += dy*speed;
if(x < -r || x > GamePanel.WIDTH + r ||
y < -r || y > GamePanel.HEIGHT + r) {
return true;
}
return false;
}
public void draw(Graphics2D g) {
g.setColor(color1);
g.fillOval((int) (x - r), (int) (y - r), 2 * r, 2 * r);
}
}
I got a similar game and this is the code I used
import java.awt.Graphics2D;
import araccoongames.pongadventure.game.Entity;
import araccoongames.pongadventure.game.Game;
import araccoongames.pongadventure.game.MapLoader;
public class Ball extends Entity {
private float speed = 8;
private float speedx;
private float speedy;
private float degree;
public Ball(float posx, float posy, Game game) {
super(0, 0, game);
this.posx = posx;
this.posy = posy;
// posx = ball x position
// posy = ball y position
// game.input.MOUSEY = mouse y position
// game.input.MOUSEX = mouse x position
degree = (float) (270 + Math.toDegrees(Math.atan2(posy - game.input.MOUSEY, posx - game.input.MOUSEX))) % 360;
speedx = (float) (speed * Math.sin(Math.toRadians(degree)));
speedy = (float) (speed * Math.cos(Math.toRadians(degree)));
}
#Override
public void render(Graphics2D g) {
drawImage(game.texture.SPRITE[0][1], g);
}
#Override
public void update() {
posx += speedx;
posy -= speedy;
}
}
I have a point following the path of a circle, and at a determined time, I want that point to "break" off and travel along the tangent line. How do I find this? I've been told that the derivative is
x = -sin(time)
and
y = -sin(time)
(not sure if I understand the "time" part of what I was told), but I don't see how that is enough to get my point to travel along this line. Any tips? Here is what I have currently.
/*
Rotor draws circle for random period of time, then moves
in a straight direction for a random period of time, beginning a
new circle
*/
Rotor r;
float timer = 0;
boolean freeze = false;
void setup() {
size(1000, 600);
smooth();
noFill();
frameRate(60);
background(255);
timeLimit();
r = new Rotor(100, 100, random(40, 100));
}
void draw() {
timer = timer + frameRate/1000;
if(timer > timeLimit()) {
timer = 0;
timeLimit();
if(freeze == true) {
freeze = false;
} else {
freeze = true;
}
}
if(!freeze) {
r.drawRotor();
} else {
r.holdSteady();
}
}
float timeLimit() {
float timeLimit = random(100);
return timeLimit;
}
Rotor Class:
class Rotor {
color c;
int thickness;
float xPoint;
float yPoint;
float nXPoint;
float nYPoint;
float radius;
float angle = 0;
float centerX;
float centerY;
float pointSpeed = frameRate/100;
Rotor(float cX, float cY, float rad) {
c = color(0);
thickness = 1;
stroke(c);
strokeWeight(thickness);
centerX = cX;
centerY = cY;
radius = rad;
}
void drawRotor() {
angle = angle + pointSpeed;
xPoint = centerX + cos(angle) * radius;
yPoint = centerY + sin(angle) * radius;
ellipse(xPoint, yPoint, thickness, thickness);
strokeWeight(2);
ellipse(centerX, centerY, 5, 5);
}
void holdSteady() {
xPoint = -sin(angle);//need tangent of circle
yPoint = -cos(angle);
ellipse(xPoint, yPoint, 4, 4);
//then set new center x and y
}
void drawNewRotor(float cX, float cy, float rad) {
}
}
You can use tan()
int f =100;
size(300,300);
stroke(0);
translate(width/2, height/2);
for(int i = 0; i< 360; i++){
point(cos(radians(i))*f,sin(radians(i))*f);
point(f,tan(radians(i))*f);
point(tan(radians(i))*f,f);
}
I have an assignment that requires us to paint a tree of Pythagoras using recursion. The tree is started with the square ABCD and the points A and B are defined by mouse clicks. Everything seems to work until I get to the recursion where I can get either the left or right part of the tree to paint, but not both. I placed a comment where I believe I am running into problems.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class PythagorasTree extends JFrame
{
public static void main(String[] args)
{
new PythagorasTree();
}
PythagorasTree()
{
super("Pythagoras Tree");
setSize(800,800);
add("Center", new DrawingPanel());
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class DrawingPanel extends JPanel
{
Random random = new Random();
int centerX;
int centerY;
int clickCount = 0;
float pixelSize;
float rWidth = 10.0F;
float rHeight = 7.5F;
float red, green, blue;
Point a = new Point();
Point b = new Point();
Point c = new Point();
Point d = new Point();
Point e = new Point();
Point u = new Point();
DrawingPanel()
{
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent click)
{
clickCount++;
if (clickCount == 1)
{
a.x = fx(click.getX());
a.y = fy(click.getY());
repaint();
}
if (clickCount == 2)
{
b.x = fx(click.getX());
b.y = fy(click.getY());
repaint();
}
}
});
}
void initgr()
{
Dimension d = getSize();
int maxX = d.width - 1;
int maxY = d.height - 1;
pixelSize = Math.max(rWidth/maxX, rHeight/maxY);
centerX = maxX/2;
centerY = maxY/2;
}
int iX(float x){return Math.round(centerX + x/pixelSize);}
int iY(float y){return Math.round(centerY - y/pixelSize);}
float fx(int x){return (x - centerX) * pixelSize;}
float fy(int y){return (centerY - y) * pixelSize;}
public void paintComponent(Graphics g)
{
initgr();
super.paintComponent(g);
setBackground(Color.white);
g.setColor(Color.red);
if (clickCount == 1)
g.drawLine(iX(a.x), iY(a.y), iX(a.x), iY(a.y));
if (clickCount > 1)
drawTree(g,a,b);
}
public void drawTree(Graphics g, Point first, Point second)
{
float xSquared = (float) Math.pow((second.x-first.x),2);
float ySquared = (float) Math.pow((second.y-first.y),2);
float length = (float) Math.sqrt(xSquared + ySquared);
if ( length > .001)
{
u.x = second.x - first.x;
u.y = second.y - first.y;
a.x = first.x;
a.y = first.y;
b.x = second.x;
b.y = second.y;
d.x = first.x + (u.y * -1);
d.y = first.y + u.x;
c.x = d.x + u.x;
c.y = d.y + u.y;
e.x = d.x + .5F * (u.x + (u.y*-1));
e.y = d.y + .5F * (u.y + u.x);
Polygon square = new Polygon();
Polygon triangle = new Polygon();
square.addPoint(iX(a.x), iY(a.y));
square.addPoint(iX(b.x), iY(b.y));
square.addPoint(iX(c.x), iY(c.y));
square.addPoint(iX(d.x), iY(d.y));
red = random.nextFloat();
green = random.nextFloat();
blue = random.nextFloat();
g.setColor(new Color(red, green, blue));
g.fillPolygon(square);
triangle.addPoint(iX(c.x), iY(c.y));
triangle.addPoint(iX(d.x), iY(d.y));
triangle.addPoint(iX(e.x), iY(e.y));
red = random.nextFloat();
green = random.nextFloat();
blue = random.nextFloat();
g.setColor(new Color(red, green, blue));
g.fillPolygon(triangle);
/* Problem code is here, tree will draw Left or Right depending on which recursive call
* is first in the code, but will never reach the 2nd call.
*/
drawTree(g,d,e); //Draw tree left
drawTree(g,e,c); //Draw tree right
}
}
}
class Point
{
public float x;
public float y;
public Point()
{
}
}
It's time this question had an answer. The problem is with these member variable declarations:
Point c = new Point();
Point e = new Point();
And this code in drawTree():
drawTree(g,d,e); //Draw tree left
drawTree(g,e,c); //Draw tree right
Since c and e are a member variables, not local, they get modified by the first recursive call to drawTree(g, d, e) so by the time we make the second call to drawTree(g, e, c), it's no longer the same c and e we thought we had. The following rework of the code makes these local (clearly not as efficient GC-wise, but also not as buggy) as well as several other small modifications:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
class Point
{
public float x;
public float y;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
public Point() {
}
}
class DrawingPanel extends JPanel
{
Random random = new Random();
int clickCount = 0;
float pixelSize;
float rWidth = 10.0F;
float rHeight = 7.5F;
float red, green, blue;
Point a = new Point();
Point b = new Point();
Point center = new Point();
DrawingPanel()
{
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent click)
{
clickCount++;
if (clickCount == 1)
{
a.x = fx(click.getX());
a.y = fy(click.getY());
repaint();
}
else if (clickCount == 2)
{
b.x = fx(click.getX());
b.y = fy(click.getY());
repaint();
}
}
});
}
void initgr()
{
Dimension d = getSize();
int maxX = d.width - 1;
int maxY = d.height - 1;
pixelSize = Math.max(rWidth / maxX, rHeight / maxY);
center.x = maxX / 2;
center.y = maxY / 2;
}
int iX(float x){ return Math.round(center.x + x / pixelSize); }
int iY(float y){ return Math.round(center.y - y / pixelSize); }
float fx(int x){ return (x - center.x) * pixelSize; }
float fy(int y){ return (center.y - y) * pixelSize; }
public void paintComponent(Graphics g)
{
super.paintComponent(g);
initgr();
setBackground(Color.white);
if (clickCount == 1)
{
g.setColor(Color.red);
g.drawLine(iX(a.x), iY(a.y), iX(a.x), iY(a.y));
}
else if (clickCount > 1) {
drawTree(g, a, b);
}
}
public void drawTree(Graphics g, Point first, Point second)
{
double xSquared = Math.pow(second.x - first.x, 2);
double ySquared = Math.pow(second.y - first.y, 2);
if (Math.sqrt(xSquared + ySquared) < 0.01) {
return;
}
Point u = new Point(second.x - first.x, second.y - first.y);
Point d = new Point(first.x - u.y, first.y + u.x);
Point c = new Point(d.x + u.x, d.y + u.y);
Point e = new Point(d.x + 0.5F * (u.x - u.y), d.y + 0.5F * (u.y + u.x));
Polygon square = new Polygon();
square.addPoint(iX(first.x), iY(first.y));
square.addPoint(iX(second.x), iY(second.y));
square.addPoint(iX(c.x), iY(c.y));
square.addPoint(iX(d.x), iY(d.y));
red = random.nextFloat();
green = random.nextFloat();
blue = random.nextFloat();
g.setColor(new Color(red, green, blue));
g.fillPolygon(square);
Polygon triangle = new Polygon();
triangle.addPoint(iX(c.x), iY(c.y));
triangle.addPoint(iX(d.x), iY(d.y));
triangle.addPoint(iX(e.x), iY(e.y));
red = random.nextFloat();
green = random.nextFloat();
blue = random.nextFloat();
g.setColor(new Color(red, green, blue));
g.fillPolygon(triangle);
drawTree(g, d, e); // Draw tree left
drawTree(g, e, c); // Draw tree right
}
}
public class PythagorasTree extends JFrame
{
PythagorasTree()
{
super("Pythagoras Tree");
setSize(800, 800);
add("Center", new DrawingPanel());
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
new PythagorasTree();
}
}
OUTPUT
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