修改Android启动图标和名称
首先,我们需要替换Android项目的默认启动图标。FlappyBird-android项目中存在一个名为res的特殊目录。在该目录中包含了Android项目专用的资源文件。
展开res目录可以看到四个以drawable为前缀的文件夹:
drawable-ldpi(低分辨率显示屏)
drawable-mdpi(中分辨率显示屏)
drawable-hdpi(高分辨率显示屏)
drawable-xdpi(极高分辨率显示屏)
这些文件被用于Android应用支持不同尺寸显示屏的设备并且Android根据显示屏的屏幕密度决定使用内容。为了简单起见,我们忽略设备分辨率的区别,这里我们创建一个公用的drawable文件夹。这样,无论在什么分辨率的设备上Android都会使用该文件夹内的资源。
下面截图是本例Android项目的默认启动图标ic_launcher.png,也就是我们当前使用的Android应用启动图标:
![](http://static.oschina.net/uploads/img/201601/27152016_5IAc.jpg)
下面图标是我们将使用的启动图标:
将上述图标文件命名为ic_launcher.png并拷贝到drawable文件夹内。因为我们并没有改变启动图标的命名,因此项目将无需再更改什么便能正常启动。相反,如果你重命名了启动图标的名称,则不要忘记修改AndroidManifest.xml文件对他的引用。AndroidManifest.xml文件对启动图标的引用行如下所示:
<application
android:icon="@drawable/ic_launcher"
.../>
接下来我们
打开android项目的res/value/string.xml文件
,将内容修改如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Flappy Bird</string>
</resources>
创建纹理集
下面截图显示了本项目使用的所有图片资源文件:
- 将libgdx-1.2.0.zip压缩文件中的extensions/tools/gdx-tools.jar文件解压出来。
- 将gdx-tools.jar文件剪切到FlappyBird-desktop/libs子文件夹中。接下来必须将扩展添加到Build Path中。
- 在Eclipse中,右键单击FlappyBird-desktop项目,然后导航到Build Path|Configure Build Path|Libraries。
- 然后单击Add JARs按钮打开JAR selection窗口。
- 在窗口列表中,找到FlappyBird-desktop项目的libs子文件夹。
- 最后,选中新添加的gdx-tools.jar扩展文件,然后点击OK按钮确认选择。
- 为FlappyBird-desktop项目创建assets-raw文件夹。然后添加一个assets-raw/images子文件夹。将所有图片资源复制到该文件夹下。
- 接下来,打开FlappyBird-desktop项目的启动类Main.java,然后添加下面两行代码:
import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.badlogic.gdx.tools.texturepacker.TexturePacker.Settings;
- 然后再Main类中添加如下代码:
package com.art.zok.flappybird; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.badlogic.gdx.tools.texturepacker.TexturePacker.Settings; public class Main { private static boolean rebuildAtlas = true; private static boolean drawDebugOutline = true; public static void main(String[] args) { if(rebuildAtlas) { Settings settings = new Settings(); settings.maxWidth = 1024; settings.maxHeight = 1024; settings.duplicatePadding = false; settings.debug = drawDebugOutline; TexturePacker.process(settings, "assets-raw/images", "../FlappyBird-android/assets/images", "flappy-bird.pack"); } LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration(); cfg.title = "FlappyBird"; cfg.width = 480; cfg.height = 800; cfg.resizable = false; new LwjglApplication(new FlappyBirdMain(), cfg); } }
![](http://static.oschina.net/uploads/img/201601/27152017_qQLW.jpg)
package com.art.zok.flappybird.util;
public class Constants {
// 视口宽度为20米
public static final float VIEWPORT_WIDTH = 50f;
// 视口高度为20米
public static final float VIEWPORT_HEIGHT = 50f;
// 纹理集描述文件路径
public static final String TEXTURE_ATLAS_OBJECTS = "images/flappy-bird.pack";
}
接下来创建Assets类并添加下面代码:
package com.art.zok.flappybird.game;
import com.art.zok.flappybird.util.Constants;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetErrorListener;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
public class Assets implements Disposable, AssetErrorListener {
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
private AssetManager assetManager;
// 单态类:阻止在其他类中实例化
private Assets () {}
public void init (AssetManager assetManager) {
this.assetManager = assetManager;
// 设定资源管理器的错误处理对象句柄
assetManager.setErrorListener(this);
// 载入纹理集
assetManager.load(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
// 开始载入资源直到完成
assetManager.finishLoading();
// 打印资源信息
Gdx.app.debug(TAG, "# of assets loaded: " + assetManager.getAssetNames().size);
for(String a : assetManager.getAssetNames()) {
Gdx.app.debug(TAG, "asset: " + a);
}
}
@Override
@SuppressWarnings("rawtypes")
public void error(AssetDescriptor asset, Throwable throwable) {
Gdx.app.debug(TAG, "Couldn't load asset '" + asset.fileName + "'", (Exception)throwable);
}
@Override
public void dispose () {
assetManager.dispose();
}
}
package com.art.zok.flappybird.game;
import com.art.zok.flappybird.util.Constants;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetErrorListener;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
public class Assets implements Disposable, AssetErrorListener {
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
TextureAtlas atlas;
private AssetManager assetManager;
public AssetFonts fonts;
public AssetBird bird;
public AssetPipe pipe;
public AssetLand land;
public AssetUI assetUI;
public AssetNumber number;
public AssetSounds sounds;
public AssetDecoration decoration;
// 单态类:阻止在其他类中实例化
private Assets () {}
public void init (AssetManager assetManager) {
this.assetManager = assetManager;
// 设定资源管理器的错误处理对象句柄
assetManager.setErrorListener(this);
// 载入纹理集
assetManager.load(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
// 载入声音文件
assetManager.load("sounds/sfx_die.ogg", Sound.class);
assetManager.load("sounds/sfx_hit.ogg", Sound.class);
assetManager.load("sounds/sfx_point.ogg", Sound.class);
assetManager.load("sounds/sfx_swooshing.ogg", Sound.class);
assetManager.load("sounds/sfx_wing.ogg", Sound.class);
assetManager.finishLoading();
// 打印资源信息
Gdx.app.debug(TAG, "# of assets loaded: " + assetManager.getAssetNames().size);
for(String a : assetManager.getAssetNames()) {
Gdx.app.debug(TAG, "asset: " + a);
}
atlas = assetManager.get(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
fonts = new AssetFonts();
bird = new AssetBird(atlas);
pipe = new AssetPipe(atlas);
land = new AssetLand(atlas);
number = new AssetNumber(atlas);
assetUI = new AssetUI(atlas);
sounds = new AssetSounds(assetManager);
decoration = new AssetDecoration(atlas);
}
@Override
@SuppressWarnings("rawtypes")
public void error(AssetDescriptor asset, Throwable throwable) {
Gdx.app.debug(TAG, "Couldn't load asset '" + asset.fileName + "'", (Exception)throwable);
}
@Override
public void dispose () {
assetManager.dispose();
}
public class AssetBird {
public final Array<AtlasRegion> bird0;
public final Array<AtlasRegion> bird1;
public final Array<AtlasRegion> bird2;
public AssetBird (TextureAtlas atlas) {
bird0 = atlas.findRegions("bird0");
bird1 = atlas.findRegions("bird1");
bird2 = atlas.findRegions("bird2");
}
}
public class AssetPipe {
public final AtlasRegion pipeUpGreen;
public final AtlasRegion pipeUpBrown;
public final AtlasRegion pipeDownGreen;
public final AtlasRegion pipeDownBrown;
public AssetPipe (TextureAtlas atlas) {
pipeUpGreen = atlas.findRegion("pipe_up");
pipeDownGreen = atlas.findRegion("pipe_down");
pipeUpBrown = atlas.findRegion("pipe2_up");
pipeDownBrown = atlas.findRegion("pipe2_down");
}
}
public class AssetLand {
public final AtlasRegion land;
public AssetLand (TextureAtlas atlas) {
land = atlas.findRegion("land");
}
}
public class AssetNumber {
public final Array<AtlasRegion> numbers_score;
public final Array<AtlasRegion> numbers_context;
public final Array<AtlasRegion> numbers_font;
public AssetNumber(TextureAtlas atlas) {
numbers_score = atlas.findRegions("number_score");
numbers_context = atlas.findRegions("number_context");
numbers_font = atlas.findRegions("font");
}
}
public class AssetUI {
public final AtlasRegion textGameOver;
public final AtlasRegion scorePanel;
public final AtlasRegion buttonMenu;
public final AtlasRegion buttonOk;
public final AtlasRegion buttonPause;
public final AtlasRegion buttonPlay;
public final AtlasRegion buttonRate;
public final AtlasRegion buttonResume;
public final AtlasRegion buttonScore;
public final AtlasRegion buttonShare;
public final AtlasRegion tutorial;
public final AtlasRegion textReady;
public final AtlasRegion textTitle;
public final AtlasRegion copyRight;
public final Array<AtlasRegion> medals;
public AssetUI(TextureAtlas atlas) {
textGameOver = atlas.findRegion("text_game_over");
scorePanel = atlas.findRegion("score_panel");
buttonMenu = atlas.findRegion("button_menu");
buttonOk = atlas.findRegion("button_ok");
buttonPause = atlas.findRegion("button_pause");
buttonPlay = atlas.findRegion("button_play");
buttonRate = atlas.findRegion("button_rate");
buttonResume = atlas.findRegion("button_resume");
buttonScore = atlas.findRegion("button_score");
buttonShare = atlas.findRegion("button_share");
tutorial = atlas.findRegion("tutorial");
medals = atlas.findRegions("medals");
textReady = atlas.findRegion("text_ready");
textTitle = atlas.findRegion("title");
copyRight = atlas.findRegion("brand_copyright");
}
}
public class AssetSounds {
public final Sound die;
public final Sound hit;
public final Sound point;
public final Sound swooshing;
public final Sound wing;
public AssetSounds(AssetManager am) {
die = am.get("sounds/sfx_die.ogg", Sound.class);
hit = am.get("sounds/sfx_hit.ogg", Sound.class);
point = am.get("sounds/sfx_point.ogg", Sound.class);
swooshing = am.get("sounds/sfx_swooshing.ogg", Sound.class);
wing = am.get("sounds/sfx_wing.ogg", Sound.class);
}
}
public class AssetDecoration {
public final Array<AtlasRegion> bg;
public final AtlasRegion white;
public AssetDecoration (TextureAtlas atlas) {
bg = new Array<AtlasRegion>();
bg.add(atlas.findRegion("bg_day"));
bg.add(atlas.findRegion("bg_night"));
white = atlas.findRegion("white");
}
}
public class AssetFonts {
public final BitmapFont defaultSmall;
public final BitmapFont defaultNormal;
public final BitmapFont defaultBig;
public AssetFonts() {
// 使用libgdx的15px位图字体文件创建三个字体
defaultSmall = new BitmapFont(
Gdx.files.internal("images/arial-15.fnt"), true);
defaultNormal = new BitmapFont(
Gdx.files.internal("images/arial-15.fnt"), true);
defaultBig = new BitmapFont(
Gdx.files.internal("images/arial-15.fnt"), true);
// 设定字体尺寸
defaultSmall.setScale(0.75f);
defaultNormal.setScale(1.0f);
defaultBig.setScale(2.0f);
// 设定字体过滤模式为线性平滑
defaultSmall.getRegion().getTexture().setFilter(
TextureFilter.Linear, TextureFilter.Linear);
defaultNormal.getRegion().getTexture().setFilter(
TextureFilter.Linear, TextureFilter.Linear);
defaultBig.getRegion().getTexture().setFilter(
TextureFilter.Linear, TextureFilter.Linear);
}
}
}
这里我们将声音资源和字体资源也加入了进来,最终Android的assets文件夹目录如下:
![](http://static.oschina.net/uploads/img/201601/27152017_Fr13.jpg)
- AssetManager.get():该方法需要两个参数,第一个是需要获得的资源的全路径名,第二个是资源类型的class对象。
- TextureAtlas.findRegions():该方法返回一个文理区域序列,只需要一个字符串参数即可,该参数必须是一系列具有相同前缀的文件名。例如我们的资源中包含了三个图片bird0_0.png,bird0_1.png和bird0_2.png,那么这里bird0就是该函数的参数,之后该方法将返回一个Array<AtlasRegion>实例,该列表包含了三个纹理域。
- TextureAtlas.findRegion():该方需要一个不带文件扩展名的资源名称作为参数,结果将返回一个AtlasRegion对象。
- Texture.setFilter():该方法设置纹理分别在放大和缩小的情况下的过滤模式,TextureFilter.Linear表示平滑过滤,即消除锯齿。
public AssetBird bird;
public AssetPipe pipe;
public AssetLand land;
public AssetUI assetUI;
public AssetNumber number;
public AssetSounds sounds;
public AssetDecoration decoration;
然后再init()方法中实例化每个成员变量,之后在任何地方我们就可以直接通过Assets.instance.fonts.defaultSmall访问字体,其他资源也可以通过相同的方法访问。