java LibGdx 如何重复背景?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14603759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 16:47:48  来源:igfitidea点击:

LibGdx How to repeat background?

javalibgdx

提问by MBRebaque

Few days ago I figured out how to do some scrolling in LibGdx. Now I'm triying to do something related. I want to repeat the background. My scrolling follows a ship (Is an s[ace ship game). In the background there is a space photo loaded as a Texture. When the ship reach the end of the backgorund, It keeps going and there's no background anymore. I have read about wrap but I don't really understand How It works. I did that:

几天前,我想出了如何在 LibGdx 中进行一些滚动。现在我正在尝试做一些相关的事情。我想重复背景。我的滚动跟随一艘船(是一个 s[ace 船游戏)。在背景中有一张作为纹理加载的空间照片。当船到达backgorund的尽头时,它继续前进,不再有背景。我已经阅读了有关 wrap 的内容,但我并不真正了解它是如何工作的。我是这样做的:

    px=new Pixmap(Gdx.files.internal("fondo.jpg"));
    background=new Texture(px);
    background.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);

And then, in my render method

然后,在我的渲染方法中

spriteBatch.begin();
    spriteBatch.draw(background,0,0,500,50);
    drawShip();
spriteBatch.end();

Of course It doesn't work, It only draws the background once. I don't know how make this wrap method work. Any help?

当然它不起作用,它只绘制一次背景。我不知道如何使这种包装方法起作用。有什么帮助吗?

SOLUTION

解决方案

I figured It out. It's not a nice code but It works.

我想到了。这不是一个很好的代码,但它有效。

First I declare two Textures with the same image

首先我声明两个具有相同图像的纹理

 bck1=new Texture(Gdx.files.internal("fondo.jpg"));
 bck2=new Texture(Gdx.files.internal("fondo.jpg"));

Also I declare two variables like this to specify the X value of the position of each bck

我还声明了两个这样的变量来指定每个 bck 位置的 X 值

 int posXBck1=0,posXBck2=0;

Then I use that in Render()

然后我在 Render() 中使用它

 public void calculoPosicionFondos(){
    posXBck2=posXBck1+ANCHODEFONDO;
    if(cam.position.x>=posXBck2+cam.viewportWidth/2){
        posXBck1=posXBck2;
    }
}

Where:

在哪里:

ANCHODEFONDO is the width of my background

ANCHODEFONDO 是我背景的宽度

Cam is an OtrhoCam.

Cam 是 OtrhoCam。

So I said that if the cam is in bck2 (wich means that you can't see bck1 anymore) It change positions, giving bck1 de position of bck2 and, in the next render loop, recalculating bck2

所以我说如果凸轮在 bck2 中(这意味着你再也看不到 bck1)它会改变位置,给出 bck2 的 bck1 de位置,并在下一个渲染循环中重新计算 bck2

Then just paint both bck in your render mode.

然后在您的渲染模式中绘制两者。

回答by Madmenyo

Like Teitus said, do not load your texture multiple times, ever! Anyway, you where on the right track with the wrapper:

就像 Teitus 所说的那样,永远不要多次加载您的纹理!无论如何,你在正确的轨道上使用包装器:

texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);

Now you can just use the draw method with the source location. The source location is the area you choose to draw on the texture.

现在您可以使用带有源位置的 draw 方法。源位置是您选择在纹理上绘制的区域。

batch.draw(texture, x, y, srcX, srcY, srcWidth, srcHeight)

To scroll your texture from right to left all you have to do is increase srcX incrementally. So create a int that increments in the update/render method.

要将纹理从右向左滚动,您所要做的就是逐渐增加 srcX。因此,创建一个在更新/渲染方法中递增的 int。

int sourceX = 0;

//render() method

//Increment the variable where to draw from on the image.
sourceX += 10;

//Simply draw it using that variable in the srcX.    
batch.draw(YourTexture, 0, 0, sourceX, 0, screenWidth, screenHeight);

Because you are wrapping the texture it will wrap/loop and scroll indefinitely. There might be a issue with the sourceX int if the game runs for a very long time because a int can only hold 2147483647. It takes a while but you can fix it by subtracting the image width each time the number goes over the total image width.

因为您正在包裹纹理,所以它将无限期地包裹/循环和滚动。如果游戏运行很长时间,sourceX int 可能有问题,因为 int 只能容纳 2147483647。这需要一段时间,但您可以通过每次数字超过总图像宽度时减去图像宽度来修复它.

回答by aacotroneo

Don't to this, please:

不要这样,请:

bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=new Texture(Gdx.files.internal("fondo.jpg"));

That will load your big background texture twice. That's a complete waste. If you want to keep your solution at least do:

这将加载您的大背景纹理两次。那完全是浪费。如果您想保留您的解决方案,请至少执行以下操作:

bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=bkg1;

Regarding the texture Wrapping. If your texture is 500px wide, and you draw a 500px sprite, you won't see any repetition. If you want it repeated 2 times, draw it 1000px wide with 0-2 texture coordinates. I'm not sure how spriteBatch handles the call you posted, you could try that one, or may be use the overload that uses a texture region and set your region manually.

关于纹理包装。如果您的纹理宽度为 500 像素,并且您绘制了一个 500 像素的精灵,您将看不到任何重复。如果您希望它重复 2 次,请使用 0-2 纹理坐标将其绘制为 1000 像素宽。我不确定 spriteBatch 如何处理您发布的调用,您可以尝试该调用,或者可能使用使用纹理区域的重载并手动设置您的区域。

回答by jjhavokk

I see this is a pretty old question, but I think there is an easier way to accomplish background scrolling. Just use the Sprite class. Here is a snippet I use for layered background images that scroll from right to left.

我看到这是一个很老的问题,但我认为有一种更简单的方法来完成背景滚动。只需使用 Sprite 类。这是我用于从右向左滚动的分层背景图像的片段。

public class LevelLayer 
{
    public float speedScalar = 1;

    private List<Sprite> backgroundSprites = new ArrayList<Sprite>();

    public LevelLayer()
    {

    }

    public void addSpriteLayer(Texture texture, float startingPointX, float y, int repeats)
    {
        for (int k = 0; k < repeats; k++)
        {
          Sprite s = new Sprite(texture);
          s.setX(startingPointX + (k*texture.getWidth()));
          s.setY(y);

          backgroundSprites.add(s);
        }
    }

  public void render(SpriteBatch spriteBatch, float speed)  
  { 
    for (Sprite s : backgroundSprites)
    {
        float delta = s.getX() - (speed * speedScalar);
        s.setX(delta);

        s.draw(spriteBatch);
    }
  }
}

Then you can use the same texture or series of textures like so:

然后你可以使用相同的纹理或一系列纹理,如下所示:

someLayer.addSpriteLayer(sideWalkTexture1, 0, 0, 15);
someLayer.addSpriteLayer(sideWalkTexture2, 15 * sideWalkTexture1.getWidth(), 0, 7);

I change background repeating sections randomly in code and make new ones or reset existing sets when they go off screen. All the layers go to a pool and get pulled randomly when a new one is needed.

我在代码中随机更改背景重复部分,并在它们离开屏幕时制作新的或重置现有的集。所有层都进入一个池,并在需要新层时随机拉出。

回答by MBRebaque

SOLUTION

解决方案

I figured It out. It's not a nice code but It works.

我想到了。这不是一个很好的代码,但它有效。

First I declare two Textures with the same image

首先我声明两个具有相同图像的纹理

 bck1=new Texture(Gdx.files.internal("fondo.jpg"));
 bck2=new Texture(Gdx.files.internal("fondo.jpg"));

Also I declare two variables like this to specify the X value of the position of each bck

我还声明了两个这样的变量来指定每个 bck 位置的 X 值

 int posXBck1=0,posXBck2=0;

Then I use that in Render()

然后我在 Render() 中使用它

 public void calculoPosicionFondos(){
    posXBck2=posXBck1+ANCHODEFONDO;
    if(cam.position.x>=posXBck2+cam.viewportWidth/2){
        posXBck1=posXBck2;
    }
}

Where:

在哪里:

ANCHODEFONDO is the width of my background

ANCHODEFONDO 是我背景的宽度

Cam is an OtrhoCam.

Cam 是 OtrhoCam。

So I said that if the cam is in bck2 (wich means that you can't see bck1 anymore) It change positions, giving bck1 de position of bck2 and, in the next render loop, recalculating bck2

所以我说如果凸轮在 bck2 中(这意味着你再也看不到 bck1)它会改变位置,给出 bck2 的 bck1 de位置,并在下一个渲染循环中重新计算 bck2

Then just draw both bck in your render()

然后在你的渲染()中绘制两个