Java – 通过阵列存储的冲突检测冲突

我目前正在为我的2D游戏进行碰撞.我做了一些研究并推断我应该使用将alpha值像素存储到实体图像的“掩码”中的方法,并且对于另一个使用相同的方法.然后,我把两个实体的x& y co-ords,以及高度和宽度,并创建一个Rectangle对象,并使用方法Rectangle.intersects(Rectangle r)检查它们是否实际碰撞,以使其更有效,而不是通过2 for循环.

如果它们相交,我会创建一个具有以下尺寸的新数组:

 int maxLengthY = Math.max(thisEntity.getMask().length, e.getMask().length);
 int maxLengthX = Math.max(thisEntity.getMask()[0].length, thisEntity.getMask()[0].length);

 int minX = Math.min(thisEntity.getX(), e.getX());
 int minY = Math.min(thisEntity.getY(), e.getY());

 int[][] map = new int[maxLengthX + minX][maxLengthY + minY];

然后将另外两个掩模添加到这个掩模上,并使用相应的y和amp; x“边界”,如下:

for(int curX = 0; curX < maxLengthX + minX; curX++) { //only loop through the co-ords that area affected                                                              
for(int curY = 0; curY < maxLengthY + minY; curY++) {                                                                                                             

    int this_x = thisEntity.getX();                                                                                                                               
    int this_width = thisEntity.getImage().getWidth();                                                                                                            
    int this_y = thisEntity.getY();                                                                                                                               
    int this_height = thisEntity.getImage().getHeight();                                                                                                          
    int[][] this_mask = thisEntity.getMask();                                                                                                                     
    if(curX < (this_x + this_width) && curX < this_x) {//check that the co-ords used are relevant for thisEntity's mask                                           

        if(curY < (this_y + this_height) && curY < this_y) {                                                                                                      
            map[curX][curY] = this_mask[Math.abs(curX - this_x)][Math.abs(curY - this_y)]; // store data from mask to map                                         
        }                                                                                                                                                         
    }                                                                                                                                                             

    int other_x = e.getX();                                                                                        
    int other_width = e.getImage().getWidth();                                                                     
    int other_y = e.getY();                                                                                        
    int other_height = e.getImage().getHeight();                                                                   
    int[][] other_mask = e.getMask();                                                                              

    if(curX < (other_x + other_width) && curX > other_x) { //check that the co-ords used are relevant for e's mask 
        if(curY < (other_y + other_height) && curY > other_y) {                                                    
            if(map[curX][curY] == 1) { //check if this segment is already written by thisEntity                    
                map[curX][curY] = 2;   //if yes, set to 2 instead of e's value to show collision                   
            } else {                                                                                               
                map[curX][curY] = other_mask[curX][curY]; // the minus to nullify minX and minY "requirements"     
            }                                                                                                      
        }                                                                                                          
    }                                                                                                              
}                                                                                                                  
}            

导致数组“地图”看起来像SO:

(原谅我1337的涂装技巧)

这是所有美丽的代码:

public Entity[] collisions(Entity thisEntity) {                                                                                                              
ArrayList<Entity> list = new ArrayList<Entity>();                                                                                                        
try {                                                                                                                                                    
    for (Entity e : getLevel().getEntities()) {                                                                                                          

        System.out.println("rect contains = "+thisEntity.getRect().contains(e.getRect()));                                                               

        if (!thisEntity.equals(e)) {                                                                                                                     
            Rectangle r = e.getRect();                                                                                                                   
            r = thisEntity.getRect();                                                                                                                    

            if (thisEntity.getRect().intersects(e.getRect())) {                                                                                          

                //get variables to create a space designated for the intersection areas involved                                                         
                int maxLengthY = Math.max(thisEntity.getMask().length, e.getMask().length);                                                              
                int maxLengthX = Math.max(thisEntity.getMask()[0].length, thisEntity.getMask()[0].length);                                               

                int minX = Math.min(thisEntity.getX(), e.getX());                                                                                        
                int minY = Math.min(thisEntity.getY(), e.getY());                                                                                        

                int[][] map = new int[maxLengthX + minX][maxLengthY + minY]; //create a matrix which merges both Entity's mask's to compare                                                                                                                                                                                                                                                                                                                                       

                for(int curX = 0; curX < maxLengthX + minX; curX++) { //only loop through the co-ords that area affected                                 
                    for(int curY = 0; curY < maxLengthY + minY; curY++) {                                                                                

                        int this_x = thisEntity.getX();                                                                                                  
                        int this_width = thisEntity.getImage().getWidth();                                                                               
                        int this_y = thisEntity.getY();                                                                                                  
                        int this_height = thisEntity.getImage().getHeight();                                                                             
                        int[][] this_mask = thisEntity.getMask();                                                                                        
                        if(curX < (this_x + this_width) && curX > this_x) {//check that the co-ords used are relevant for thisEntity's mask              

                            if(curY < (this_y + this_height) && curY > this_y) {                                                                         
                                map[curX][curY] = this_mask[Math.abs(curX - this_x)][Math.abs(curY - this_y)]; // store data from mask to map            
                            }                                                                                                                            
                        }                                                                                                                                

                        int other_x = e.getX();                                                                                                          
                        int other_width = e.getImage().getWidth();                                                                                       
                        int other_y = e.getY();                                                                                                          
                        int other_height = e.getImage().getHeight();                                                                                     
                        int[][] other_mask = e.getMask();                                                                                                

                        if(curX < (other_x + other_width) && curX > other_x) { //check that the co-ords used are relevant for e's mask                   
                            if(curY < (other_y + other_height) && curY > other_y) {                                                                      
                                if(map[curX][curY] == 1) { //check if this segment is already written by thisEntity                                      
                                    map[curX][curY] = 2;   //if yes, set to 2 instead of e's value to show collision                                     
                                } else {                                                                                                                 
                                    map[curX][curY] = other_mask[curX][curY]; // the minus to nullify minX and minY "requirements"                       
                                }                                                                                                                        
                            }                                                                                                                            
                        }                                                                                                                                
                    }                                                                                                                                    
                }                                                                                                                                                                                                                                                                             
            }                                                                                                                                            
        }                                                                                                                                                
    }                                                                                                                                                    
} catch (Exception excp) {                                                                                                                               
    excp.printStackTrace();                                                                                                                              
}                                                                                                                                                        
return list.toArray(new Entity[1]);                                                                                                                      
}                                                                                                                                                            

另外,这是方法getMask():

    public int[][] getMask() {
        return mask;
    }

    ...

    private void createMask(BufferedImage image) {

    final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
    final int width = image.getWidth();
    final int height = image.getHeight();
    final boolean hasAlphaChannel = image.getAlphaRaster() != null;

    int[][] result = new int[height][width];
    if (hasAlphaChannel) {
        for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += 4) {
            int alpha = pixels[pixel];
            if(alpha != 0) {
                result[row][col] = 1;
            } else {
                result[row][col] = 0;
            }

            if (col == width) {
                col = 0;
                row++;
            }
        }
    }
    mask = result;

}

但是……这段代码没有按预期工作,在某些情况下,就像在将各个蒙版添加到地图时一样,我得到了IndexOutOfBounds,即使它应该有效,所以它可能只是我忽略了一些东西……

总而言之,我需要帮助我的代码:

>它有什么问题?
>我该如何解决?
>有没有更有效的方式来进行这种类型的碰撞?
>您是否推荐其他类型的碰撞?如果是这样,他们是什么?

解决方法:

创建实体时,是否从完全相同大小的图像创建蒙版?因为否则实体的掩码和图像映射将使用不同的坐标系(entity.mask [0] [0]可能位于其角落,当map [0] [0]位于“世界”的角落时,并且你在线上比较相同的指数:

map[curX][curY] = other_mask[curX][curY];

(上面的代码中你实际上得到的是与Math.abs(a-b)相同的坐标系)

至于更有效的方法来检测碰撞,您可以在*上的collision detection in general查看binary space partitioning及更多内容.

上一篇:在哈希冲突中,CPython如何知道在索引HASHVALUE中存储哪个值以及哪个值存储在RESOLUTIONINDEX中


下一篇:c# – 具有厚壁的2D迷宫中的碰撞检测