Is there a way to check if one method draws over a

2019-08-25 02:14发布

问题:

I'm creating a rudimentary game and need to implement collision detection between the drawObstacle and drawRocketShip methods. I need to check if one method creates an image that overlaps another method. These aren't separated into different classes because of some randomization and position similarity checks I employ that have been omitted for the sake of brevity. I can elaborate further if required, but I thought that it wasn't necessarily needed to begin with.

public class SideScrollGame extends PApplet {

// Variables determining motion, window size, etc.

    public float rock1;
    public float rock2;
    public float rock3;
    public float rock4;
    public float rock5;


    public void setup(){
        size(width,height);
        //rock1 to rock5 are randomized values determining height.
    }

    public void draw(){
        moveShip();
        moveRock();

        drawObstacle(rock1, 3);
        drawObstacle(rock2, 3);
        drawObstacle(rock3, 3);
        drawObstacle(rock4, 3);
        drawObstacle(rock5, 3);         

        translate(x,y);
        // Code behind motion omitted for sake of brevity. It just moves the 
        // ship up and down across the Processing applet
        drawRocketShip();
        // drawObstacle and drawRocketShip create composite images using the
        // ellipse(), rect(), and triangle() functions.

    }
}

回答1:

You could maybe do it that way using the get() function. You can find more info in the reference, but basically it allows you to get the color at a specific pixel. You could perform some logic based on that.

But honestly, that's not the way you should be thinking about this. Instead of basing your collision detection on what's actually drawn, you should base your collision detection on a set of shapes that you store in memory. For most cases, a simple circle or rectangle will work just fine.

This gets more complicated if you're using the translate() function to draw everything, but you can convert your coordinates into screen coordinates using the screenX() and screenY() functions. Again, more info can be found in the reference.

Shameless self-promotion: I've written a tutorial on collision detection in Processing available here, but there are a ton of resources on the internet.

If you're still having trouble, please narrow your problem down to a MCVE and we'll go from there. Good luck.



回答2:

I need to check if one method creates an image that overlaps another method.

Your approach to detect collisions on the display is somewhat flaky...

Each program consist of 3 layers

  1. The Model, which holds the applications state,
  2. The Controller which provides the Business Logic
  3. The View which does User Interaction (input/output).

Even if your program does not explicitly expose this layers it has behavior that should be explicitly assigned to one of them.

To make the long story short: You try to find the collision in the View layer. But the Controller layer should look at the Model and find collisions there. This would enable you to change the UI (eg. from Swing to FX) or add a zoom feature without the collision detection logic being affected.

The problem I see (and which you have to solve) is that you currently have only images to represent the shapes of your objects. You need to convert that images to model classes that can calculate their distance:


/// represents a point in an abstract coordinate system where 
/// the coordinates must be less than Integer.MAX_VAL/2 
/// and bigger than Integer.MIN_VAL/2
/// to avoid integer overflows on calculations 
class GameCoordinate{
   public final int x; 
   public final int y;
   GameCoordinate(int x,  int y){
     this.x = x;
     this.y = y;
   }
}

/// something that can cause a colision
interface GameObject{
   GameCoordinate getCenter();
   GameCoordinate getNearestSurfacePointTo(GameObject other);
   boolean collidesWith(GameObject other);
} 

class Cycle implements GameObject{
   private final GameCoordinate center;
   private final int radius;
   Cycle(GameCoordinate center, radius){
     this.center = center;
     this.radius = radius;     
   }
   @Override
   GameCoordinate getCenter(){
     return center;
   }
   @Override
   GameCoordinate getNearestSurfacePointTo(GameObject other){
      deltaX= (int)(center.x-other.getCenter().x); 
      deltaY= (int)(center.y-other.getCenter().y); 
      return new GameCoordinate(
         center.x +(radius*(deltaY/deltaX))),
         center.y +(radius*(deltaX/deltaY))));      
   }
   @Override
   boolean collidesWith(GameObject other){
      GameCoordinate othersNearestPointToMe = other.getNearestSurfacePointTo(center);
      deltaX= (int)(center.x-othersNearestPointToMe.getCenter().x); 
      deltaY= (int)(center.y-othersNearestPointToMe.getCenter().y);
      return radius >= (int)Math.abs(Math.sqr( deltaX*deltaX+deltaY*deltaY));     
   }   
}

Calculations for polygons might be more complex...