Libgdx 之SpriteBatch深入分析

Libgdx共享资源

因为Libgdx可以在多平台上运行,因此理论上资源应该放在core目录下,因为Android和桌面版都包含主目录。但是Android对于如何存放这些文件有严格的规则,我们必须把资源放在固定的目录下。因此如果创建的工程需要在Android设备下运行的话,必须把资源放在Android项目自动创建的资源目录下。如果只是练习的可以放在core工程下面。

SpriteBatch的使用一

从上面涂可以看出SpriteBatch继承在Disposable,因此在游戏的最后必须调用dispose方法来释放内存。

SpriteBatch使用屏幕坐标(关于坐标可以看上一节的内容),原点在屏幕左下角,x轴向右,y轴向上。origin也在屏幕左下角。

All drawing commands of the Batch operate in screen coordinates. The screen coordinate system has an x-axis pointing to the right, an y-axis pointing upwards and the origin is in the lower left corner of the screen

从代码可以指定SpriteBatch最多可以绘制5460个对象,否则程序会抛出异常

// 32767 is max index, so 32767 / 6 - (32767 / 6 % 3) = 5460.

if (size > 5460) throw new IllegalArgumentException(“Can’t have more than 5460 sprites per batch: ” + size);

从目前知道的情况下SpriteBatch和Stage可以在屏幕上绘制图像资源,但是还有其它的方法比如Box2d等,但是那个离教程还很遥远。由于SpriteBatch是很消耗内存的对象,因此建议整个游戏中只有一个,在游戏结束时要调用dispose方法

要想绘制对象,首先要调用 begin()方法来告诉libgdx要准备绘制,绘制结束要调用end()方法来告诉libgdx绘制结束,准备收尾工作。这个过程是将要绘制的对象放到缓存中一起绘制,也可以先调用flush()来提前绘制对象

/** Draws a rectangle with the bottom left corner at x,y having the given width and height in pixels. The rectangle is offset by
     * originX, originY relative to the origin. Scale specifies the scaling factor by which the rectangle should be scaled around
     * originX, originY. Rotation specifies the angle of counter clockwise rotation of the rectangle around originX, originY. The
     * portion of the {@link Texture} given by srcX, srcY and srcWidth, srcHeight is used. These coordinates and sizes are given in
     * texels. FlipX and flipY specify whether the texture portion should be flipped horizontally or vertically.
     * @param x the x-coordinate in screen space
     * @param y the y-coordinate in screen space
     * @param originX the x-coordinate of the scaling and rotation origin relative to the screen space coordinates
     * @param originY the y-coordinate of the scaling and rotation origin relative to the screen space coordinates
     * @param width the width in pixels
     * @param height the height in pixels
     * @param scaleX the scale of the rectangle around originX/originY in x
     * @param scaleY the scale of the rectangle around originX/originY in y
     * @param rotation the angle of counter clockwise rotation of the rectangle around originX/originY
     * @param srcX the x-coordinate in texel space
     * @param srcY the y-coordinate in texel space
     * @param srcWidth the source with in texels
     * @param srcHeight the source height in texels
     * @param flipX whether to flip the sprite horizontally
     * @param flipY whether to flip the sprite vertically */
    public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX,
        float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY);

上面是SpriteBatch绘制Texture最全的一个方法了,了解这个方法,其余的方法就很容易理解。目前创建的app默认窗口是640*480,

public LwjglApplication (ApplicationListener listener) { this(listener, null, 640, 480);},也可以自己通过config修改。下面的代码注释有一个详细解释

    private static final String TAG = SpriteBatchTest1.class.getSimpleName();

    SpriteBatch batch;
    Texture img;
    int width, height;
    int screenWidth, screenHeight;
    float angle = 10f;

    @Override
    public void create() {
        batch = new SpriteBatch();
        img = new Texture("badlogic.jpg");

        // 图片资源的大小
        width = img.getWidth();
        height = img.getHeight();
        Gdx.app.log(TAG, "Texture widht="+ width + "  height="+height);

        screenWidth = Gdx.graphics.getWidth();
        screenHeight = Gdx.graphics.getHeight();
        Gdx.app.log(TAG, "screen width="+ screenWidth + " height="+ Gdx.graphics.getHeight());

    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        angle = (angle + 2) % 360;
        batch.begin();
        // 以默认Texture的大小来绘制图片
//      batch.draw(img, 0, 0);
        // 这个效果和上面的效果一样
        batch.draw(img, 0, 0, width * 0.5f, height * 0.5f, width, height,
                1.0f, 1.0f, 0.0f, 0, 0, width, height, false, false);
        // 从屏幕中心开始,以Texture的一半来绘制图像,这个相当于图像缩小了一半
        batch.draw(img, screenWidth * 0.5f, screenHeight * 0.5f, width *0.5f, height * 0.5f);
        // 在(350,0)这个位置以Texture的大小,但是只绘制纹理100*100
        batch.draw(img, 350, 0, width * 0.5f, height * 0.5f, width, height,
                1.0f, 1.0f, 0.0f, 0, 0, 100, 100, false, false);
        // 在(0,300)这个位置以100*100的大小绘制图片,同时origin大小也要换成100*0.5,同时图片以固定速度旋转
        batch.draw(img, 0, 300, 100 * 0.5f, 100 * 0.5f, 100, 100,
                    1.0f, 1.0f, angle, 0, 0, width, height, false, false);
        batch.end();
    }

    @Override
    public void dispose() {
        // 不用的资源要销毁,它们的共同点事implements Disposable
        batch.dispose();
        img.dispose();
    }

剩余代码可以自己补齐,最终效果如下图:

SpriteBatch的使用二

在我们参考其它人的代码实经常看见,在使用过程中camera于viewport相结合使用,因为在实际世界中我们使用的是一个千米千克,因此需要一个转化,如果我每小时跑10KM,转换一下就是2.77777778每秒(10 * 1000 / 3600)。下面代码就是对其过程的一个简单介绍

private static final String TAG = SpriteBatchTest2.class.getSimpleName();

    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;

    SpriteBatch batch;
    Texture img;
    Viewport viewport;
    OrthographicCamera camera;
    int width;
    int height;
    float originX;
    float originY;
    float angle = 10f;

    @Override
    public void create () {
        Gdx.app.log(TAG, "create");
        batch = new SpriteBatch();
        img = new Texture("badlogic.jpg");

        camera = new OrthographicCamera();
        camera.position.set(SCENE_WIDTH / 2f,  SCENE_HEIGHT / 2f, 0.0f);
        camera.update();
        Gdx.app.log(TAG, "camera.x" + camera.position.x);
//      viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);
        // 为了方便观察效果,将FitViewport转换为StretchViewport
        viewport = new StretchViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);

        width = img.getWidth();
        height = img.getHeight();
        originX = width * 0.5f;
        originY = height * 0.5f;

        Gdx.app.log(TAG, "width=" + width + " height="+height);
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        angle = (angle + 2) % 360;
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
//      batch.draw(img, 0, 0, width * WORLD_TO_SCREEN, height * WORLD_TO_SCREEN);
        // 上面和下面的语句效果是一样的
        batch.draw(img, 0, 0, originX * WORLD_TO_SCREEN, originY * WORLD_TO_SCREEN, width  * WORLD_TO_SCREEN,
                height * WORLD_TO_SCREEN, 1.0f, 1.0f, 0.0f, 0, 0, width, height, false, false);
//      batch.draw(img, 6.4f, 3.6f, width * WORLD_TO_SCREEN, height * WORLD_TO_SCREEN);
        // 上面和下面语句是一样的不过加了一个角度旋转图片,要想效果一样origin也需要*WORLD_TO_SCREEN,不过以固定角度旋转
        batch.draw(img, 6.4f, 3.6f, originX * WORLD_TO_SCREEN, originY * WORLD_TO_SCREEN, width  * WORLD_TO_SCREEN,
                height * WORLD_TO_SCREEN, 1.0f, 1.0f, angle, 0, 0, width, height, false, false);
        batch.draw(img, 0.0f, 7.2f - height * WORLD_TO_SCREEN, width * WORLD_TO_SCREEN, height * WORLD_TO_SCREEN);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
        Gdx.app.log(TAG, "resize");
    }

    @Override
    public void pause() {
        Gdx.app.log(TAG, "pause");
    }

    @Override
    public void resume() {
        Gdx.app.log(TAG, "resume");
    }

    @Override
    public void dispose() {
        img.dispose();
        batch.dispose();
        Gdx.app.log(TAG, "dispose");
    }   

首先是一个将camera是采用正交投影来观看我们的游戏世界,为了方便绘图,将其进行一个移动,最开始的时候的坐标如下图

但是通过方法 进行了转换,这样camera的投影就正好和screen看的一样

camera.position.set(SCENE_WIDTH / 2f, SCENE_HEIGHT / 2f, 0.0f);

camera.update();

最终程序运行效果如下图

时间: 2024-08-07 17:39:24

Libgdx 之SpriteBatch深入分析的相关文章

Android游戏框架Libgdx使用入门

转载自:http://blog.csdn.net/cping1982/article/details/6176191 Libgdx作者博客:http://www.badlogicgames.com/ Libgdx项目地址:http://code.google.com/p/libgdx/ Libgdx是一款支持2D与3D游戏开发的游戏类库,兼容大多数微机平台(标准JavaSE实现,能执行在Mac.Linux.Windows等系统)与Android平台(Android1.5以上就可以使用.Andro

LibGdx----Texture, TextureRegion, SpriteBatch

Introduction 本章介绍2D图形相关的一些基本内容,包括如何使用Texture,TextureRegion和SpriteBatch. Texture 略.. SpriteBatch LibGdx使用SpriteBatch来完成纹理映射并在屏幕上显示被纹理映射的四边形的所有工作.它使得在屏幕上绘制图形极为简单,并且经过优化.它在屏幕坐标系中工作,使用屏幕像素的绝对坐标.左下角是原点(0,0),X轴向右,Y轴向上.由于SpriteBatch可以同时处理多个绘制请求.使用GPU进行渲染加速并

Libgdx之国际化 中英文菜单切换

有时候我们做的游戏不仅仅发布在国内市场,有时候也需要发布在国际市场,这时候我们至少需要中英2套菜单来供不同的玩家使用,毕竟中文不是每个人都能看懂. Libgdx中提供了I18NBundle来供我们使用,I18NBundle提供了一套机制可以使我们从属性(properties)文件中加载资源, 属性文件中的资源是以"name"和"values"的形式存在的,而且资源最好有一个父文件,这样防止资源丢失时,可以使用父文件中的值: 通过上面图片可以看出string.prop

Libgdx之正交相机 OrthographicCamera

本翻译自Libgdx Wiki 本文主要介绍OrthographicCamera相机类和用法.OrthographicCamera是正交相机,用在2D游戏开发中,无论游戏物体放在游戏世界中的那个位置,用正交相机看到的物体都不会被缩放. 描述 正交相机的操作非常简单,就像我们在现实世界中操作相机一样,文章中主要介绍: 相机的移动和旋转 相机的放到和缩小 改变相机的视窗大小 在窗口(widow)坐标系和(世界)坐标系之间切换点的位置 使用正交相机可以在不必去操作矩阵的情况下非常方便的来移动游戏世界,

libgdx 裁剪多边形(clip polygon、masking polygon)

直接放例子代码,代码中以任意四边形为例,如果需要做任意多边形,注意libgdx不能直接用ShapeRender填充多边形,需要先切割成三角形. public static void drawClip(Batch batch, Polygon polygon, TextureRegion region, float x, float y) { float[] vertices = polygon.getVertices(); if (shapes == null) { shapes = new S

libgdx学习记录19——图片动态打包PixmapPacker

libgdx中,opengl 1.x要求图片长宽必须为2的整次幂,一般有如下解决方法 1. 将opengl 1.x改为opengl 2.0.(libgdx 1.0版本后不支持1.x,当然不存在这个问题,这里针对的是0.9.9版本) 2. 使用TexturePacker将图片打包好然后作成一张大图添加进来. 第二种方法是常用方法,但是不太灵活,添加.删除某些图片不太方便,改动较大.这里可以考虑使用PixmapPacker将图片进行动态打包. 主要方法: pack(String name, Pixm

libgdx学习记录17——照相机Camera

照相机在libgdx中的地位举足轻重,贯穿于整个游戏开发过程的始终.一般我们都通过Stage封装而间接使用Camera,同时我们也可以单独使用Camera以完成背景的移动.元素的放大.旋转等操作. Camera分为PerspectiveCamera(远景照相机)和OrthographicCamera(正交照相机). PerspectiveCamera为正常的照相机,当距离物体越远,则物体越小,一般在3D空间中使用. OrthographicCamera忽略了其Z轴,不管距离物体多远,其大小始终不

libgdx学习记录11——平铺地图TiledMap

地图对于游戏场景十分重要,很多游戏都需要对地图进行编辑,可使用TileMap进行编辑并生成对应的tmx格式地图文件. 编辑好后,可通过TmxMapLoader来读取地图文件.可通过一个正交相机OthographicCamera和正交地图渲染器OrthogonalTiledMapRenderer来进行显示. 实例如下: 1 package com.fxb.newtest; 2 3 import com.badlogic.gdx.ApplicationAdapter; 4 import com.ba

libGDX游戏的生命周期

一,ApplicationListener和ApplicationAdapter 提及到libGDX的游戏生命周期,那么不得不提一个非常重要的接口ApplicationListener,这个接口位于com.badlogic.gdx包里,ApplicationListener的主要职责是创建和显示窗口.下图为ApplicationListener里的函数: 既然ApplicationListener是接口,那么就一定是需要去实现才能使用了,但是每次使用都要去实现这么多个方法,似乎有点吃力不讨好,而