当前位置: 首页 > 知识库问答 >
问题:

libgdx中的突破球碰撞

吴胜
2023-03-14

我目前正在尝试使用java和libgdx制作一个突破性的克隆。我现在很难让球以合适的角度从挡块上弹起。简而言之,我遇到的问题是,球每帧移动12个像素,并不总是与砖的边缘对齐。如果有人对更好的移动球的方法或其他检查碰撞的方法有任何建议,我们将不胜感激!

主要游戏类

    package com.kyleparker.breakout;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;

public class BreakoutGameScreen implements ApplicationListener {
   Texture dropImage;
   Sound dropSound;
   Music rainMusic;
   SpriteBatch batch;
   OrthographicCamera camera;
   Rectangle bucket;
   Paddle paddle;
   //Brick bricks[];
   Array<Brick> bricks;
   Ball ball;

   @Override
   public void create() {
      // load the images for the droplet, 64x64 pixels
      dropImage = new Texture(Gdx.files.internal("droplet.png"));

      // load the drop sound effect and the rain background "music"
      dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
      rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

      // start the playback of the background music immediately
      rainMusic.setLooping(true);
      rainMusic.play();

      // create the camera and the SpriteBatch
      camera = new OrthographicCamera();
      camera.setToOrtho(false, 1280, 720);
      batch = new SpriteBatch();

      paddle = new Paddle(new Texture(Gdx.files.internal("bucket.png")));

      bricks = new Array<Brick>();
      populateBricks();

      ball = new Ball(new Texture(Gdx.files.internal("bucket.png")), paddle, bricks);
   }

   private void populateBricks() {
       bricks.add(new Brick(200,100));
       for (int i = 0; i < 5; i++) {
           for (int j = 0; j <= 7; j++) {
               bricks.add(new Brick (j * 144 + 76, i * 80 + 300)); //Offsets each new brick
           }
       }
   }

   @Override
   public void render() {
       // clear the screen with a dark blue color. The
       // arguments to glClearColor are the red, green
       // blue and alpha component in the range [0,1]
       // of the color to be used to clear the screen.
       Gdx.gl.glClearColor(0, 0, 0.2f, 1);
       Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

       // tell the camera to update its matrices.
       camera.update();

       // tell the SpriteBatch to render in the
       // coordinate system specified by the camera.
       batch.setProjectionMatrix(camera.combined);

       // begin a new batch and draw the bucket and
       // all drops
       batch.begin();

       paddle.render(batch, camera);

       ball.move();
       ball.render(batch, camera);

       for (int x = bricks.size - 1; x > 0; x--) {
           bricks.get(x).render(batch,camera);
       }

       batch.end();     
   }

   @Override
   public void dispose() {
      // dispose of all the native resources
      dropImage.dispose();
      dropSound.dispose();
      rainMusic.dispose();
      batch.dispose();
      paddle.dispose();
   }

   @Override
   public void resize(int width, int height) {
   }

   @Override
   public void pause() {
   }

   @Override
   public void resume() {
   }
}

Ball类

    package com.kyleparker.breakout;

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;

public class Ball{
   Texture ballImage;
   Rectangle ball;
   private int xdir;
   private int ydir;
   Paddle paddle;
   Array<Brick> bricks;
   final int BALL_SPEED = 12;

   public Ball(Texture ballImage, Paddle paddle, Array<Brick> bricks) {
      // load the ball image
      this.ballImage = ballImage;
      xdir = 1;
      ydir = -1;

      // create a Rectangle for the balls collision
      ball = new Rectangle();
      ball.x = 1280 / 2 - 64 / 2; // center the ball
      ball.y = 100; // put the ball 200px away from the bottom of the screen
      ball.width = 64;
      ball.height = 64;

      this.paddle = paddle;
      this.bricks = bricks;
   }

   public void render(SpriteBatch batch, OrthographicCamera camera) {
       // draw the paddle onto the batch of the level
       batch.draw(ballImage, ball.x, ball.y);
   }

   public void move() {
       ball.x += xdir * BALL_SPEED;
       ball.y += ydir * BALL_SPEED;

       if (ball.x <= 0) {
           setXDir(1);
       }

       if (ball.x >= 1280 - 64) {
           setXDir(-1);
       }

       if (ball.y <= 0) {
           setYDir(1);
       }

       if (ball.y >= 720 - 64) {
           setYDir(-1);
       }

       if (ball.overlaps(paddle.getRect())) {        
          setYDir(1);
       }

       for (int i = 0; i < bricks.size; i++) {
           if (ball.overlaps(bricks.get(i).getRect())) {
               if ((ball.x == (bricks.get(i).getRect().x + 128))) 
               { 
                   setXDir(1);
                   bricks.get(i).setDestroyed(true);
                   System.out.println("Collision RIGHT");
               }
               if (((ball.x + 64) == bricks.get(i).getRect().x)) 
               { 
                   setXDir(-1);
                   bricks.get(i).setDestroyed(true);
                   System.out.println("Collision LEFT");
               }
               if ((ball.y == (bricks.get(i).getRect().y + 64))) 
               { 
                   setYDir(1);
                   bricks.get(i).setDestroyed(true);
                   System.out.println("Collision TOP");
               }
               if (((ball.y + 64) == bricks.get(i).getRect().y)) 
               {                  
                   setYDir(-1);
                   bricks.get(i).setDestroyed(true);
                   System.out.println("Collision BOTTOM");
               }
           }
       }// end of for
   }

   public void setXDir(int x) {
       xdir = x;
   }

   public void setYDir(int y) {
       ydir = y;
   }

   public int getYDir() {
       return ydir;
   }

   public int getXDir() {
       return xdir;
   }

   public Rectangle getRect() {
       // return the collision rectangle for checking overlaps
       return ball;
   }

   public void dispose() {
      // dispose of all the native resources
      ballImage.dispose();
   }
}// end of class

砖块代码以防万一

package com.kyleparker.breakout;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;

public class Brick{
   Texture brickImage;
   Rectangle brick;
   boolean destroyed;

   public Brick(int x, int y) {
       brickImage = new Texture(Gdx.files.internal("brick.png"));   

       // create a Rectangle for the bricks collision
       brick = new Rectangle();
       brick.x = x;
       brick.y = y;
       brick.width = 128;
       brick.height = 64;

       destroyed = false;
   }

   public void render(SpriteBatch batch, OrthographicCamera camera) {
       // draw the brick onto the batch of the level
       batch.draw(brickImage, brick.x, brick.y);
   }

   public boolean isDestroyed() {
       // return the collision rectangle for checking overlaps
       return destroyed;
   }

   public void setDestroyed(boolean destroyed)
   {
     this.destroyed = destroyed;

     if (this.destroyed == true) {
         dispose();
         brick.x = -1000;
         brick.y = -1000;
     }
   }

   public Rectangle getRect() {
       return brick;
   }

   public void dispose() {
      // dispose of all the native resources
      brickImage.dispose();
   }
}

共有2个答案

袁泰平
2023-03-14

我会用box2d来完成整个事情。你没有用过box2d可能意味着你没有这方面的经验,所以这将是一个小障碍,但我相信你能很快理解它。这是一个链接:http://code.google.com/p/libgdx/wiki/PhysicsBox2D

姜经武
2023-03-14

不要担心球并不总是与需要处理碰撞的对象对齐,这实际上并不相关。你可以(也应该)不那么“精确”地处理碰撞也就是说,球的路径是固定的,因此可以计算其在未来任何点的位置。检查其位置,计算其在下一帧中的位置(无论如何都必须这样绘制),并添加一些代码来处理即将发生的碰撞,而不是试图检测和处理已经发生的碰撞。如果你真的想要一个干净的反射,你可以减慢球的速度,或者你可以加快帧速率,或者你可以让球在反射之前被物体部分“吸收”:

public class Ball {
. . .
    public void move() {
    . . .
        if (collisionObject.overlaps(new Rectangle(ball.x + xdir, ball.y + ydir, ball.width, ball.height))) {
            //a collision will have occurred in the next frame
            //handle the collision however you please
        }
    }
}

我还注意到,您的球速字段的名称不准确。按照目前的编码,球始终以45°角移动,速度约为每帧17像素(在该方向)。您已将其x和y偏移量编码为12像素,但如果(何时?)你改变球的方向,你会发现速度波动很大,这取决于xdir和ydir字段的值。例如,如果要(某种程度上)随机化这些,但保持代码的其余部分不变,则在一个实例上可能会发现xdir=2和ydir=4,在另一个实例上可能会发现xdir=6和ydir=12。注意,这些描述了相同的方向,但第二个版本的移动速度将是原来的三倍。

为了正确处理球的方向和速度,指定一个角度,并通过适当的三角函数(xdir=ball\u speed*Math.cos(ballAngle)ydir=ball\u speed*Math)计算xdir和ydir值。sin(巴郎格))。

 类似资料:
  • 我正在创建一个突破游戏来熟悉Java。目前我已经把一切都做好了,但我注意到球似乎是朝着同一个方向飞的。 我已经对它进行了编程,当球碰到球拍时,Y速度是相反的。这是可行的,但球似乎遵循相同的路线。。。 如何让碰撞看起来更真实? 当球击中桨的左侧时,我想将其重新定向到左侧,但我不确定在哪个角度反射它。有人能提供一个公式来帮助我计算出当球接触桨的左侧或右侧时需要引导的角度吗?

  • 我正在为一项大学作业创建一个项目,我遇到了一点障碍。这个问题很小,很可能被认为是没有被注意到的,但它仍然困扰着我,作为一个程序性的人,在完成工作方面,我不能继续做任何事情,直到它被解决。 我有桨和球代码工作良好,以及一个简单的角速度的基础上,球击中桨,但我的问题是当球击中砖块。代码大多有效,似乎完美无瑕,但当球做以下两件事之一时,情况会发生变化: 击中砖块的一个角可能会错误地扭转球的速度轴 同时击

  • 我的问题主要与它背后的理论有关。我为一个项目制作了一个2D游戏,通过使用Rectangle类中的.overlapps方法检测碰撞,碰撞处理得很好。首先,被认为是连续或离散碰撞技术。当我读到这个理论时,我说它是离散的,但我在网上的文章中读到离散的主要缺点是它在实际发生碰撞后检测到碰撞。所以,我的问题是:它实际上是离散的吗?如果是这样的话,我看不出它有什么缺点吗?谢谢

  • 所以我正在android studio中制作一款突破性游戏。 在做了一个游戏循环和与桨和桨的基本碰撞后,我注意到我的球在提高速度后开始穿过我的桨和桨。 问题在于它在一帧中碰撞了两次,所以我的基本碰撞还不够。 我读过关于使用向量数学求解的书。但这对我来说太过分了,我的头也被它缠住了。我指的是这个问题的答案:

  • 我试图让我的游戏中的碰撞完全完美。我测试的是,如果你和玩家撞墙,你就会停下来。我只实现了当玩家撞墙左侧时(当墙在玩家右侧时)的碰撞代码。这是代码。 注意:如果我走得很慢,它会在我想要停止的地方停止玩家,但是走得很快,它不会按照我想要的方式进行碰撞 本质上,代码指出如果墙在右边,它将检查玩家矩形的右下角,减去墙的左下角,并检查两者之间的距离是否0.001. 0.001几乎是一个不明显的距离,因此我使

  • 这两个球在画布上弹来弹去。 如果球碰撞了,帆布应该说游戏结束。 这是一个代码,我已经为碰撞到目前为止