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

LibGDX SpriteBatch draw方法产生了没有意义的结果

劳和雅
2023-03-14

我已经阅读了文档:https://libgdx.badlogicgames.com/ci/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/SpriteBatch.html#draw-com.badlogic.gdx.graphics.Texture-float-float-float-float-float-float-float-float-float-int-int-int-int-boolean-boolean -

我以为我理解了x、y、originX和originY参数的行为,但显然没有。我正在玩一个简单的教程,在屏幕上绘制一个SpriteBatch。游戏使用的是OrthographicCamera和FitViewport。下面的代码在屏幕中间绘制纹理

float halfW = width * 0.5f;
float halfH = height * 0.5f;            

batch.draw(cavemanTexture,                              // Texture
                   -halfW, -halfH,                      // x, y
                   halfW, halfH,                        // originX, originY
                   width, height,                       // width, height
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,    // scaleX, scaleY
                   0.0f,                                // rotation
                   0, 0,                                // srcX, srcY
                   width, height,                       // srcWidth, srcHeight
                   false, false);                       // flipX, flipY

我想我不明白文档在句子中说“偏移”是什么意思,“矩形被原始X偏移,原始Y相对于原点。”

对我来说,如果你想把纹理放在屏幕的中心,你可以简单地执行以下操作:

batch.draw(cavemanTexture,                              // Texture
                   -halfW, -halfH,                      // x, y
                   0, 0,                        // originX, originY
                   width, height,                       // width, height
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,    // scaleX, scaleY
                   0.0f,                                // rotation
                   0, 0,                                // srcX, srcY
                   width, height,                       // srcWidth, srcHeight
                   false, false);                       // flipX, flipY

因为这样会将左下角向左移动,足以使纹理居中。但如果我尝试这样做,图像实际上会从屏幕上消失。

以下是完整的原始代码:

package com.cookbook.samples;


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;

public class SpriteBatchSample extends GdxSample {
    private static final Color BACKGROUND_COLOR = new Color(0.39f, 0.58f, 0.92f, 1.0f);
    private static final float WORLD_TO_SCREEN = 1.0f / 100.0f;
    private static final float SCENE_WIDTH = 12.80f;
    private static final float SCENE_HEIGHT = 7.20f;

    private OrthographicCamera camera;
    private Viewport viewport;
    private SpriteBatch batch;
    private Texture cavemanTexture;
    private Color oldColor;

    @Override
    public void create() {      
        camera = new OrthographicCamera();
        viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);
        batch = new SpriteBatch();
        oldColor = new Color();

        cavemanTexture = new Texture(Gdx.files.internal("data/caveman.png"));
        cavemanTexture.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
    }

    @Override
    public void dispose() {
        batch.dispose();
        cavemanTexture.dispose();
    }

    @Override
    public void render() {      
        Gdx.gl.glClearColor(BACKGROUND_COLOR.r,
                            BACKGROUND_COLOR.g,
                            BACKGROUND_COLOR.b,
                            BACKGROUND_COLOR.a);

        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.setProjectionMatrix(camera.combined);

        batch.begin();

        int width = cavemanTexture.getWidth();
        int height = cavemanTexture.getHeight();
        float originX = width * 0.5f;
        float originY = height * 0.5f;

        // Render caveman centered on the screen
        batch.draw(cavemanTexture,                      // Texture
                   -originX, -originY,                  // x, y
                   originX, originY,                    // originX, originY
                   width, height,                       // width, height
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,    // scaleX, scaleY
                   0.0f,                                // rotation
                   0, 0,                                // srcX, srcY
                   width, height,                       // srcWidth, srcHeight
                   false, false);                       // flipX, flipY

        // Render caveman on the top left corner at 2x size
        batch.draw(cavemanTexture,
                   -4.0f - originX, 1.5f - originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN * 2.0f, WORLD_TO_SCREEN * 2.0f,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render caveman on the bottom left corner at 0.5x size
        batch.draw(cavemanTexture,
                   -4.0f - originX, -1.5f - originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN * 0.5f, WORLD_TO_SCREEN * 0.5f,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render caveman on top right corner at 2x size and rotated 45 degrees
        batch.draw(cavemanTexture,
                   4.0f - originX, 1.5f - originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN * 2.0f, WORLD_TO_SCREEN * 2.0f,
                   45.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render caveman on bottom right corner at 1.5x size and flipped around X and Y
        batch.draw(cavemanTexture,
                   4.0f - originX, -1.5f - originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN * 1.5f, WORLD_TO_SCREEN * 1.5f,
                   0.0f,
                   0, 0,
                   cavemanTexture.getWidth(), height,
                   true, true);

        // Save batch color
        oldColor.set(batch.getColor());

        // Render blue caveman
        batch.setColor(Color.CYAN);
        batch.draw(cavemanTexture, 
                   -2.0f - originX, -originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render red caveman
        batch.setColor(Color.RED);
        batch.draw(cavemanTexture, 
                   -originX, -originY + 2.0f,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render green caveman
        batch.setColor(Color.GREEN);
        batch.draw(cavemanTexture, 
                   2.0f - originX, -originY,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        // Render yellow caveman
        batch.setColor(Color.YELLOW);
        batch.draw(cavemanTexture, 
                   -originX, -originY - 2.0f,
                   originX, originY,
                   width, height,
                   WORLD_TO_SCREEN, WORLD_TO_SCREEN,
                   0.0f,
                   0, 0,
                   width, height,
                   false, false);

        batch.setColor(oldColor);

        batch.end();
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height, false);
    }
}

共有2个答案

柴博
2023-03-14

在这里,对象被缩放并围绕x,y旋转

public class Enemy {
static final float scale = .4f;

int type_ship;
int x = 0;
int y = 0;
int angle = 0;
Rectangle rect;
TextureRegion region;


public Enemy(int type_ship, int x, int y) {
    this.type_ship = type_ship;
    this.x = x;
    this.y = y;
    rect = SpriteMaps.get_sprite_rect(SpriteMaps.ENEMY_RED);
    region = new TextureRegion(Textures.getShipsTexture(),
            (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
}

public void update() {

}

public void draw(SpriteBatch batch) {

    float width = rect.width;
    float height = rect.height;

    float draw_x = this.x - width / 2;
    float draw_y = this.y - height / 2;

    batch.draw(region, draw_x,  draw_y, width / 2, height / 2,
            rect.width, rect.height, scale, scale, angle);
}

}
空浩淼
2023-03-14

您的比例因子(WORLD_TO_SCREEN)的名称使我怀疑您误解了视口的工作原理。使用视口的全部意义在于,当您在游戏世界中放置内容时,您不必考虑屏幕尺寸。传递给视口构造函数的大小是您希望在游戏世界中可见的程度。使用视口的摄像机绘制某些内容时,其大小不应与屏幕尺寸相关,因为视口已经将其抽象出来。您应该以世界单位应有的大小绘制它。

如果原点在(0,0)左侧,则纹理的左下角在(< code>x,< code>y)处绘制。原点是相对于底角的偏移,围绕该点应用缩放和旋转。如果比例为1,旋转为0,原点x和y将没有任何影响。

如果你不打算用旋转来绘制精灵,我会避免复杂的< code>draw方法,而只使用< code > sprite batch . draw(texture region,x,y,width,height)。在一个典型的游戏中,你会有一个TextureRegions的TextureAtlas,所以你永远不会把一个Texture对象传递给SpriteBatch。

你要么想用米(或类似的)单位来思考你的世界,要么如果你在做复古像素艺术,你可能想用复古像素(而不是屏幕像素)单位。所以你的穴居人可能有1米高,你想看到一个16米x 9米高的游戏世界。在这种情况下,可以使用FitViewport(16f,9f)实例化视口。当你画你的穴居人时,你会画出类似这样的东西

batch.draw(cavemanRegion, x, y, 1f / cavemanRegion.height * cavemanRegion.Width, 1f) 

其中 x 和 y 是游戏世界中左下角应该出现的位置。

 类似资料:
  • 片段着色器 结果是一个绿色屏幕,里面有一个黑色矩形。但我希望长方形改为蓝色。我的代码有问题吗?

  • 我有一个用户表和一个高尔夫比赛分数表。当用户参加比赛时,他使用表格在结果表中记录分数。我想显示一个结果表,显示用户的完整列表和比赛的分数。表中有八列分数——每门课一列。我正在努力使用php代码来显示结果分数。如果一名球员已经比赛,他的得分将正确显示,但如果表中的下一名球员没有比赛,则他的得分将显示为表中高于他的球员的得分。这将在列表中继续下去,直到获得真正的分数。我试图找到答案,但没有成功。这是我

  • 问题内容: 我需要在Java中执行一些浮点运算,如下面的代码所示: 这是为了模拟Betfair Spinner小部件作为输出给出的值的范围。 Java中的浮点算术似乎引入了一些意外错误。例如,我得到2.180000000000001而不是2.18。浮点数有什么用,您不相信对它们执行的算术结果吗?我该如何解决这个问题? 问题答案: 如果您需要精确的十进制值,则应使用java.math.BigDeci

  • 问题内容: 可以有一个 实现所有方法 的抽象类-里面没有抽象方法。 例如。: 与拥有与具体类相同的类相比,拥有这样的抽象类(如果有)有什么优势? 我能想到的是,当我将其声明为抽象时,它将不会被实例化。但是,我可以通过将其具体化并将其构造函数设为私有来达到相同的效果。 TIA。 // ================== 编辑:我能想到的另一种用途: 它可能会扩展另一个抽象类或实现一个接口,而不实现

  • 问题内容: 我有一个名为“单词”的列表,其中包含字符串。在这里Log.i可以很好地处理“ word”标签,但不会执行“step”语句。似乎如果条件不能很好地工作。尽管“单词”列表包含类似的字符串,但这种方法永远不会进入它。怎么了 请帮助 问题答案: 您需要使用,不。检查两个Object引用是否引用相同的内容Object: 从部分15.21.3引用相等运算符==和=!在的Java语言规范3.0: 虽