碰撞检测复杂形状 [英] Collision detection with complex shapes

查看:356
本文介绍了碰撞检测复杂形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使游戏具有从图像加载每个级别。
我想提请了Photoshop中的整体水平,然后将其设置为背景,让玩家走了过来了。
我想另一个无形的形象走了过来顶部,这将是黑色,我想与碰撞的所有地方。

我不希望使用的瓷砖,这与矩形碰撞和这样更容易究其原因,是因为会有复杂的角落,而不是一切都将是长方形。

这是一个好主意,是有可能这样做容易吗?
这将是一个很大的CPU猪还是有更好的方式来做到这一点?

等级图片

红色

显示障碍


解决方案

  

..会有复杂的角落,而不是一切都将是矩形。


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


  • 黄色是一个小动画播放器。

  • 重新包含播放器的路径present墙壁图像的边界(它反弹关闭它们)。

  • 障碍是涂成绿色时,不碰撞,红色其他。

 进口java.awt中的*。
java.awt.event中导入*。
导入的java.awt.geom *。
进口java.awt.image.BufferedImage中;
进口的javax.swing *。类ShapeCollision {    私人的BufferedImage IMG;
    私有区[] =障碍新Area [4];
    私人区域的墙壁;    INT X;
    诠释Ÿ;
    INT xDelta = 3;
    INT yDelta = 2;    / **的方法来确定区域的两个实例相交* /
    公共布尔doAreasCollide(区区域1,区域区域2){
        布尔碰撞= FALSE;        区collide1 =新的区域(区域);
        collide1.subtract(AREA2);
        如果(!collide1.equals(区域)){
            碰撞= TRUE;
        }        区collide2 =新的区域(区域2);
        collide2.subtract(区域);
        如果(!collide2.equals(AREA2)){
            碰撞= TRUE;
        }        返回碰撞;
    }    ShapeCollision(){
        INT W = 400;
        INT H = 200;
        IMG =新的BufferedImage(W,H,BufferedImage.TYPE_INT_RGB);
        最终的JLabel imageLabel =新的JLabel(新的ImageIcon(IMG));
        X = W / 2;
        Y = H / 2;        //圈
        障碍[0] =新所在区域(新Ellipse2D.Double(40,40,30,30));        INT [] = xTriangle {330360345};
        INT [] = yTriangle {60,60,40};
        //三角形
        障碍[1] =新Area(新多边形(xTriangle,yTriangle,3));        INT [] = xDiamond {60,80,60,40};
        INT [] = yDiamond {120140160140};
        //钻石
        障碍[2] =新所在区域(新的多边形(xDiamond,yDiamond,4));        INT [] = xOther {360340360340};
        INT [] = yOther {130110170150};
        //其他
        障碍[3] =新所在区域(新的多边形(xOther,yOther,4));        墙壁=新区域(新的Rectangle(0,0,W,H));        ActionListener的动画=新的ActionListener(){            @覆盖
            公共无效的actionPerformed(ActionEvent的五){
                动画();
                imageLabel.repaint();
            }
        };
        定时器定时器=新定时器(50,动画);        timer.start();
        JOptionPane.showMessageDialog(NULL,imageLabel);
        timer.stop();
    }    公共无效动画(){
        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;
        区域播放器=新区域(新Ellipse2D.Double(X,Y,S,S));        //边缘碰撞的严峻考验;
        如果(doAreasCollide(播放器,壁)){
            如果(X + S取代; img.getWidth()|| X - 小于0){
                xDelta * = -1;
            }
            如果(Y + S取代; img.getHeight()|| Y'小于0){
                yDelta * = -1;
            }
        }
        g.setColor(Color.ORANGE);
        对于(区障碍:障碍){
            如果(doAreasCollide(障碍,播放器)){
                g.setColor(Color.RED);
            }其他{
                g.setColor(Color.GREEN);
            }
            g.fill(障碍);
        }        g.setColor(Color.YELLOW);
        g.fill(播放器);
        g.dispose();
    }    公共静态无效的主要(字串[] args){
        可运行R =新的Runnable(){            @覆盖
            公共无效的run(){
                新ShapeCollision();
            }
        };
        //摇摆的GUI应创建和更新的EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(R);
    }
}

修改


  

使检测所有红色,并设置为碰撞边界


在启动时,使用平滑锯齿路径看到源的问题得到红色的轮廓像素(请参阅 getOutline(彩色目标的BufferedImage BI)方法)。存储作为启动时的单一障碍。

I am wanting to make a game that has each level loaded from an image. I want to draw up the whole level in Photoshop, and then set it as the background and allow the player to walk over it. I want another invisible image to go over top which will be black in all places that I want to collide with.

The reason I don't want to use tiles, which are much easier with rectangle collision and such, is because there will be complex corners and not everything will be rectangle.

Is this a good idea, and is it possible to do easily? Would this be a big CPU hog or is there a better way to do this?

Level image

Obstacles shown in red

解决方案

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

This could be achieved by drawing and dealing with Shape and Area instances. E.G.

  • Yellow is a little animated 'player'.
  • The bounds of the image represent walls that contain the path of the player (it bounces off them).
  • Obstacles are painted green when not in collision, red otherwise.

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

Edit

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

At start-up, use the source seen in the Smoothing a jagged path question to get an outline of the red pixels (see the getOutline(Color target, BufferedImage bi) method). Store that Area as the single obstacle on start-up.

这篇关于碰撞检测复杂形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆