实现像素完美碰撞--Libgdx

时间:2017-10-01 13:35:27

标签: java libgdx collision-detection

我刚开始通过libgdx框架学习游戏编程,我正处于开发的碰撞检测阶段。我制作了一个非常简单的游戏,它有一些基本的边界框碰撞检测系统。但是,我想实现像素完美碰撞以保证准确性。

我将展示我认为对帮助您了解正在发生的事情非常重要的代码片段。

创建一个二维数组来定义屏幕上瓷砖的位置:

int[][] map = {
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,1,1,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,1,1,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
        {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    };

我的主游戏类中的这个create()方法将一个玩家和三个实体添加到ArrayList类型Entity

  @Override
  public void create () {
      batch = new SpriteBatch();
      tileTexture = new Texture("block.png");  
      screenWidth = Gdx.graphics.getWidth();
      screenHeight = Gdx.graphics.getHeight();

      // add some entities including a player
      entities.add(new Player(this, 100, 150, 20, 20, 120.0f, new Texture("player.png")));
      entities.add(new Entity(this, 50, 150, 20, 20, 120.0f, new Texture("enemy.png")));
      entities.add(new Entity(this, 200, 200, 20, 20, 120.0f, new Texture("enemy.png")));
      entities.add(new Entity(this, 180, 50, 20, 20, 120.0f, new Texture("enemy.png")));
  }

render() method在游戏运行时绘制平铺贴图和实体。另一个名为Entity的类包含特定实体的数据(可以是块/播放器)。数据可以是该实体的xy位置。

      // draw tile map
      // go over each row bottom to top
      for(int y = 0; y < mapHeight; y++) {
          // go over each column left to right      
          for(int x = 0; x < mapWidth; x++) {
              // tile
              if(map[x][y] == 1) {
                  batch.draw(tileTexture, x * tileSize, y * tileSize);
              }
          }
      }

      // draw all entities
      for(int i = entities.size() - 1; i >= 0; i--) {
          Entity e = entities.get(i);
          batch.draw(e.texture, e.x, e.y);
      }

这会产生: Game screen when started

要在玩家(绿色区块)移动时检查碰撞,我有两种方法可以检查玩家是否与实体或图块发生碰撞。

tileCollision()方法:

  public boolean tileCollision(Entity e, Direction direction, float newX, float newY) {
      boolean collision = false;

      // determine affected tiles
      int x1 = (int) Math.floor(Math.min(e.x, newX) / tileSize);
      int y1 = (int) Math.floor(Math.min(e.y, newY) / tileSize);
      int x2 = (int) Math.floor((Math.max(e.x, newX) + e.width - 0.1f) / tileSize);
      int y2 = (int) Math.floor((Math.max(e.y, newY) + e.height - 0.1f) / tileSize);

      // tile checks
      for(int x = x1; x <= x2; x++) {
          for(int y = y1; y <= y2; y++) {
              if(map[x][y] == 1) {
                  collision = true;
                  e.tileCollision(map[x][y], x, y, newX, newY, direction);
              }
          }
      }
      return collision;
  }

此方法中的代码行e.tileCollision(map[x][y], x, y, newX, newY, direction);调用Entity类中的tileCollision()方法,该方法打印块与tile碰撞的位置。

要检查实体之间的冲突,我们有这个方法:

  public boolean entityCollision(Entity e1, Direction direction, float newX, float newY) {
      boolean collision = false;

      for(int i = 0; i < entities.size(); i++) {
          Entity e2 = entities.get(i);

          // we don't want to check for collisions between the same entity
          if(e1 != e2) {
              // axis aligned rectangle rectangle collision detection
              if(newX < e2.x + e2.width && e2.x < newX + e1.width &&
                  newY < e2.y + e2.height && e2.y < newY + e1.height) {
                  collision = true;

                  e1.entityCollision(e2, newX, newY, direction);
              }
          }
      }

      return collision;
  }

注意:绿色块可以在实体中移动,但无法通过切片。这是因为行e1.entityCollision(e2, newX, newY, direction);调用类entityCollision()中允许绿色块移动的Entity方法。

这种类型的碰撞检测似乎是基本且低效的(时间复杂度为O(n^2))。

如何在此上下文中实现像素完美碰撞

其他问题:如果我想提高效率,我可以使用什么碰撞检测系统来消除不必要的检查?

0 个答案:

没有答案