java LibGdx 如何使用 OrthographicCamera 滚动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14509261/
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:29:10  来源:igfitidea点击:

LibGdx How to Scroll using OrthographicCamera?

javascrolllibgdx

提问by MBRebaque

enter image description here

在此处输入图片说明

I have been loocking for 10 hours (literally) and I'm done, I need to ask. Thing is I'm learning How use LibGdx to program Java games. I'm doing a Horizontal Space Ship Game. So, my worst problem here is that I do not know how do scroll (I think draw will explain better). I want to draw a hudge background (Space) and make my OrthographicCamera move right like with my SpaceShip, so it will create a Scroll effect with the Space Background. No enemys and nothing but the ship on the screen.

我已经找了 10 个小时(字面意思),我已经完成了,我需要问一下。事情是我正在学习如何使用 LibGdx 来编写 Java 游戏。我正在做一个水平太空飞船游戏。所以,我最糟糕的问题是我不知道如何滚动(我认为 draw 会更好地解释)。我想绘制一个 hudge 背景(空间)并使我的 OrthographicCamera 像我的 SpaceShip 一样向右移动,因此它将创建一个带有空间背景的滚动效果。没有敌人,只有屏幕上的船。

I'm triying this

我正在尝试这个

 public void moveCamera(float x,float y){
    cam.position.set(x, y, 0);
 }

Then I use that method in my WorldRender render() method:

然后我在 WorldRender render() 方法中使用该方法:

public void render(float delta){ 
    ship.Move(delta);
    moveCamera(ship.getPosition().x,ship.getPosition().y);
    cam.update();
    System.out.println(""+cam.position);
    spriteBatch.begin();
        drawBackground();
        drawShip();
    spriteBatch.end();
}

I actually move the camera position (I can see that thanks to the println), but It isn't moving in the game, so SpaceShip just dissapears by the edge of the window.

我实际上移动了相机位置(由于 println 我可以看到),但它在游戏中没有移动,所以 SpaceShip 只是在窗口边缘消失了。

I also tried this before spriteBatch.end()

我在 spriteBatch.end() 之前也试过这个

spriteBatch.setProjectionMatrix(camera.combined);

but when I do that windows oly shows a black screen, no ship, no nothing. As I said, I'm desperate, I see lot of examples (scroll with mouse, paralexscrolling etc) but all are to advanced or just nothing to do with my code. Any help wil be appreciated

但是当我这样做时,Windows oly 显示黑屏,没有船,什么也没有。正如我所说,我很绝望,我看到了很多例子(用鼠标滚动、paralexscrolling 等),但都是先进的,或者与我的代码无关。任何帮助将不胜感激

This is how I draw stuff. Background and ship are textures inside WorldRender. I draw background image very wide, so my intention is do some scrolling over as I said. That's the code

这就是我画东西的方式。背景和船是 WorldRender 中的纹理。我画的背景图像很宽,所以我的目的是像我说的那样滚动一下。这就是代码

private void loadTextures(){
    shipTexture=new Texture(Gdx.files.internal("nave.png"));
    background=new Texture(Gdx.files.internal("fondo.jpg"));
}

public void drawShip(){
    spriteBatch.draw(shipTexture,ship.getPosition().x*ppuX,ship.getPosition().y*ppuY, ship.WIDTH*ppuX,ship.HEIGHT*ppuY);
}

public void drawBackground(){
    spriteBatch.draw(background, -10*ppuX,0*ppuY, Gdx.graphics.getWidth()*10,Gdx.graphics.getHeight());     
}

Here you can download the code if someone want to help in hardcore mode

如果有人想在硬核模式下提供帮助,您可以在这里下载代码

My code (not working)

我的代码(不工作)

I FINALLY SOLVED IT!!!! WIIIIIIIIII!!! That's the code I used in a class name WorldRenderer, wich have methods that are calle within GameScreen for render, resize etc

我终于解决了!!!!WIIIIIIIIII!!!这是我在类名 WorldRenderer 中使用的代码,其中包含在 GameScreen 中调用的用于渲染、调整大小等的方法

 public WorldRenderer(World world) {
    // TODO Auto-generated constructor stub

    this.world=world;
    this.ship=world.getShip();
    this.cam = new OrthographicCamera(CAMERA_WIDTH,CAMERA_HEIGHT);

    this.cam.setToOrtho(false,CAMERA_WIDTH,CAMERA_HEIGHT);
    this.cam.position.set(ship.getPosition().x,CAMERA_HEIGHT/2,0);
    this.cam.update();//actualizamos la camara
    spriteBatch=new SpriteBatch();
    loadTextures();
}

private void loadTextures(){
    shipTexture=new Texture(Gdx.files.internal("nave.png"));
    background=new Texture(Gdx.files.internal("fondo.jpg"));
}

  public void drawShip(){
          spriteBatch.draw(shipTexture,ship.getPosition().x,ship.getPosition().y,10,10);
}

public void drawBackground(){
    spriteBatch.draw(background, 0,0, 500,50);
} 

 public void render(float delta){ 
    ship.Move(delta);
    moveCamera(ship.getPosition().x);
    spriteBatch.setProjectionMatrix(cam.combined); 
    spriteBatch.begin();
        drawBackground();
        drawShip();
    spriteBatch.end();
}

 public void moveCemara(float x){
    cam.position.set(x+20,cam.position.y, 0);
    cam.update();
}

Inside the Ship I have this method wich I call within render in WorldRenderer to move It

在 Ship 内部我有这个方法,我在 WorldRenderer 中调用 render 来移动它

public void Move(float delta){
    if(Gdx.input.isKeyPressed(Keys.LEFT)) this.position.x -=velocity *delta;
    if(Gdx.input.isKeyPressed(Keys.RIGHT)) this.position.x +=velocity *delta;
    if(Gdx.input.isKeyPressed(Keys.UP)) this.position.y +=velocity *delta;
    if(Gdx.input.isKeyPressed(Keys.DOWN)) this.position.y -=velocity *delta;
}

Also I want to thanks very much to the people who helped me. I'm marking first answer as the good one, but, mix both was what gave me the real solution.

也非常感谢帮助过我的人。我将第一个答案标记为好的答案,但是,将两者混合在一起才是真正的解决方案。

I leave here some tutos I followed wich are pretty good for noobs

我在这里留下了一些我遵循的教程,这些教程对新手来说非常好

Thats a good everything-from-scratching-tuto LiGdxForNoobs

这是一个很好的从零开始的 教程 LiGdxForNoobs

A simple plataform game platformGame

一个简单的平台游戏平台游戏

A very simple game bucketGame

一个非常简单的游戏 bucketGame

采纳答案by joey.enfield

Its not clear how your drawing? I'm not sure if your doing this approach correctly.. Can you provide details of your background and ship? Can you provide details on you background image, is it a huge image that your scrolling around or is it a repeated image you want to repeat as you scroll?

不清楚你的绘图如何?我不确定您是否正确执行此方法.. 您能否提供有关您的背景和船舶的详细信息?您能否提供有关背景图像的详细信息,是滚动的大图像还是滚动时要重复的重复图像?

--EDIT--

- 编辑 -

ok i think i have an idea what might be up. I would normally apply the camera to the current context.

好的,我想我知道可能会发生什么。我通常会将相机应用于当前上下文。

Place the following in your resize

将以下内容放在您的调整大小中

    public void resize(int width, int height) {
    cam = new OrthographicCamera(width, height);
    cam.translate(width / 2, height / 2, 0);
}

Place the following in the start of your render()

将以下内容放在 render() 的开头

cam.position.set(posX,posY,0);
cam.update();
cam.apply(Gdx.gl10);
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // #14

This will make you have a clear screen with the origin set at the bottom left of the window. You should then draw your background first

这将使您有一个清晰的屏幕,原点设置在窗口的左下角。然后你应该先画你的背景

spriteBatch.setProjectionMatrix(cam.combined);
spriteBatch.begin();
spriteBatch.draw(background,0,0,sizeX,sizeY);
spriteBatch.end()

see how that looks as you move your camera position posX and posY. Then add your ship to the mix

看看当您移动相机位置 posX 和 posY 时的样子。然后将你的船加入混合物中

-- MORE EDITS ---

-- 更多编辑 --

you can then calculate the posX and posY as

然后你可以计算 posX 和 posY 为

posX = defaultOffsetX+shipX

posX = defaultOffsetX+shipX

and so on..

等等..

Anyhow hope this helps I'm still only learning myself so this might not be the best method.. but it seems to work.

无论如何希望这有助于我仍然只学习自己所以这可能不是最好的方法..但它似乎有效。

回答by aacotroneo

I can't tell if this is your only mistake, but this is ONE mistake. If this is what you say you were doing:

我不知道这是否是你唯一的错误,但这是一个错误。如果这就是你所说的你正在做的:

spriteBatch.begin();
drawBackground();
drawShip();
spriteBatch.setProjectionMatrix(camera.combined); 
spriteBatch.end();

You wont see anything. When setProjectionMatrix is called inside a begin()/end() block. the current batch is flushed to the gpu. So, you are actually not drawing anything with the camera matrix. You should do this instead:

你不会看到任何东西。在 begin()/end() 块内调用 setProjectionMatrix 时。当前批次被刷新到 GPU。因此,您实际上并未使用相机矩阵绘制任何内容。你应该这样做:

    spriteBatch.setProjectionMatrix(camera.combined); 
    spriteBatch.begin();
    drawBackground();
    drawShip();
    spriteBatch.end();

EDIT:

编辑:

If you don't call that line, spriteBatch uses its own default camera (which wont notice your camera.update() modifications, so that's not what you want).

如果您不调用该行, spriteBatch 将使用其自己的默认相机(它不会注意到您的 camera.update() 修改,因此这不是您想要的)。

You should now pay more attention to the coordinates you are using. I'm not quite sure you really need the ppu conversion thing. To begin with, define everything in imaginary world coordinates, note that you'll see some stretching in your world.

您现在应该更加注意您使用的坐标。我不太确定你真的需要 ppu 转换的东西。首先,在虚构的世界坐标中定义所有内容,注意您会在世界中看到一些拉伸。

public void drawShip(){
    spriteBatch.draw(shipTexture,ship.getPosition().x,ship.getPosition().y, 10, 10);
}//your ship is 10 units wide and tall!

public void drawBackground(){
    spriteBatch.draw(background, -10,0, 500, 100);     
} //your background is 500 units wide, and 100 units tall

//camera setup
camera = new OrthographicCamera(50, 50);
//your camera will print to screen 50 units of your world

If you get to see a stretched world, try to understand how it's working (if you can't see anything, there is something wrong somewhere).

如果您能看到一个拉伸的世界,请尝试了解它是如何工作的(如果您什么都看不到,则说明某处有问题)。

EDIT 2

编辑 2

I took a look at your code. First remove ppu's, as it obscures your code. You were setting your cam position to the ship.postion, while drawing at ship.position * ppu. Also your background was way too big (that's why you see it pixelated). You should see something reasonable with this. (someday you'll have to initialize your camera in another way to deal with stretching, but forget it until you understand how all works).

我看了一下你的代码。首先删除 ppu,因为它掩盖了您的代码。您将凸轮位置设置为ship.postion,同时在ship.position * ppu 处绘图。另外你的背景太大了(这就是你看到它像素化的原因)。你应该看到一些合理的东西。(总有一天你将不得不以另一种方式初始化你的相机来处理拉伸,但在你了解所有工作原理之前忘记它)。

this.cam = new OrthographicCamera(CAMERA_WIDTH,CAMERA_HEIGHT);

public void drawShip(){ 
    spriteBatch.draw(shipTexture, ship.getPosition().x ,ship.getPosition().y, 10, 10);
}

public void drawBackground(){
    spriteBatch.draw(background, -CAMERA_WIDTH/2, -CAMERA_HEIGHT/2, 100, 100); //let bg begin where camera starts. (0,0)
}


public void render(float delta){ 
    ship.Move(delta);
    moverCamara(ship.getPosition().x, ship.getPosition().y);
    spriteBatch.setProjectionMatrix(cam.combined);
    spriteBatch.begin();
        drawBackground();
        drawShip();
    spriteBatch.end();
}

回答by joey.enfield

I've edited your code. Have a look at the following:

我已经编辑了你的代码。看看以下内容:

public class WorldRenderer {

private World world;
private Ship ship;

private Texture shipTexture,background;
private SpriteBatch spriteBatch;

private OrthographicCamera cam;

float screenSizeX = 100;
float screenSizeY = 100;

float shipSizeX = 10;
float shipSizeY = 10;

public void setSize (int w, int h) {
    cam = new OrthographicCamera(screenSizeX,screenSizeY);
}


public WorldRenderer(World world) { 
    this.world=world;
    this.ship=world.getShip();
    spriteBatch=new SpriteBatch();
    loadTextures();
}



private void loadTextures(){
    shipTexture=new Texture(Gdx.files.internal("nave.png"));
    background=new Texture(Gdx.files.internal("fondo2.jpg"));
}

public void drawShip(){ 
    spriteBatch.draw(shipTexture, ship.getPosition().x,ship.getPosition().y, shipSizeX,shipSizeY);
}

public void drawBackground(){

    spriteBatch.draw(background, 0,0);
}


public void render(float delta){ 

    ship.Move(delta);

    moverCamara(ship.getPosition().x,ship.getPosition().y);

    spriteBatch.setProjectionMatrix(cam.combined);      
    spriteBatch.begin();
        drawBackground();
        drawShip();
    spriteBatch.end();
}




public void moverCamara(float x,float y){
    cam.position.set(x, y, 0);
    cam.update();
}

}

This way, your ship is always in the middle of the screen and the background moves. Hope this helps.

这样,您的船始终位于屏幕中间并且背景会移动。希望这可以帮助。