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

查看:206
本文介绍了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.

方法1:

之前我开始使用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. 如果找到任何非透明像素 - >碰撞

  1. Detect rectangle collision
  2. Calculate overlapping rectangle section
  3. Check every single pixel of the overlapping part of the skill for transparency
  4. If there is any non-transparent pixel found -> Collision

这是一种沉重的方式,但由于只检查重叠的像素,而游戏的其余部分非常轻,所以它完全正常。

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类,可以进行像素检查。问题是:将它们加载为Pixmaps另外将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.

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

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:


  • 物理主体编辑器连接到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:


  • 是否有任何平滑的工具可以从图像中生成多边形形状(并且不需要太多时间)?

  • 我不认为像这样的工具(如果存在)可以直接使用Textures。它可能需要Pixmaps。在创建Polygon之后,不需要保持te Pixmaps加载。仍然是一项非常繁重的任务!

我当前的想法

我在这一点上陷入困​​境,因为有几种可能的方法,但所有方法都有困难。在我选择一条路径并继续编码之前,如果你能留下你的一些想法和知识,那就太棒了。

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.

你怎么看?

问候
Felix

Greetings Felix

推荐答案

我使用了你引用的那个精确的正文编辑器,它能够为你生​​成多边形和/或圆形。我还使用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天全站免登陆