简体   繁体   English

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

[英]Best way to detect the touched object (moving) from collection in libgdx

This is my first attempt in game development. 这是我第一次尝试游戏开发。 I just started experimenting libgdx and understanding the different aspects of game programming. 我刚开始尝试libgdx并理解游戏编程的不同方面。 I looked at the sample projects, i can understand the overall architecture of the libgdx game. 我查看了示例项目,我可以理解libgdx游戏的整体架构。 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

Initially i thought of going to try libgdx stage & actor concept, but ruled out that to do without the scene API. 最初我想过尝试libgdx阶段和演员概念,但排除了没有场景API。 And I started this to experiment with different aspects of basic gaming and better understand the concepts behind libgdx. 我开始尝试基本游戏的不同方面,并更好地理解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. 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 我通过触摸坐标来contains Rectangle (Box)的方法来弄清楚

something like this 这样的事情

  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. Box is moving 2px in x axis each frame, to make flying effect Box每帧在x轴上移动2px,以产生飞行效果
  2. But i am assuming, some frames has passed since the touch event. 但我假设,自触摸事件以来已经过了一些帧。 Thats why i am not getting the expected result 这就是为什么我没有得到预期的结果

My questions are 我的问题是

  1. How to solve this issue? 如何解决这个问题?
  2. Whats the best way to detect collision in libgdx? 什么是检测libgdx中碰撞的最佳方法?

Update 更新

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;
}

In your update- 在您的更新中 -

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

You can also look into Intersector class. 您还可以查看Intersector类。

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. 现在为了碰撞,如果你的游戏节奏很快,玩家可以碰到许多敌人,你迟早会使用box2d类型的库,因为如果移动速度很快,你可能不会得到任何碰撞回调。 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. 您可以尝试使用velocity和deltaTime在碰撞发生之前预测碰撞,但它仍然不够,您将最终重新发明轮子。

Mario's SuperJumper is a great demo to start libGDX. Mario的SuperJumper是一个很棒的演示来启动libGDX。 Try it. 试试吧。

EDIT: 编辑:

Have an instance member- 有一个实例成员 -

Vector3 touchPoint;

On create- 在创造 -

touchPoint = new Vector3();

On update- 在更新 -

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

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

Please take note of the coordinate system in libGDX. 请注意libGDX中的坐标系。 For testing, create one rectangle on screen. 要进行测试,请在屏幕上创建一个矩形。 On click, print/debug the coordinates of both the rectangle and touchPoint. 单击,打印/调试矩形和touchPoint的坐标。

I've solved the problem by making an invisible rectangle which will follow the tap location and I made an if statement checking for overlapping of the invisible rectangle and checking for if the screen was just tapped. 我通过制作一个隐藏的矩形来解决问题,该矩形将跟随水龙头位置,我做了一个if语句检查不可见矩形的重叠并检查屏幕是否刚被点击。

Here is the code: 这是代码:

if(Gdx.input.isTouched()) {
        Vector3 pointerPos = new Vector3();
        pointerPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
        cam.unproject(pointerPos);
        touchPos.x = pointerPos.x /*+ 64 / 2*/;
        touchPos.y = pointerPos.y /*+ 64 / 2*/;
    }

    Iterator<Rectangle> iter = raindrops.iterator();
    while(iter.hasNext()) {
        Rectangle raindrop = iter.next();
        raindrop.y -= 300 * Gdx.graphics.getDeltaTime();
        if(raindrop.y + 64 < 0) {
            iter.remove();
        }
        if(raindrop.overlaps(touchPos) && Gdx.input.justTouched()) {
            iter.remove();
            dropSound.play();
        }

all of this code is in the render method. 所有这些代码都在render方法中。

PS: Change raindrops to the fly objects you want PS:将雨滴改为你想要的苍蝇对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM