上次弄好了文字显示,可能有的同学感觉很繁琐。今天开始之前先给大家介绍下另外一种文字显示方法。直接使用字体文件。
拷贝今天刚刚更新编译的好的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
注意:图片资源来自于互联网,仅限学习,请勿用于商业用途,否则后果自负。