проверить коллизию между двумя разными пользовательскими представлениями, чьи родители разные - PullRequest
0 голосов
/ 30 августа 2018

У меня есть собственное представление "Stick", которое расширяет RelativeLayout. У меня есть другой пользовательский вид "Ball", который также расширяет RelativeLayout. И их родители разные. В любое время на экране есть несколько (или один) автоматически движущихся шаров и палочек. Я хочу получать информацию, когда мяч сталкивается с палкой. Значит, я хочу что-то сделать, когда происходит столкновение. В настоящее время я запускаю бесконечный цикл, чтобы проверить, пересекается ли текущий ограничивающий прямоугольник шара с текущим ограничивающим прямоугольником палочек. Но это слишком дорого, и если на экране несколько палочек и шаров, этот метод не работает или почти не работает. Есть ли лучший способ сделать это или есть слушатель столкновения зрения в Android?

Ниже приведен класс ручки

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.RelativeLayout;
import java.util.ArrayList;

public class Stick extends RelativeLayout {

    int height;
    String dest;
    Context context;
    RelativeLayout.LayoutParams layoutParams;
    private static int stickDecelerate = 2000;
    private static ArrayList<Stick> stickList = new ArrayList<Stick>();

    public static ArrayList<Stick> getStickList() {
        return stickList;
    }

    public static int getStickDecelerate() {
        return stickDecelerate;
    }

    public static void setStickDecelerate(int stickDecelerate) {
        Stick.stickDecelerate = stickDecelerate;
    }

    public Stick(Context context){
        super(context);
    }

    public Stick(Context context, int height, String dest, int leftMargin, int topMargin) {
        super(context);
        this.context = context;
        this.height = height;
        this.dest = dest;

        if(dest.equals("left") || dest.equals("right")){
            layoutParams = new RelativeLayout.LayoutParams(height*5, height);
            layoutParams.setMargins(leftMargin-(height*5)/2, topMargin-height/2, 0, 0);
        }
        else{
            layoutParams = new RelativeLayout.LayoutParams(height, height*5);
            layoutParams.setMargins(leftMargin-height/2, topMargin-(height*5)/2, 0, 0);
        }
        this.setLayoutParams(layoutParams);
    }

    public void release(){
        Stick stick = new Stick(context);
        stick.setBackgroundColor(Color.YELLOW);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(this.getWidth(), this.getHeight());
        stick.setLayoutParams(layoutParams);
        this.addView(stick);
        ObjectAnimator animation;
        if(dest.equals("right")) animation = ObjectAnimator.ofFloat(stick, "translationX", GameScreen.getMin());
        else if(dest.equals("left")) animation = ObjectAnimator.ofFloat(stick, "translationX", -GameScreen.getMin());
        else if(dest.equals("up")) animation = ObjectAnimator.ofFloat(stick, "translationY", -GameScreen.getMin());
        else animation = ObjectAnimator.ofFloat(stick, "translationY", GameScreen.getMin());
        animation.setDuration(stickDecelerate);
        animation.start();
        stickList.add(stick);

        animation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                stickList.remove(stick);
                stick.setVisibility(View.GONE);
            }
        });

    }

    public void preview(){

    }

}

ниже класса Мяч

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.view.View;
import android.widget.RelativeLayout;

import java.util.Random;

public class Ball extends View{

    int circleBounds;

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        canvas.drawCircle(circleBounds/4, circleBounds/4, circleBounds/4, paint);
    }

    public Ball(Context context) {
        super(context);
    }

    public Ball(Context context, int circleBounds) {
        super(context);
        this.circleBounds = circleBounds;
        RelativeLayout.LayoutParams ballParams = new RelativeLayout.LayoutParams(circleBounds/2, circleBounds/2);
        this.setLayoutParams(ballParams);
        startMoving();
    }

    private void startMoving(){
        Random randomAngle = new Random();
        int random = randomAngle.nextInt(360);
        int x = (int) ((int) GameScreen.getMin()*Math.cos(random));
        int y = (int) ((int) GameScreen.getMin()*Math.sin(random));
        ObjectAnimator animX = ObjectAnimator.ofFloat(this, "x", x);
        ObjectAnimator animY = ObjectAnimator.ofFloat(this, "y", y);
        long animDuration = (long) (Stick.getStickDecelerate()*2.2);
        animX.setDuration(animDuration);
        animY.setDuration(animDuration);
        AnimatorSet animation = new AnimatorSet();
        animation.playTogether(animX, animY);
        animation.start();
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(Important.checkCollision(Ball.this)){
                    animation.cancel();
                    Ball.this.setVisibility(View.GONE);
                    return;
                }
                handler.postDelayed(this, 0);
            }
        }, 0);
        animation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                Ball.this.setVisibility(View.GONE);
            }
        });
    }

}

и ниже - метод проверки столкновения

public static boolean checkCollision(View ball){
    ArrayList<Stick> stickList = Stick.getStickList();
    int[] rec1Pos = new int[2];
    ball.getLocationOnScreen(rec1Pos);
    int v1_w = ball.getWidth();
    int v1_h = ball.getHeight();
    Rect ballBound = new Rect(rec1Pos[0], rec1Pos[1], rec1Pos[0] + v1_w, rec1Pos[1] + v1_h);
    for(Stick stick:stickList){
        int[] rec2Pos = new int[2];
        stick.getLocationOnScreen(rec2Pos);
        int v2_w = stick.getWidth();
        int v2_h = stick.getHeight();
        Rect stickBound = new Rect(rec2Pos[0], rec2Pos[1], rec2Pos[0] + v2_w, rec2Pos[1] + v2_h);
        return ballBound.intersect(stickBound);
    }
    return false;
}

1 Ответ

0 голосов
/ 30 августа 2018

Хорошо, попробуйте этот логический метод, верните true, если мяч столкнулся.

public boolean checkCollision(View ball)
{
    boolean result = false;

    for(Stick stick : Stick.getStickList())
    {
         if(collision(ball, stick))
         {
             result = true;
             break;
         }
         else result = false;
     }

    return result;
}

/*Gets View HitRect*/
public boolean collision(View a, View b)
{
   Rect aRect = new Rect();
   a.getHitRect(aRect);
   Rect bRect = new Rect();
   b.getHitRect(bRect);
   return aRect.intersect(bRect);
}

И Render() метод вашей игры:

Thread t = new Thread() {
 @Override
 public void run() {
 try {
    while (!isInterrupted()) {
         Thread.sleep(100);
         runOnUiThread(new Runnable() {
         @Override
         public void run(){Render();}});}
         }catch (InterruptedException e) {}}};

 t.start();
}

public void Render()
{
    if(checkCollision(ball))
    {
      //Do something
    }
}
...