libgdx学习笔记系列(三)会动的小人

(重要提示:Stage类在3.19号被作者更新后初始化方法已经改变,本篇代码在最新的版本中,会出错。详细请参考源码,及文档和第七篇笔记viewpoint的介绍
上次弄好了文字显示,可能有的同学感觉很繁琐。今天开始之前先给大家介绍下另外一种文字显示方法。直接使用字体文件。
拷贝今天刚刚更新编译的好的freetype的相关jar包和so文件。还有字体文件,(系统盘中的windows/fonts目录下有大量字体可以用,当然你也可以下载个性字体。)
修改上篇的代码如下:

@Override
    public void create() {
        //加载字体文件从电脑上拷贝的华文琥珀字体,当然你可以使用任意一种中文字体。
        FreeTypeFontGenerator freeTypeFontGenerator =
                new FreeTypeFontGenerator(Gdx.files.internal("data/font/STHUPO.TTF"));
        
        //关于字体的一些配置参数,详细的可以看官方API和FreeTypeFontGenerator的源码
        FreeTypeFontGenerator.FreeTypeFontParameter fontParameter = 
                new FreeTypeFontGenerator.FreeTypeFontParameter();
        
        //注意这不是我们要显示的文字,其实相当于我们上篇使用的文字工具编辑的字符串内容,
        // 这里是默认的字符串加上了我们要使用的汉字。
        fontParameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + "你好";
        
        //根据参数设置生成的字体数据,这就相当于上篇的myfont.fnt文件和myfont.png
        FreeTypeFontGenerator.FreeTypeBitmapFontData fontData =
                freeTypeFontGenerator.generateData(fontParameter);
        
        //及时释放资源,避免内存泄漏,因为中文字体文件一般都比较大
        freeTypeFontGenerator.dispose();
        
        //从字面看,其实也是加载的图片
        bitmapFont = new BitmapFont(fontData, fontData.getTextureRegions(), false);
        batch = new SpriteBatch();
        //文字绘制 (注释掉昨天的)
//        bitmapFont = new BitmapFont(Gdx.files.internal("data/font/myfont.fnt"),
//                Gdx.files.internal("data/font/myfont.png"), false);

    }

确实比原来的方便了点,起码不用使用工具类手动编辑文字了。
如果游戏中的文字比较少,推荐使用上篇手动生成,节省系统资源,毕竟加载字体文件开销还是比较大的。如果文字比较多,可以使用这种方法。但是一定注意及时释放资源。


好了,接下来显示个人物吧
人物图片


拷贝人物图片到android中的assets目录
我放到了data/image目录下

修改Mygame如下:
package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;

public class MyGame implements ApplicationListener {
    private SpriteBatch batch;
    private BitmapFont bitmapFont;
    private Texture texture;

    @Override
    public void create() {
        //加载字体文件从电脑上拷贝的华文琥珀字体,当然你可以使用任意一种中文字体。
        FreeTypeFontGenerator freeTypeFontGenerator =
                new FreeTypeFontGenerator(Gdx.files.internal("data/font/STHUPO.TTF"));

        //关于字体的一些配置参数,详细的可以看官方API和FreeTypeFontGenerator的源码
        FreeTypeFontGenerator.FreeTypeFontParameter fontParameter =
                new FreeTypeFontGenerator.FreeTypeFontParameter();

        //注意这不是我们要显示的文字,其实相当于我们上篇使用的文字工具编辑的字符串内容,
        // 这里是默认的字符串加上了我们要使用的汉字。
        fontParameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + "你好";

        //根据参数设置生成的字体数据,这就相当于上篇的myfont.fnt文件和myfont.png
        FreeTypeFontGenerator.FreeTypeBitmapFontData fontData =
                freeTypeFontGenerator.generateData(fontParameter);

        //及时释放资源,避免内存泄漏,因为中文字体文件一般都比较大
        freeTypeFontGenerator.dispose();

        //从字面看,其实也是加载的图片
        bitmapFont = new BitmapFont(fontData, fontData.getTextureRegions(), false);
        batch = new SpriteBatch();
        //文字绘制 (注释掉昨天的)
//        bitmapFont = new BitmapFont(Gdx.files.internal("data/font/myfont.fnt"),
//                Gdx.files.internal("data/font/myfont.png"), false);

        texture = new Texture(Gdx.files.internal("data/image/girl.png"));

    }

    @Override
    public void render() {
        //这个经常出现的代码就是opengl ES的清屏方法
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        //使用一种颜色填充屏幕
        //前三个是屏幕颜色的参数,最后一个是透明度,注意颜色不是我们熟悉的RGB
        Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);

        batch.begin();
        bitmapFont.draw(batch, "你好libgdx!......", Gdx.graphics.getWidth() * 0.4f, Gdx.graphics.getHeight() / 2);
        batch.draw(texture,0, 0);
        batch.end();

    }

    @Override
    public void dispose() {
        batch.dispose();
        bitmapFont.dispose();
        texture.dispose();

    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }


}


其实主要就2行代码
加载人物
 texture = new Texture(Gdx.files.internal("data/image/01.png"));

显示出来
 batch.draw(texture,0, 0);

注意后边的三个参数,texture人物纹理,后边两个参数其实就是指屏幕的左下角原点。
libgdx是以屏幕左下角为起始点的。


但是这个小人还不会动。
在开始动之前,先要说下Stage和Actor的概念。顾名思义,舞台和演员。
其实很好理解。以现实中的舞台和演员为例。比如京剧,其中演员就是指的具体的角色青衣,花旦等等扮演者都是演员。舞台当然就是表演的场所了。
具体在游戏中,演员本身有自己的一些特性,比如会走动,会唱歌,跳舞等等,舞台就是容纳演员表演的舞台。游戏中的演员一般就是指具体的游戏元素,例如我们图片中的人物,还有中间显示的文字。
再举个大家大部分都玩过的游戏。愤怒的小鸟,什么是演员呢。小鸟,猪,弹弓,被关的小鸟,场景中的各种冰块,石头,木制。建筑物,甚至于,显示的分数,碰撞的特效都可以称为演员。舞台呢,就是容纳这些演员的一个容器。
我们先看看Actor的源码中的解释
2D scene graph node. An actor has a position, rectangular size, origin, scale, rotation, Z index, and color. The position
 * corresponds to the unrotated, unscaled bottom left corner of the actor. The position is relative to the actor's parent. The
 * origin is relative to the position and is used for scale and rotation.
 * <p>
 * An actor has a list of in progress {@link Action actions} that are applied to the actor (often over time). These are generally
 * used to change the presentation of the actor (moving it, resizing it, etc). See {@link #act(float)}, {@link Action} and its
 * many subclasses.
 * <p>
 * An actor has two kinds of listeners associated with it: "capture" and regular. The listeners are notified of events the actor
 * or its children receive. The regular listeners are designed to allow an actor to respond to events that have been delivered.
 * The capture listeners are designed to allow a parent or container actor to handle events before child actors. See {@link #fire}
 * for more details.
 * <p>
 * An {@link InputListener} can receive all the basic input events. More complex listeners (like {@link ClickListener} and
 * {@link ActorGestureListener}) can listen for and combine primitive events and recognize complex interactions like multi-touch
 * or pinch.

演员中主要包括它的位置信息,大小,缩放,旋转,颜色等等特征。
具体可参考官方的API文档。
源码+API文档=最权威教程
希望大家善用API文档和源码。
然后再看下stage的源码和文档的解释。



我们看到Group root;这个定义。group是什么呢
Group 就是舞台中的所有演员,舞台是通过Group的 addActor方法来添加演员的。
大概概念介绍到这里,如有疑问可以参考一些教程和官方文档

我们来新建一个演员类如下
package com.me.mygdxgame;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;


public class GirlActor extends Actor {
    TextureRegion[] girlRegion;
    float stateTime;
    //当前帧
    TextureRegion currentFrame;
    Animation animation;

    public GirlActor(Texture[] texture) {
        girlRegion = new TextureRegion[16];
        //把Texture转换下
        for (int i = 0; i < 16; i++) {
            girlRegion[i] = new TextureRegion(texture[i]);
        }
        //动画播放,参数为动画播放速度。和纹理数组
        //0.06*16=0.96 大概就是1秒钟播放完这个动画。
        animation = new Animation(0.06f, girlRegion);
    }


    @Override
    public void draw(Batch batch, float parentAlpha) {
        stateTime += Gdx.graphics.getDeltaTime();
        //下一帧
        currentFrame = animation.getKeyFrame(stateTime, true);
        //绘制人物
        batch.draw(currentFrame, 0, 0);
    }
}


修改MyGame类
package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;

import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;

public class MyGame implements ApplicationListener {
    private SpriteBatch batch;
    private BitmapFont bitmapFont;
    private Texture texture;
    private Stage stage;

    @Override
    public void create() {
        //加载字体文件从电脑上拷贝的华文琥珀字体,当然你可以使用任意一种中文字体。
        FreeTypeFontGenerator freeTypeFontGenerator =
                new FreeTypeFontGenerator(Gdx.files.internal("data/font/STHUPO.TTF"));

        //关于字体的一些配置参数,详细的可以看官方API和FreeTypeFontGenerator的源码
        FreeTypeFontGenerator.FreeTypeFontParameter fontParameter =
                new FreeTypeFontGenerator.FreeTypeFontParameter();

        //注意这不是我们要显示的文字,其实相当于我们上篇使用的文字工具编辑的字符串内容,
        // 这里是默认的字符串加上了我们要使用的汉字。
        fontParameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + "你好";

        //根据参数设置生成的字体数据,这就相当于上篇的myfont.fnt文件和myfont.png
        FreeTypeFontGenerator.FreeTypeBitmapFontData fontData =
                freeTypeFontGenerator.generateData(fontParameter);

        //及时释放资源,避免内存泄漏,因为中文字体文件一般都比较大
        freeTypeFontGenerator.dispose();

        //从字面看,其实也是加载的图片
        bitmapFont = new BitmapFont(fontData, fontData.getTextureRegions(), false);
        batch = new SpriteBatch();
        //文字绘制 (注释掉昨天的)
//        bitmapFont = new BitmapFont(Gdx.files.internal("data/font/myfont.fnt"),
//                Gdx.files.internal("data/font/myfont.png"), false);
        texture = new Texture(Gdx.files.internal("data/image/girl.png"));
        Texture[] girlTextures = new Texture[16];
        //加载人物动作的16幅图片
        for (int i = 0; i < 16; i++) {
            girlTextures[i] = new Texture(Gdx.files.internal("data/image/" + (i + 1) + ".png"));
        }
        //初始化演员类
        GirlActor girlActor = new GirlActor(girlTextures);
        //初始化舞台,舞台大小为屏幕大小
        stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);

        //把演员放入舞台
        stage.addActor(girlActor);


    }

    @Override
    public void render() {
        //这个经常出现的代码就是opengl ES的清屏方法
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        //使用一种颜色填充屏幕
        //前三个是屏幕颜色的参数,最后一个是透明度,注意颜色不是我们熟悉的RGB
        Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);


        stage.act();
        //画出舞台中的演员,draw方法其实就跟下边的方法类似也是以begin开始,end结束,所以我们就不用再写了。
        stage.draw();


        batch.begin();
        bitmapFont.draw(batch, "你好libgdx!......", Gdx.graphics.getWidth() * 0.4f, Gdx.graphics.getHeight() / 2);
//        batch.draw(texture,0, 0);
        batch.end();

    }

    @Override
    public void dispose() {
        batch.dispose();
        bitmapFont.dispose();
        texture.dispose();
        stage.dispose();


    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }


}


运行下,好了,动起来了。(相关图片可以在源码中获取)
Animation 是我们实现动画的关键类。其实通过查看它的源码我们可以知道。
其实它就是通过切换单个图片文件来实现连续动画的。并且我们还可以改变它的播放模式,
例如动画只播放一次,循环播放,倒退播放(可以想象下磁带倒着播放),循环随机播放等等
这里我们使用的是正常播放模式,默认循环播放。
Gdx.graphics.getDeltaTime();

这是干什么用的呢。还是那句话,看源码
return the time span between the current frame and the last frame in seconds. Might be smoothed over n frames.
什么意思呢,它返回的是当前帧和前一帧之间的时间跨度。
为了更直观。我输出了下它的变化。
 @Override
    public void draw(Batch batch, float parentAlpha) {
        System.out.println("DeltaTime====="+Gdx.graphics.getDeltaTime());
        stateTime += Gdx.graphics.getDeltaTime();
        //下一帧
        currentFrame = animation.getKeyFrame(stateTime, true);
        //绘制人物
        batch.draw(currentFrame, 0, 0);

输出结果(注意,这里我使用的是真实的设备:华为C8813)
03-18 08:51:57.994    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016970333
03-18 08:51:58.004    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016164333
03-18 08:51:58.024    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016304668
03-18 08:51:58.034    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016325668
03-18 08:51:58.054    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.015347001
03-18 08:51:58.074    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.015698
03-18 08:51:58.084    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016385
03-18 08:51:58.104    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016376335
03-18 08:51:58.124    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016360667
03-18 08:51:58.134    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016013334
03-18 08:51:58.154    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016335
03-18 08:51:58.164    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016316334
03-18 08:51:58.184    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016595
03-18 08:51:58.204    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016330667
03-18 08:51:58.214    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016255334
03-18 08:51:58.234    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016421335
03-18 08:51:58.254    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016354334
03-18 08:51:58.264    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016077667
03-18 08:51:58.284    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016364332
03-18 08:51:58.304    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016402
03-18 08:51:58.314    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016265666
03-18 08:51:58.334    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016333
03-18 08:51:58.344    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016339
03-18 08:51:58.364    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016320666
03-18 08:51:58.394    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016559333
03-18 08:51:58.404    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.017074665
03-18 08:51:58.414    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016678333
03-18 08:51:58.434    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016316665
03-18 08:51:58.444    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016318668
03-18 08:51:58.464    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016178
03-18 08:51:58.474    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.015533668
03-18 08:51:58.504    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016484333
03-18 08:51:58.514    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016375002
03-18 08:51:58.534    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016400667
03-18 08:51:58.544    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016734667
03-18 08:51:58.564    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016447667
03-18 08:51:58.574    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.015874667
03-18 08:51:58.594    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016333
03-18 08:51:58.614    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016313998
03-18 08:51:58.624    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.015864002
03-18 08:51:58.644    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016313668
03-18 08:51:58.654    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016386667
03-18 08:51:58.674    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016461
03-18 08:51:58.694    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016348667
03-18 08:51:58.704    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016316665
03-18 08:51:58.724    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016343666
03-18 08:51:58.744    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016439
03-18 08:51:58.754    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016340334
03-18 08:51:58.774    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016478999
03-18 08:51:58.794    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016400333
03-18 08:51:58.804    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016583
03-18 08:51:58.824    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016164333
03-18 08:51:58.834    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016223
03-18 08:51:58.854    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016178
03-18 08:51:58.874    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016279334
03-18 08:51:58.884    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016175
03-18 08:51:58.904    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016370334
03-18 08:51:58.924    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016302332
03-18 08:51:58.934    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016382333
03-18 08:51:58.954    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016404334
03-18 08:51:58.974    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016325668
03-18 08:51:58.984    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016703665
03-18 08:51:59.004    3604-3747/com.me.mygdxgame I/System.out﹕ DeltaTime=====0.016402332

恩,每帧之间的间隔大约是0.016s。这说明什么呢。
在理解这个之前我们要先了解下帧和帧率的概念,什么是帧呢,简单理解就是屏幕刷新一次。显示出我们需要看到的内容。还记得以前的老电影吗?播放胶片的那个(当然现在也是播放胶片),它每秒大约播放24张胶片,每张胶片为1帧,相当于每秒刷新24次,那么它的帧率就是24.对于游戏简单来说,帧率就是我们每秒刷新屏幕的次数,还记得前面说的render()方法吗,我不是说它其实就像个循环方法一样不停循环码,其实这个可以认为是它每秒执行了多少次。执行了多少次呢。算下吧。1s/0.016s≈62.5 也就是大概60。大家可以数下上面日志输出的个数。从第二行58秒开始到倒数第二行结束。这一秒内输出了多少次。
当然为了验证下我的计算和猜测。我们来输出下我们游戏真实的帧率。
修改MyGame代码如下
package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;

import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;

public class MyGame implements ApplicationListener {
    private SpriteBatch batch;
    private BitmapFont bitmapFont;
    private Texture texture;
    private Stage stage;
    Label fps;
    Label newFPS;

    @Override
    public void create() {
        //加载字体文件从电脑上拷贝的华文琥珀字体,当然你可以使用任意一种中文字体。
        FreeTypeFontGenerator freeTypeFontGenerator =
                new FreeTypeFontGenerator(Gdx.files.internal("data/font/STHUPO.TTF"));

        //关于字体的一些配置参数,详细的可以看官方API和FreeTypeFontGenerator的源码
        FreeTypeFontGenerator.FreeTypeFontParameter fontParameter =
                new FreeTypeFontGenerator.FreeTypeFontParameter();

        //注意这不是我们要显示的文字,其实相当于我们上篇使用的文字工具编辑的字符串内容,
        // 这里是默认的字符串加上了我们要使用的汉字。
        fontParameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + "你好";

        //根据参数设置生成的字体数据,这就相当于上篇的myfont.fnt文件和myfont.png
        FreeTypeFontGenerator.FreeTypeBitmapFontData fontData =
                freeTypeFontGenerator.generateData(fontParameter);

        //及时释放资源,避免内存泄漏,因为中文字体文件一般都比较大
        freeTypeFontGenerator.dispose();

        //从字面看,其实也是加载的图片
        bitmapFont = new BitmapFont(fontData, fontData.getTextureRegions(), false);
        batch = new SpriteBatch();
        //文字绘制 (注释掉昨天的)
//        bitmapFont = new BitmapFont(Gdx.files.internal("data/font/myfont.fnt"),
//                Gdx.files.internal("data/font/myfont.png"), false);
        texture = new Texture(Gdx.files.internal("data/image/girl.png"));
        Texture[] girlTextures = new Texture[16];
        //加载人物动作的16幅图片
        for (int i = 0; i < 16; i++) {
            girlTextures[i] = new Texture(Gdx.files.internal("data/image/" + (i + 1) + ".png"));
        }
        //初始化演员类
        GirlActor girlActor = new GirlActor(girlTextures);
        //初始化舞台,舞台大小为屏幕大小
        stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);

        //黑色显示
        Label.LabelStyle labelStyle = new Label.LabelStyle(new BitmapFont(), Color.BLACK);
        //显示内容
        fps = new Label("FPS:", labelStyle);
        fps.setName("fps");
        //显示在左上角位置,减去显示字体的高度,要不然会跑到屏幕外面,根本看不到
        fps.setY(Gdx.graphics.getHeight() - fps.getHeight());
        fps.setX(0);


        //把演员放入舞台
        stage.addActor(girlActor);
        stage.addActor(fps);

    }

    @Override
    public void render() {
        //这个经常出现的代码就是opengl ES的清屏方法
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        //使用一种颜色填充屏幕
        //前三个是屏幕颜色的参数,最后一个是透明度,注意颜色不是我们熟悉的RGB
        Gdx.gl.glClearColor(0.57f, 0.40f, 0.55f, 1.0f);

        //因为render方法在不停执行,那么我们就在这里实时的更新系统帧率的数据
        //获取fps,然后修改它的显示为获取的系统帧率值
        newFPS = (Label) stage.getRoot().findActor("fps");
        newFPS.setText("FPS:" + Gdx.graphics.getFramesPerSecond());

        stage.act();
        //画出舞台中的演员,draw方法其实就跟下边的方法类似也是以begin开始,end结束,所以我们就不用再写了。
        stage.draw();


        batch.begin();
        bitmapFont.draw(batch, "你好libgdx!......", Gdx.graphics.getWidth() * 0.4f, Gdx.graphics.getHeight() / 2);
//        batch.draw(texture,0, 0);
        batch.end();

    }

    @Override
    public void dispose() {
        batch.dispose();
        bitmapFont.dispose();
        texture.dispose();
        stage.dispose();


    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }


}




62的帧率。验证了我的猜测。
在这里我要提醒下大家,不要把帧率,和动画播放速度弄混了。
动画切换速度为0.06s。帧率间隔为0.016,为了直观算作0.02好了。
估算下,每张图片显示的时间,屏幕刷新了几次。
这么弱的数学题我就不算了
  stateTime += Gdx.graphics.getDeltaTime();
        //下一帧
        currentFrame = animation.getKeyFrame(stateTime, true);

通过上面的介绍,相信都能了解上面两句的含义了。留给大家理解。
好了,收工。
源码地址:http://pan.baidu.com/s/1sjHFJh7
注意:图片资源来自于互联网,仅限学习,请勿用于商业用途,否则后果自负。

猜你喜欢

转载自archy123.iteye.com/blog/2032023