[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提供了跨平台的声音播放功能 ...
随机推荐
- PHPExcel 导出包含图片excel
<?php // 这里用的PHPExcel版本号为1.8.0 // 下载地址https://github.com/PHPOffice/PHPExcel 下载ZIP压缩包 // 下载后将Class ...
- tomcat 启动报错 解决办法 A child container failed during
控制台报错: Caused by: org.apache.catalina.LifecycleException: A child container failed during start at o ...
- Chromium之文件类型
.grp: Generate your project. 是由Json(JavaScript Object Notation)(or Python?)来解析,根据环境(OS,Compiler..)来生 ...
- vsCode怎么为一个前端项目配置ts的运行环境
vsCode为一个前端项目配置ts的运行环境,ts文件保存的时候自动编译成js文件: 假设此前端项目名称为Web:文件结构如图 1. 在根目录中新建一个“.vscode”文件夹,里面建一个“tasks ...
- 玩Vim
1)我一个脚本中粘贴的都是当年在vim下粘的东西,都是带行号的,我现在想把所有的行号都换成回车键,要怎么办呢? %s/[0-9]/^M/g 注:其中回车在vim的输入方法是ctrl+V,会得到^,此时 ...
- 【python】Python中给List添加元素的4种方法分享
List 是 Python 中常用的数据类型,它一个有序集合,即其中的元素始终保持着初始时的定义的顺序(除非你对它们进行排序或其他修改操作). 在Python中,向List添加元素,方法有如下4种方法 ...
- 数据结构—队列(Queue)
队列的定义--Queue 队列是只允许在表的队尾插入,在表的队头进行删除.队列具有先进先出的特性(FIFO, First In First Out). 队列提供了下面的操作 q.empty() 如果队 ...
- CF762E Radio Stations
题目戳这里. 我还以为是KDtree呢,但是KDtree应该也可以做吧. 这是一道数据结构好题.考虑到由于\(K \le 10\),所以我们用两个大vector--\(Left,Right\),\(L ...
- 十个迅速提升JQuery性能的技巧
本文提供即刻提升你的脚本性能的十个步骤.不用担心,这并不是什么高深的技巧.人人皆可运用!这些技巧包括: 使用最新版本 合并.最小化脚本 用for替代each 用ID替代class选择器 给选择器指定前 ...
- HTML页面为什么设置了UTF-8仍然中文乱码
如题,其实问题很简单,在用EditPlus写html页面的时候,发现设置为UTF-8的时候仍然出现了乱码,这是一个很奇怪的问题,而且我完全考虑了浏览器的解析问题,将title放在了了meta标签之后, ...