0

我刚开始使用 eclipse 进行 Android 编程,最近遇到了这个问题。我有一堆精灵分配给一个数组列表。现在,我想让它自动检测精灵之间的碰撞,但我当前使用的模板只能检测表面边界和移动精灵之间的碰撞。每个精灵的位置和速度都是随机生成的。如何更改我的 Sprite() 类中的 update() 函数以检测移动精灵本身之间的碰撞以及同时改变/反弹到相反方向?这是我的 Sprite 类模板:

package com.gameproject.cai_test;

import java.util.Random;


   public Sprite(GameView gameView, Bitmap bmp) {
         this.width = bmp.getWidth() / BMP_COLUMNS;
         this.height = bmp.getHeight() / BMP_ROWS;
         this.gameView = gameView;
         this.bmp = bmp;


         Random rnd = new Random();
         x = rnd.nextInt(gameView.getWidth() - width);
         y = rnd.nextInt(gameView.getHeight() - height);
         xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
         ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
   }

private void update() {
         if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
                xSpeed = -xSpeed;
         }
         x = x + xSpeed;
         if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
                ySpeed = -ySpeed;
         }
         y = y + ySpeed;

         currentFrame = ++currentFrame % BMP_COLUMNS;
   }

   public void onDraw(Canvas canvas) {
         update();
         int srcX = currentFrame * width;
         int srcY = getAnimationRow() * height;
         Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
         Rect dst = new Rect(x, y, x + width, y + height);

         canvas.drawBitmap(bmp, src, dst, null);
   }

   private int getAnimationRow() {
         double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
         int direction = (int) Math.round(dirDouble) % BMP_ROWS;
         return DIRECTION_TO_ANIMATION_MAP[direction];
   }


   //gameplay operations

   //only values from 0 to 9 will be picked; each assigned its own sprite in the list
   public int randomValue(){
       Random rnd = new Random();
       RandomValue = rnd.nextInt(10);
       return RandomValue; 
   }

   //sequence operation from addition, subtraction, multiplication, and division
   public int produceSum(){
       int addOne = 0;
       int addTwo = 0;
       Sum = addOne + addTwo;
       return Sum;
   }

   public int produceDiff(){
       int deductOne = 0;
       int deductTwo = 0;
       Difference = deductOne - deductTwo;
       return Difference;
   }

   public int produceProduct(){
       int multiOne = 0;
       int multiTwo = 0;
       Product = multiOne * multiTwo;
       return Product;
   }

   public int produceQuotient(){
       int divideOne = 0;
       int divideTwo = 0;
       Quotient = divideOne / divideTwo;
       return Quotient;
   }

   //each time this returns true, the game is reset with new operation
   //compares the value of the bubble picked to the random number being compared through operations
   public boolean compareBubbleValue(int randomBubble, int bubbleValue){

       if (randomBubble == bubbleValue){
           return true;
       }
       return false;
   }

}

如您所见,update() 方法只检查移动精灵和边界之间的碰撞。

4

3 回答 3

0

好的,所以让我们命名你的精灵数组spriteArray并循环两次

 public Rect getBounds(){ //put this in your sprite and enemy-class.
   return new Rect(x, y, x+width, y+height);
 }

 Public void checkCollision(){
    for (int i = 0; i<spriteArray.size(); i++){
           Rect mySprite = spriteArray.get(i).getBounds(); //create rect for every sprite in array
             for (int j = 0; j<spriteArray.size(); i++){
                Rect myOtherSprite = spriteArray.get(i).getBounds();
                  if(mySprite.intersect(myOtherSprite)){ //check if they touch
                   //Todo code here
             }
          }
      }
  }

然后您只需将此方法放入您的更新方法中。

于 2012-09-28T16:24:11.070 回答
0

这是 GameView 类的编码(请原谅,这是一堆乱七八糟的代码和注释):

package com.gameproject.cai_test;


public class GameView extends SurfaceView {
   private Bitmap bmp;
   private Bitmap background;
   private Bitmap backgroundImage;
   private Bitmap pop;
   private SurfaceHolder holder;
   private GameLoopThread gameLoopThread;
   private List<Sprite> sprites = new ArrayList<Sprite>();
   private List<TempSprite> temps = new ArrayList<TempSprite>();
   private int[] bubbleValue = {0,1,2,3,4,5,6,7,8,9,10};
   private long lastClick;
   private SpriteObject timer;
   private SpriteObject morebanner;
   private SpriteObject formulaBox;
   private SpriteObject levelbanner1;
   private SurfaceHolder surfaceHolder;


   public GameView(Context context) {
         super(context);
         gameLoopThread = new GameLoopThread(this);
         timer = new SpriteObject (BitmapFactory.decodeResource(getResources(), R.drawable.hourglass), 1200, 100);
         morebanner = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.morebanner), 650, 300);
         formulaBox = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.formulabox), 650, 600);
         background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
         backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
         pop = BitmapFactory.decodeResource(getResources(), R.drawable.pop);
         final Toast toast1 = Toast.makeText(context, "LEVEL 1 start", Toast.LENGTH_LONG);
         holder = getHolder();
         holder.addCallback(new Callback() {

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                       //setSurfaceSize(getWidth(), getHeight());
                       toast1.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
                       toast1.show();
                       createSprites();
                       gameLoopThread.setRunning(true);
                       gameLoopThread.start();
                       //banner();
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                              int width, int height) {
                }
         });

   }

   private void createSprites() {
         sprites.add(createSprite(R.drawable.bubble1));
         sprites.add(createSprite(R.drawable.bubble2));
         sprites.add(createSprite(R.drawable.bubble3));
         sprites.add(createSprite(R.drawable.bubble4));
         sprites.add(createSprite(R.drawable.bubble5));
         sprites.add(createSprite(R.drawable.bubble6));
         sprites.add(createSprite(R.drawable.bubble7));
         sprites.add(createSprite(R.drawable.bubble8));
         sprites.add(createSprite(R.drawable.bubble9));
         sprites.add(createSprite(R.drawable.bubble10));
         for (int i = 0; i <= 10; i++){
            bubbleValue[i] = sprites.indexOf(i);
         }
   }

   private Sprite createSprite(int resource) {
         Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
         return new Sprite(this, bmp);
   }


   public void setSurfaceSize(int width, int height)
   {
      synchronized (surfaceHolder)
      {
         int canvasWidth = width;
         int canvasHeight = height;

         backgroundImage = Bitmap.createScaledBitmap(backgroundImage, width, height, true);
      }
   }


   @Override
   protected void onDraw(Canvas canvas) {
         canvas.drawColor(Color.WHITE);
         //levelbanner1.draw(canvas);//causes error when applied;for reference only
         for (int i = temps.size() - 1; i >= 0; i--) {
             temps.get(i).onDraw(canvas);
         }
         for (Sprite sprite : sprites) {
             timer.draw(canvas);
             //formulaBox.draw(canvas);   
             sprite.onDraw(canvas);
         }

         if (sprites.size() == 0){
             morebanner.draw(canvas);
         }

   }

   @Override
   public boolean onTouchEvent(MotionEvent event) {
         if (System.currentTimeMillis() - lastClick > 300) {
                lastClick = System.currentTimeMillis();
                float x = event.getX();
                float y = event.getY();
                synchronized (getHolder()) {
                       for (int i = sprites.size() - 1; i >= 0; i--) {
                              Sprite sprite = sprites.get(i);
                              if (sprite.isCollition(x, y)) {
                                    sprites.remove(sprite);
                                    temps.add(new TempSprite(temps, this, x, y, pop));
                                    break;
                              }
                       }
                }
         }
         return true;
   }


   public void update(){


       //for possible check of collision bet. sprites
       //

   }

}

我尝试在这里为精灵分配一个 Rect 并检查底部 update() 函数的碰撞,但结果出错并产生运行时错误。如果它在 Sprite 类 update() 函数中自动化可能会更好,就像它对边界碰撞所做的那样。

于 2012-09-28T20:14:43.597 回答
0

如果你想在你的精灵之间有很好的和适当的碰撞,也许看看像http://www.jbox2d.org/这样的物理引擎会有所帮助。

它将为您处理许多复杂的特定情况(隧道、影响时间、早期丢弃的广泛阶段......)

于 2012-10-03T14:26:09.280 回答