欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-21 10:25:38
...
(重要提示:Stage类在3.19号被作者更新后初始化方法已经改变,本篇代码在最新的版本中,会出错。详细请参考源码,及文档和第七篇笔记viewpoint的介绍libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
上次弄好了文字显示,可能有的同学感觉很繁琐。今天开始之前先给大家介绍下另外一种文字显示方法。直接使用字体文件。
拷贝今天刚刚更新编译的好的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);

    }

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

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

libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
拷贝人物图片到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是以屏幕左下角为起始点的。

libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
但是这个小人还不会动。
在开始动之前,先要说下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的源码和文档的解释。

libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android

我们看到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() {

    }


}



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

通过上面的介绍,相信都能了解上面两句的含义了。留给大家理解。
好了,收工。
源码地址:http://pan.baidu.com/s/1sjHFJh7
注意:图片资源来自于互联网,仅限学习,请勿用于商业用途,否则后果自负。
  • libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
  • 大小: 24.2 KB
  • libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
  • 大小: 4.1 KB
  • libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
  • 大小: 46.5 KB
  • libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
  • 大小: 179.7 KB
  • libgdx学习笔记系列(三)会动的小人
            
    
    博客分类: libgdx libgdx游戏android
  • 大小: 44.9 KB