java - 在libGDX游戏中实现视差效果

标签 java android libgdx

我正在和一些 friend 一起玩游戏,我们有一个很大的水平世界和一个 OrthographicCamera那只显示了它的 1/3。当玩家的水平位置发生变化时,此摄像机会移动,因此摄像机只会向左和向右移动。

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

这是一个简单的图像来更好地解释它: enter image description here 左边的视口(viewport)显示了游戏的 3 个对象。绿色的在玩家附近,红色的椭圆在远处,黄色的在中间。在右侧的视口(viewport)中,相机已向右移动,因此所有对象都消失在左侧。问题是绿色矩形的相对运动大于黄色的运动。同理,黄色物体的运动大于红色物体的运动。

我创建了我的所有 Assets ,考虑到它们有多远,但现在,我如何使用 libGDX 模拟这个视角?有什么类(class)可以做到吗?如果我必须在每次迭代中设置元素位置,我该如何计算正确的位置?

最佳答案

请注意,下面的示例未经过测试,因为我只是记忆我是如何做的。这个想法很简单 - 创建层,每个层都有一个额外的层,每个层都有初始位置和速度并移动它们。如果一层离开了边缘,则在相对的边缘放置另一层(这就是我们创建额外层的原因)。

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

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 取自 SuperJumper演示-

public class DynamicGameObject extends GameObject {

    public final Vector2 velocity;
    public final Vector2 accel;

    public DynamicGameObject(float x, float y, float width, float height) {
        super(x, y, width, height);
        velocity = new Vector2();
        accel = new Vector2();
    }
}

还有 GameObject-

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

我们可以像这样创建图层-

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

您可以使用 OrthographicCamera 和 SpriteBatch 来绘制视差层。您实际上可以使用现有的游戏摄像头,但我认为使用单独的摄像头要干净得多。无论如何,视差纹理通常足够大,可以在单独的调用中进行批处理,因此使用游戏相机很可能不会为您节省绘图调用。

关于java - 在libGDX游戏中实现视差效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23672797/

相关文章:

java - 将 JSON 转换为 Java 类(从 Android 应用程序调用 WebApi)

java - 计算两个字符串有多少个重复字符

android - getView() 方法、CheckBox 和 setOnClickListener()

java - Libgdx 如何设置闹钟?

java - 选择状态微调器后填充城市微调器

java - 是否可以通过它的 key 同步 ConcurrentHashMap 更新?

android - 切换到替代布局时,LoaderManager restartLoader 无法按预期工作

android - OpenGL ES2 : Vertex Indices and Texture coordinates?

java - libGdx 屏幕错误

java - 在 Windows 7 中运行 Jar 时为 "Execution Protection Violation"