我目前正在尝试测试坠落物体和盒子之间的碰撞。我理解基本的碰撞检测,但我的问题是我必须测试它是否有无限数量的坠落物体。创建这些对象(开花)时,它们存储在ArrayList中。 ArrayList处理画布上对象的绘制(使用for each来更新位置)。我的问题出现在一个开花被“抓住”的盒子里。如何在没有空引用的情况下使其从屏幕上消失/从数组列表中删除?我可以向你展示我到目前为止的逻辑......请让我知道你的想法。我真的被困住了,但觉得我已经非常接近这个了。
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;
}
}
}
}
答案 0 :(得分:2)
你可以做到这一点的一种方法是在Blossom
上有一个字段来指示它是否处于活动状态,然后只有在它处于活动状态时才绘制它。如果它处于非活动状态,则另一个Blossom
可以在列表中替换它。
答案 1 :(得分:1)
设置可见性标志是一种可行的方法,但是我建议不要这样做,因为你要向ArrayList添加不确定数量的Bitmaps ......你会发现自己很快耗尽了内存。将碰撞检测迭代器从foreach更改为手写循环,这将避免您在上面列出的代码中遇到的并发问题。
for (int i = 0; i < blossomArrayList.size(); i++)
{
if(blossom.hit(box_x,box_y, box_x + boxWidth, box_y + boxHeight)) {
blossomArrayList.remove(i);
}
}
此外,我建议将所有ArrayList foreach迭代器更改为手写for循环,因为迭代ArrayLists(但不是任何其他对象)在Android上相对较慢并且可能导致意外的并发问题。
第三,似乎你只需要在UpdatePositions循环完成后运行一次Collision()方法,因为你已经在你的Collision()方法中检查了每个Blossom。