java - 如何检测碰撞?

标签 java image collision-detection

我在 Board 类中的世界中有两个图像(一只猫和一只狗)。猫在随机方向移动,而狗只有在我按下箭头键时才会移动。我现在的问题是,当两个图像发生碰撞时,我怎样才能让猫消失?任何答案或想法将不胜感激。

这是我试过的...

public class Cat extends Sprite implements ImageObserver
{
private java.awt.Image catImage;

private final Board board;
private double x;
private double y;
private double speed;
private double angle;
private boolean visible;

public Cat(Board board, double x, double y, double speed)
{
    this.board = board;
    this.x = x;
    this.y = y;
    this.speed = convertToMeterPerSecond(speed);
    visible = true;

    URL iU = this.getClass().getResource("cat.gif");
    ImageIcon icon = new ImageIcon(iU);
    catImage = icon.getImage();
}

public Image getImage()
{
    return catImage;
}

public void move(long dt)
{
    double dt_s = dt / 1e9;
    double dx_m = speed * dt_s * Math.sin(angle);
    double dy_m = speed * dt_s * Math.cos(angle);

    final double right_wall = board.x1_world;
    final double up_wall = board.y1_world;
    final double down_wall = 0.0;
    final double left_wall = 0.0;

    x += dx_m;
    y += dy_m;

    if (x >= right_wall)
    {
        x = right_wall;

        setRandomDirection();
    }
    if (y > up_wall)
    {
         y = up_wall;
        setRandomDirection();
    }
    if (x <= left_wall)
    {
        x = left_wall;
        setRandomDirection();
    }
    if (y < down_wall)
    {
         y = down_wall;
        setRandomDirection();
    }

}

public void setRandomDirection()
{
    Cat myObject = this;
    myObject.setAngle(Math.PI * 2 * Math.random());
}

@Override
public void render(Graphics2D g2d)
{
    AffineTransform t = g2d.getTransform();
    double height = 0.3; //meter
    double width = 0.3;  //meter

    double cat_footy = height;
    double cat_footx = width / 2;

    int xx = board.convertToPixelX(x - cat_footx);
    int yy = board.convertToPixelY(y + cat_footy);

    g2d.translate(xx, yy);

    double x_expected_pixels = width * board.meter;
    double y_expected_pixels = height * board.meter;

    double x_s = x_expected_pixels / ((ToolkitImage) catImage).getWidth();
    double y_s = y_expected_pixels / ((ToolkitImage) catImage).getHeight();

    double w = ((ToolkitImage) catImage).getWidth();
    double h = ((ToolkitImage) catImage).getHeight();


    g2d.scale(x_s, y_s);
    g2d.drawImage(getImage(), 0, 0, this); // upper left corner
    g2d.setColor(Color.BLACK);
    g2d.drawRect(0, 0, (int) w, (int) h);
    g2d.setTransform(t);
}

public void moveAt(double distance_x, double distance_y)
{
    this.x = (int) distance_x;
    this.y = (int) distance_y;
}

@Override
public Rectangle getBounds()
{
    double w = ((ToolkitImage) catImage).getWidth();
    double h = ((ToolkitImage) catImage).getHeight();

    return new Rectangle((int) x, (int) y, (int) w, (int) h);
}

public void setAngle(double angle)
{
    this.angle = angle;
}

public boolean isVisible()
{
    return visible;
}

public void setVisible(Boolean visible)
{
    this.visible = visible;
}

@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
    return true;
}
}

我的猫课

public class Dog extends Sprite implements ImageObserver
{
private java.awt.Image humanImage;
private final Board board;
private double x;
private double y;
private double speed;
private boolean visible;
private double angle;
private double dx_m;
private double dy_m;

public Dog(Board board, double x, double y, double speed)
{
    this.board = board;
    this.x = x;
    this.y = y;
    this.speed = convertToMeterPerSecond(speed);
    visible = true;

    URL iU = this.getClass().getResource("dog.jpg");
    ImageIcon icon = new ImageIcon(iU);
    dogImage = icon.getImage();

}

public Image getImage()
{
    return dogImage;
}

public void keyPressed(KeyEvent e)
{

    int key = e.getKeyCode();

    if (key == KeyEvent.VK_LEFT)
    {
        dx_m = -0.3;
    }

    if (key == KeyEvent.VK_RIGHT)
    {
        dx_m = 0.3;
    }

    if (key == KeyEvent.VK_UP)
    {
        dy_m = 0.3;
    }

    if (key == KeyEvent.VK_DOWN)
    {
        dy_m = -0.3;

    }
}

public void keyReleased(KeyEvent e)
{
    int key = e.getKeyCode();

    if (key == KeyEvent.VK_LEFT)
    {
        dx_m = 0;
    }

    if (key == KeyEvent.VK_RIGHT)
    {
        dx_m = 0;
    }

    if (key == KeyEvent.VK_UP)
    {
        dy_m = 0;
    }

    if (key == KeyEvent.VK_DOWN)
    {
        dy_m = 0;
    }
}

@Override
public void move(long dt)
{
    double dt_s = dt / 1e9;

    final double right_wall = board.x1_world;
    final double up_wall = board.y1_world;
    final double down_wall = 0.0;
    final double left_wall = 0.0;

    x += dx_m;
    y += dy_m;
    if (x <= left_wall)
    {
        x = left_wall;
    }
    if (x >= right_wall)
    {
        x = right_wall;
    }

    if (y <= down_wall)
    {
        y = down_wall;
    }
    if (y >= up_wall)
    {
        y=up_wall;
    }
}

public void setRandomDirection()
{
    Dog myObject = this;
    myObject.setAngle(Math.PI * 2 * Math.random());
}

@Override
public void render(Graphics2D g2d)
{
    AffineTransform t = g2d.getTransform();

    final double dogHeight = 1.6;// meter
    final double dogWidth = 1.8;  //meter

    final double foot_position_y = dogHeight;
    final double foot_position_x = dogWidth / 2;

    int xx = board.convertToPixelX(x - foot_position_x); // to find the upper-left corner
    int yy = board.convertToPixelY(y + foot_position_y); // to find the upper-left corner

    g2d.translate(xx, yy);

    // ratio for actual Image size

    double x_expected_pixels = dogHeight * board.meter;
    double y_expected_pixels = dogWidth * board.meter;

    double w = ((ToolkitImage) dogImage).getWidth();
    double h = ((ToolkitImage) dogImage).getHeight();

    double x_s = x_expected_pixels / w;
    double y_s = y_expected_pixels / h;

    g2d.scale(x_s, y_s);
    g2d.drawImage(getImage(), 0, 0, this); // upper left corner
    g2d.setColor(Color.BLACK);
    g2d.drawRect(0, 0, (int) w, (int) h);
    g2d.setTransform(t);

}

@Override
public void moveAt(double distance_x, double distance_y)
{
    this.x = distance_x;
    this.y = distance_y;
}

public void setAngle(double angle)
{
    this.angle = angle;
}

@Override
public Rectangle getBounds()
{
    double width = ((ToolkitImage) dogImage).getWidth();
    double height = ((ToolkitImage) dogImage).getHeight();
    return new Rectangle((int) x, (int) y, (int) width, (int) height);
}

public boolean isVisible()
{
    return visible;
}

public void setVisible(Boolean visible)
{
    this.visible = visible;
}

@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
    return true;
}
}

我的狗类

public class Board extends Canvas
{
private Cat cat;
public static final long SECOND = 1000 * 1000 * 1000;

public double meter;//PIXEL
private HumanBeing humanBeing;

/**
 * ascending from 0 to N
 * 0 : most far way...
 * N : is the closest (painted the last)
 */
private final java.util.List<Sprite> z_sorted_sprites = new ArrayList<Sprite>();

private BufferStrategy strategy;

int x0_pixel;
int y0_pixel;

int x1_pixel;
int y1_pixel;

double x1_world;
double y1_world;
private final Frame frame;


public Board(Frame frame, double meter)
{
    addKeyListener(new TAdapter());
    this.frame = frame;
    this.setIgnoreRepaint(true);

    this.meter = meter;

    setFocusable(true);
    dog = new Dog(this, 5, 5, 40);

    init();

    addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentResized(ComponentEvent e)
        {
            render();
        }
    });
}

public void init()
{

    z_sorted_sprites.add(new Cat(this, 0, 0, 30));
    z_sorted_sprites.add(new Cat(this, 1, 1, 10));
    z_sorted_sprites.add(new Cat(this, 2, 2, 20));
    z_sorted_sprites.add(new Cat(this, 3, 3, 100));

}

public void render()
{
    setupStrategy();

    x0_pixel = 0;
    y0_pixel = 0;

    x1_pixel = getWidth();
    y1_pixel = getHeight();

    x1_world = x1_pixel / meter;
    y1_world = y1_pixel / meter;

    Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();

    g2d.setBackground(Color.lightGray);
    g2d.clearRect(0, 0, x1_pixel, y1_pixel);

    g2d.setColor(Color.BLACK);

    for (double x = 0; x < x1_world; x++)
    {
        for (double y = 0; y < y1_world; y++)
        {
            int xx = convertToPixelX(x);
            int yy = convertToPixelY(y);

            g2d.drawOval(xx, yy, 2, 2);
        }
    }

    for (Sprite z_sorted_sprite : z_sorted_sprites)
    {
        z_sorted_sprite.render(g2d);
    }
    dog.render(g2d);

    g2d.dispose();

    strategy.show();

    Toolkit.getDefaultToolkit().sync();
}


public int convertToPixelX(double distance)
{
    return (int) (distance * meter);
}

public int convertToPixelY(double y_world)
{
    return (int) (y1_pixel - (y_world * meter));
}

public void onZoomUpdated(int value)
{
    meter = value;
    render();
}

private void setupStrategy()
{
    if (strategy == null)
    {
        this.createBufferStrategy(2);
        strategy = this.getBufferStrategy();
    }
}

public void start() throws InterruptedException
{
    long prevLoopStart = System.nanoTime();

    Avg avg = new Avg();

    while (true)
    {
        final long loopStart = System.nanoTime();
        final long dt = loopStart - prevLoopStart;

        for (Sprite sprite : z_sorted_sprites)
        {
            sprite.move(dt);

        }
        dog.move(dt);

        render();


        frame.onFpsUpdated(1.0 / dt * SECOND, avg.add(loopStart));

        final long elapsed_ns = System.nanoTime() - loopStart;

        long expected_elapsed_ms = 1000 / 60;
        long elapsed_ms = (long) (elapsed_ns / (1000.0 * 1000.0));
        long sleep_ms = expected_elapsed_ms - elapsed_ms;

        if (sleep_ms > 0)
        {
            Thread.sleep(sleep_ms  /* ms */);
        }

        prevLoopStart = loopStart;

    }
}

private void checkCollision()
{
    Rectangle r2 = cat.getBounds();
    Rectangle r3 = dog.getBounds();

    if (r3.intersects(r2))
    {
        dog.setVisible(false);
        cat.setVisible(false);
    }


}

static class Avg
{
    java.util.List<Long> ticks = new ArrayList<Long>();

    /**
     * @return the rate for the last second
     */
    int add(long tick)
    {
        ticks.add(0, tick);

        if (ticks.size() < 2)
        {
            return -1;
        }

        int last = -1;

        for (int pos = ticks.size() - 1; pos >= 0; pos--)
        {
            if (tick - ticks.get(pos) <= SECOND)
            {
                last = pos;
                break;
            }
        }

        while (ticks.size() - 1 > last)
        {
            ticks.remove(ticks.size() - 1);
        }

        return ticks.size();
    }
}

private class TAdapter extends KeyAdapter
{
    public void keyReleased(KeyEvent e)
    {
        dog.keyReleased(e);
    }

    public void keyPressed(KeyEvent e)
    {
        dog.keyPressed(e);
    }
}
}

对于我的 Board 类

public abstract class Sprite
{
public Sprite()
{

}

public Rectangle getBounds()
{
    return new Rectangle();
}


public static double convertToMeterPerSecond(double speed)
{
    // 25 km / hour
    //  25000 m / 3600 s
    return speed / 3.6;
}

public abstract void move(long dt);

public abstract void moveAt(double distance_x, double distance_y);

public abstract void render(Graphics2D g2d);

public abstract void setVisible(Boolean visible);

}

对于我的 Sprite 类

public boolean checkCollisions(java.util.List<Sprite> sprites)
{
    Dog dog = this;
    Rectangle r1 = dog.getBounds();

    for (int i = 0; i < sprites.size(); i++)
    {
        Rectangle r2 = sprites.get(i).getBounds();
        if (r1.intersects(r2))
        {
            sprites.remove(i);
        }
    }
    return true;
}

最佳答案

您提供了很多代码,但正如 Sibbo 所说,我没有看到您的 checkCollisions 方法在任何地方被调用。应该在游戏的每个循环中调用它。

Check out this tutorial ,具体看Game类中的gameLoop方法。当我制作一个需要大量碰撞检测的基于 sprite 的游戏时,本教程帮了我很多。

关于java - 如何检测碰撞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7872828/

相关文章:

java - GeoMesa Native API (Accumulo) - 多边形相交过滤器 : missing "the_geom" in SimpleFeature

java - Spock 测试因 NullPointerException 失败

java - SAAJ:TextNode 中的 XML。报价未转义

java - 用单个空格替换单词之间的多个空格

javascript - 如何阻止 collide2D 检测 p5.js

python - 如何反转矩形移动的方向?

ios - 如何在单个 ImageView 中添加多个图像并每 2 秒连续显示所有图像

php - Android中通过php上传照片到Ubuntu服务器

android - 挂载 Android 模拟器镜像

python - 在 Pygame 中,如何使 Sprite blitting 两次具有两个单独的碰撞盒?