android游戏开发框架libgdx的使用(十八)—简单的AVG游戏效果实现
转载声明:http://www.cnblogs.com/htynkn/archive/2012/03/02/libgdx_18.html
好久没有写libgdx的东西了,主要是最近迷上了各种算法…
文章是关于实现简单的AVG游戏效果,可能会有好几篇。
想用libgdx做点AVG效果主要是因为目前Android上运行的AVG游戏(主要是恋爱模拟类型)的基本基于NScripter引擎移植出来的,我的2B中兴机子跑着巨卡,所以想自己做个。
何为AVG游戏
冒险类游戏AVG (Adventure Game)通常是玩家控制角色进行虚拟冒险的游戏,其故事情节往往是以完成某个任务或是解开一个谜题的形式出现的。
我这里说的AVG主要是指日式AVG,就是在最初的文字冒险游戏的基础上利用精美的CG图片和动人的音响效果加以强化,靠优秀的文字和剧情打动人心的一种游戏形式。
比如夜明前的琉璃色
简单分析
AVG游戏主要是由对话,CG图和音效组成。
拆分下来其实很简单,如下图
再看一张:
就不举其他例子了,每个场景基本由背景(场景图),对话,人物组成。要是以前玩过的话就很清楚了,背景切换比较少,人物的变化也比较少,文字是点击或者触摸就切换到下一句去。
我是选用的libgdx的Stage,背景和人物做成Image,对话由Label实现,对话边框由NinePatch实现,然后触摸对话框区域就切换到下一句去。
文字处理
AVG游戏的对话占据了很大部分,中文的处理很重要。
libgdx支持中文有两种方法,一是使用Hiero制作,二是使用ttf字库(好像目前还有点问题,暂时不推荐使用)。
最全的汉字字库有文字9万余个,但是常用的字并不多(相对于所有文字)。
对比中国大陆、中国台湾和香港特区各自的常用字标准,可以得到3500个常用字,全部做成libgdx用的字体文件。
总共生成12张图,共1.90M
还是有点大就是了。我比较偏向于先使用这个常用字开发,完成后在重新根据实际使用制作字库。
libgdx实现
我选用的是Stage,游戏由Game和Screen控制。新建一个类AVGScreen,实现Screen接口。
1 private Stage stage; //舞台 2 private TextureRegion background; //背景 3 private List<String[]> dialogues; //对话 4 private BitmapFont bitmapFont; //文字 5 private NinePatch border; //边框 6 private int currentSize; //当前对话序号
在show方法中,先实例化Stage,然后添加背景,添加边框,在render方法中修改文字。
背景是铺满就行了,对话的边框宽度是100%,高度是25%左右。
文字绘制是在边框内部。边框我选用的是
具体的拆分如下:
label定位的代码:
1 label.x = border.getLeftWidth() + 10; 2 label.y = borderImage.height - border.getTopHeight() - 10; 3 4 至于触摸切换到下一句在边框添加一个ClickListener就行了。 5 6 borderImage.setClickListener(new ClickListener() { 7 8 @Override 9 public void click(Actor actor, float x, float y) { 10 System.out.println("click"); 11 if (currentSize < dialogues.size() - 1) { 12 currentSize++; 13 } 14 } 15 });
而List<String[]> dialogues中的数据就是对话数据,由【人物名称】和【对话】组成。
如:
1 List<String[]> list = new ArrayList<String[]>(); 2 for (int i = 0; i < 10; i++) { 3 list.add(new String[] { "人物", "这是对话" + i }); 4 }
AVGScreen完整代码:
1 package com.cnblogs.htynkn.ui; 2 3 import java.util.List; 4 5 import com.badlogic.gdx.Gdx; 6 import com.badlogic.gdx.Screen; 7 import com.badlogic.gdx.graphics.Color; 8 import com.badlogic.gdx.graphics.GL10; 9 import com.badlogic.gdx.graphics.g2d.BitmapFont; 10 import com.badlogic.gdx.graphics.g2d.NinePatch; 11 import com.badlogic.gdx.graphics.g2d.TextureRegion; 12 import com.badlogic.gdx.scenes.scene2d.Actor; 13 import com.badlogic.gdx.scenes.scene2d.Stage; 14 import com.badlogic.gdx.scenes.scene2d.ui.ClickListener; 15 import com.badlogic.gdx.scenes.scene2d.ui.Image; 16 import com.badlogic.gdx.scenes.scene2d.ui.Label; 17 import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; 18 19 public class AVGScreen implements Screen { 20 21 private Stage stage; //舞台 22 private TextureRegion background; //背景 23 private List<String[]> dialogues; //对话 24 private BitmapFont bitmapFont; //文字 25 private NinePatch border; //边框 26 private int currentSize; //当前对话序号 27 28 public AVGScreen(TextureRegion background, NinePatch border, 29 List<String[]> dialogues) { 30 this.background = background; 31 this.dialogues = dialogues; 32 this.border = border; 33 bitmapFont = new BitmapFont(); 34 } 35 36 public AVGScreen(TextureRegion background, NinePatch border, 37 List<String[]> dialogues,BitmapFont bitmapFont) { 38 this.background = background; 39 this.dialogues = dialogues; 40 this.border = border; 41 this.bitmapFont = bitmapFont; 42 } 43 44 @Override 45 public void dispose() { 46 // TODO Auto-generated method stub 47 48 } 49 50 @Override 51 public void hide() { 52 // TODO Auto-generated method stub 53 54 } 55 56 @Override 57 public void pause() { 58 // TODO Auto-generated method stub 59 60 } 61 62 @Override 63 public void render(float delta) { 64 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 65 66 ((Label) stage.findActor("label")) 67 .setText(dialogues.get(currentSize)[0] + " : " 68 + dialogues.get(currentSize)[1]); 69 70 stage.act(Gdx.graphics.getDeltaTime()); 71 stage.draw(); 72 } 73 74 @Override 75 public void resize(int width, int height) { 76 // TODO Auto-generated method stub 77 78 } 79 80 @Override 81 public void resume() { 82 // TODO Auto-generated method stub 83 84 } 85 86 @Override 87 public void show() { 88 currentSize = 0; 89 90 stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 91 false); 92 Image backgroundImage = new Image(background); 93 backgroundImage.x = backgroundImage.y = 0; 94 backgroundImage.setFillParent(true); 95 96 Image borderImage = new Image(border); 97 borderImage.x = borderImage.y = 0; 98 borderImage.width = Gdx.graphics.getWidth(); 99 borderImage.height = Gdx.graphics.getHeight() / 4; 100 borderImage.setClickListener(new ClickListener() { 101 102 @Override 103 public void click(Actor actor, float x, float y) { 104 System.out.println("click"); 105 if (currentSize < dialogues.size() - 1) { 106 currentSize++; 107 } 108 } 109 }); 110 111 LabelStyle labelStyle = new LabelStyle(bitmapFont, Color.BLACK); 112 Label label = new Label("", labelStyle, "label"); 113 label.x = border.getLeftWidth() + 10; 114 label.y = borderImage.height - border.getTopHeight() - 10; 115 stage.addActor(backgroundImage); 116 stage.addActor(borderImage); 117 stage.addActor(label); 118 Gdx.input.setInputProcessor(stage); 119 } 120 }
演示效果:
可以看出基本效果是实现了,但是还有一些问题,比如人物的添加还有对话框的美观,而且这段代码是在很烂,不易扩展,没有权责分离。
下一篇文章会介绍人物的添加还有使用配置文件保存对话等数据。
最后来一个黎明前的琉璃色的效果:










浙公网安备 33010602011771号