Java 2d 游戏 - 增量时间和碰撞问题

标签 java collision 2d-games timedelta

我正在尝试制作一个 java 2d 游戏,总体来说效果似乎不错。唯一的问题是,我不知道如何放置我的“增量”时间,以使 Action 在 30 FPS 和 1000 FPS 上移动相同。

这是我的实体类代码:

import java.awt.Rectangle;

import map.Tile;
import graphics.Sprite;

public class Entity {
private String name;
private float positionx, positiony; // Current coordinate
private int targetx,targety; // Target coordinate
private double vx, vy; // Current vector
private double lx, ly; // Last vector

private float speed;
private Sprite sprite;

public Entity(String name, int x, int y, Sprite sprite){
    this.name = name;
    this.speed = 1f;

    this.positionx = x;
    this.positiony = y;

    this.sprite = sprite;

    main.Main.e.addEntity(this); // These kind of calls are ugly, and should be fixed.
}

public void remove(){
    main.Main.e.removeEntity(this);
    sprite.remove();
}

public void setVector(double vx, double vy){
    this.vx = vx;
    this.vy = vy;
}

public void update(long delta){
    //Multiply modifier to make it act the same on 30 fps as 1000 fps.
    vx = vx*delta;
    vy = vy*delta;

    // Calculate vector
    double distance = Math.sqrt((vx * vx) + (vy * vy));

    if(distance > 0){ // Have we reached the target yet?
        vx = ((vx / distance));
        vy = ((vy / distance));
    }else{
        vx = 0;
        vy = 0;
    }

    //Check collision with objects:
    Rectangle rx = new Rectangle((int) (vx+positionx), (int)positiony, 32, 32);
    Rectangle ry = new Rectangle((int) positionx, (int)(vy+positiony), 32, 32);

    for(Entity e : main.Main.e.getEntities()){
        if(this != e){
            if(isIntersecting(rx, e.getBounds())){
                vx = 0; // Disallow x direction.
            }
            if(isIntersecting(ry, e.getBounds())){
                vy = 0; // Disallow y direction.
            }
        }
    }

    //Check tiles:
    for(Tile t : main.Main.m.getNeighbours(positionx,positiony)){
        if(t.isBlocking()){
            if(isIntersecting(rx, t.getBounds())){
                vx = 0;
            }
            if(isIntersecting(ry, t.getBounds())){
                vy = 0;
            }
        }
    }

    //Update the position:
    positionx += vx*speed;
    positiony += vy*speed;

    //Animate:
    animate(vx, vy);
}

public boolean isIntersecting(Rectangle r1, Rectangle r2){
    return r1.intersects(r2);
}

public Rectangle getBounds(){
    return new Rectangle((int) positionx,(int) positiony,32,32);
}

public void setMoveTo(int x, int y){
    this.targetx = x;
    this.targety = y;
}

//This function is used by the bots, and not on players (they are setting the vector and use update directly):
public void moveTo(long delta){
    setVector((targetx-positionx),(targety-positiony));
    update(delta);
}

public void animate(double dx, double dy){
    sprite.setPosition((int)positionx, (int)positiony);

    if(dx > 0){
        sprite.setAnimation(0, 7, 100); // Walk right.
    }else if(dx < 0){
        sprite.setAnimation(1, 7, 100); // Walk left.
    }else{
        if(lx > 0){
            sprite.setAnimation(2, 3, 200); // Stand right.
        }else if(lx < 0){
            sprite.setAnimation(3, 3, 200); // Stand left.
        }
    }

    lx = dx;
    ly = dy;
}
}

我经常遇到的两个问题:

1# 游戏在 60FPS 和 500FPS 上的运行方式不同。

2# 游戏在 60FPS 和 500FPS 下的运行速度相同,但我的碰撞发生了问题,而且我无法移动到距离其他物体超过 15px 的地方。我想我需要实现类似的东西:如果我不能靠近10px,那么将其移动10px,但我不知道如何实现它。

如何正确实现?这会有很大帮助!

最佳答案

最简单的方法是考虑,如果您想要恒定速度下的恒定位移,您可以相对于 30 FPS 的增量缩放所有增量,如下所示:

enter image description here

因此,如果您以 60 FPS 运行,但想要与 30 FPS alpha 相同的位移,则为 (1/30)/(1/60) = 2

所以 删除vx = vx*delta; vy = vy*delta;

并将您的位置更新更改为

alpha = (1.0/30)*delta;
positionx += alpha*vx*speed;
positiony += alpha*vy*speed;

这只是一个粗略的解决方案,让我知道它是如何工作的,我稍后会更新以获得更正确的解决方案(考虑到由于渲染和计算需要一些时间,增量并不总是 1/FPS) .

编辑:变量增量稍后会出现。但一些优化:

  1. 您不需要在 Y 和 X 上构造一个矩形来进行碰撞检测,请尝试绘制两个矩形,如果它们相交,它们就会在两个轴上相交。只需从 vx + posx, vy+posy 创建一个矩形并检查与此的交集。
  2. 以上应该可以让你的碰撞检查减半。为了进一步优化,请考虑使用 QuadTree可以找到一个实现 here .

  3. 针对“ block 状”碰撞测试的问题(您从阻挡对象处停止 X 像素)。您可以用伪代码执行以下操作:

     if(new position will make this colide)
       while(this.position is more than one pixel away from blocking object)
         keep moving one pixel
    

这将使您在距目标 1 像素处停止。

关于Java 2d 游戏 - 增量时间和碰撞问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18147880/

相关文章:

java - H2O 中的 GridSearch API

c# - .net 中的 HashTable/Dictionary 实现选择了哪种类型的冲突解决方案?

java - 创建玩家乒乓 block 时的类(class)组织问题

javascript - 为什么我的 Sprite 不会出现在我的背景之上?

java - 我的刚体碰撞代码如何不一致?

javascript - 贪吃蛇游戏 : how to check if the head collides with its own body

java - Smack API,ChatMessageListener 接口(interface)无法正常工作

java - 有没有什么好的解释java语言的库?

java - 使用 JAXB 编码 xml 期间忽略 null 标签

C++ 冲突问题