Java 在libGDX游戏中实现视差效果

Java 在libGDX游戏中实现视差效果,java,android,libgdx,Java,Android,Libgdx,我正在和一些朋友一起玩一个游戏,在这个游戏中,我们有一个很大的水平世界和一个只有1/3的水平世界。当播放器的水平位置改变时,相机会移动,所以相机只会向左和向右移动 游戏中显示的一些对象靠近玩家的视角,但其他对象则远离(例如,岛屿)。考虑到这一点,我们不能为元素设置固定位置,而只能移动相机。我们需要考虑到元素的距离来实现视差效果 下面是一个简单的图像,可以更好地解释它: 左侧的视口显示游戏的3个对象。绿色的在玩家的附近,红色的椭圆很远,黄色的椭圆在中间。在右侧的视口中,摄影机已向右移动,因此所有对

我正在和一些朋友一起玩一个游戏,在这个游戏中,我们有一个很大的水平世界和一个只有1/3的水平世界。当播放器的水平位置改变时,相机会移动,所以相机只会向左和向右移动

游戏中显示的一些对象靠近玩家的视角,但其他对象则远离(例如,岛屿)。考虑到这一点,我们不能为元素设置固定位置,而只能移动相机。我们需要考虑到元素的距离来实现视差效果

下面是一个简单的图像,可以更好地解释它: 左侧的视口显示游戏的3个对象。绿色的在玩家的附近,红色的椭圆很远,黄色的椭圆在中间。在右侧的视口中,摄影机已向右移动,因此所有对象都会从左侧消失。问题是,绿色矩形的相对运动大于黄色矩形的运动。同样,黄色对象的移动大于红色对象的移动


我创建了我的所有资产,考虑到它们的距离,但是现在,我如何使用libGDX模拟这个透视图呢?有课可以做吗?如果我必须在每次迭代中设置元素的位置,我如何计算正确的位置?

请注意,下面的示例没有经过测试,因为我只是回忆我是如何做的。这个想法很简单——为每个层创建一个额外的层,每个层具有初始位置和速度,并移动它们。如果一个层离开了边缘,那么在另一个边缘放置另一个层(这就是为什么我们要创建一个额外的层)

假设有一个视差对象,它具有初始位置、大小和速度-

public class Parallax extends DynamicGameObject {

    public float width, height; // Use setter/getter if you prefer

    public Parallax(float x, float y, float width, float height, float velocityX, float velocityY) {

        super(x, y, width, height);
        velocity.set(velocityX, velocityY);
        this.width = width;
        this.height = height;

    }

    public void update(float deltaTime) {
        position.add(velocity.x * deltaTime, velocity.y * deltaTime);
    }

    public void setPosition(float x, float y) {
        position.set(x, y);
    }
}
DynamicGameObject取自演示-

游戏对象也是如此-

public class GameObject {

    public final Vector2 position;
    public final Rectangle bounds;

    public GameObject(float x, float y, float width, float height) {
        this.position = new Vector2(x,y);
        this.bounds = new Rectangle(x - width/2f, y - height/2f, width, height);
    }
}
假设我们有两层——一层在前面,另一层在后面。我们每个都有一个纹理。每个纹理填充整个屏幕。我们为每一层创建两个实例,这样当一个纹理开始离开屏幕时,另一个纹理显示在边缘以填充间隙。如果有较小的纹理,则需要首先确定需要填充屏幕的纹理数量,然后使用一个额外的纹理来填充层之间的间隙

我们可以在创建世界时创建视差层阵列-

Array<Parallax> parallaxList = new Array<Parallax>(4);
我们在每个帧中的更新调用中更新层-

// In our example, TOTAL_LAYERS is 4
for (int i = 0; i < TOTAL_LAYERS; i++) {

    int tmpInt;
    Parallax parallax = parallaxList.get(i);

    parallax.update(deltaTime);

    // If one layer is off the edge, put it at the right of the next one
    // In this example, layers are moving from right to left
    if (parallax.position.x <= -parallax.width) {

        // We know that parallaxList's indexes 0 and 1 hold the back layers
        // and indexes 2 and 3 have the front layers. You can add additional
        // parameters in Parallax class to indicate a group so that you do not
        // have to determine the group in dirty way like this
        if(i == 0){
            tmpInt = 1;
        } else if(i == 1) {
            tmpInt = 0;
        } else if(i == 2) {
            tmpInt = 3;
        } else {
            tmpInt = 2;
        }

        parallax.setPosition(parallaxList.get(tmpInt).position.x + parallax.width, parallax.position.y);            
    }        
}
//在我们的示例中,共有4层
对于(int i=0;i如果(视差.position.x我会为每一层使用不同的正交摄影机。将每一层视为具有自己的坐标系比例。其中一层将是游戏物理发生的主层。在每一帧上,更新主层的摄影机后,抓住它的位置,并将其缩放版本应用为positioni在每个其他层的“摄影机”位置上(每个层应具有摄影机位置比例参数)。对于每个层,在添加该层的精灵之前,首先将其摄影机的组合矩阵应用于精灵批的投影矩阵。下面是一个示例。他们使用正交摄影机子类的单个实例进行了此操作,但这是相同的基本概念。
// Back
/* First parallax for back layer is at 0 x-axis. If you want to move the texture from right to left, the value of BACK_VELOCITY_X should be negative. You can experiment with velocity value for desire pace of movement. We do not want our layer to move on y-axis. Hence, it is set to 0. */

parallaxList.add(new Parallax(0, BACK_TEXTURE_HEIGHT, BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, BACK_VELOCITY_X, 0));

/* This one is also for back layer but it is positioned at the right edge of the layer above*/
parallaxList.add(new Parallax(BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, SOME_VELOCITY_X, 0));

// Front
parallaxList.add(new Parallax(0, 0, FRONT_TEXTURE_WIDTH, FRONT_TEXTURE_HEIGHT, FRONT_VELOCITY_X, 0));
parallaxList.add(new Parallax(FRONT_TEXTURE_WIDTH, 0, FRONT_TEXTURE_WIDTH, FRONT_TEXTURE_HEIGHT, FRONT_VELOCITY_X, 0));
// In our example, TOTAL_LAYERS is 4
for (int i = 0; i < TOTAL_LAYERS; i++) {

    int tmpInt;
    Parallax parallax = parallaxList.get(i);

    parallax.update(deltaTime);

    // If one layer is off the edge, put it at the right of the next one
    // In this example, layers are moving from right to left
    if (parallax.position.x <= -parallax.width) {

        // We know that parallaxList's indexes 0 and 1 hold the back layers
        // and indexes 2 and 3 have the front layers. You can add additional
        // parameters in Parallax class to indicate a group so that you do not
        // have to determine the group in dirty way like this
        if(i == 0){
            tmpInt = 1;
        } else if(i == 1) {
            tmpInt = 0;
        } else if(i == 2) {
            tmpInt = 3;
        } else {
            tmpInt = 2;
        }

        parallax.setPosition(parallaxList.get(tmpInt).position.x + parallax.width, parallax.position.y);            
    }        
}