libGDX-精确碰撞检测-多边形创建? [英] libGDX- Exact collision detection - Polygon creation?

查看:24
本文介绍了libGDX-精确碰撞检测-多边形创建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于 libGDX 碰撞检测的问题.因为这是一个相当具体的问题,我还没有在互联网上找到任何好的解决方案.

I've got a question about libGDX collision detection. Because it's a rather specific question I have not found any good solution on the internet yet.

所以,我已经创建了由不同身体部位组成的人类",每个部位都有矩形碰撞检测.

So, I already created "humans" that consist of different body parts, each with rectangle-shaped collision detection.

现在我想实现武器和技能,例如如下所示:

Now I want to implement weapons and skills, which for example look like this:

技能示例图片

问题

当有这样的技能时,在碰撞检测中使用矩形会让玩家非常沮丧:他们可以成功躲避技能,但碰撞检测器仍然会伤害他们.

Working with rectangles in collision detections would be really frustrating for players when there are skills like this: They would dodge a skill successfully but the collision detector would still damage them.

方法一:

在开始使用 Libgdx 之前,我已经创建了一个具有自定义引擎和类似技能的 Android 游戏.我通过以下方式解决了问题:

Before I started working with Libgdx I have created an Android game with a custom engine and similar skills. There I solved the problem following way:

  1. 检测矩形碰撞
  2. 计算重叠矩形部分
  3. 检查技能重叠部分的每个像素的透明度
  4. 如果发现任何不透明像素 -> 碰撞

这是一种繁重的方式,但由于只检查重叠像素而游戏的其余部分非常轻巧,因此完全可以正常工作.

That's a kind of heavy way, but as only overlapping pixels are checked and the rest of the game is really light, it works completely fine.

目前我的技能图像加载为TextureRegion",无法访问单个像素.我发现 libGDX 有一个 Pixmap 类,它允许这样的像素检查.问题是:将它们加载为像素图另外会 1. 更重 2. 破坏纹理系统的整个目的.

At the moment my skill images are loaded as "TextureRegion", where it is not possible to access single pixels. I have found out that libGDX has a Pixmap class, which would allow such pixel checks. Problem is: having them loaded as Pixmaps additionally would 1. be even more heavy and 2. defeat the whole purpose of the Texture system.

另一种方法是仅将所有技能加载为像素图.你怎么看:这会是一个好方法吗?是否可以在屏幕上绘制许多像素图而没有任何问题和滞后?

An alternative could be to load all skills as Pixmap only. What do you think: Would this be a good way? Is it possible to draw many Pixmaps on the screen without any issues and lag?

方法2:

另一种方法是创建具有技能形状的多边形并将它们用于碰撞检测.

An other way would be to create Polygons with the shape of the skills and use them for the collision detection.

a)但是我如何为每一项技能定义一个多边形形状(其中有超过 150 个)?浏览了一段时间后,我发现了这个有用的工具:http://www.aurelienribon.com/blog/projects/physics-body-editor/它允许手动创建多边形形状,然后将它们保存为 JSON 文件,可由 libGDX 应用程序读取.现在困难来了:

a) But how would I define a Polygon shape for every single skill (there are over 150 of them)? Well after browsing a while, I found this useful tool: http://www.aurelienribon.com/blog/projects/physics-body-editor/ it allows to create Polygon shapes by hand and then save them as JSON files, readable by the libGDX application. Now here come the difficulties:

  • Physics Body Editor 已连接到 Box2d(我没有使用).我要么只因为一个微小的碰撞检测就必须添加整个 Box2d 物理引擎(我根本不需要),要么我必须编写一个自定义 BodyEditorLoader,这将是一项艰巨、复杂且耗时的任务
  • 同一技能精灵的某些图像在形状上存在很大差异(如第二个技能精灵示例).在使用 BodyEditor 工具时,我不仅要定义每个技能的形状,而且还必须定义每个技能的多个图像(最多 12 个)的形状.在实现这几十个多边形形状时,这将非常耗时且一团糟

b)如果有任何平滑的方法可以从图像中自动生成多边形,那可能就是解决方案.我可以简单地将每个精灵部分连接到生成的多边形并以这种方式检查碰撞.不过也有一些问题:

b) If there is any smooth way to automatically generate Polygons out of images, that could be the solution. I could simply connect every sprite section to a generated polygon and check for collisions that way. There are a few problems though:

  • 是否有任何平滑工具可以从图像中生成多边形形状(并且不需要太多时间)?
  • 我不认为像这样的工具(如果存在的话)可以直接使用纹理.它可能需要像素图.不过,在多边形创建之后不需要保持像素图的加载.仍然是一项极其繁重的任务!

我目前的想法

我被困在这一点上,因为有几种可能的方法,但它们都有自己的困难.在我选择一条路继续编码之前,如果您能留下一些想法和知识,那就太好了.

I'm stuck at this point because there are several possible approaches but all of them have their difficulties. Before I choose one path and continue coding, it would be great if you could leave some of your ideas and knowledge.

libGDX 中可能包含有用的类和代码,可以在几秒钟内解决我的问题 - 因为我是 libGDX 的新手,所以我对它还不太了解.

There might be helpful classes and code included in libGDX that solve my problems within seconds - as I am really new at libGDX I just don't know a lot about it yet.

目前我认为我会采用方法 1:使用像素检测.这样我就可以在我之前的 Android 游戏中进行精确的碰撞检测.

Currently I think I would go with approach 1: Work with pixel detection. That way I made exact collision detections possible in my previous Android game.

你怎么看?

问候费利克斯

推荐答案

我已经使用了您引用的那个精确的正文编辑器,它能够为您生成多边形和/或圆形.我还使用 Jackson 库为生成的 JSON 制作了一个加载器.这可能不是您的答案,因为您必须实现 box2d.但无论如何,这就是我的做法.

I've used that exact body editor you referenced and it has the ability to generate polygons and/or circles for you. I also made a loader for the generated JSON with the Jackson library. This may not be the answer for you since you'd have to implement box2d. But here's how how I did it anyway.

/**
* Adds all the fixtures defined in jsonPath with the name'lookupName', and 
* attach them to the 'body' with the properties defined in 'fixtureDef'. 
* Then converts to the proper scale with 'width'.
*
* @param body the body to attach fixtures to
* @param fixtureDef the fixture's properties
* @param jsonPath the path to the collision shapes definition file
* @param lookupName the name to find in jsonPath json file
* @param width the width of the sprite, used to scale fixtures and find origin.
* @param height the height of the sprite, used to find origin.
*/
public void addFixtures(Body body, FixtureDef fixtureDef, String jsonPath, String lookupName, float width, float height) {
  JsonNode collisionShapes = null;
  try {
    collisionShapes = json.readTree(Gdx.files.internal(jsonPath).readString());
  } catch (JsonProcessingException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
  for (JsonNode node : collisionShapes.findPath("rigidBodies")) {
    if (node.path("name").asText().equals(lookupName)) {
      Array<PolygonShape> polyShapes = new Array<PolygonShape>();
      Array<CircleShape> circleShapes = new Array<CircleShape>();

      for (JsonNode polygon : node.findPath("polygons")) {
        Array<Vector2> vertices = new Array<Vector2>(Vector2.class);
        for (JsonNode vector : polygon) {
          vertices.add(new Vector2(
            (float)vector.path("x").asDouble() * width,
            (float)vector.path("y").asDouble() * width)
            .sub(width/2, height/2));
        }
        polyShapes.add(new PolygonShape());
        polyShapes.peek().set(vertices.toArray());
      }

      for (final JsonNode circle : node.findPath("circles")) {
        circleShapes.add(new CircleShape());
        circleShapes.peek().setPosition(new Vector2(
          (float)circle.path("cx").asDouble() * width,
          (float)circle.path("cy").asDouble() * width)
          .sub(width/2, height/2));

        circleShapes.peek().setRadius((float)circle.path("r").asDouble() * width);
      }

      for (PolygonShape shape : polyShapes) {
        Vector2 vectors[] = new Vector2[shape.getVertexCount()];
        for (int i = 0; i < shape.getVertexCount(); i++) {
          vectors[i] = new Vector2();
          shape.getVertex(i, vectors[i]);
        }
        shape.set(vectors);
        fixtureDef.shape = shape;
        body.createFixture(fixtureDef);
      }

      for (CircleShape shape : circleShapes) {
        fixtureDef.shape = shape;
        body.createFixture(fixtureDef);
      }
    }
  }
}

我会这样称呼它:

physics.addFixtures(body, fixtureDef, "ship/collision_shapes.json", shipType, width, height);

然后进行碰撞检测:

public ContactListener shipsExplode() {
  ContactListener listener = new ContactListener() {

    @Override
    public void beginContact(Contact contact) {
      Body bodyA = contact.getFixtureA().getBody();
      Body bodyB = contact.getFixtureB().getBody();

      for (Ship ship : ships) {
        if (ship.body == bodyA) {
          ship.setExplode();
        }
        if (ship.body == bodyB) {
          ship.setExplode();
        }
      }
    }
  };
  return listener;
}

然后你将监听器添加到世界中:

then you would add the listener to the world:

world.setContactListener(physics.shipsExplode());

我的精灵的宽度和高度很小,因为一旦你开始使用 box2d,你就在处理米而不是像素.例如,一个精灵高度为 0.8f,宽度为 1.2f.如果你以像素为单位制作精灵的宽度和高度,物理引擎会达到 http://www 中内置的速度限制.iforce2d.net/b2dtut/gotchas

my sprites' width and height were small since you're dealing in meters not pixels once you start using box2d. One sprite height was 0.8f and width was 1.2f for example. If you made the sprites width and height in pixels the physics engine hits speed limits that are built in http://www.iforce2d.net/b2dtut/gotchas

这篇关于libGDX-精确碰撞检测-多边形创建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆