首页 文章

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

提问于
浏览
3

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

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

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阶段和演员概念,但排除了没有场景API . 我开始尝试基本游戏的不同方面,并更好地理解libgdx背后的概念 . 所以我制作了这个简单的应用程序,我能够使对象随机掉落 .

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;

}

}

但我无法从落下的物体中找出被触摸的物品 . 我正在做的是找出盒子是否在触摸范围内

  • 循环遍历数组中的所有框

  • 检查触摸坐标是否在框坐标内

  • 我通过触摸坐标 Rectangle (方框) contains 方法来弄清楚

这样的事情

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


    }

但它不起作用 . 我想我想到了这个问题 . 它的

  • Box每帧在x轴上移动2px,以产生飞行效果

  • 但我假设,自触摸事件以来已经过了一些帧 . 这就是为什么我没有得到预期的结果

我的问题是

  • 如何解决这个问题?

  • 什么是在libgdx中检测碰撞的最佳方法?

Update

我发现触摸坐标和盒子坐标之间存在很多不匹配 . 没有触摸范围内的盒子 . 怎么可能 . 样本跟踪下方

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

2 回答

  • 5
    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类型的库,因为如果移动速度很高,你可能不会得到任何碰撞回调 . 事情可能会相互影响 . 您可以尝试使用velocity和deltaTime在碰撞发生之前预测碰撞,但它仍然不够,您将最终重新发明轮子 .

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

    EDIT:

    有一个实例成员 -

    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中的坐标系 . 要进行测试,请在屏幕上创建一个矩形 . 单击,打印/调试矩形和touchPoint的坐标 .

  • 1

    我已经通过制作一个隐藏的矩形来解决问题,该矩形将跟随水龙头位置,我做了一个if语句检查不可见矩形的重叠并检查屏幕是否刚刚被点击 .

    这是代码:

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

    所有这些代码都在render方法中 .

    P.S:将雨滴改为你想要的苍蝇对象

相关问题