当前位置: 首页 > 知识库问答 >
问题:

LibGdx如何使用正交相机滚动?

柴宏阔
2023-03-14

我已经找了10个小时了(字面意思),我已经完成了,我需要问一下。问题是我正在学习如何使用LibGdx编程Java游戏。我在做一个水平太空飞船游戏。所以,我这里最糟糕的问题是我不知道如何滚动(我认为画画会解释得更好)。我想画一个巨大的背景(空间),让我的正交相机像我的太空船一样移动,这样它就会用空间背景产生滚动效果。没有敌人,除了屏幕上的船什么都没有。

我正在尝试这个:

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

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

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

我实际上移动了摄像机的位置(我可以看到这多亏了println),但它在游戏中没有移动,所以宇宙飞船就消失在窗口的边缘。

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

spriteBatch.setProjectionMatrix(camera.combined);

但当我这样做的时候,windows只显示一个黑屏,没有飞船,什么也没有。正如我所说的,我很绝望,我看到了很多例子(用鼠标滚动,并行滚动等),但都是高级的,或者只是与我的代码无关。

这就是我画东西的方式。背景和船舶是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());     
}

如果有人想在硬核模式下帮忙,你可以在这里下载代码

我的代码(不工作)

我终于解决了!

这是我在一个类名WorldRenader中使用的代码,它有在游戏屏幕中调用的渲染、调整大小等方法

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

在船里面,我有这个方法,我在渲染中调用它来移动它

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

我还要非常感谢帮助我的人。我把第一个答案标记为好答案,但是,混合两者给了我真正的解决方案。

我在这里留下了一些我遵循的教程,它们对noobs非常有用

这是一个很好的一切从抓挠教程

一款简单的平台游戏platformGame

一款非常简单的棋子游戏

共有3个答案

斜浩穰
2023-03-14

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

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

}

这样,你的船总是在屏幕中间,背景移动。希望这有帮助。

黎鹤轩
2023-03-14

不清楚你的画是怎么画的?我不确定你的方法是否正确。。你能提供你的背景和船的细节吗?你能提供背景图像的详细信息吗?你滚动的是一个巨大的图像还是你想在滚动时重复的图像?

--编辑--

好的,我想我知道会发生什么。我通常会将相机应用于当前环境。

在调整大小时放置以下内容

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

将以下内容放置在渲染()的开头

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

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

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

当你移动相机的位置posX和posY时,看看它是什么样子。然后把你的船加入混合

--更多编辑---

然后,您可以计算posX和posY为

默认配置

等等

无论如何,我希望这能有所帮助,我还在自学,所以这可能不是最好的方法。。但它似乎奏效了。

林念
2023-03-14

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

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

你什么也看不见。在begin()/end()块内调用setProjectionMatrix时。当前批被刷新到gpu。所以,你实际上没有用相机矩阵画任何东西。您应该这样做:

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

编辑:

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

现在,您应该更加注意正在使用的坐标。我不太确定你是否真的需要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

如果你看到一个伸展的世界,试着去理解它是如何运作的(如果你什么都看不见,那就是哪里出了问题)。

编辑2

我看了你的代码。首先删除ppu,因为它会模糊您的代码。你在把你的摄像机定位到船上。在船上绘图时的位置。位置*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();
}
 类似资料:
  • 问题内容: 我正在开发一个可以显示一些3D模型的应用程序。我们加载模型,创建网格,将其添加到场景中…标准过程。添加最后一个网格后,我们使用总几何尺寸和视口尺寸进行数学运算,从而计算出边界框以移动摄像机并覆盖所有场景。 是包含边框的宽度和高度的对象。经过此计算,我们移动了相机(加上一点点比例,只是为了美观,我们希望在几何体和屏幕边框之间留出一点空间:))并进行渲染 到目前为止,这已实现并且可以正常运

  • 这一摄像机使用orthographic projection(正交投影)来进行投影。 在这种投影模式下,无论物体距离相机距离远或者近,在最终渲染的图片中物体的大小都保持不变。 这对于渲染2D场景或者UI元素是非常有用的。 代码示例 const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, hei

  • 我目前正在libgdx中试验不同的相机(使用ShapeRenderer)。然而,我发现在某些旋转时,它会停止渲染形状的部分。 例如,带有相机的正常形状 位置:(8.999996,7.699995,5.599995) 方向: (0.04838332,-0.60004705,-0.7576189): 但是,对于相机位置:(8.999996,7.699995,5.0999956)方向:(0.678907

  • 我有一个用WASD控制的相机,但是我一直在左右移动它。我一直在网上寻找,它说要找到一个垂直于另一个向量的向量,你改变x和y的圆,并将其中一个乘以-1。我在下面的代码中尝试过这个: 我一直在向前移动,工作得很好,实际上是在转动相机,但由于某些原因,这不起作用,老实说,我不确定它到底是做什么的,因为当我按下或(他们称之为该功能)时,相机会发疯,开始非常快速地转动,有时会向前移动,或者像100万英里以外

  • 正交投影照相机(Orthographic Camera)设置起来较为直观,它的构造函数是: THREE.OrthographicCamera(left, right, top, bottom, near, far) 这六个参数分别代表正交投影照相机拍摄到的空间的六个面的位置,这六个面围成一个长方体,我们称其为视景体(Frustum)。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,

  • 我刚刚开始使用LibGDX进行编码和应用程序开发,我有一些关于它的一般问题和一些更具体的问题。 在我开始之前:我知道我的一些问题可能已经在互联网上的某个地方被问到了,但我发现很难得到一个直接的答案。 所以,最基本的问题第一: 是否有可能在合理的时间内在LibGDX中创建一个普通的应用程序(如愤怒的小鸟或涂鸦跳跃)?在浏览互联网时,我遇到许多人说Unity这样的引擎“使用起来非常简单”,你可以用Li