sprites sokoban games java collision-detection

sokoban - java sprites



Detección de colisión entre dos imágenes en Java (9)

Esta es la clase principal de mi programa de detección de colisiones.
Puede verlo ejecutarse en: 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

Tengo dos personajes en el juego que estoy escribiendo, el jugador y el enemigo. definido como tal

public void player(Graphics g) { g.drawImage(plimg, x, y, this); } public void enemy(Graphics g) { g.drawImage(enemy, 200, 200, this); }

Luego llamado con:

player(g); enemy(g);

Puedo mover el jugador () alrededor con el teclado, pero estoy perdido al tratar de detectar una colisión entre los dos. Mucha gente ha dicho que use Rectangles, pero como soy principiante, no veo cómo vincular esto con mi código existente. ¿Alguien puede ofrecerme algún consejo?


Aquí hay un útil de un juego de código abierto que usa muchas colisiones: http://robocode.sourceforge.net/

Puede echarle un vistazo al código y complementarlo con las respuestas escritas aquí.


Como Java no tiene una función de intersección (¡en serio !?) puede realizar la detección de colisión simplemente comparando los valores X e Y, Ancho y Alto de los cuadros delimitadores (rectángulo) para cada uno de los objetos que podrían colisionar.

Entonces ... en el objeto base de cada objeto que colisiona ... es decir, si tu jugador y tu enemigo tienen una base común, puedes poner un objeto Rectángulo simple llamado algo así como BoundingBox. Si la base común es una clase Java incorporada, deberá crear una clase que amplíe la compilación en clase y que el jugador y los objetos enemigos amplíen su nueva clase o sean instancias de esa clase.

En la creación (y cada tictac o actualización) necesitarás establecer los parámetros de BoundingBox para tu jugador y tu enemigo. No tengo la clase Rectangle enfrente de mí, pero es más probable que tenga algo como X, Y, Width y finalmente Height. X e Y son la ubicación de objetos en tu mundo de juego. El ancho y la altura son autoexplicativos, creo. Lo más probable es que salgan por la derecha de la ubicación de los jugadores, así que si la X y la Y fueran molestas en 0 y tu Ancho y Altura estuvieran en 256, no verías nada porque el personaje estaría en la esquina superior izquierda. fuera de la pantalla.

De todos modos ... para detectar una colisión, querrás comparar los atributos del jugador y los BoundingBoxes enemigos. Entonces algo como esto ...

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. }

La lógica puede ser algo complicada, pero deberá comparar las distancias entre cada BoundingBox y comparar ubicaciones.


Creo que tu problema es que no estás usando un buen diseño OO para tu jugador y tus enemigos. Crea dos clases:

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 }

Su reproductor debe tener variables X, Y, Ancho y Altura.

Tus enemigos también deberían.

En tu ciclo de juego, haz algo como esto (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(); } }

Para acelerar las cosas, no te molestes en comprobar si los coords de los enemigos están fuera de pantalla.


No desea tener el código de verificación de colisión dentro del código de pintura. La pintura debe ser rápida. La colisión puede ir en el bucle del juego. Por lo tanto, necesita una representación interna de los objetos independientes de sus sprites.


hay un problema con:

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


esto también se puede aplicar a círculos:

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



Para verificar si tocas el borde de una pantalla, puedes usar lo siguiente:

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 }


Usa un rectángulo para rodear a cada jugador y enemigo, la altura y el ancho de los rectángulos deben corresponderse con el objeto que rodeas, imagínate que está en una caja lo suficientemente grande como para caber.

Ahora, mueve estos rectángulos igual que los objetos, por lo que tienen un ''cuadro delimitador''

No estoy seguro de si Java tiene esto, pero podría tener un método en el objeto rectángulo llamado .intersects (), por lo que haría si (rectangle1.intersectS (rectangle2) comprueba si un objeto colisionó con otro.

De lo contrario, puede obtener las coordenadas xey de las casillas y al usar la altura / ancho de ellas, puede detectar si se han cruzado.

De todos modos, puede usar eso para hacer un evento en intersección (hacer explotar uno, o lo que sea) o evitar que se dibuje el movimiento. (volver a las coordenadas anteriores)

editar: aquí vamos

booleano

intersects (Rectangle r) Determina si este Rectangle y el Rectángulo especificado se intersectan o no.

Así que lo haría (y no pegue este código, lo más probable es que no funcione, no lo haga por mucho tiempo y no hice gráficos cuando lo usé).

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"); }

obviamente necesitarías encajar eso en alguna parte.


Primero, use los cuadros delimitadores como lo describe Jonathan Holland para ver si puede tener una colisión.

Desde los sprites (multicolores), crea versiones en blanco y negro. Probablemente ya los tengas si tus sprites son transparentes (es decir, hay lugares que están dentro del cuadro delimitador pero aún puedes ver el fondo). Estas son "máscaras".

Use Image.getRGB() en la máscara para obtener los píxeles. Para cada píxel que no sea transparente, establezca un bit en una matriz de enteros ( playerArray y enemyArray continuación). El tamaño de la matriz es height si width <= 32 píxeles, (width+31)/32*height caso contrario. El código a continuación es para width <= 32 .

Si tiene una colisión de los cuadros delimitadores, haga esto:

// 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! } }

Enlaces: JGame , Framework para pequeños juegos Java


No es necesario usar rectángulos ... compare constantemente las coordenadas de 2 jugadores.

como if(x1===x&&y1==y) recuerda aumentar el rango de x cuando lo comparas.

si tu ancho de rectángulo es 30, toma como if (x1>x&&x2>x+30) ..