从 libgdx 中的集合中检测触摸对象(移动)的最佳方法

2022-01-12 00:00:00 game-engine android java libgdx

这是我第一次尝试游戏开发.我刚刚开始尝试 libgdx 并了解游戏编程的不同方面.我查看了示例项目,我可以了解 libgdx 游戏的整体架构.但是为了掌握游戏动力学的基础知识,我开始玩一些低级的东西,比如如何绘制简单的形状,如何移动它们,如何处理这样的碰撞.

This is my first attempt in game development. I just started experimenting libgdx and understanding the different aspects of game programming. I looked at the sample projects, i can understand the overall architecture of the libgdx game. But to get hold of the basics of game dynamics, i started playing with low level stuff like how to draw simple shapes, how to move them, how to handle collision like that.

所以我打算写一个死的简单的安卓游戏(它甚至不是一个游戏肯定).就是这个思路

So i planned to write a dead simple android game(Its not even a game for sure). This is the idea

1. Create random shapes and make it fly (move)
2. When user touches the shape, it ll explode or hide or play simple animation
3. Has to show Hit & Miss count

最初我想尝试一下 libgdx stage &actor 的概念,但排除了没有场景 API 的情况.我开始这个实验是为了尝试基本游戏的不同方面,并更好地理解 libgdx 背后的概念.所以我做了这个简单的应用程序,我可以让物体随机掉落.

Initially i thought of going to try libgdx stage & actor concept, but ruled out that to do without the scene API. And I started this to experiment with different aspects of basic gaming and better understand the concepts behind libgdx. So i made this simple app, i am able to make objects fall random.

public class A1GameScreen implements Screen {

    OrthographicCamera camera;
    ShapeRenderer debugRenderer = new ShapeRenderer();
    Array<Rectangle> boxes;   
    long lastFlew;
    int fliesCaught;

    A1GameScreen(){

         camera = new OrthographicCamera();
         camera.setToOrtho(false, 800, 480);       
         boxes=new Array<Rectangle>();
         throwboxes();
    }
@Override
public void render(float delta) {

    Gdx.gl.glClearColor(0, 0, 0.2f, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);


          camera.update();


    debugRenderer.setProjectionMatrix(camera.combined);
    debugRenderer.begin(ShapeType.Line);

    for (Rectangle fly : boxes) {
        debugRenderer.rect(fly.x, fly.y, fly.width, fly.height);
    }
    debugRenderer.end();

    //Handle the user input

    if (Gdx.input.isTouched()){          
        hit(Gdx.input.getX(),Gdx.input.getY());
    }

    if (TimeUtils.nanoTime() - lastFlew > 1000000000)
        throwboxes();


    Iterator<Rectangle> iter = boxes.iterator();
    while (iter.hasNext()) {
        Rectangle fly = iter.next();        
        fly.x -= 2;
        if (fly.x + 32 < 0)
            iter.remove();

    }

}

//Method to create flies at random interval
private void throwBoxes(){

    Rectangle fly = new Rectangle();
    fly.y = MathUtils.random(0, 480 - 32);
    fly.x = 800;
    fly.width = 32;
    fly.height = 32;
    boxes.add(fly);

    lastFlew = TimeUtils.nanoTime();

}

private boolean hit (float x, float y) {
    boolean found=false;

    for (Rectangle fly : boxes) {
        found = fly.contains(x,y);
        if (found){
            found = true;
            fly.width=100;
            break;
        }


    }

    return found;

}

}

但我无法从坠落的物体中找出被触摸的物品.这就是我正在做的以确定盒子是否在触摸范围内

But i couldn't able to find out the touched item from the falling objects. This is what i am doing to find out whether the box is in touched range

  1. 遍历数组中的所有框
  2. 检查触摸坐标是否在框坐标内
  3. 我将触摸坐标传递给 Rectangle (Box) 的 contains 方法来弄清楚
  1. Loop through all the boxes in the array
  2. Check if the touch co-ordinates falls within the box co-ordinates
  3. I passed touch co-ordinates to contains method of the Rectangle (Box) to figure out that

类似的东西

  for (Rectangle fly : boxes) {
        found = fly.contains(x,y);
        if (found){
            found = true;
            fly.width=100;
            break;
        }


    }

但它不起作用.我想我发现了问题所在.它的

But its not working. I think i figured the problem. Its

  1. 框每帧在 x 轴移动 2px,以产生飞行效果
  2. 但我假设,自触摸事件以来已经过去了一些帧.这就是为什么我没有得到预期的结果

我的问题是

  1. 如何解决这个问题?
  2. 在 libgdx 中检测碰撞的最佳方法是什么?

更新

我发现触摸坐标和框坐标之间存在很多不匹配.触摸范围内没有任何框.怎么可能.在示例跟踪下方

I see lot of mismatch between the touch co-ordinates and box co-ordinates. None of the boxes in the touch range. Hows that possible. Below the sample trace

Touch coords: x-651.0 y-362.0

Fly coords: x-384.0 y-277.0
Fly coords: x-504.0 y-34.0
Fly coords: x-624.0 y-103.0
Fly coords: x-744.0 y-238.0



Touch coords: x-441.0 y-193.0

Fly coords: x-52.0 y-34.0
Fly coords: x-172.0 y-103.0
Fly coords: x-292.0 y-238.0
Fly coords: x-414.0 y-261.0
Fly coords: x-534.0 y-109.0
Fly coords: x-656.0 y-283.0
Fly coords: x-776.0 y-323.0


Touch coords: x-568.0 y-162.0

Fly coords: x-42.0 y-267.0
Fly coords: x-162.0 y-166.0
Fly coords: x-282.0 y-266.0
Fly coords: x-404.0 y-52.0
Fly coords: x-526.0 y-296.0
Fly coords: x-646.0 y-64.0
Fly coords: x-766.0 y-16.0

推荐答案

public static boolean pointInRectangle (Rectangle r, float x, float y) {
    return r.x <= x && r.x + r.width >= x && r.y <= y && r.y + r.height >= y;
}

在你的更新中-

if(pointInRectangle(flyRectangle, Gdx.input.getX(), Gdx.input.getY())){
  // Do whatever you want to do with the rectangle. maybe register them for effect
}

您还可以查看 Intersector 类.

现在来说碰撞,如果你的游戏是快节奏的,有很多敌人在四处移动,玩家可能会与之发生碰撞,迟早你会使用 box2d 类型库,因为如果移动速度很高,你可能不会得到任何碰撞回调.事情可能会相互影响.您可以尝试使用速度和 deltaTime 在碰撞发生之前预测碰撞,但这仍然不够,您最终将重新发明轮子.

Now for collision, if your game is fast-paced, with lots of enemies moving around that the player can collide with, sooner or later you will use a box2d type library because if the movement speed is high, you might not get any collision callback. Things might go through each other. You can try predicting the collision before it happens using the velocity and deltaTime, but it's still not going to be enough and you will end up reinventing the wheel.

Mario 的 SuperJumper 是启动 libGDX 的绝佳演示.试试看.

Mario's SuperJumper is a great demo to start libGDX. Try it.

有一个实例成员-

Vector3 touchPoint;

创建时-

touchPoint = new Vector3();

更新时-

camera.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));

if (Gdx.input.justTouched()) {
    if (pointInRectangle(rectangle, touchPoint.x, touchPoint.y)) {
    }
}

请注意 libGDX 中的坐标系.为了测试,在屏幕上创建一个矩形.单击时,打印/调试矩形和触摸点的坐标.

Please take note of the coordinate system in libGDX. For testing, create one rectangle on screen. On click, print/debug the coordinates of both the rectangle and touchPoint.

相关文章