从ArrayList的冲突检测/删除对象冲突、对象、ArrayList

2023-09-08 09:07:51 作者:想星星想饿了

我目前正在测试一个下落的物体和一个盒子之间的碰撞。我了解基本的碰撞检测,但在这里,我的问题是,我不得不测试它的掉落物品数量不确定。当创建这些对象(开花),它们被存储在一个ArrayList。该ArrayList处理画布(使用每个更新的位置)上的对象的图形。我的问题是当一个盛开在盒子中招。我如何使它从屏幕/从数组列表没有空引用删除发生的消失?我可以告诉你我迄今为止的逻辑......请让我知道你在想什么。我很坚持,但感觉我如此接近搞清楚了这一点。

花类

 公共类花{私人位图开花;私人INT blossom_x = 0;私人INT blossom_y = 0;私人INT blossomWidth = 0;私人INT blossomHeight = 0;私人布尔命中= FALSE;私人随机发生器=新的随机();RectF blossomRect;私有静态最后弦乐TAG =调试;市民花(位图位图){    花=位图;    blossomWidth = blossom.getWidth();    blossomHeight = blossom.getHeight();    blossom_x = generator.nextInt(320-blossom.getWidth());    blossomRect =新RectF(blossom_x,blossom_y,blossom_x + blossomWidth,blossom_y + blossomHeight);}公共位图getBitmap(){    返回开花;}公共布尔命中(INT boxLeft,诠释boxTop,诠释boxRight,诠释boxBottom){    如果(blossom_x> boxLeft&安培; blossom_y> boxTop            &安培; blossom_x + blossom.getWidth()&下; boxRight            &安培; blossom_y + blossom.getHeight()&下; boxBottom)    {        Log.v(TAG,碰撞检测);        返回true;    }    其他    {        返回false;    }}公众持股量getBlossomX(){    返回blossom_x;}公众持股量getBlossomY(){    返回blossom_y;}公众持股量getBlossomWidth(){    返回blossomWidth;}公众持股量getBlossomHeight(){    返回blossomHeight;}公共无效抽奖(帆布油画){    //绘制花卉下降    如果(命中== FALSE)    {        canvas.drawBitmap(开花,blossom_x,            blossom_y = blossom_y + 5,NULL);    }}公共无效UpdatePosition(){    blossomRect.set(blossom_x,blossom_y,blossom_x + 25,+ blossom_y 25);} 

}

BoardView

 公共类BoardView扩展SurfaceView实现SurfaceHolder.Callback {上下文mContext;位图箱=    (BitmapFactory.de codeResource            (getResources(),R.drawable.box));私人BoardThread螺纹;私人INT box_x = 140;私人INT box_y = 378;私人INT boxWidth = box.getWidth();私人INT boxHeight = box.getHeight();私人的ArrayList<&开花GT; blossomArrayList =新的ArrayList<&开花GT;();私人INT blossomNum = 0;私人字符串分;私人INT currentScore = 0;螺纹定时器;布尔模式= FALSE;布尔游戏= FALSE;私有静态最后弦乐TAG =调试;最终油漆scorePaint =新的油漆();公共BoardView(上下文的背景下){    超级(上下文);    scorePaint.setColor(Color.BLACK);    scorePaint.setTextSize(12);    scorePaint.setTypeface(Typeface.MONOSPACE);    // surfaceHolder规定,我们在画布上绘制    。getHolder()的addCallback(本);    //控制图纸    线程=新BoardThread(getHolder(),这一点,blossomArrayList,box_x,box_y,            boxWidth,boxHeight);    定时器=新的Thread(){        公共无效的run(){            //确保玩家仍留下3个生命            而(游戏== FALSE){                uiCallback.sendEmptyMessage(0);                尝试{                    视频下载(2000); //绘制下一花前等待两秒钟                }赶上(InterruptedException的E){                    // TODO自动生成catch块                    e.printStackTrace();                } //睡眠2秒            }        }    };    timer.start();    //拦截触摸事件    setFocusable(真);}@覆盖公共无效的onDraw(帆布油画){    canvas.drawColor(Color.WHITE);    分数=分数:+ currentScore;    //注意:要注意命令你借鉴的东西    //不改变顺序,否则花朵将下降    //在盒子的顶部,而不是变成了。    //显示记分牌    canvas.drawText(评分,240420,scorePaint);    //抽奖箱,并设置起始位置    对于(花开花:blossomArrayList)//这里得到错误    {            blossom.Draw(画布);            blossom.hit(box_x,box_y,box_x + boxWidth,box_y + boxHeight);    }    canvas.drawBitmap(盒,box_x,box_y,NULL);}@覆盖公共布尔onTouchEvent(MotionEvent事件){    //处理盒的运动    如果(event.getAction()== MotionEvent.ACTION_DOWN){        如果(event.getX()> box_x&放大器; event.getY()> box_y&放大器;                event.getX()&下; box_x + boxWidth&安培; event.getY()&下; box_y + boxHeight)        {            模式=真实的;        }    }    如果(event.getAction()== MotionEvent.ACTION_MOVE){        如果(event.getX()> box_x&放大器; event.getY()> box_y&放大器;                event.getX()&下; box_x + boxWidth&安培; event.getY()&下; box_y + boxHeight)        {            模式=真实的;        }        如果(模式==真){            box_x =(int)的event.getX();        }    }    如果(event.getAction()== MotionEvent.ACTION_UP){        模式= FALSE;    }    无效();    返回true;}@覆盖公共无效surfaceChanged(SurfaceHolder持有人,        INT格式,诠释的宽度,高度INT){    Log.v(TAG,表面改变);    //不知何故这些似乎并不奏效}@覆盖公共无效surfaceCreated(SurfaceHolder持有人){    thread.startRunning(真);    thread.start();}@覆盖公共无效surfaceDestroyed(SurfaceHolder持有人){    Log.v(TAG,表面被摧毁);    //不知何故这些似乎并不奏效    thread.startRunning(假);    使用Thread.stop();    timer.interrupt();    timer.stop();}私人处理程序uiCallback =新的处理程序(){    公共无效的handleMessage(消息MSG){        //添加一个新的开花到开花的ArrayList!        blossomArrayList.add(新花(            (BitmapFactory.de codeResource                    (getResources(),R.drawable.blossom))));        blossomNum ++;        //删除列表neccesary花        Log.v(TAG,+ blossomNum玉堂数=);    }}; 

}

BoardThread

 公共类BoardThread继承Thread {私人SurfaceHolder surfaceHolder;私人BoardView boardView;私人的ArrayList<&开花GT; blossomArrayList;私人诠释BOXX;私人诠释四四方方;私人诠释boxWidth;私人诠释boxHeight;私人布尔mrun = FALSE;公共BoardThread(SurfaceHolder架,BoardView boardView2,        ArrayList的<&开花GT; blossomArrayList1,        INT box_x,诠释box_y,诠释boxW,诠释boxH){    surfaceHolder =持有人;    boardView = boardView2;    blossomArrayList = blossomArrayList1;    BOXX = box_x;    四四方方= box_y;    boxW = boxWidth;    boxH = boxHeight;}公共无效startRunning(布尔运行){    mrun =运行;}@覆盖公共无效的run(){    super.run();     帆布油画;     而(mrun){        帆布= NULL;         尝试{             帆布= surfaceHolder.lockCanvas(NULL);              同步(surfaceHolder){                 //测试碰撞                 碰撞(blossomArrayList,BOXX,四四方方,boxWidth,boxHeight);                 //划花                 boardView.onDraw(画布); //这里得到错误 - 并行             }         } {最后                 如果(帆布!= NULL){                 surfaceHolder.unlockCanvasAndPost(画布);             }         }     }  }公共无效碰撞(ArrayList的<&开花GT; blossomArrayList,诠释box_x,INT box_y,        INT boxWidth,诠释boxHeight){    对于(花开花:blossomArrayList)    {        blossom.UpdatePosition();        如果(blossom.hit(box_x,box_y,box_x + boxWidth,box_y + boxHeight)==真)        {            ///如果花抓,增加得分            // currentScore + = 100;        }    }}} 
ArrayList集合使用

解决方案

设置可视性标志是去你的,不过我建议你反对它,因为您要添加的位图不定量到一个ArrayList ...一种方式会发现自己很快耗尽内存pretty的。从一个foreach于手写循环更改碰撞检测的迭代器,这将避免你可能在你上面列出的code运行并发的问题。

 的for(int i = 0; I< blossomArrayList.size();我++)            {                如果(blossom.hit(box_x,box_y,box_x + boxWidth,box_y + boxHeight)){                    blossomArrayList.remove(ⅰ);                }            } 

此外,我建议改变所有的ArrayList的foreach迭代器手写for循环,作为迭代的ArrayList(而不是任何其他物体)是Android上的相对较慢,并且会导致意想不到的并发问题。

第三,它好像你只需要你的UpdatePositions循环后运行一次的碰撞()方法已经完成了,因为你已经在你的碰撞检查每花()方法。

I am currently trying to test collision between a falling object and a box. I understand basic collision detection, but my problem here is that I have to test it for an indefinite number of falling objects. When these objects(blossoms) are created, they are stored in an ArrayList. The ArrayList handles the drawing of the object on the canvas (using a for each to update the position). My problem comes when a blossom is "caught" in the box. How do I make it disappear from the screen/removed from the array list without a null reference happening? I can show you the logic I have so far...please let me know what you think. I am REALLY stuck, but feel like I'm so close to figuring this out.

Blossom Class

public class Blossom{
private Bitmap blossom;
private int blossom_x = 0;
private int blossom_y = 0;
private int blossomWidth = 0;
private int blossomHeight = 0;
private boolean hit = false;

private Random generator = new Random();
RectF blossomRect;

private static final String TAG = "Debug";

public Blossom(Bitmap bitmap)
{
    blossom = bitmap;
    blossomWidth = blossom.getWidth();
    blossomHeight = blossom.getHeight();
    blossom_x = generator.nextInt(320-blossom.getWidth());
    blossomRect = new RectF(blossom_x,blossom_y, blossom_x + blossomWidth, blossom_y + blossomHeight);
}

public Bitmap getBitmap()
{
    return blossom;
}

public Boolean hit(int boxLeft, int boxTop, int boxRight,int boxBottom)
{
    if(blossom_x > boxLeft & blossom_y > boxTop
            & blossom_x + blossom.getWidth() < boxRight
            & blossom_y + blossom.getHeight() < boxBottom)
    {
        Log.v(TAG, "Collision Detected");
        return true;
    }
    else
    {
        return false;
    }
}

public float getBlossomX()
{
    return blossom_x;
}

public float getBlossomY()
{
    return blossom_y;
}

public float getBlossomWidth()
{
    return blossomWidth;
}

public float getBlossomHeight()
{
    return blossomHeight;
}

public void Draw(Canvas canvas)
{
    //draws the flower falling
    if (hit == false)
    {
        canvas.drawBitmap(blossom, blossom_x,
            blossom_y = blossom_y+5 , null);
    }

}

public void UpdatePosition()
{
    blossomRect.set(blossom_x, blossom_y, blossom_x + 25, blossom_y + 25);
}

}

BoardView

public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;

Bitmap box = 
    (BitmapFactory.decodeResource
            (getResources(), R.drawable.box));

private BoardThread thread;
private int box_x = 140;
private int box_y = 378;
private int boxWidth = box.getWidth();
private int boxHeight = box.getHeight();
private ArrayList<Blossom> blossomArrayList = new ArrayList<Blossom>();
private int blossomNum = 0;
private String score;
private int currentScore = 0;
Thread timer;

boolean mode = false;
boolean game = false;

private static final String TAG = "Debug";
final Paint scorePaint = new Paint();

public BoardView(Context context){
    super(context);

    scorePaint.setColor(Color.BLACK);
    scorePaint.setTextSize(12);
    scorePaint.setTypeface(Typeface.MONOSPACE);


    //surfaceHolder provides canvas that we draw on
    getHolder().addCallback(this);

    // controls drawings
    thread = new BoardThread(getHolder(),this, blossomArrayList, box_x, box_y, 
            boxWidth, boxHeight);

    timer = new Thread(){
        public void run(){
            //makes sure the player still has 3 lives left
            while(game == false){
                uiCallback.sendEmptyMessage(0);
                try {
                    Thread.sleep(2000); // wait two seconds before drawing the next flower
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } //sleep for 2 seconds
            }
        }
    };
    timer.start();

    //intercepts touch events
    setFocusable(true);

}

@Override

public void onDraw(Canvas canvas){
    canvas.drawColor(Color.WHITE);
    score = "SCORE: " + currentScore;

    //note: pay attention to order you draw things
    //don't change order or else blossoms will fall
    //on top of box, not "into" it.

    //display the scoreboard
    canvas.drawText(score,240,420,scorePaint);
    //draw box and set start location

    for(Blossom blossom: blossomArrayList)   // getting errors here
    {
            blossom.Draw(canvas);
            blossom.hit(box_x,box_y, box_x + boxWidth, box_y + boxHeight);

    }

    canvas.drawBitmap(box, box_x, box_y, null);

}

@Override
public boolean onTouchEvent(MotionEvent event){
    //handles movement of box
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        if(event.getX() > box_x & event.getY() > box_y & 
                event.getX() < box_x + boxWidth & event.getY() < box_y + boxHeight)
        {
            mode = true;
        }
    }

    if(event.getAction() == MotionEvent.ACTION_MOVE) {
        if(event.getX() > box_x & event.getY() > box_y & 
                event.getX() < box_x + boxWidth & event.getY() < box_y + boxHeight)
        {
            mode = true;
        }
        if(mode == true){
            box_x = (int)event.getX();
        }   

    }

    if(event.getAction() == MotionEvent.ACTION_UP){
        mode = false;
    }

    invalidate();
    return true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, 
        int format, int width, int height ){
    Log.v(TAG, "Surface Changed");
    //somehow these don't seem to be working
}

@Override
public void surfaceCreated(SurfaceHolder holder){
    thread.startRunning(true);
    thread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder){
    Log.v(TAG, "Surface Destroyed");
    //somehow these don't seem to be working
    thread.startRunning(false);
    thread.stop();
    timer.interrupt();
    timer.stop();
}

private Handler uiCallback = new Handler(){
    public void handleMessage(Message msg){
        //add a new blossom to the blossom ArrayList!!
        blossomArrayList.add(new Blossom( 
            (BitmapFactory.decodeResource
                    (getResources(), R.drawable.blossom))));
        blossomNum++;

        //remove neccesary blossoms from list
        Log.v(TAG, "Number of Blossoms =" + blossomNum);
    }
};

}

BoardThread

public class BoardThread extends Thread {

private SurfaceHolder surfaceHolder;
private BoardView boardView;

private ArrayList<Blossom> blossomArrayList;
private int boxX;
private int boxY;
private int boxWidth;
private int boxHeight;
private boolean mrun =false;

public BoardThread(SurfaceHolder holder, BoardView boardView2, 
        ArrayList<Blossom> blossomArrayList1,
        int box_x, int box_y, int boxW, int boxH) {

    surfaceHolder = holder;
    boardView=boardView2;

    blossomArrayList = blossomArrayList1;
    boxX = box_x;
    boxY = box_y;
    boxW = boxWidth;
    boxH = boxHeight;
}

public void startRunning(boolean run) {

    mrun=run;
}

@Override
public void run() {

    super.run();
     Canvas canvas;
     while (mrun) {
        canvas=null;
         try {
             canvas = surfaceHolder.lockCanvas(null);
              synchronized (surfaceHolder) {
                 //test for collision
                 Collision(blossomArrayList, boxX, boxY, boxWidth, boxHeight);
                 // draw flowers
                 boardView.onDraw(canvas);   // and getting errors here - concurrent 
             }
         } finally {
                 if (canvas != null) {
                 surfaceHolder.unlockCanvasAndPost(canvas);
             }
         }
     }
  }

public void Collision(ArrayList<Blossom> blossomArrayList, int box_x, int box_y, 
        int boxWidth, int boxHeight)
{
    for(Blossom blossom: blossomArrayList)
    {
        blossom.UpdatePosition();
        if(blossom.hit(box_x,box_y, box_x + boxWidth, box_y + boxHeight) == true)
        {
            ///if flower is caught, add to score
            //currentScore += 100;
        }

    }
}

}

解决方案

Setting a visibility flag is one way to go, however I'd recommend against it since you are adding an indeterminate amount of Bitmaps to an ArrayList...you'll find yourself running out of memory pretty quickly. Change your collision detection iterator from a foreach to a handwritten loop, this will avoid concurrency issues you may run to in the code you have listed above.

for (int i = 0; i < blossomArrayList.size(); i++)
            {
                if(blossom.hit(box_x,box_y, box_x + boxWidth, box_y + boxHeight)) {
                    blossomArrayList.remove(i);
                }
            }

Additionally, I'd recommend changing all your ArrayList foreach iterators to hand written for loops, as iterating ArrayLists (but not any other object) is relatively slow on Android and can lead to unexpected concurrency issues.

Thirdly, it seems as though you only need to run your Collision() method once after your UpdatePositions loop has completed since you're already checking every Blossom in your Collision() method.

 
精彩推荐
图片推荐