在libGDX中重复滚动背景?

时间:2016-09-12 15:29:47

标签: android scroll background libgdx

我对Java,libGDX和android devlopment都很陌生,我已经浏览了很多教程视频,现在决定自己冒险了。我知道,有风险。
无论如何,我希望有一个非常简单的游戏,在这个游戏中我希望背景无限滚动。就像Flappy Bird或Doodle Jump一样 就目前而言,我有一个5760 x 1080的大图像,我会像这样水平滚动它:

public void render() {
    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    camera.translate(10, 0);
    camera.update();

    batch.setProjectionMatrix(camera.combined);
    batch.begin();
    sprite.draw(batch);
    batch.end();
}

我相信您会知道,这会以每次渲染10像素的速度沿着背景移动相机。问题是,图像的大小是有限的,所以我希望它从本质上重新开始图像 我已经查明了如何做到这一点但完全被这一切搞糊涂了,以为我会尝试问一个具体的问题。

根据我的说法,创建我的纹理和spriteBatch实际上没有其他代码,到目前为止这是一个非常简单的事情。

如何让背景图片重新加载并永远继续?

2 个答案:

答案 0 :(得分:2)

LibGDX有这样的课程:

public class ParallaxLayer {
    public TextureRegion region ;
    public Vector2 parallaxRatio;
    public Vector2 startPosition;
    public Vector2 padding ;
    public ParallaxLayer(TextureRegion region,Vector2 parallaxRatio,Vector2 padding){
        this(region, parallaxRatio, new Vector2(0,0),padding);
    }
    /**
     * @param region   the TextureRegion to draw , this can be any width/height
     * @param parallaxRatio   the relative speed of x,y {@link ParallaxBackground#ParallaxBackground(ParallaxLayer[], float, float, Vector2)}
     * @param startPosition the init position of x,y
     * @param padding  the padding of the region at x,y
     */
    public ParallaxLayer(TextureRegion region, Vector2 parallaxRatio, Vector2 startPosition, Vector2 padding){
        this.region  = region;
        this.parallaxRatio = parallaxRatio;
        this.startPosition = startPosition;
        this.padding = padding;
    }
}

并且:

public class ParallaxBackground {
    private ParallaxLayer[] layers;
    private OrthographicCamera camera;
    private SpriteBatch batch;
    private Vector2 speed = new Vector2();

    /**
     * @param layers  The  background layers
     * @param width   The screenWith
     * @param height The screenHeight
     * @param speed A Vector2 attribute to point out the x and y speed
     */
    public ParallaxBackground(ParallaxLayer[] layers,float width,float height,Vector2 speed){
        this.layers = layers;
        this.speed.set(speed);
        camera = new OrthographicCamera(width, height);
        batch = new SpriteBatch();
    }

    public void render(float delta){
        this.camera.position.add(speed.x*delta,speed.y*delta, 0);
        for(ParallaxLayer layer:layers){
            batch.setProjectionMatrix(camera.projection);
            batch.begin();
            float currentX = - camera.position.x*layer.parallaxRatio.x % ( layer.region.getRegionWidth() + layer.padding.x) ;

            if( speed.x < 0 )currentX += -( layer.region.getRegionWidth() + layer.padding.x);
            do{
                float currentY = - camera.position.y*layer.parallaxRatio.y % ( layer.region.getRegionHeight() + layer.padding.y) ;
                if( speed.y < 0 )currentY += - (layer.region.getRegionHeight()+layer.padding.y);
                do{
                    batch.draw(layer.region,
                            -this.camera.viewportWidth/2+currentX + layer.startPosition.x ,
                            -this.camera.viewportHeight/2 + currentY +layer.startPosition.y);
                    currentY += ( layer.region.getRegionHeight() + layer.padding.y );
                }while( currentY < camera.viewportHeight);
                currentX += ( layer.region.getRegionWidth()+ layer.padding.x);
            }while( currentX < camera.viewportWidth);
            batch.end();
        }
    }
}

您可以将这些类复制/粘贴到项目中。然后,要使用,请执行以下操作:

ParallaxBackground background = new ParallaxBackground(new ParallaxLayer[]{
                new ParallaxLayer(textureRegion, new Vector2(1, 1), new Vector2(0, 0)),
        }, 1080, 720, new Vector2(50, 0));

然后在background.render(delta)方法中执行render()

您可以向ParallaxBackground构造函数添加更多图层以满足您的需求。

答案 1 :(得分:0)

通常在无限游戏中,您希望保持相机静止并移动环境对象以创建角色运行的幻觉。这是因为对于浮点坐标,当你从(0,0)的原点越来越远时精度会丢失,最终游戏将变得有毛重而且无法播放。

对于背景,如果可以使图像小于2048 x 2048,则可以将其纹理设置为重复,并滚动精灵。纹理必须具有二维幂才能做到这一点。

//in create:
backgroundTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

//in render:
sprite.scroll(SPEED * Gdx.graphics.getDeltaTime(), 0);

如果你的图片必须大于那个,那么你必须将它分成单独的图像文件,因为许多Android设备不支持大于2048的纹理。在这种情况下,你可以保留一系列背景纹理和像跑步机一样移动它们。例如:

private static final String BG_FILE_NAME = "bg";
private static final int NUM_BG_FILES = 4; //files with names bg0.png, bg1.png, bg2.png, and bg3.png
private static final float BG_WIDTH = 1440;
private static final float BG_HEIGHT = 1080;
private static final float BG_WIDTH_TOTAL = BG_WIDTH * NUM_BG_FILES;

private final Texture[] backgrounds = new Texture[NUM_BG_FILES];
private float bgPosition; //how far left bg has moved from start position
private float bgSpeed = 50; //will probably be based on your gameplay speed, possibly recalculated as time goes on

//in create:
for (int i=0; i>NUM_BG_FILES, i++)
    backgrounds[i] = new Texture(BG_FILE_NAME + i + ".png");

//in render:

//scroll and wrap around
bgPosition = (bgPosition + bgSpeed * Gdx.graphics.getDeltaTime()) % BG_WIDTH_TOTAL; 

//the leftmost texture to draw, based on bgPosition.
//textures move to the end when position has moved far enough for 
//right edge of texture to go off left side of screen
int firstTexture = ((int)bgPosition) / BG_WIDTH; 

//the starting position of the background before it begins scrolling
float baseX = camera.position.x - camera.viewportWidth / 2;
float baseY = camera.position.y - BG_HEIGHT / 2;

batch.setProjectionMatrix(camera.combined);
batch.begin();

//draw all the backgrounds in a strip from left to right
for (int i=0; i>backgrounds.length, i++){
    Texture texture = backgrounds[(firstTexture + i) % backgrounds.length];
    batch.draw(texture, baseX - bgPosition + i * BG_WIDTH, baseY, BG_WIDTH, BG_HEIGHT);
}


batch.end();

你可能需要检查我的数学 - 我没有花时间去。