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

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

}

确实比原来的方便了点,起码不用使用工具类手动编辑文字了。
如果游戏中的文字比较少,推荐使用上篇手动生成,节省系统资源,毕竟加载字体文件开销还是比较大的。如果文字比较多,可以使用这种方法。但是一定注意及时释放资源。
[img]http://dl2.iteye.com/upload/attachment/0094/9775/86a51983-b497-373f-93f7-a6f758490ff1.png[/img]

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

[img]http://dl2.iteye.com/upload/attachment/0094/9852/58eb01db-7043-3402-9c9e-3ab07054df66.png[/img]
拷贝人物图片到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是以屏幕左下角为起始点的。

[img]http://dl2.iteye.com/upload/attachment/0094/9856/cea3468b-df0f-36bf-90ef-70a6ce734d26.png[/img]
但是这个小人还不会动。
在开始动之前,先要说下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的源码和文档的解释。

[img]http://dl2.iteye.com/upload/attachment/0094/9881/26e9cf60-79e1-39c4-89ef-35844a3084cf.jpg[/img]

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

}


}



[img]http://dl2.iteye.com/upload/attachment/0095/0101/e99c78a9-3c7b-37b9-9ba2-d7f425a9c076.png[/img]
62的帧率。验证了我的猜测。
在这里我要提醒下大家,不要把帧率,和动画播放速度弄混了。
动画切换速度为0.06s。帧率间隔为0.016,为了直观算作0.02好了。
估算下,每张图片显示的时间,屏幕刷新了几次。
这么弱的数学题我就不算了 :wink:

stateTime += Gdx.graphics.getDeltaTime();
//下一帧
currentFrame = animation.getKeyFrame(stateTime, true);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值