15

我正在编写的游戏中显示了两个角色,玩家和敌人。定义为:

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(),但是在尝试检测两者之间的碰撞时我不知所措。很多人都说要使用矩形,但作为一个初学者,我看不出如何将它链接到我现有的代码中。谁能给我一些建议?

4

9 回答 9

21

我认为你的问题是你没有为你的玩家和敌人使用好的 OO 设计。创建两个类:

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
}

您的 Player 应该有 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();
    }
}

为了加快速度,不要费心检查敌人的坐标是否在屏幕外。

于 2008-12-02T23:35:25.547 回答
5

首先,使用Jonathan Holland描述的边界框来确定是否可能发生碰撞。

从(多色)精灵中,创建黑白版本。如果您的精灵是透明的,您可能已经拥有这些(即边界框内有一些地方,但您仍然可以看到背景)。这些是“面具”。

在蒙版上使用Image.getRGB()以获取像素。对于每个不透明的像素,在整数数组(playerArrayenemyArray以下)中设置一个位。数组的大小是像素,height否则。下面的代码是针对.width <= 32(width+31)/32*heightwidth <= 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 游戏框架

于 2008-12-03T09:28:11.060 回答
3

您不希望在绘画代码中包含碰撞检查代码。绘画需要快速。碰撞可以进入游戏循环。因此,您需要独立于其精灵的对象的内部表示。

于 2008-12-02T22:26:16.387 回答
3

这是我的碰撞检测程序的主要课程。
您可以在以下位置看到它运行: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
于 2011-06-02T01:11:57.333 回答
2

由于 Java 没有相交函数(真的!?),您可以通过简单地比较每个可能发生碰撞的对象的边界框(矩形)的 X 和 Y、宽度和高度值来进行碰撞检测。

所以...在每个碰撞对象的基础对象中...即,如果您的玩家和敌人有一个共同的基础,您可以放置​​一个简单的矩形对象,称为 BoundingBox。如果公共基础是内置 Java 类,那么您需要创建一个扩展内置类的类,并让玩家和敌人对象扩展您的新类或者是该类的实例。

在创建时(以及每次滴答或更新),您需要为您的玩家和敌人设置 BoundingBox 参数。我面前没有 Rectangle 类,但它很可能是 X、Y、Width 和最后的 Height。X 和 Y 是游戏世界中的对象位置。我认为宽度和高度是不言自明的。它们很可能会从玩家位置的右侧出现,因此,如果 X 和 Y 都为 0 并且您的宽度和高度都为 256,您将看不到任何东西,因为角色将位于左上角屏幕之外。

无论如何...要检测碰撞,您需要比较玩家和敌人边界框的属性。所以像这样的事情......

 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 之间的距离并比较位置。

于 2008-12-02T22:57:35.873 回答
2

这是一个使用大量碰撞的开源游戏的有用之处:http ://robocode.sourceforge.net/

您可以查看代码并补充此处编写的答案。

于 2008-12-02T23:28:12.923 回答
2

是否有问题:

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
}
于 2014-10-27T12:04:17.573 回答
1

使用一个矩形来包围每个玩家和敌人,矩形的高度和宽度应该与你周围的对象相对应,想象它在一个足够大的盒子里。

现在,您像移动对象一样移动这些矩形,所以它们有一个“边界框”

我不确定Java是否有这个,但它可能在矩形对象上有一个名为 .intersects() 的方法,所以你会做 if(rectangle1.intersectS(rectangle2) 来检查一个对象是否与另一个对象发生碰撞。

否则,您可以获得框的 x 和 y 坐标,并使用它们的高度/宽度来检测它们是否与您自己相交。

无论如何,您可以使用它在交叉路口执行事件(使一个爆炸或其他)或阻止绘制运动。(恢复到以前的坐标)

编辑:我们走

布尔值

intersects(Rectangle r) 确定此 Rectangle 是否与指定的 Rectangle 相交。

所以我会做(并且不要粘贴这段代码,它很可能不会工作,很长时间没有做过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");
}

显然你需要把它放在某个地方。

于 2008-12-02T22:04:07.477 回答
1

无需使用矩形...不断比较 2 个玩家的坐标。

喜欢 if(x1===x&&y1==y) 在比较时记得增加 x 的范围。

如果你的矩形宽度为 30 则取为if (x1>x&&x2>x+30)..likely y

于 2017-11-27T12:16:34.037 回答