有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

复杂形状的java冲突检测

我想做一个游戏,有每一个级别的图像加载。 我想在Photoshop中绘制整个关卡,然后将其设置为背景,让玩家在其上行走。 我希望另一个不可见的图像越过顶部,在所有我想碰撞的地方都是黑色的

我不想使用平铺的原因是因为会有复杂的角点,而不是所有的东西都是矩形的,因为矩形的碰撞更容易

这是一个好主意吗?有可能很容易做到吗? 这是一个巨大的CPU消耗,还是有更好的方法来做到这一点

水平图像

Level image

红色显示的障碍物

Obstacle in Red


共 (1) 个答案

  1. # 1 楼答案

    ..there will be complex corners and not everything will be rectangle.

    这可以通过绘制和处理ShapeArea实例来实现。例如

    • 黄色是一个小小的动画“播放器”
    • 图像的边界表示包含玩家路径的墙(它从墙上反弹)
    • 未发生碰撞时,障碍物漆成绿色,否则漆成红色

    ShapeCollision

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    
    class ShapeCollision {
    
        private BufferedImage img;
        private Area[] obstacles = new Area[4];
        private Area walls;
    
        int x; 
        int y;
        int xDelta = 3;
        int yDelta = 2;
    
        /** A method to determine if two instances of Area intersect */
        public boolean doAreasCollide(Area area1, Area area2) {
            boolean collide = false;
    
            Area collide1 = new Area(area1);
            collide1.subtract(area2);
            if (!collide1.equals(area1)) {
                collide = true;
            }
    
            Area collide2 = new Area(area2);
            collide2.subtract(area1);
            if (!collide2.equals(area2)) {
                collide = true;
            }
    
            return collide;
        }
    
        ShapeCollision() {
            int w = 400;
            int h = 200;
            img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            final JLabel imageLabel = new JLabel(new ImageIcon(img));
            x = w/2;
            y = h/2;
    
            //circle 
            obstacles[0] = new Area(new Ellipse2D.Double(40, 40, 30, 30));
    
            int[] xTriangle = {330,360,345};
            int[] yTriangle = {60,60,40};
            //triangle 
            obstacles[1] = new Area(new Polygon(xTriangle, yTriangle, 3));
    
            int[] xDiamond = {60,80,60,40};
            int[] yDiamond = {120,140,160,140};
            //diamond 
            obstacles[2] = new Area(new Polygon(xDiamond, yDiamond, 4));
    
            int[] xOther = {360,340,360,340};
            int[] yOther = {130,110,170,150};
            // other 
            obstacles[3] = new Area(new Polygon(xOther, yOther, 4));
    
            walls = new Area(new Rectangle(0,0,w,h));
    
            ActionListener animate = new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    animate();
                    imageLabel.repaint();
                }
            };
            Timer timer = new Timer(50, animate);
    
            timer.start();
            JOptionPane.showMessageDialog(null, imageLabel);
            timer.stop();
        }
    
        public void animate() {
            Graphics2D g = img.createGraphics();
            g.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
    
            g.setColor(Color.BLUE);
            g.fillRect(0, 0, img.getWidth(), img.getHeight());
            x+=xDelta;
            y+=yDelta;
            int s = 15;
            Area player = new Area(new Ellipse2D.Double(x, y, s, s));
    
            // Acid test of edge collision;
            if (doAreasCollide(player,walls)) {
                if ( x+s>img.getWidth() || x<0 ) {
                    xDelta *= -1;
                } 
                if(y+s>img.getHeight() || y<0 ) {
                    yDelta *= -1;
                }
            }
            g.setColor(Color.ORANGE);
            for (Area obstacle : obstacles) {
                if (doAreasCollide(obstacle, player)) {
                    g.setColor(Color.RED);
                } else {
                    g.setColor(Color.GREEN);
                }
                g.fill(obstacle);
            }
    
            g.setColor(Color.YELLOW);
            g.fill(player);
    
    
            g.dispose();
        }
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    new ShapeCollision();
                }
            };
            // Swing GUIs should be created and updated on the EDT
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
            SwingUtilities.invokeLater(r);
        }
    }
    

    编辑

    make it detect all the red color and set that as the collision bounds

    在启动时,使用Smoothing a jagged path问题中看到的源获取红色像素的轮廓(参见getOutline(Color target, BufferedImage bi)方法)。将Area存储为启动时的单个障碍物