Обнаружение столкновений между двумя изображениями в Java - PullRequest
13 голосов
/ 03 декабря 2008

В игре, которую я пишу, отображаются два персонажа: игрок и враг. определяется как таковой:

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

public void enemy(Graphics g) {
    g.drawImage(enemy, 200, 200, this);
}

Затем вызывается с:

player(g);
enemy(g);

Я могу перемещать player () с помощью клавиатуры, но затрудняюсь обнаружить столкновение между ними. Многие люди говорят, что используют прямоугольники, но, будучи новичком, я не понимаю, как бы связать это с моим существующим кодом. Кто-нибудь может дать мне совет?

Ответы [ 9 ]

18 голосов
/ 03 декабря 2008

Я думаю, что ваша проблема в том, что вы не используете хороший дизайн ОО для своего игрока и врагов. Создайте два класса:

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
}

Ваш плеер должен иметь переменные X, Y, Width и Height.

Твоим врагам тоже следует.

В вашем игровом цикле сделайте что-то вроде этого (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();
    }
}

Чтобы ускорить процесс, не беспокойтесь о том, что координаты врагов за кадром.

5 голосов
/ 03 декабря 2008

Во-первых, используйте ограничивающие рамки, как описано Джонатаном Холландом , чтобы выяснить, нет ли у вас столкновения.

Из (многоцветных) спрайтов создайте черно-белые версии. Возможно, они у вас уже есть, если ваши спрайты прозрачны (то есть есть места, которые находятся внутри ограничительной рамки, но вы все равно можете видеть фон). Это "маски".

Используйте Image.getRGB() на маске, чтобы получить пиксели. Для каждого непрозрачного пикселя установите бит в массиве целых чисел (playerArray и enemyArray ниже). Размер массива составляет height, если width <= 32 пикселей, (width+31)/32*height в противном случае. Код ниже для width <= 32.

Если у вас есть столкновение ограничивающих рамок, сделайте следующее:

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

}

Ссылки: JGame , Каркас для небольших Java-игр

3 голосов
/ 02 июня 2011

Вот основной класс из моей программы обнаружения столкновений.
Вы можете видеть, что это бежит в: 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
3 голосов
/ 03 декабря 2008

Вы не хотите иметь код проверки столкновения внутри кода рисования. Картина должна быть быстрой. Столкновение может пойти в игровой цикл. Следовательно, вам необходимо внутреннее представление объектов независимо от их спрайтов.

2 голосов
/ 27 октября 2014

есть ли проблема с:

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 


это также может быть применено к кругам:

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



чтобы проверить, ударили ли вы по краю экрана, вы можете использовать следующее:

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
}
2 голосов
/ 03 декабря 2008

Вот полезная игра с открытым исходным кодом, которая использует много столкновений: http://robocode.sourceforge.net/

Вы можете взглянуть на код и дополнить ответы, написанные здесь.

2 голосов
/ 03 декабря 2008

Поскольку в Java нет функции пересечения (правда !?), вы можете выполнить обнаружение столкновений, просто сравнив значения X и Y, ширины и высоты ограничивающих рамок (прямоугольник) для каждого из объектов, которые могут потенциально сталкиваться .

Итак ... в базовом объекте каждого сталкивающегося объекта ... т.е. если у вашего игрока и врага общая база, вы можете поместить простой объект Rectangle, называемый чем-то вроде BoundingBox. Если общая база представляет собой встроенный класс Java, то вам необходимо создать класс, который расширяет класс сборки и в котором объекты player и вражеского объекта расширяют ваш новый класс или являются экземплярами этого класса.

При создании (и каждом тике или обновлении) вам необходимо установить параметры BoundingBox для вашего игрока и врага. У меня нет класса Rectangle передо мной, но скорее всего это что-то вроде X, Y, Width и, наконец, Height. X и Y - это расположение объектов в вашем игровом мире. Думаю, ширина и высота говорят сами за себя. Скорее всего, они появятся справа от местоположения игроков, хотя, если бы X и Y были в 0, а ваши Ширина и Высота были в 256, вы бы ничего не увидели, потому что персонаж был бы слева вверху. за пределами экрана.

В любом случае ... чтобы обнаружить столкновение, вам нужно сравнить атрибуты игрока и вражеских BoundingBoxes. Так что-то вроде этого ...

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

Логика может быть довольно сложной, но вам необходимо сравнить расстояния между каждым BoundingBox и сравнить местоположения.

2 голосов
/ 03 декабря 2008

Используйте прямоугольник, чтобы окружить каждого игрока и врага, высота и ширина прямоугольников должны соответствовать объекту, который вы окружаете, представьте, что он находится в коробке, достаточно большой, чтобы уместиться.

Теперь вы перемещаете эти прямоугольники так же, как вы делаете объекты, поэтому у них есть «ограничивающий прямоугольник»

Я не уверен, что в Java это есть, но у объекта прямоугольника может быть метод с именем .intersects (), поэтому вы должны выполнить if (rectangle1.intersectS (rectangle2), чтобы проверить, не столкнулся ли объект с другим.

В противном случае вы можете получить координаты x и y блоков и, используя их высоту / ширину, определить, пересекались ли они сами.

В любом случае, вы можете использовать это для того, чтобы сделать событие на перекрестке (сделать один взрыв или что-то еще) или предотвратить рисование движения. (вернуться к предыдущим координатам)

редактировать: здесь мы идем

логическое значение

пересекается (прямоугольник r) Определяет, является ли этот прямоугольник и указанный Прямоугольник пересекается.

Так что я бы сделал (и не вставляю этот код, он, скорее всего, не будет работать, не делал Java долгое время, и я не делал графику, когда я его использовал).

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

очевидно, вам нужно куда-то вписать это.

1 голос
/ 27 ноября 2017

Не нужно использовать прямоугольники ... сравнивайте координаты 2 игроков постоянно.

как if(x1===x&&y1==y) не забудьте увеличить диапазон x при сравнении.

если ширина прямоугольника равна 30, примите if (x1>x&&x2>x+30) .. аналогично y

...