2017-06-25 6 views
9

私は、CustomViewとImageビューを持っています。 CustomViewは、画面の周りを移動して壁から跳ね返るボールです。画像は四分円で、タッチすると円で回転できます。私は自分のゲームを作成しようとしているので、ImageViewからの塗りつぶされたピクセルで、CustomViewの交差パスから塗りつぶされたピクセルが検出されたときに衝突が検出されます。私が抱えている問題は、各ビューに塗りつぶされたピクセルがどこにあるかを取得する方法がわかりません。カスタムビューとImageView間のピクセル完全衝突検出

private class MyOnTouchListener implements View.OnTouchListener { 

    private double startAngle; 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 

     switch (event.getAction()) { 

      case MotionEvent.ACTION_DOWN: 
       startAngle = getAngle(event.getX(), event.getY()); 
       break; 

      case MotionEvent.ACTION_MOVE: 
       double currentAngle = getAngle(event.getX(), event.getY()); 
       rotateDialer((float) (startAngle - currentAngle)); 
       startAngle = currentAngle; 
       break; 

      case MotionEvent.ACTION_UP: 
       break; 
     } 
     return true; 
    } 
} 

private double getAngle(double xTouch, double yTouch) { 
    double x = xTouch - (dialerWidth/2d); 
    double y = dialerHeight - yTouch - (dialerHeight/2d); 

    switch (getQuadrant(x, y)) { 
     case 1: 
      return Math.asin(y/Math.hypot(x, y)) * 180/Math.PI; 
     case 2: 
      return 180 - Math.asin(y/Math.hypot(x, y)) * 180/Math.PI; 
     case 3: 
      return 180 + (-1 * Math.asin(y/Math.hypot(x, y)) * 180/Math.PI); 
     case 4: 
      return 360 + Math.asin(y/Math.hypot(x, y)) * 180/Math.PI; 
     default: 
      return 0; 
    } 
} 

/** 
* @return The selected quadrant. 
*/ 
private static int getQuadrant(double x, double y) { 
    if (x >= 0) { 
     return y >= 0 ? 1 : 4; 
    } else { 
     return y >= 0 ? 2 : 3; 
    } 
} 

/** 
* Rotate the dialer. 
* 
* @param degrees The degrees, the dialer should get rotated. 
*/ 
private void rotateDialer(float degrees) { 
    matrix.postRotate(degrees, dialerWidth/2, dialerHeight/2); 

    dialer.setImageMatrix(matrix); 
} 

そして、私のAnimatedView

public class AnimatedView extends ImageView { 

private Context mContext; 
int x = -1; 
int y = -1; 
private int xVelocity = 10; 
private int yVelocity = 5; 
private Handler h; 
private final int FRAME_RATE = 60; 

public AnimatedView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    mContext = context; 
    h = new Handler(); 
} 

private Runnable r = new Runnable() { 
    @Override 
    public void run() { 
     invalidate(); 
    } 
}; 

protected void onDraw(Canvas c) { 
    BitmapDrawable ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.smallerball); 

    if (x<0 && y <0) { 
     x = this.getWidth()/2; 
     y = this.getHeight()/2; 
    } else { 
     x += xVelocity; 
     y += yVelocity; 
     if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) { 
      xVelocity = xVelocity*-1; 
     } 
     if ((y > this.getHeight() - ball.getBitmap().getHeight()) || (y < 0)) { 
      yVelocity = yVelocity*-1; 
     } 
    } 

    c.drawBitmap(ball.getBitmap(), x, y, null); 
    h.postDelayed(r, FRAME_RATE); 
} 

public float getX() { 
    return x; 
} 

public float getY() { 
    return y; 
} 

} 
:ここ

は私のXMLコード

<com.leytontaylor.bouncyballz.AnimatedView 
    android:id="@+id/anim_view" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent" 
    /> 

<ImageView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:id="@+id/quartCircle" 
    android:layout_gravity="center_horizontal" 
    android:src="@drawable/quartercircle" 
    android:scaleType="matrix"/> 

マイMainActivity

public class MainActivity extends AppCompatActivity { 

private static Bitmap imageOriginal, imageScaled; 
private static Matrix matrix; 

private ImageView dialer; 
private int dialerHeight, dialerWidth; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // load the image only once 
    if (imageOriginal == null) { 
     imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.quartercircle); 
    } 

    // initialize the matrix only once 
    if (matrix == null) { 
     matrix = new Matrix(); 
    } else { 
     // not needed, you can also post the matrix immediately to restore the old state 
     matrix.reset(); 
    } 

    dialer = (ImageView) findViewById(R.id.quartCircle); 
    dialer.setOnTouchListener(new MyOnTouchListener()); 
    dialer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 

     @Override 
     public void onGlobalLayout() { 
      // method called more than once, but the values only need to be initialized one time 
      if (dialerHeight == 0 || dialerWidth == 0) { 
       dialerHeight = dialer.getHeight(); 
       dialerWidth = dialer.getWidth(); 

       // resize 
       Matrix resize = new Matrix(); 
       resize.postScale((float) Math.min(dialerWidth, dialerHeight)/(float) imageOriginal.getWidth(), (float) Math.min(dialerWidth, dialerHeight)/(float) imageOriginal.getHeight()); 
       imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false); 

       // translate to the image view's center 
       float translateX = dialerWidth/2 - imageScaled.getWidth()/2; 
       float translateY = dialerHeight/2 - imageScaled.getHeight()/2; 
       matrix.postTranslate(translateX, translateY); 

       dialer.setImageBitmap(imageScaled); 
       dialer.setImageMatrix(matrix); 

      } 
     } 
    }); 
} 

MyOnTouchListenerクラスです3210

私の質問は:これらのビューの両方から塗りつぶされたピクセルを取得し、衝突を検出する関数にそれらを渡すにはどうすればよいですか。

助けを事前に感謝を!:)

+4

「Pixel-perfect」と「Android」は良い友達ではありませんでした。 –

+0

@Rotwangアニメーションオブジェクトの衝突検出にはどのような提案がありますか? – Leyton

+0

私は分かりません。私はゲームにはない。私は画面密度に比例した何らかの座標系を仮定しています。 –

答えて

1

"塗りつぶされたピクセル"を定義する必要があります。私はあなたが非透明ピクセルを意味すると仮定します。それらを見つける最も簡単な方法は、ビュー全体をビットマップに変換し、そのピクセルを反復することです。あなたViewはこのようなBitmapに変換することができます

private Bitmap getBitmapFromView(View view) { 
    view.buildDrawingCache(); 
    Bitmap returnedBitmap = Bitmap.createBitmap(view.measuredWidth, 
      view.measuredHeight, 
      Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(returnedBitmap); 
    canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN); 
    Drawable drawable = view.background; 
    drawable.draw(canvas); 
    view.draw(canvas); 
    return returnedBitmap; 
} 

ます。また、ビューの絶対位置を取得する必要があるだろう:

Point getViewLocationOnScreen(View v) { 
    int[] coor = new int[]{0, 0}; 
    v.getLocationOnScreen(coor); 
    return new Point(coor[0], coor[1]); 
} 

次に、あなただけのそれぞれのピクセルを反復処理する必要がありますBitmapの色をチェックして、色が塗りつぶされているかどうかを確認し、ビットマップ内での調整と画面上のビューの絶対位置に基づいてオーバーラップしているかどうかもチェックします。

for (int x = 0; x < myBitmap.getWidth(); x++) { 
    for (int y = 0; y < myBitmap.getHeight(); y++) { 
     int color = myBitmap.getPixel(x, y); 
    } 
} 

しかし、私は本当に良いアイデアですUIスレッド上に重い計算のこの種を行わないと思う、と言わなければならない:ビットマップのを反復

は次のように行われます。ピクセル完全チェックよりも衝突を検出する方法が数多くあります。これはおそらく極端に遅いです。

1

あなたは(原点に基づいてそれらを計算する/し、移動中にそれらを更新)あなたの境界座標をマーキングポイントの配列を使用して画像をカプセル化することができ、あなたのことができるようになりますオブジェクトが接触しているかどうかを判断する(配列が重なると同じ点を共有する場合)