How can I detect the proximity between two images [duplicate] - java

I have two characters displayed in a game I am writing, the player and the enemy. defined as such:
public void player(Graphics g) {
g.drawImage(plimg, x, y, this);
}
public void enemy(Graphics g) {
g.drawImage(enemy, 200, 200, this);
}
Then called with:
player(g);
enemy(g);
I am able to move player() around with the keyboard, but I am at a loss when trying to detect a collision between the two. A lot of people have said to use Rectangles, but being a beginner I cannot see how I would link this into my existing code. Can anyone offer some advice for me?

I think your problem is that you are not using good OO design for your player and enemies. Create two classes:
public class Player
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
public class Enemy
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
Your Player should have X,Y,Width,and Height variables.
Your enemies should as well.
In your game loop, do something like this (C#):
foreach (Enemy e in EnemyCollection)
{
Rectangle r = new Rectangle(e.X,e.Y,e.Width,e.Height);
Rectangle p = new Rectangle(player.X,player.Y,player.Width,player.Height);
// Assuming there is an intersect method, otherwise just handcompare the values
if (r.Intersects(p))
{
// A Collision!
// we know which enemy (e), so we can call e.DoCollision();
e.DoCollision();
}
}
To speed things up, don't bother checking if the enemies coords are offscreen.

First, use the bounding boxes as described by Jonathan Holland to find if you may have a collision.
From the (multi-color) sprites, create black and white versions. You probably already have these if your sprites are transparent (i.e. there are places which are inside the bounding box but you can still see the background). These are "masks".
Use Image.getRGB() on the mask to get at the pixels. For each pixel which isn't transparent, set a bit in an integer array (playerArray and enemyArray below). The size of the array is height if width <= 32 pixels, (width+31)/32*height otherwise. The code below is for width <= 32.
If you have a collision of the bounding boxes, do this:
// Find the first line where the two sprites might overlap
int linePlayer, lineEnemy;
if (player.y <= enemy.y) {
linePlayer = enemy.y - player.y;
lineEnemy = 0;
} else {
linePlayer = 0;
lineEnemy = player.y - enemy.y;
}
int line = Math.max(linePlayer, lineEnemy);
// Get the shift between the two
x = player.x - enemy.x;
int maxLines = Math.max(player.height, enemy.height);
for ( line < maxLines; line ++) {
// if width > 32, then you need a second loop here
long playerMask = playerArray[linePlayer];
long enemyMask = enemyArray[lineEnemy];
// Reproduce the shift between the two sprites
if (x < 0) playerMask << (-x);
else enemyMask << x;
// If the two masks have common bits, binary AND will return != 0
if ((playerMask & enemyMask) != 0) {
// Contact!
}
}
Links: JGame, Framework for Small Java Games

You don't want to have the collision check code inside the painting code. The painting needs to be fast. Collision can go in the game loop. Therefore you need an internal representation of the objects independent of their sprites.

Here's the main class from my collision detection program.
You can see it run at: http://www.youtube.com/watch?v=JIXhCvXgjsQ
/**
*
* #author Tyler Griffin
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.GraphicsDevice.*;
import java.util.ArrayList;
import java.awt.Graphics;
import java.awt.geom.Line2D;
public class collision extends JFrame implements KeyListener, MouseMotionListener, MouseListener
{
ArrayList everything=new ArrayList<tile>();
int time=0, x, y, width, height, up=0, down=0, left=0, right=0, mouse1=0, mouse2=0;
int mouseX, mouseY;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice screen = environment.getDefaultScreenDevice();
DisplayMode displayMode = screen.getDisplayMode();
//private BufferStrategy strategy;
JLayeredPane pane = new JLayeredPane();
tile Tile;
circle Circle;
rectangle Rectangle;
textPane text;
public collision()
{
setUndecorated(screen.isFullScreenSupported());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
setResizable(false);
screen.setFullScreenWindow(this);
width=displayMode.getWidth();
height=displayMode.getHeight();
Circle=new circle(-(int)Math.round((double)height/7*2),-(int)Math.round((double)height/7*2),(int)Math.round((double)height/7*.85),this);
Rectangle=new rectangle(-(int)Math.round((double)height/7*1.5),-(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),this);
Tile=Circle;
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
text=new textPane(0,0,width,height,this);
everything.add(new circle((int)Math.round((double)width/100*75),(int)Math.round((double)height/100*15),(int)Math.round((double)width/100*10),this));
everything.add(new rectangle((int)Math.round((double)width/100*70),(int)Math.round((double)height/100*60),(int)Math.round((double)width/100*20),(int)Math.round((double)height/100*20),this));
//everything.add(new line(750,250,750,750,this));
/*everything.add(new line(width/700*419,height/700*68,width/700*495,height/700*345,this));
everything.add(new line(width/700*495,height/700*345,width/700*749,height/700*350,this));
everything.add(new line(width/700*749,height/700*350,width/700*549,height/700*519,this));
everything.add(new line(width/700*549,height/700*519,width/700*624,height/700*800,this));
everything.add(new line(width/700*624,height/700*800,width/700*419,height/700*638,this));
everything.add(new line(width/700*419,height/700*638,width/700*203,height/700*800,this));
everything.add(new line(width/700*203,height/700*800,width/700*279,height/700*519,this));
everything.add(new line(width/700*279,height/700*519,width/700*76,height/700*350,this));
everything.add(new line(width/700*76,height/700*350,width/700*333,height/700*345,this));
everything.add(new line(width/700*333,height/700*345,width/700*419,height/700*68,this));
everything.add(new line(width/950*419,height/700*68,width/950*624,height/700*800,this));
everything.add(new line(width/950*419,height/700*68,width/950*203,height/700*800,this));
everything.add(new line(width/950*76,height/700*350,width/950*624,height/700*800,this));
everything.add(new line(width/950*203,height/700*800,width/950*749,height/700*350,this));
everything.add(new rectangle(width/950*76,height/700*350,width/950*673,1,this));*/
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),(int)Math.round((double)width/1350*749),(int)Math.round((double)height/1000*350),this));
everything.add(new rectangle((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*673),1,this));
addKeyListener(this);
addMouseMotionListener(this);
addMouseListener(this);
}
public void keyReleased(KeyEvent e)
{
Object source=e.getSource();
int released=e.getKeyCode();
if (released==KeyEvent.VK_A){left=0;}
if (released==KeyEvent.VK_W){up=0;}
if (released==KeyEvent.VK_D){right=0;}
if (released==KeyEvent.VK_S){down=0;}
}//end keyReleased
public void keyPressed(KeyEvent e)
{
Object source=e.getSource();
int pressed=e.getKeyCode();
if (pressed==KeyEvent.VK_A){left=1;}
if (pressed==KeyEvent.VK_W){up=1;}
if (pressed==KeyEvent.VK_D){right=1;}
if (pressed==KeyEvent.VK_S){down=1;}
if (pressed==KeyEvent.VK_PAUSE&&pressed==KeyEvent.VK_P)
{
//if (paused==0){paused=1;}
//else paused=0;
}
}//end keyPressed
public void keyTyped(KeyEvent e){}
//***********************************************************************************************
public void mouseDragged(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
public void mouseMoved(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
//***********************************************************************************************
public void mousePressed(MouseEvent e)
{
if(e.getX()==0 && e.getY()==0){System.exit(0);}
mouseX=(e.getX()+x);
mouseY=(e.getY()+y);
if(Tile instanceof circle)
{
Circle.move(0-Circle.width, 0-Circle.height);
Circle.setBounds(Circle.x, Circle.y, Circle.width, Circle.height);
Tile=Rectangle;
}
else
{
Rectangle.move(0-Rectangle.width, 0-Rectangle.height);
Rectangle.setBounds(Rectangle.x, Rectangle.y, Rectangle.width, Rectangle.height);
Tile=Circle;
}
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
}
public void mouseReleased(MouseEvent e)
{
//run();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
//***********************************************************************************************
public void run()//run collision detection
{
while (this == this)
{
Tile.move(Tile.x + ((mouseX - (Tile.x + (Tile.width / 2))) / 10), Tile.y + ((mouseY - (Tile.y + (Tile.height / 2))) / 10));
//Tile.move((mouseX - Tile.width / 2), mouseY - (Tile.height / 2));
for (int i = 0; i < everything.size(); i++)
{
tile Temp = (tile) everything.get(i);
if (Temp.x < (Tile.x + Tile.width) && (Temp.x + Temp.width) > Tile.x && Temp.y < (Tile.y + Tile.height) && (Temp.y + Temp.height) > Tile.y)//rectangles collided
{
if (Temp instanceof rectangle)
{
if (Tile instanceof rectangle){rectangleRectangle(Temp);}
else {circleRectangle(Temp);}//Tile instanceof circle
}
else
{
if (Temp instanceof circle)
{
if (Tile instanceof rectangle) {rectangleCircle(Temp);}
else {circleCircle(Temp);}
}
else//line
{
if (Tile instanceof rectangle){rectangleLine(Temp);}
else{circleLine(Temp);}
}
}
}//end if
}//end for
try {Thread.sleep(16L);}
catch (Exception e) {}
Tile.setBounds(Tile.x, Tile.y, Tile.width, Tile.height);
//Rectangle.setBounds(x, y, width, height);
//Circle.setBounds(x, y, width, height);
repaint();
text.out=" ";
}//end while loop
}//end run
//***************************************special collision detection/handling functions************************************************
void rectangleRectangle(tile Temp)
{
int lapTop, lapBot, lapLeft, lapRight, small, scootX=0, scootY=0;
lapTop=(Temp.y+Temp.height)-Tile.y;
lapBot=(Tile.y+Tile.height)-Temp.y;
lapLeft=(Temp.x+Temp.width)-Tile.x;
lapRight=(Tile.x+Tile.width)-Temp.x;
small=999999999;
if (lapTop<small){small=lapTop; scootX=0; scootY=lapTop;}
if (lapBot<small){small=lapBot; scootX=0; scootY=lapBot*-1;}
if (lapLeft<small){small=lapLeft; scootX=lapLeft; scootY=0;}
if (lapRight<small){small=lapRight; scootX=lapRight*-1; scootY=0;}
Tile.move(Tile.x+scootX, Tile.y+scootY);text.out="collision detected!";
}
void circleRectangle(tile Temp)
{
if((Tile.x+Tile.width/2<=Temp.x+Temp.width && Tile.x+Tile.width/2>=Temp.x)||(Tile.y+Tile.height/2>=Temp.y && Tile.y+Tile.height/2<=Temp.y+Temp.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2<Temp.y){x=Temp.x+Temp.width; y=Temp.y;}
else if(Tile.x+Tile.width/2<Temp.x && Tile.y+Tile.height/2<Temp.y){x=Temp.x; y=Temp.y;}
else if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2>Temp.y+Temp.height){x=Temp.x+Temp.width; y=Temp.y+Temp.height;}
else {x=Temp.x; y=Temp.y+Temp.height;}
double distance = Math.sqrt(Math.pow(Tile.x+(Tile.width/2) - x, 2) + Math.pow(Tile.y+(Tile.height/2) - y, 2));
if((int)Math.round(distance)<Tile.height/2)
{
double normY = ((Tile.y+(Tile.height/2) - y) / distance);
double normX = ((Tile.x+(Tile.width/2) - x) / distance);
Tile.move(x-Tile.width/2+(int)Math.round(normX*((Tile.width/2))) , y-Tile.height/2+(int)Math.round(normY*((Tile.height/2))));text.out="collision detected!";
}
}
}
void rectangleCircle(tile Temp)
{
if((Temp.x+Temp.width/2<=Tile.x+Tile.width && Temp.x+Temp.width/2>=Tile.x)||(Temp.y+Temp.height/2>=Tile.y && Temp.y+Temp.height/2<=Tile.y+Tile.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){x=Tile.x+Tile.width; y=Tile.y;}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){x=Tile.x; y=Tile.y;}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){x=Tile.x+Tile.width; y=Tile.y+Tile.height;}
else {x=Tile.x; y=Tile.y+Tile.height;}
double distance = Math.sqrt(Math.pow(Temp.x+(Temp.width/2) - x, 2) + Math.pow(Temp.y+(Temp.height/2) - y, 2));
if((int)Math.round(distance)<Temp.height/2)
{
double normY = ((Temp.y+(Temp.height/2) - y) / distance);
double normX = ((Temp.x+(Temp.width/2) - x) / distance);
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
else {Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
}
}
}
void circleCircle(tile Temp)
{
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2)),2) + Math.pow((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2)), 2));
if((int)distance<(Tile.width/2+Temp.width/2))
{
double normX = ((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2))) / distance;
double normY = ((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2))) / distance;
Tile.move((Temp.x+(Temp.width/2))+(int)Math.round(normX*(Tile.width/2+Temp.width/2))-(Tile.width/2) , (Temp.y+(Temp.height/2))+(int)Math.round(normY*(Tile.height/2+Temp.height/2))-(Tile.height/2));text.out="collision detected!";
}
}
void circleLine(tile Temp)
{
line Line=(line)Temp;
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
int x1=0, y1=0, x2=Tile.x+(Tile.width/2), y2=Tile.y+(Tile.height/2);
x1=Tile.x+(Tile.width/2)-Line.height;//(int)Math.round(Line.xNorm*1000);
x2=Tile.x+(Tile.width/2)+Line.height;
if(Line.posSlope)
{
y1=Tile.y+(Tile.height/2)-Line.width;
y2=Tile.y+(Tile.height/2)+Line.width;
}
else
{
y1=Tile.y+(Tile.height/2)+Line.width;
y2=Tile.y+(Tile.height/2)-Line.width;
}
Point point=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
if (point.x < (Line.x + Line.width) && point.x > Line.x && point.y < (Line.y + Line.height) && point.y > Line.y)//line intersects within line segment
{
//if(point!=null){System.out.println(point.x+","+point.y);}
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - point.x,2) + Math.pow((Tile.y+(Tile.width/2)) - point.y, 2));
if((int)distance<Tile.width/2)
{
//System.out.println("hit");
double normX = ((Tile.x+(Tile.width/2)) - point.x) / distance;
double normY = ((Tile.y+(Tile.height/2)) - point.y) / distance;
Tile.move((point.x)+(int)Math.round(normX*(Tile.width/2))-(Tile.width/2) , (point.y)+(int)Math.round(normY*(Tile.height/2))-(Tile.height/2));text.out="collision detected!";
//System.out.println(point.x+","+point.y);
}
}
//new bullet(this, (int)Math.round(tryX), (int)Math.round(tryY));
}
void rectangleLine(tile Temp)
{
line Line=(line)Temp;
if(new Line2D.Double(Line.x1,Line.y1,Line.x2,Line.y2).intersects(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height)))
{
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if(Line.posSlope)//positive sloped line
{
//first we'll do the top left corner
int x1=Tile.x-Line.height;
int x2=Tile.x+Line.height;
int y1=Tile.y-Line.width;
int y2=Tile.y+Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom right corner
x1=Tile.x+Tile.width-Line.height;
x2=Tile.x+Tile.width+Line.height;
y1=Tile.y+Tile.height-Line.width;
y2=Tile.y+Tile.height+Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow((Tile.x+Tile.width) - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x-Tile.width,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
else//negative sloped lne
{
//first we'll do the top right corner
int x1=Tile.x+Tile.width-Line.height;
int x2=Tile.x+Tile.width+Line.height;
int y1=Tile.y+Line.width;
int y2=Tile.y-Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x + Tile.width - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom left corner
x1=Tile.x-Line.height;
x2=Tile.x+Line.height;
y1=Tile.y+Tile.height+Line.width;
y2=Tile.y+Tile.height-Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow(Tile.x - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x-Tile.width,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
}
}
public Point intersection(double x1, double y1, double x2, double y2,double x3, double y3, double x4, double y4)//I didn't write this. got it from http://www.ahristov.com/tutorial/geometry-games/intersection-lines.html (I altered it)
{
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
int x=(int)Math.round(xi);
int y=(int)Math.round(yi);
return new Point(x, y);
}
//***************************************************************************************
public static void main(String[] args)
{
final collision Collision=new collision();
Collision.run();
}//end main
}//end class

Since Java doesn't have an intersect function (really!?) you can do collision detection by simply comparying the X and Y, Width and Height values of the bounding boxes (rectangle) for each of the objects that could potentially collide.
So... in the base object of each colliding object... i.e. if your player and enemy have a common base you can put a simple Rectangle object called something like BoundingBox. If the common base is a built in Java class then you'll need to create a class that extends the build in class and have the player and enemy objects extend your new class or are instances of that class.
At creation (and each tick or update) you'll need to set the BoundingBox paremeters for both your player and enemy. I don't have the Rectangle class infront of me but its most likely something like X, Y, Width and finally Height. X and Y are that objects location in your game world. The width and height are self explanatory I think. They'll most likely come out from the right of the players location though so, if the X and Y were bothe at 0 and your Width and Height were both at 256 you wouldn't see anything because the character would be at the top left outside of the screen.
Anyways... to detect a collision, you'll want to compare the attributes of the player and enemy BoundingBoxes. So something like this...
if( Player.BoundingBox.X = Enemy.BoundingBox.X && If( Player.BoundingBox.Y = Enemy.BoundingBox.Y )
{
//Oh noes! The enemy and player are on top of eachother.
}
The logic can get sort of complicated but you'll need to compare the distances between each BoundingBox and compare locations.

Here's a useful of an open source game that uses a lot of collisions: http://robocode.sourceforge.net/
You may take a look at the code and complement with the answers written here.

is there a problem with:
Rectangle box1 = new Rectangle(100,100,100,100);
Rectangle box2 = new Rectangle(200,200,100,100);
// what this means is if any pixel in box2 enters (hits) box1
if (box1.contains(box2))
{
// collision occurred
}
// your code for moving the boxes
this can also be applied to circles:
Ellipse2D.Double ball1 = new Ellipse2D.Double(100,100,200,200);
Ellipse2D.Double ball2 = new Ellipse2D.Double(400,100,200,200);
// what this means is if any pixel on the circumference in ball2 touches (hits)
// ball1
if (ball1.contains(ball2))
{
// collision occurred
}
// your code for moving the balls
to check whether youve hit the edge of a screen you could use the following:
Rectangle screenBounds = jpanel.getBounds();
Ellipse2D.Double ball = new Ellipse2D.Double(100,100,200,200); // diameter 200
Rectangle ballBounds = ball.getBounds();
if (!screenBounds.contains(ballBounds))
{
// the ball touched the edge of the screen
}

Use a rectangle to surround each player and enemy, the height and width of the rectangles should correspond to the object you're surrounding, imagine it being in a box only big enough to fit it.
Now, you move these rectangles the same as you do the objects, so they have a 'bounding box'
I'm not sure if Java has this, but it might have a method on the rectangle object called .intersects() so you'd do if(rectangle1.intersectS(rectangle2) to check to see if an object has collided with another.
Otherwise you can get the x and y co-ordinates of the boxes and using the height/width of them detect whether they've intersected yourself.
Anyway, you can use that to either do an event on intersection (make one explode, or whatever) or prevent the movement from being drawn. (revert to previous co-ordinates)
edit: here we go
boolean
intersects(Rectangle r)
Determines whether or not this Rectangle and the specified
Rectangle intersect.
So I would do (and don't paste this code, it most likely won't work, not done java for a long time and I didn't do graphics when I did use it.)
Rectangle rect1 = new Rectangle(player.x, player.y, player.width, player.height);
Rectangle rect2 = new Rectangle(enemy.x, enemy.y, enemy.width, enemy.height);
//detects when the two rectangles hit
if(rect1.intersects(rect2))
{
System.out.println("game over, g");
}
obviously you'd need to fit that in somewhere.

No need to use rectangles ... compare the coordinates of 2 players constantly.
like
if(x1===x&&y1==y)
remember to increase the range of x when ur comparing.
if ur rectangle width is 30 take as if (x1>x&&x2>x+30)..likewise y

It's Java code for collision of two or more ImageViews not rectangles or other,use ImageViews Instead.
1.This code of Collision works every where in any views or layouts.
2.Add a timer to repeat it and to detect collision repeatedly.
3.It only works with views and layout.
if ((getLocationX(_v1) > (getLocationX(_v2) - ((_w2*3) + 40))) && (getLocationX(_v1) < (getLocationX(_v2) + ((_w2*3) +40)))){
if ((getLocationY(_v1) > (getLocationY(_v2) - ((_h2*3) + 40))) && (getLocationY(_v1) < (getLocationY(_v2) + ((_h2*3) +40)))){
showMessage("Collided");
}
}

Related

Remove enemy when bullet hits them

class Bullet {
float bulletX, bulletY;
float angle;
int x;
int y;
int score; // add a score variable
static final float BULLET_SPEED = 5; // define a constant for the bullet's speed
Bullet(float x, float y, float angle) {
this.bulletX = x;
this.bulletY = y;
this.angle = angle;
}
// Updates the position of the bullet based on its angle and speed.
void update() {
bulletX += cos(angle) * BULLET_SPEED;
bulletY += sin(angle) * BULLET_SPEED;
}
// Draws the bullet image on the screen.
void show() {
drawBullet();
}
// Draws the bullet image on the screen.
void drawBullet() {
image(Bulletimg, bulletX, bulletY);
Bulletimg.resize(30, 30);
}
//Returns true if the bullet is off screen, false otherwise.
boolean offScreen() {
return bulletX < 0 || bulletX > width || bulletY < 0 || bulletY > height;
}
//Checks if the bullet hits the enemy, and updates the score and enemy position accordingly.
// check for collision
void checkCollision(Enemy e) {
float distance = dist(bulletX, bulletY, e.x, e.y);
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
}
}
}
I tried changing around the check collision(enemy e) block and I'm not sure how i would go about removing an enemy object and also updating my score. i've tried messing about with the draw(); method but i cant seem to figure it out without breaking my entire game. any help with this class would be much appreciated.
You can use/create some attribute in your Enemy object to know/check if is alive or death.
For example in your check collision you can add
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
e.alive = false
}
Edit: I dont know how your manage the Enemy object and if it can be modified directly in the check collision method if this is not possible then you need to find a way to have access inside the method or use a return and manage that return outside.

How to make multiple objects move randomly?

I'm trying to make a sort of Agar.io clone in Processing. I have spawned in a lot of food dots, but I wanted to also make them move about and bounce off the edges of the screen border to add some flair. However I am not too sure how to go about making the dots all move about randomly.
ArrayList<Ellipse> ellipse = new ArrayList <Ellipse>();
//Images
PImage background;
int x = 2;
//Words
PFont arial;
void setup(){
size(1920,1080);
//Background change
if (x == 1){
background = loadImage("backdrop1.jpg");
}
if (x == 2){
background = loadImage("backdrop2.jpg");
}
//Creating the font
arial = createFont ("Arial", 16, true); //the true is for antialiasing
//Load from text file
//tbd...
//Adding the food ellipses
for(int foodSpawn = 0; foodSpawn < 50; foodSpawn++){
ellipse.add(new Ellipse(random(100,1820),random(100,980), 50, 50));
}
}
void draw(){
background(background);
for(int i = 0; i<ellipse.size(); i++){
Ellipse e = ellipse.get(i);
fill(#62C3E8);
ellipse(e.xLoc,e.yLoc, e.eWidth, e.eHeight);
}
}
class Ellipse {
float xLoc;
float yLoc;
float eWidth;
float eHeight;
public Ellipse(float xLoc, float yLoc, float eWidth, float eHeight){
this.xLoc = xLoc;
this.yLoc = yLoc;
this.eWidth = eWidth;
this.eHeight = eHeight;
}
}
The ellipses already have position attributes, so simply adding a method to move them should work. If you want them to collide realistically with the walls, you'll need to give each ellipse an initial random velocity. Then, you update the position at set time intervals based on the current velocity and the interval length. E.g.:
public void move() {
// Note: these are signed, and xvel and vyel are in pixels/second
float x_move_dist = this.xvel*time_int
float y_move_dist = this.yvel*time_int
// Update xloc
// Check collision with left wall
if (this.xloc + x_move_dist - this.eWidth/2 < 0) {
// Assuming conservation of momentum, we can reflect the movement off the wall
this.xloc = -(this.xloc + x_move_dist + this.eWidth/2)
}
// Check collision with right wall
else if (this.xloc + x_move_dist + this.eWidth/2 > 1920) {
// Again, reflect off wall
this.xloc = 1920 - ((this.xloc + x_move_dist) - 1920) - this.eWidth/2
}
// Otherwise, just update normally
else {
this.xloc = this.xloc + x_move_dist
}
// Update yloc
// Check collision with bottom wall
if (this.yloc + y_move_dist - this.eHeight/2 < 0) {
// Again, reflect off wall
this.yloc = -(this.yloc + y_move_dist) + this.eHeight/2
}
// Check collision with top wall
else if (this.yloc + y_move_dist + this.eHeight/2 > 1080) {
// Again, reflect off wall
this.yloc = 1920 - ((this.yloc + y_move_dist) - 1920) - this.eHeight/2
}
// Otherwise, just update normally
else {
this.yloc = this.yloc + y_move_dist
}
}

Error displaying bufferedImage repainting with mouse Listening

Im having difficulty drawing a Sub Image of a Buffered Image everytime the Mouse Pointer Location equals that of the each border of the JPanel. The problem is that the BufferedImage that is equals the SubImage wont display
Here is the JPanel the initialization might not be correct Im still learning the components of Java and 2D graphics.
public class Map extends JPanel implements MouseListener, MouseMotionListener {
private final int SCR_W = 800;
private final int SCR_H = 600;
private int x;
private int y;
private int dx;
private int dy;
String dir = "C:\\imgs\\war\\";
private BufferedImage map_buffer;
public BufferedImage scr_buffer;
public void initScreen(int x, int y, int stage){
if(stage == 0){
try{ map_buffer = ImageIO.read(new File(dir + "map" + stage + ".jpg" ));
}catch(Exception error) { System.out.println("Error: cannot read tileset image.");
}
}
scr_buffer = map_buffer.getSubimage(x, y, SCR_W, SCR_H);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(scr_buffer == null)
initScreen(x, y, 0);
g.drawImage(scr_buffer, 0, 0, this);
}
boolean isLeftBorder = false;
boolean isRightBorder = false;
boolean isTopBorder = false;
boolean isBottomBorder = false;
public Map(){
addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
/**
* Check location of mouse pointer if(specified_edge)move(scr_buffer)
*
*/
System.out.println("MouseMove: " + e.getPoint().getX() + " , " + e.getPoint().getY());
if(e.getPoint().getX() == SCR_W)isRightBorder = true;
if(e.getPoint().getY() == SCR_H)isBottomBorder = true;
if(e.getPoint().getX() == 0 && e.getPoint().getY() == SCR_H)isLeftBorder = true;
if(e.getPoint().getY() == 0 && e.getPoint().getX() == SCR_W)isTopBorder = true;
if(e.getPoint().getX() != 0 && e.getPoint().getX() != SCR_W
&& e.getPoint().getY() != 0 && e.getPoint().getY() != SCR_H){
isLeftBorder = false;
isRightBorder = false;
isTopBorder = false;
isBottomBorder = false;
}
if(isRightBorder){ x += 2; repaint(); }
if(isBottomBorder){ y -= 2; repaint(); }
if(isLeftBorder){ x -= 2; repaint();}
if(isTopBorder){ y += 2; repaint(); }
}
});
}
}
In the main I init a JFrame to contain the Panel all im getting is a error
public static void main(String[] args) {
JFrame f = new JFrame("War");
f.setSize(800, 600);
f.setLayout(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Map m = new Map();
f.getContentPane().add(f);
f.setVisible(true);
}
In order to detect mouse movement you should use a MosuseMotionListener, while technically MouseAdapter implements this, you need to register it with the JPanel correctly
Instead of using addMouseListener, you'll want to use addMouseMotionListener instead
I'd also be worried about the use of SRC_W and SRC_H, as you can't guarantee the size of the panel. Instead, you should be using getWidth and getHeight, which will tell you the actual size of the component
You can improve the chances of obtaining the size you want by overriding the getPreferredSize and return the size you would like. You'd then use pack on the frame to wrap the frame about it
f.getContentPane().add(f); is adding the frame to itself, it should probably be more like f.getContentPane().add(m);
f.setLayout(null); will prevent any of the child components from been sized and positioned and is best avoid, just get rid of it.
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
This scr_buffer = map_buffer.getSubimage(x, y, SCR_W, SCR_H); is also a little dangerous, as it could be asking for more of the image then is available, you should be testing to see if x + SCR_W < image width (and same goes for the height)
I don't know if this deliberate or not, but you never reset the "border" flags, so once set, they will always be true...
addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
/**
* Check location of mouse pointer if(specified_edge)move(scr_buffer)
*
*/
isRightBorder = false;
isBottomBorder = false;
isTopBorder = false;
isLeftBorder = false;
You may also want to have a "space" around the edge, which when the mouse enters it, it will set the border flags, for example...
if (e.getPoint().getX() >= getWidth() - 4) {
isRightBorder = true;
}
if (e.getPoint().getY() >= getHeight() - 4) {
isBottomBorder = true;
}
if (e.getPoint().getX() <= 4) {
isLeftBorder = true;
}
if (e.getPoint().getY() <= 4) {
isTopBorder = true;
}
Your logic for the vertical movement is wrong, when the mouse is within the bottom border, it should add to the y position and subtract when it's within the top border...
if (isBottomBorder) {
y += 2;
}
if (isTopBorder) {
y -= 2;
}
You need to perform some range checking after you've modified the x/y positions to make sure you're not request for a portion of the image which is not available...
if (x < 0) {
x = 0;
} else if (x + getWidth() > map_buffer.getWidth()) {
x = map_buffer.getWidth() - getWidth();
}
if (y < 0) {
y = 0;
} else if (y + getHeight() > map_buffer.getHeight()) {
y = map_buffer.getHeight() - getHeight();
}
There is a logic error within the initScreen method, src_buffer is never set to null, meaning that once it has a "sub image", it never tries to obtain a new one (also, you shouldn't be loading the map_buffer in there either).
scr_buffer = null;
repaint();
Thank you for you time and understanding.
Inside mouse moved
if (e.getPoint().getX() >= getWidth() - 4) {
isRightBorder = true; // unnecessary
scr_buffer = null;
x = x + 2;
repaint();
}

kinect Gesture recognition in SimpleOpenNI

I want to implement a kind of drums. For every hit I want to play a song. So I need to detect every "hit" and the position. before I start implementing a function who will analyse the positions and detect "hits" I want to be sure that there is no other solution, so is there any event, gesture detection who allow me to detect that ?
As far as I know there is no "event" that is defined natively other than stream callbacks which are called when you receive data such as the joint positions and depth image which should be enough to get you started.
I would take a look at this:https://code.google.com/p/kineticspace/ in order to know what to expect or how to proceed with your own code.
Once you manage to get the skeleton data just find where the hand is at that time, put a threshold to its position and start tracking for a certain amount time and see if its movement path fits your pattern for a particular gesture such as "translation in y direction for x amount of seconds". Then you have very simple "hit" gesture detection. This can get as complex as you need, but there is not much to it at the basics in terms of what you receive from the library side.
Good luck.
I made a drum kit with the Kinect using this is a wonderful class for placing and using boxes in Kinect.
Import Libraries:
import processing.opengl.*;
import SimpleOpenNI.*;
Use something like this bit of code inside your Setup()
myTrigger = new Hotpoint(200, 10, 800, size);
Use the methods inside your draw()
if(myTrigger.currentlyHit()) {
myTrigger.play();
println("trigger hit");
}
Use the following methods inside this class!
class Hotpoint {
PVector center;
color fillColor;
color strokeColor;
int size;
int pointsIncluded;
int maxPoints;
boolean wasJustHit;
int threshold;
Hotpoint(float centerX, float centerY, float centerZ, int boxSize) {
center = new PVector(centerX, centerY, centerZ);
size = boxSize;
pointsIncluded = 0;
maxPoints = 1000;
threshold = 0;
fillColor = strokeColor = color(random(255), random(255), random(255));
}
void setThreshold( int newThreshold ){
threshold = newThreshold;
}
void setMaxPoints(int newMaxPoints) {
maxPoints = newMaxPoints;
}
void setColor(float red, float blue, float green){
fillColor = strokeColor = color(red, blue, green);
}
boolean check(PVector point) {
boolean result = false;
if (point.x > center.x - size/2 && point.x < center.x + size/2) {
if (point.y > center.y - size/2 && point.y < center.y + size/2) {
if (point.z > center.z - size/2 && point.z < center.z + size/2) {
result = true;
pointsIncluded++;
}
}
}
return result;
}
void draw() {
pushMatrix();
translate(center.x, center.y, center.z);
fill(red(fillColor), blue(fillColor), green(fillColor),
255 * percentIncluded());
stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
box(size);
popMatrix();
}
float percentIncluded() {
return map(pointsIncluded, 0, maxPoints, 0, 1);
}
boolean currentlyHit() {
return (pointsIncluded > threshold);
}
boolean isHit() {
return currentlyHit() && !wasJustHit;
}
void clear() {
wasJustHit = currentlyHit();
pointsIncluded = 0;
}
}

Lock graphice object in J2ME

it seems to be very stupid question, but I really need a help, I'm making a task with drawing a background transparent gradient image and then draw some objects over it, the problem is I want to draw this image once but the other objects will be drawn multi time to perform some animation
the code is as following, this is the code that i want to run once, and I have created a boolen variable = false and then set it to true
public void drawLockLayer(Graphics g) {
try {
lock = Image.createImage(Paths.lock);
g.drawImage(lock, 0, 0, LGBMainMidlet.width, LGBMainMidlet.height);
System.out.println("After Draw Image");
drawOnce = true;
} catch (Exception ex) {
ex.printStackTrace();
}
}
other code is as following
public void paint(Graphics g, Rectangle rect) {
synchronized (g) {
if (drawOnce == false) {
drawLockLayer(g);
}
}
pos = (int) ((System.currentTimeMillis() % 2700) / 300);
int i = 0;
g.setColor(bgColor);
g.fillRoundRect(startX, startY, width, height, 20, 20);
g.setColor(fgColor);
g.setFont(font);
g.drawString(loadMsg, startX + (spacing / 4), startY + (spacing / 4));
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
int thickness = 6;
if (i == pos) {
thickness = 14;
} else if (i == pos - 1) {
thickness = 10;
}
g.fillRect((startX + x * spacing - (thickness / 2)) + (width / 3), (startY + y * spacing - (thickness / 2)) + (height / 3), thickness, thickness);
i++;
}
}
}
it is enter the method but it is not draw the background image , What I want to do is to lock the graphics object until he finish drawing the image then continue with other code
can anyone help please
Several issues with the code:
synchronizing on a Graphics is generally a bad idea
paint is only supposed to be called from one thread. are you sure it isn't and you actually need to synchronize? where does rect come from?
to make it easier to maintain, you should set drawOnce to true in paint()
You need to set drawOnce to false before calling paint.
It looks like your code is based on GameCanvas. What do you think of the below approach?
class MainCanvas extends GameCanvas {
// rect is an attribute
private void updateScreen() {
drawOnce = false;
paint(getGraphics(), rect);
}
public void start() {
new DataThread().start();
new AnimationThread().start();
}
class DataThread extends Thread {
public void run() {
while (/*IO stuff not done*/) {
// save data
updateScreen();
}
}
}
class AnimationThread extends Thread {
public void run() {
while (/*IO stuff not done*/) {
// sleep a little
updateScreen();
}
}
}
// drawLockLayer and paint(Graphics, Rectangle) methods
} // end of MainCanvas class

Categories