[libgdx游戏开发教程]使用Libgdx进行游戏开发(4)-素材管理
游戏中总是有大量的图像资源,我们通常的做法是把要用的图片做成图片集,这样做的好处就不多说了。直接来看怎么用。
这里我们使用自己的类Assets来管理它们,让这个工具类作为我们的资源管家,从而可以在任何类里使用我们加载的素材。
原始图片素材:http://files.cnblogs.com/mignet/assets-raw.zip
1,使用Libgdx提供的打包程序
在最新版里是叫TexturePacker.process
在任意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.debug = drawDebugOutline;
TexturePacker2.process(settings, "../core/assets/images",
"/assets/images", "canyonbunny.pack");
}
}
如果使用Android Studio,先设置路径

然后代码做如下修改:
TexturePacker.process(settings, "images", "images", "canyonbunny");
说明:这是最新版libGDX 1.9.4的用法
2,使用Libgdx提供的打包工具
http://www.codeandweb.com/texturepacker

现在打包好了,怎么用呢?这样:
TextureAtlas atlas = assetManager.get("images/canyonbunny.pack");
head = atlas.findRegion("bunny_head");
我们都知道一般Texture的用法,通常少不了下面三步:
1. Texture texture = new Texture(Gdx.files.internal("texture.png"));//prepare
2. batch.draw(texture, x, y);//draw
3. texture.dispose();//dispose
但是这样引起的问题是,如果我们有很多很多资源,这样会使代码很杂乱。
根据面向对象的思想,我们这时需要对对象各自处理自己的资源了,为了统一管理资源(包括加载资源,重加载资源,跟踪资源,卸载资源),Libgdx 提供了AssetManager这个类。
它可以异步加载资源,但实际上我们不能简单的给个资源列表给它就完事了。我们需要自己的资源类来组织资源并保证在任何地方可以使用它。
首先定义一个常量来指向我们的atlas文件:
public class Constants {
// Visible game world is 5 meters wide
public static final float VIEWPORT_WIDTH = 5.0f;
// Visible game world is 5 meters tall
public static final float VIEWPORT_HEIGHT = 5.0f;
// Location of description file for texture atlas
public static final String TEXTURE_ATLAS_OBJECTS =
"images/canyonbunny.pack";//最新版本里打包之后是使用atlas的文件名:canyonbunny.atlas
}
然后创建我们的资源管理类Assets(当然它是单例的)
package com.packtpub.libgdx.canyonbunny.game; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetErrorListener;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Disposable;
import com.packtpub.libgdx.canyonbunny.util.Constants; public class Assets implements Disposable, AssetErrorListener {
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
private AssetManager assetManager; // singleton: prevent instantiation from other classes
private Assets() {
} public void init(AssetManager assetManager) {
this.assetManager = assetManager;
// set asset manager error handler
assetManager.setErrorListener(this);
// load texture atlas
assetManager.load(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
// start loading assets and wait until finished
assetManager.finishLoading();
Gdx.app.debug(TAG,
"# of assets loaded: " + assetManager.getAssetNames().size);
for (String a : assetManager.getAssetNames())
Gdx.app.debug(TAG, "asset: " + a);
} @Override
public void dispose() {
assetManager.dispose();
} @Override
public void error(String filename, Class type, Throwable throwable) {
Gdx.app.error(TAG, "Couldn't load asset '" + filename + "'",
(Exception) throwable);
}
}
接下来就是从atlas里面取子图了,使用findRegion(“name”),注意这个查找方法是一个很昂贵的功能调用,所以调用之后就把结果存起来吧,避免重复调用该方法造成性能问题。
为了达到这一目的,我们在该类中增加很多小的内部类以便于在逻辑上组织他们并完成持久化存储。以兔子头为例:
public class AssetBunny {
public final AtlasRegion head;
public AssetBunny(TextureAtlas atlas) {
head = atlas.findRegion("bunny_head");
}
}
其他的像岩石啊金币啊装饰物啊等等一一添加。
public class AssetRock {
public final AtlasRegion edge;
public final AtlasRegion middle;
public AssetRock(TextureAtlas atlas) {
edge = atlas.findRegion("rock_edge");
middle = atlas.findRegion("rock_middle");
}
}
public class AssetGoldCoin {
public final AtlasRegion goldCoin;
public AssetGoldCoin(TextureAtlas atlas) {
goldCoin = atlas.findRegion("item_gold_coin");
}
}
public class AssetFeather {
public final AtlasRegion feather;
public AssetFeather(TextureAtlas atlas) {
feather = atlas.findRegion("item_feather");
}
}
public class AssetLevelDecoration {
public final AtlasRegion cloud01;
public final AtlasRegion cloud02;
public final AtlasRegion cloud03;
public final AtlasRegion mountainLeft;
public final AtlasRegion mountainRight;
public final AtlasRegion waterOverlay;
public AssetLevelDecoration(TextureAtlas atlas) {
cloud01 = atlas.findRegion("cloud01");
cloud02 = atlas.findRegion("cloud02");
cloud03 = atlas.findRegion("cloud03");
mountainLeft = atlas.findRegion("mountain_left");
mountainRight = atlas.findRegion("mountain_right");
waterOverlay = atlas.findRegion("water_overlay");
}
}
现在我们需要Assert类提供外部的对象供系统在其他地方调用
public AssetBunny bunny;
public AssetRock rock;
public AssetGoldCoin goldCoin;
public AssetFeather feather;
public AssetLevelDecoration levelDecoration;
public void init(AssetManager assetManager) {
this.assetManager = assetManager;
// set asset manager error handler
assetManager.setErrorListener(this);
// load texture atlas
assetManager.load(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
// start loading assets and wait until finished
assetManager.finishLoading();
Gdx.app.debug(TAG,"# of assets loaded: " + assetManager.getAssetNames().size);
for (String a : assetManager.getAssetNames())
Gdx.app.debug(TAG, "asset: " + a); TextureAtlas atlas = assetManager.get(Constants.TEXTURE_ATLAS_OBJECTS);
// enable texture filtering for pixel smoothing
for (Texture t : atlas.getTextures())
t.setFilter(TextureFilter.Linear, TextureFilter.Linear);
// create game resource objects
bunny = new AssetBunny(atlas);
rock = new AssetRock(atlas);
goldCoin = new AssetGoldCoin(atlas);
feather = new AssetFeather(atlas);
levelDecoration = new AssetLevelDecoration(atlas);
}
注意到程序中使用的参数TextureFilter.Linear,这里的两个参数分别对应图片放大和缩小的模式。默认的模式是TextureFilter.Nearest。看看它们的区别

ok,一切就绪,拉出来遛遛。
使用资源的话,最基本有3个地方:加载,重加载,卸载。
在游戏开始之前加载,那么应该是Main的create里:Assets.instance.init(new AssetManager());
重加载一般在返回游戏的时候(resume方法):Assets.instance.init(new AssetManager());
卸载当然是在dispose里:Assets.instance.dispose();
最后,将我们前面用的TestSprites(还记得那5个箱子吧)替换成现在的Texture:(这里使用了Libgdx的Array的random功能,随机返回Array的项)
private void initTestObjects () {
// Create new array for 5 sprites
testSprites = new Sprite[5];
// Create a list of texture regions
Array<TextureRegion> regions = new Array<TextureRegion>();
regions.add(Assets.instance.bunny.head);
regions.add(Assets.instance.feather.feather);
regions.add(Assets.instance.goldCoin.goldCoin);
// Create new sprites using a random texture region
for (int i = 0; i < testSprites.length; i++) {
Sprite spr = new Sprite(regions.random());
// Define sprite size to be 1m x 1m in game world
spr.setSize(1, 1);
// Set origin to sprite's center
spr.setOrigin(spr.getWidth() / 2.0f,
spr.getHeight() / 2.0f);
// Calculate random position for sprite
float randomX = MathUtils.random(-2.0f, 2.0f);
float randomY = MathUtils.random(-2.0f, 2.0f);
spr.setPosition(randomX, randomY);
// Put new sprite into array
testSprites[i] = spr;
}
// Set first sprite as selected one
selectedSprite = 0;
}
跑起,你应该看到类似下面这样的画面了,素材的使用让游戏正式向艺术迈进了。

红色的边框,就是在第一步打包时设置drawDebugOutline=true的效果。
[libgdx游戏开发教程]使用Libgdx进行游戏开发(4)-素材管理的更多相关文章
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制
在<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>中,我介绍了获取AccessToken(通用接口)的方法. 在实际的开发过程中,所有的高级接口都需 ...
- [libGDX游戏开发教程]使用libGDX进行游戏开发(12)-Action动画
前文章节列表: 使用libGDX进行游戏开发(11)-高级编程技巧 使用libGDX进行游戏开发(10)-音乐音效不求人,程序员也可以DIY 使用libGDX进行游戏开发(9)-场景过渡 ...
- [libGDX游戏开发教程]使用libGDX进行游戏开发(1)-游戏设计
声明:<使用Libgdx进行游戏开发>是一个系列,文章的原文是<Learning Libgdx Game Development>,大家请周知.后续的文章连接在这里 使用Lib ...
- [libgdx游戏开发教程]使用Libgdx进行游戏开发(7)-屏幕布局的最佳实践
管理多个屏幕 我们的菜单屏有2个按钮,一个play一个option.option里就是一些开关的设置,比如音乐音效等.这些设置将会保存到Preferences中. 多屏幕切换是游戏的基本机制,Libg ...
- 使用Html5+C#+微信 开发移动端游戏详细教程: (四)游戏中层的概念与设计
众所周知,网站的前端页面结构一般是由div组成,父div包涵子div,子div包涵各种标签和项, 同理,游戏中我们也将若干游戏模块拆分成层,在后续的代码维护和游戏程序逻辑中将更加清晰和便于控制. We ...
- 使用Html5+C#+微信 开发移动端游戏详细教程 :(五)游戏图像的加载与操作
当我们进入游戏时,是不可能看到所有的图像的,很多图像都是随着游戏功能的打开而出现, 比如只有我打开了"宝石"菜单才会显示宝石的图像,如果是需要显示的时候才加载, 会对用户体验大打折 ...
- 微信小程序开发教程 #043 - 在小程序开发中使用 npm
本文介绍了如何在微信小程序开发中使用 npm 中包的功能,大大提高微信小程序的开发效率,同时也是微信小程序系列教程的视频版更新. 微信小程序在发布之初没有对 npm 的支持功能,这也是目前很多前端开发 ...
- PythonWeb开发教程(一),开发之前需要准备什么
什么是web开发呢,其实就是开发一个网站了.那开发网站需要用到哪些知识呢 1.python基础,因为用python开发的,所以python指定要会,最起码你也得会条件判断,循环,函数,类这些知识: 2 ...
- [libgdx游戏开发教程]使用Libgdx进行游戏开发(11)-高级编程技巧 Box2d和Shader
高级编程技巧只是相对的,其实主要是讲物理模拟和着色器程序的使用. 本章主要讲解利用Box2D并用它来实现萝卜雨,然后是使用单色着色器shader让画面呈现单色状态:http://files.cnblo ...
- [libgdx游戏开发教程]使用Libgdx进行游戏开发(10)-音乐和音效
本章音效文件都来自于公共许可: http://files.cnblogs.com/mignet/sounds.zip 在游戏中,播放背景音乐和音效是基本的功能. Libgdx提供了跨平台的声音播放功能 ...
随机推荐
- 基于C#的PISDK研究(理论)
本篇文章主要对PISDK体系结构以及重点类进行阐述. 当我们决定使用PISDK时,可能会使用到下面的类库: 在上表中,PISDK.dll为核心类,大部分主要功能都在该类中.PISDKCommon.dl ...
- SQL Server “超过了锁请求超时时段”错误
错误提示:“已超过了锁请求超时时段. (Microsoft SQL Server,错误: 1222)”(英文:“Lock Request time out period exceeded.(Micro ...
- 一张图彻底搞懂JavaScript的==运算
一张图彻底搞懂JavaScript的==运算 来源 https://zhuanlan.zhihu.com/p/21650547 PS:最后,把图改了一下,仅供娱乐 : ) 大家知道,==是JavaSc ...
- HTML5 Canvas圣诞树
又逢圣诞了,为了让小站NowaMagic有点节日气氛,这里也弄一棵圣诞树放放-大家可以先看下效果. 效果演示 <canvas id="c"></canvas> ...
- Covered Points Count(思维题)
C. Covered Points Count time limit per test 3 seconds memory limit per test 256 megabytes input stan ...
- 动态性能视图v$session_longops
v$session_longops This view displays the status of various operations that run for longer than 6 sec ...
- bzoj1420/1319 Discrete Root
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1420 http://www.lydsy.com/JudgeOnline/problem.ph ...
- 【Atcoder】ARC083 D - Restoring Road Network
[算法]图论,最短路? [题意]原图为无向连通图,现给定原图的最短路矩阵,求原图最小边权和,n<=300. [题解]要求最小边权和下,原图的所有边一定是所连两端点的最短路. 那么现在将所有最短路 ...
- 【Atcoder】ARC 080 F - Prime Flip
[算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...
- 阶段性总结⓵触摸事件&手势识别⓶Quartz2D绘图⓷CALayer图层⓸CAAnimation⓹UIDynamic UI动力学⓺KVC&KVO
知识点复习 1. 触摸事件&手势识别 1> 4个触摸事件,针对视图的 2> 6个手势识别(除了用代码添加,也可以用Storyboard添加) 附加在某一个特定视图上的, ...