碰撞检测复杂形状 [英] Collision detection with complex shapes
问题描述
我想使游戏具有从图像加载每个级别。
我想提请了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
andArea
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 thatArea
as the single obstacle on start-up.这篇关于碰撞检测复杂形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!