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

时间:2015-01-29 22:56:34

标签: java arrays collision

我目前正在为2D游戏进行碰撞。我做了一些研究并扣除了我应该使用将α值像素存储到"掩码中的方法。实体的形象,另一个的形象。然后,我采取两个实体' 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& 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"     
            }                                                                                                      
        }                                                                                                          
    }                                                                                                              
}                                                                                                                  
}            

生成Array&#34;地图&#34;看起来像SO:

img (原谅我的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,即使它应该有效,所以它也是如此。可能只是我忽略了一些事情......

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

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

1 个答案:

答案 0 :(得分:1)

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

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

(上面的代码中你实际上是那些带有Math.abs(a-b)的同一坐标系的代码)

至于更有效的方法来检测碰撞,您可以在维基百科上的binary space partitioning上查看collision detection in general等内容。