如何使用LGame中的LTexturePack(移值到其它环境也行……) 如何使用LGame中的LTexturePack(移值到其它环境也行……)...

如何使用LGame中的LTexturePack(移值到其它环境也行……)

分类:JAVA游戏开发JAVA应用 1422人阅读 评论(8) 收藏 举报
修正声明:

借写本例的机会,刚刚修正了某个【小】BUG。问题点在于LTexturePack的其中一个draw函数,本来在分图时需传入dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2等八个数值,结果小弟在接值时脑子进水,误将sx1,sx2,sy1,sy2写“扎堆”了(写错就是上述样子)……因为这是取图参数,即从sx1,sy1坐标开始取图,取到sx2,sy2的位置中止,弄错以后取出图立马变毕加索油画~所以小弟刚才将LGame-0.3.2-release这个包重新发了一遍,如果有用到LTexturePack的话请重新下载,抱歉抱歉(另外还改了3处问题)……

下载地址:http://loon-simple.googlecode.com/files/LGame-0.3.2-release.7z


关于TexturePack:

LGame中提供的LTexturePack类,是一个专门用于整合图像资源的辅助用类,它的最大作用是将许多零碎的图片画零为整,从而减少不必要的资源损耗。另一方面来讲,由于减少了渲染用纹理数量,避免了反复与图形系统交互,使用LTexturePack的速度通常会比单独使用零散LTexture为高。


最简单的使用方式:

[java] view plain copy
  1. packageorg.loon.test;
  2. importorg.loon.framework.javase.game.GameScene;
  3. importorg.loon.framework.javase.game.action.sprite.Arrow;
  4. importorg.loon.framework.javase.game.core.graphics.Screen;
  5. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  6. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  7. importorg.loon.framework.javase.game.core.input.LTouch;
  8. importorg.loon.framework.javase.game.core.input.LTransition;
  9. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  10. publicclassLTexturePackTestextendsScreen{
  11. LTexturePackimagePack;
  12. Arrowarrow;
  13. /**
  14. *无Transition效果。
  15. *
  16. *PS:目前LGame设定为,如果首个Screen没有加载特效,将强制运行一个随机特效。但是,返回Empty则不进行加载。
  17. */
  18. publicLTransitiononTransition(){
  19. returnLTransition.newEmpty();
  20. }
  21. publicvoidonLoad(){
  22. imagePack=newLTexturePack();
  23. //加载小图到LTexturePack
  24. imagePack.putImage("assets/h_a.png");
  25. imagePack.putImage("assets/h_b.png");
  26. imagePack.putImage("assets/h_c.png");
  27. imagePack.putImage("assets/e_a.png");
  28. imagePack.putImage("assets/e_b.png");
  29. imagePack.putImage("assets/e_c.png");
  30. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理)
  31. imagePack.packed();
  32. }
  33. publicvoidalter(LTimerContexttimer){
  34. }
  35. publicvoiddraw(GLExg){
  36. if(isOnLoadComplete()){
  37. intsize=32;
  38. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  39. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  40. //可能会受到一定影响(每次渲染都单独提交)。
  41. imagePack.glBegin();
  42. //LTexturePack中的数据可以按照索引加载
  43. imagePack.draw(0,32,size);
  44. //也可以按照文件名加载
  45. imagePack.draw("assets/h_b.png",32,size+=32);
  46. imagePack.draw(2,32,size+=32);
  47. size=32;
  48. imagePack.draw(3,256,size);
  49. imagePack.draw(4,256,size+=32);
  50. imagePack.draw(5,256,size+=32);
  51. //提交渲染结果到游戏画面
  52. imagePack.glEnd();
  53. //实例化一个动态箭头精灵
  54. if(arrow==null){
  55. arrow=newArrow(212,212,188,188);
  56. add(arrow);
  57. }
  58. //显示实际纹理
  59. g.drawTexture(imagePack.getTexture(),32,size+50);
  60. g.drawString("Texture",235,size+124);
  61. }
  62. }
  63. publicvoidtouchDown(LTouche){
  64. }
  65. publicvoidtouchDrag(LTouche){
  66. }
  67. publicvoidtouchMove(LTouche){
  68. }
  69. publicvoidtouchUp(LTouche){
  70. }
  71. publicvoiddispose(){
  72. if(imagePack!=null){
  73. imagePack.dispose();
  74. imagePack=null;
  75. }
  76. }
  77. publicstaticvoidmain(String[]args){
  78. GameScenegame=newGameScene("LTexturePackTest",480,320);
  79. game.setShowFPS(true);
  80. game.setShowLogo(false);
  81. game.setScreen(newLTexturePackTest());
  82. game.showScreen();
  83. }
  84. }

这时大家可以看到,在上述画面中,其实只有游戏中箭头指出的地方才是真正的纹理。而其余细分处,仅是大图纹理中的一部分罢了,然而在用户眼中,这些又有什么不同呢?不过,我们所能节省出的图像资源,却是非常巨大的。

当然,如果载入的是连续画面,那么仅仅能得到原画根本没用,不过没关系,我们也可以继续细分出我们满意的画面(上图具体代码和下例重复,故不再赘述)。


图像移动:

[java] view plain copy
  1. packageorg.loon.test;
  2. importorg.loon.framework.javase.game.GameScene;
  3. importorg.loon.framework.javase.game.action.collision.Gravity;
  4. importorg.loon.framework.javase.game.action.collision.GravityHandler;
  5. importorg.loon.framework.javase.game.action.sprite.Bind;
  6. importorg.loon.framework.javase.game.action.sprite.effect.SmashEffect;
  7. importorg.loon.framework.javase.game.core.geom.RectBox;
  8. importorg.loon.framework.javase.game.core.graphics.Screen;
  9. importorg.loon.framework.javase.game.core.graphics.opengl.GLColor;
  10. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  11. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  12. importorg.loon.framework.javase.game.core.input.LTouch;
  13. importorg.loon.framework.javase.game.core.input.LTransition;
  14. importorg.loon.framework.javase.game.core.timer.LTimer;
  15. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  16. publicclassLTexturePackTestextendsScreen{
  17. SmashEffectsmashEffect=newSmashEffect();
  18. //显示用精灵大小
  19. finalintshow_size=64;
  20. //实际精灵大小
  21. finalintreally_size=24;
  22. LTexturePackimagePack;
  23. /**
  24. *建立一个移动对象,用以管理LTexturePack中图像的移动
  25. */
  26. publicclassMove{
  27. RectBoxrect=newRectBox(0,0,show_size,show_size);
  28. LTimertimer=newLTimer(150);
  29. intid;
  30. floatx,y;
  31. intaction=1;
  32. inttype=-1;
  33. publicvoidsetX(floatx){
  34. this.x=x;
  35. rect.setX(x);
  36. }
  37. publicvoidsetY(floaty){
  38. this.y=y;
  39. rect.setY(y);
  40. }
  41. publicfloatgetX(){
  42. returnx;
  43. }
  44. publicfloatgetY(){
  45. returny;
  46. }
  47. publicbooleanintersects(Movem){
  48. returnrect.intersects(m.rect);
  49. }
  50. publicvoidupdate(){
  51. if(timer.action(elapsedTime)){
  52. action++;
  53. if(action>4){
  54. action=1;
  55. }
  56. }
  57. }
  58. }
  59. /**
  60. *无Transition效果。
  61. *
  62. *PS:目前LGame设定为,如果首个Screen没有加载特效,将强制运行一个随机特效。但是,返回Empty则不进行加载。
  63. */
  64. publicLTransitiononTransition(){
  65. returnLTransition.newEmpty();
  66. }
  67. publicvoidonLoad(){
  68. imagePack=newLTexturePack();
  69. //加载小图到LTexturePack
  70. intheroId=imagePack.putImage("assets/h_a.png");
  71. intenemyId=imagePack.putImage("assets/e_a.png");
  72. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理)
  73. imagePack.packed();
  74. finalMovemoveHero=newMove();
  75. moveHero.id=heroId;
  76. moveHero.x=0;
  77. moveHero.y=128;
  78. moveHero.type=0;
  79. finalMovemoveEnemy=newMove();
  80. moveEnemy.id=enemyId;
  81. moveEnemy.x=getWidth()-show_size;
  82. moveEnemy.y=128;
  83. moveEnemy.type=1;
  84. /**
  85. *获得一个内置的重力管理器
  86. *
  87. *PS:所有具备setX、setY函数的公有类(必须公有,否则反射不到……),都可以被GravityHandler绑定
  88. */
  89. finalGravityHandlergravityHandler=getGravityHandler();
  90. //用重力控制器将moveHero对象打包,并且向右方匀速移动(速度100)
  91. Gravityg1=newGravity(moveHero);
  92. g1.setVelocityX(100);
  93. //用重力控制器将moveHero对象打包,并且向左方匀速移动(速度100)
  94. Gravityg2=newGravity(moveEnemy);
  95. g2.setVelocityX(-100);
  96. //添加重力干预
  97. gravityHandler.add(g1);
  98. gravityHandler.add(g2);
  99. //构建重力监控
  100. GravityHandler.Updateupdate=newGravityHandler.Update(){
  101. publicvoidaction(Gravityg,floatx,floaty){
  102. //让当前重力控制触边实效(具体到本例,人物也将消失)
  103. if(x<0){
  104. gravityHandler.remove(g);
  105. }
  106. if(x>getWidth()-show_size){
  107. gravityHandler.remove(g);
  108. }
  109. }
  110. };
  111. //添加监控(每次Gravity对象坐标发生变更时生效)
  112. gravityHandler.onUpdate(update);
  113. }
  114. publicvoidalter(LTimerContexttimer){
  115. smashEffect.update(timer.getTimeSinceLastUpdate());
  116. }
  117. publicvoiddraw(GLExg){
  118. if(isOnLoadComplete()){
  119. smashEffect.draw(g);
  120. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  121. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  122. //可能会受到一定影响(每次渲染都单独提交)。
  123. imagePack.glBegin();
  124. //获得重力控制器(如果绑定为Sprite,Actor,LComponent等对象则不必额外处理显示步骤,
  125. //此处图像已统一打包入LTexturePack较为特殊)
  126. GravityHandlergravityHandler=getGravityHandler();
  127. //获得重力实例数量
  128. intsize=gravityHandler.getCount();
  129. //保存上一个Move实例
  130. Movefirst=null;
  131. for(inti=0;i<size;i++){
  132. //获得实例
  133. Gravitygravity=gravityHandler.get(i);
  134. Bindbind=gravity.getBind();
  135. //反射回绑定的对象
  136. Moveo=(Move)bind.ref();
  137. //判定两个图像的移动位置是否发生了碰撞(这里使用了比较流氓(就俩,省了-_-)的方式,实际应该建立一个精灵预警区,
  138. //然后搜索该区域内是否存在精灵,有的话再让移动中精灵与该精灵进行碰撞比较)
  139. if(first!=null&&first.intersects(o)){
  140. //碰撞后象征性的显示一个粉碎特效
  141. if(first.action!=5){
  142. smashEffect.createSmallExplosionEffect(getHalfWidth(),
  143. getHalfHeight());
  144. }
  145. o.action=5;
  146. first.action=5;
  147. g.setColor(GLColor.red);
  148. }
  149. switch(o.type){
  150. case0:
  151. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  152. (o.action-1)*really_size,0,o.action
  153. *really_size,really_size);
  154. break;
  155. case1:
  156. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  157. o.action*really_size,0,(o.action-1)
  158. *really_size,really_size);
  159. break;
  160. }
  161. first=o;
  162. o.update();
  163. }
  164. //提交渲染结果到游戏画面
  165. imagePack.glEnd();
  166. }
  167. }
  168. publicvoidtouchDown(LTouche){
  169. }
  170. publicvoidtouchDrag(LTouche){
  171. }
  172. publicvoidtouchMove(LTouche){
  173. }
  174. publicvoidtouchUp(LTouche){
  175. }
  176. publicvoiddispose(){
  177. if(imagePack!=null){
  178. imagePack.dispose();
  179. imagePack=null;
  180. }
  181. }
  182. publicstaticvoidmain(String[]args){
  183. GameScenegame=newGameScene("LTexturePackTest",480,320);
  184. game.setShowFPS(true);
  185. game.setShowLogo(false);
  186. game.setScreen(newLTexturePackTest());
  187. game.showScreen();
  188. }
  189. }

让LTexturePack中的两个精灵进行单挑

多个图像移动:

[java] view plain copy
  1. packageorg.loon.test;
  2. importjava.util.ArrayList;
  3. importorg.loon.framework.javase.game.GameScene;
  4. importorg.loon.framework.javase.game.action.collision.Gravity;
  5. importorg.loon.framework.javase.game.action.collision.GravityHandler;
  6. importorg.loon.framework.javase.game.core.LSystem;
  7. importorg.loon.framework.javase.game.core.geom.RectBox;
  8. importorg.loon.framework.javase.game.core.graphics.Screen;
  9. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  10. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  11. importorg.loon.framework.javase.game.core.input.LTouch;
  12. importorg.loon.framework.javase.game.core.input.LTransition;
  13. importorg.loon.framework.javase.game.core.timer.LTimer;
  14. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  15. publicclassLTexturePackTestextendsScreen{
  16. ArrayList<Move>moveList;
  17. //显示用精灵大小
  18. finalintshow_size=64;
  19. //实际精灵大小
  20. finalintreally_size=24;
  21. LTexturePackimagePack;
  22. /**
  23. *建立一个移动对象,用以管理LTexturePack中图像的移动
  24. */
  25. publicclassMove{
  26. RectBoxrect=newRectBox(0,0,show_size,show_size);
  27. LTimertimer=newLTimer(150);
  28. intid;
  29. floatx,y;
  30. intaction=1;
  31. inttype=-1;
  32. publicMove(intid,inttype,floatx,floaty){
  33. this.id=id;
  34. this.type=type;
  35. this.x=x;
  36. this.y=y;
  37. }
  38. publicvoidsetX(floatx){
  39. this.x=x;
  40. rect.setX(x);
  41. }
  42. publicvoidsetY(floaty){
  43. this.y=y;
  44. rect.setY(y);
  45. }
  46. publicfloatgetX(){
  47. returnx;
  48. }
  49. publicfloatgetY(){
  50. returny;
  51. }
  52. publicbooleanintersects(Movem){
  53. returnrect.intersects(m.rect);
  54. }
  55. publicvoidupdate(){
  56. if(timer.action(elapsedTime)){
  57. action++;
  58. if(action>4){
  59. action=1;
  60. }
  61. }
  62. }
  63. }
  64. publicLTransitiononTransition(){
  65. returnLTransition.newCrossRandom();
  66. }
  67. publicvoidonLoad(){
  68. imagePack=newLTexturePack();
  69. //加载小图到LTexturePack
  70. intheroImgId=imagePack.putImage("assets/h_a.png");
  71. intenemyImgId=imagePack.putImage("assets/e_a.png");
  72. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理;如果不调用此函数,
  73. //LTexturePack将允许动态增减图像,但是已加载的小图资源不会自动释放(可手动释放,或者dispose全部清空))
  74. imagePack.packed();
  75. //构建一个Move集合,用以控制图像移动与显示
  76. this.moveList=newArrayList<Move>(10);
  77. moveList.add(newMove(heroImgId,0,0,32));
  78. moveList.add(newMove(heroImgId,0,0,136));
  79. moveList.add(newMove(heroImgId,0,0,220));
  80. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,32));
  81. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,136));
  82. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,220));
  83. /**
  84. *获得一个内置的重力管理器
  85. *
  86. *PS:所有具备setX、setY函数的公有类(必须公有,否则反射不到……),都可以被GravityHandler绑定
  87. */
  88. finalGravityHandlergravityHandler=getGravityHandler();
  89. //批量载入重力控制
  90. for(Movem:moveList){
  91. Gravityg=newGravity(m);
  92. if(m.type==0){
  93. g.setVelocityX(LSystem.getRandom(50,80));
  94. }elseif(m.type==1){
  95. g.setVelocityX(-LSystem.getRandom(50,100));
  96. }
  97. gravityHandler.add(g);
  98. }
  99. //构建重力监控
  100. GravityHandler.Updateupdate=newGravityHandler.Update(){
  101. publicvoidaction(Gravityg,floatx,floaty){
  102. synchronized(moveList){
  103. Movesrc=(Move)g.getBind().ref();
  104. //仅让我方与敌人产生碰撞
  105. if(src.type==0&&src.action!=5){
  106. for(Moveobj:moveList){
  107. if(src.type!=obj.type&&!src.equals(obj)
  108. &&src.intersects(obj)){
  109. src.action=5;
  110. obj.action=6;
  111. }
  112. }
  113. }
  114. if(src.action<5){
  115. //让移动有一定几率上下浮动(比较贴近真实行走)
  116. g.setVelocityY(LSystem.getRandom(-100,100));
  117. }else{
  118. //打人或挨打时不能上下浮动
  119. g.setVelocityY(0);
  120. }
  121. //让当前重力控制触边实效(更上例不同,此方式仅暂停重力控制,而非删除,这意味着可以唤醒)
  122. if(x<0){
  123. g.setEnabled(false);
  124. }
  125. if(x>getWidth()-show_size){
  126. g.setEnabled(false);
  127. }
  128. }
  129. }
  130. };
  131. //添加监控(每次Gravity对象坐标发生变更时生效)
  132. gravityHandler.onUpdate(update);
  133. }
  134. publicvoidalter(LTimerContexttimer){
  135. }
  136. publicvoiddraw(GLExg){
  137. if(isOnLoadComplete()){
  138. synchronized(moveList){
  139. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  140. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  141. //可能会受到一定影响(每次渲染都单独提交)。
  142. imagePack.glBegin();
  143. for(Moveo:moveList){
  144. switch(o.type){
  145. case0:
  146. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  147. (o.action-1)*really_size,0,o.action
  148. *really_size,really_size);
  149. break;
  150. case1:
  151. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  152. o.action*really_size,0,(o.action-1)
  153. *really_size,really_size);
  154. break;
  155. }
  156. o.update();
  157. }
  158. //提交渲染结果到游戏画面
  159. imagePack.glEnd();
  160. }
  161. }
  162. }
  163. publicvoidtouchDown(LTouche){
  164. }
  165. publicvoidtouchDrag(LTouche){
  166. }
  167. publicvoidtouchMove(LTouche){
  168. }
  169. publicvoidtouchUp(LTouche){
  170. }
  171. publicvoiddispose(){
  172. if(imagePack!=null){
  173. imagePack.dispose();
  174. imagePack=null;
  175. }
  176. }
  177. publicstaticvoidmain(String[]args){
  178. GameScenegame=newGameScene("LTexturePackTest",480,320);
  179. game.setShowFPS(true);
  180. game.setShowLogo(false);
  181. game.setScreen(newLTexturePackTest());
  182. game.showScreen();
  183. }
  184. }

让单独纹理中的多个精灵进行混战



——————————

除了动态加载小图为统一纹理外,LTexturePack工具也允许根据XML设定来分解单独的大图为指定格式小图。

以上例为准,当我们执行下列代码:

System.out.println(imagePack.toString());

将可以在控制台见到如下输出:

<?xml version="1.0" standalone="yes" ?>
<pack file="null">
<block id="0" name="assets/h_a.png" left="0" top="0" right="144" bottom="24"/>
<block id="1" name="assets/e_a.png" left="0" top="24" right="144" bottom="48"/>
</pack>


这一输出,其实就是LTexturePack工具的XML文档解析格式。如果有单独的复合素材图(所有小图合成一张大图的那种),只要我们构建一个符合上述格式的XML文档,就能直接导入LTexturePack中使用。具体来说,<pack file="null">这项必须存在,其中file需要填写为素材图所在路径;id、left、top、right、bottom这五项也必须存在,否则无法定位和获取小图;name项如果想根据name取小图时必须存在,如果无此要求可不填。

另外,在LAE和LSE包中并无此工具类及类似工具存在。原因在于,使用LTexturePack工具虽然可以有效的节约图像资源,可惜调用方法不够直观,与LAE和LSE包的Easy特性并不相符。而且在Bitmap分图时,效率损耗要大于Texture,虽然能节约一定的显存空间,却会使本就不快的Canvas绘图变得更慢。因此,没有为LAE和LSE包提供相关扩展。

____________________

示例中用到了一些MD版梦幻模拟战的素材,资源在此(用什么图原理都一样):

http://115.com/file/dnr4wd6b#


临时想到的一些杂项:

1、关于LGame屏幕设置:

LGame默认提供有的Activity子类LGameAndroid2DActivity,只要继承该类的Activity就可以获得onMain、onGamePaused、onGameResumed三个接口。通常来说,在onMain中就足以完成我们所有的游戏初始化设置。

下面是一个最典型的基本设置:

[java] view plain copy
  1. publicvoidonMain(){
  2. //横屏,全屏显示
  3. this.initialization(true,LMode.Fill);
  4. //不显示logo
  5. this.setShowLogo(false);
  6. //显示实际fps
  7. this.setShowFPS(true);
  8. //注入游戏Screen
  9. this.setScreen(newMyScreen());
  10. //显示画面
  11. this.showScreen();
  12. }

如果我们设置initialization(true),这时游戏屏幕为横屏显示,而initialization(false)为竖屏显示,在布尔值后还可追加一项LMode,通过该类可以设定屏幕的显示方式,如全屏、自适屏、默认大小等等。而在调用initialization之前,我们可以调用maxScreen函数设定默认的屏幕大小,屏幕缩放以此作为依据,如果不进行设置,则默认游戏屏幕大小为480x320。

2、怎样提高游戏速度:

单以效率论,除了能起到缓存(或跳过冗余步骤)的模块外,绝大多数Java类在游戏开发中只能起到减速作用,游戏模块越多,意味着速度被放缓的可能性也就越大。所以游戏引擎也并不一定在所有场景都是快速的,因使用者不同,引擎即可能成为游戏加速的工具,也可能沦为游戏减速的利器。

仅以小弟愚见,提高速度的最简便诀窍在于——“能够执行一次的地方,就绝不给他第二次执行的机会”,真能做到这样,足矣。
cping1982原文: http://blog.csdn.net/cping1982/article/details/7002541
修正声明:

借写本例的机会,刚刚修正了某个【小】BUG。问题点在于LTexturePack的其中一个draw函数,本来在分图时需传入dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2等八个数值,结果小弟在接值时脑子进水,误将sx1,sx2,sy1,sy2写“扎堆”了(写错就是上述样子)……因为这是取图参数,即从sx1,sy1坐标开始取图,取到sx2,sy2的位置中止,弄错以后取出图立马变毕加索油画~所以小弟刚才将LGame-0.3.2-release这个包重新发了一遍,如果有用到LTexturePack的话请重新下载,抱歉抱歉(另外还改了3处问题)……

下载地址:http://loon-simple.googlecode.com/files/LGame-0.3.2-release.7z


关于TexturePack:

LGame中提供的LTexturePack类,是一个专门用于整合图像资源的辅助用类,它的最大作用是将许多零碎的图片画零为整,从而减少不必要的资源损耗。另一方面来讲,由于减少了渲染用纹理数量,避免了反复与图形系统交互,使用LTexturePack的速度通常会比单独使用零散LTexture为高。


最简单的使用方式:

[java] view plain copy
  1. packageorg.loon.test;
  2. importorg.loon.framework.javase.game.GameScene;
  3. importorg.loon.framework.javase.game.action.sprite.Arrow;
  4. importorg.loon.framework.javase.game.core.graphics.Screen;
  5. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  6. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  7. importorg.loon.framework.javase.game.core.input.LTouch;
  8. importorg.loon.framework.javase.game.core.input.LTransition;
  9. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  10. publicclassLTexturePackTestextendsScreen{
  11. LTexturePackimagePack;
  12. Arrowarrow;
  13. /**
  14. *无Transition效果。
  15. *
  16. *PS:目前LGame设定为,如果首个Screen没有加载特效,将强制运行一个随机特效。但是,返回Empty则不进行加载。
  17. */
  18. publicLTransitiononTransition(){
  19. returnLTransition.newEmpty();
  20. }
  21. publicvoidonLoad(){
  22. imagePack=newLTexturePack();
  23. //加载小图到LTexturePack
  24. imagePack.putImage("assets/h_a.png");
  25. imagePack.putImage("assets/h_b.png");
  26. imagePack.putImage("assets/h_c.png");
  27. imagePack.putImage("assets/e_a.png");
  28. imagePack.putImage("assets/e_b.png");
  29. imagePack.putImage("assets/e_c.png");
  30. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理)
  31. imagePack.packed();
  32. }
  33. publicvoidalter(LTimerContexttimer){
  34. }
  35. publicvoiddraw(GLExg){
  36. if(isOnLoadComplete()){
  37. intsize=32;
  38. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  39. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  40. //可能会受到一定影响(每次渲染都单独提交)。
  41. imagePack.glBegin();
  42. //LTexturePack中的数据可以按照索引加载
  43. imagePack.draw(0,32,size);
  44. //也可以按照文件名加载
  45. imagePack.draw("assets/h_b.png",32,size+=32);
  46. imagePack.draw(2,32,size+=32);
  47. size=32;
  48. imagePack.draw(3,256,size);
  49. imagePack.draw(4,256,size+=32);
  50. imagePack.draw(5,256,size+=32);
  51. //提交渲染结果到游戏画面
  52. imagePack.glEnd();
  53. //实例化一个动态箭头精灵
  54. if(arrow==null){
  55. arrow=newArrow(212,212,188,188);
  56. add(arrow);
  57. }
  58. //显示实际纹理
  59. g.drawTexture(imagePack.getTexture(),32,size+50);
  60. g.drawString("Texture",235,size+124);
  61. }
  62. }
  63. publicvoidtouchDown(LTouche){
  64. }
  65. publicvoidtouchDrag(LTouche){
  66. }
  67. publicvoidtouchMove(LTouche){
  68. }
  69. publicvoidtouchUp(LTouche){
  70. }
  71. publicvoiddispose(){
  72. if(imagePack!=null){
  73. imagePack.dispose();
  74. imagePack=null;
  75. }
  76. }
  77. publicstaticvoidmain(String[]args){
  78. GameScenegame=newGameScene("LTexturePackTest",480,320);
  79. game.setShowFPS(true);
  80. game.setShowLogo(false);
  81. game.setScreen(newLTexturePackTest());
  82. game.showScreen();
  83. }
  84. }

这时大家可以看到,在上述画面中,其实只有游戏中箭头指出的地方才是真正的纹理。而其余细分处,仅是大图纹理中的一部分罢了,然而在用户眼中,这些又有什么不同呢?不过,我们所能节省出的图像资源,却是非常巨大的。

当然,如果载入的是连续画面,那么仅仅能得到原画根本没用,不过没关系,我们也可以继续细分出我们满意的画面(上图具体代码和下例重复,故不再赘述)。


图像移动:

[java] view plain copy
  1. packageorg.loon.test;
  2. importorg.loon.framework.javase.game.GameScene;
  3. importorg.loon.framework.javase.game.action.collision.Gravity;
  4. importorg.loon.framework.javase.game.action.collision.GravityHandler;
  5. importorg.loon.framework.javase.game.action.sprite.Bind;
  6. importorg.loon.framework.javase.game.action.sprite.effect.SmashEffect;
  7. importorg.loon.framework.javase.game.core.geom.RectBox;
  8. importorg.loon.framework.javase.game.core.graphics.Screen;
  9. importorg.loon.framework.javase.game.core.graphics.opengl.GLColor;
  10. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  11. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  12. importorg.loon.framework.javase.game.core.input.LTouch;
  13. importorg.loon.framework.javase.game.core.input.LTransition;
  14. importorg.loon.framework.javase.game.core.timer.LTimer;
  15. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  16. publicclassLTexturePackTestextendsScreen{
  17. SmashEffectsmashEffect=newSmashEffect();
  18. //显示用精灵大小
  19. finalintshow_size=64;
  20. //实际精灵大小
  21. finalintreally_size=24;
  22. LTexturePackimagePack;
  23. /**
  24. *建立一个移动对象,用以管理LTexturePack中图像的移动
  25. */
  26. publicclassMove{
  27. RectBoxrect=newRectBox(0,0,show_size,show_size);
  28. LTimertimer=newLTimer(150);
  29. intid;
  30. floatx,y;
  31. intaction=1;
  32. inttype=-1;
  33. publicvoidsetX(floatx){
  34. this.x=x;
  35. rect.setX(x);
  36. }
  37. publicvoidsetY(floaty){
  38. this.y=y;
  39. rect.setY(y);
  40. }
  41. publicfloatgetX(){
  42. returnx;
  43. }
  44. publicfloatgetY(){
  45. returny;
  46. }
  47. publicbooleanintersects(Movem){
  48. returnrect.intersects(m.rect);
  49. }
  50. publicvoidupdate(){
  51. if(timer.action(elapsedTime)){
  52. action++;
  53. if(action>4){
  54. action=1;
  55. }
  56. }
  57. }
  58. }
  59. /**
  60. *无Transition效果。
  61. *
  62. *PS:目前LGame设定为,如果首个Screen没有加载特效,将强制运行一个随机特效。但是,返回Empty则不进行加载。
  63. */
  64. publicLTransitiononTransition(){
  65. returnLTransition.newEmpty();
  66. }
  67. publicvoidonLoad(){
  68. imagePack=newLTexturePack();
  69. //加载小图到LTexturePack
  70. intheroId=imagePack.putImage("assets/h_a.png");
  71. intenemyId=imagePack.putImage("assets/e_a.png");
  72. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理)
  73. imagePack.packed();
  74. finalMovemoveHero=newMove();
  75. moveHero.id=heroId;
  76. moveHero.x=0;
  77. moveHero.y=128;
  78. moveHero.type=0;
  79. finalMovemoveEnemy=newMove();
  80. moveEnemy.id=enemyId;
  81. moveEnemy.x=getWidth()-show_size;
  82. moveEnemy.y=128;
  83. moveEnemy.type=1;
  84. /**
  85. *获得一个内置的重力管理器
  86. *
  87. *PS:所有具备setX、setY函数的公有类(必须公有,否则反射不到……),都可以被GravityHandler绑定
  88. */
  89. finalGravityHandlergravityHandler=getGravityHandler();
  90. //用重力控制器将moveHero对象打包,并且向右方匀速移动(速度100)
  91. Gravityg1=newGravity(moveHero);
  92. g1.setVelocityX(100);
  93. //用重力控制器将moveHero对象打包,并且向左方匀速移动(速度100)
  94. Gravityg2=newGravity(moveEnemy);
  95. g2.setVelocityX(-100);
  96. //添加重力干预
  97. gravityHandler.add(g1);
  98. gravityHandler.add(g2);
  99. //构建重力监控
  100. GravityHandler.Updateupdate=newGravityHandler.Update(){
  101. publicvoidaction(Gravityg,floatx,floaty){
  102. //让当前重力控制触边实效(具体到本例,人物也将消失)
  103. if(x<0){
  104. gravityHandler.remove(g);
  105. }
  106. if(x>getWidth()-show_size){
  107. gravityHandler.remove(g);
  108. }
  109. }
  110. };
  111. //添加监控(每次Gravity对象坐标发生变更时生效)
  112. gravityHandler.onUpdate(update);
  113. }
  114. publicvoidalter(LTimerContexttimer){
  115. smashEffect.update(timer.getTimeSinceLastUpdate());
  116. }
  117. publicvoiddraw(GLExg){
  118. if(isOnLoadComplete()){
  119. smashEffect.draw(g);
  120. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  121. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  122. //可能会受到一定影响(每次渲染都单独提交)。
  123. imagePack.glBegin();
  124. //获得重力控制器(如果绑定为Sprite,Actor,LComponent等对象则不必额外处理显示步骤,
  125. //此处图像已统一打包入LTexturePack较为特殊)
  126. GravityHandlergravityHandler=getGravityHandler();
  127. //获得重力实例数量
  128. intsize=gravityHandler.getCount();
  129. //保存上一个Move实例
  130. Movefirst=null;
  131. for(inti=0;i<size;i++){
  132. //获得实例
  133. Gravitygravity=gravityHandler.get(i);
  134. Bindbind=gravity.getBind();
  135. //反射回绑定的对象
  136. Moveo=(Move)bind.ref();
  137. //判定两个图像的移动位置是否发生了碰撞(这里使用了比较流氓(就俩,省了-_-)的方式,实际应该建立一个精灵预警区,
  138. //然后搜索该区域内是否存在精灵,有的话再让移动中精灵与该精灵进行碰撞比较)
  139. if(first!=null&&first.intersects(o)){
  140. //碰撞后象征性的显示一个粉碎特效
  141. if(first.action!=5){
  142. smashEffect.createSmallExplosionEffect(getHalfWidth(),
  143. getHalfHeight());
  144. }
  145. o.action=5;
  146. first.action=5;
  147. g.setColor(GLColor.red);
  148. }
  149. switch(o.type){
  150. case0:
  151. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  152. (o.action-1)*really_size,0,o.action
  153. *really_size,really_size);
  154. break;
  155. case1:
  156. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  157. o.action*really_size,0,(o.action-1)
  158. *really_size,really_size);
  159. break;
  160. }
  161. first=o;
  162. o.update();
  163. }
  164. //提交渲染结果到游戏画面
  165. imagePack.glEnd();
  166. }
  167. }
  168. publicvoidtouchDown(LTouche){
  169. }
  170. publicvoidtouchDrag(LTouche){
  171. }
  172. publicvoidtouchMove(LTouche){
  173. }
  174. publicvoidtouchUp(LTouche){
  175. }
  176. publicvoiddispose(){
  177. if(imagePack!=null){
  178. imagePack.dispose();
  179. imagePack=null;
  180. }
  181. }
  182. publicstaticvoidmain(String[]args){
  183. GameScenegame=newGameScene("LTexturePackTest",480,320);
  184. game.setShowFPS(true);
  185. game.setShowLogo(false);
  186. game.setScreen(newLTexturePackTest());
  187. game.showScreen();
  188. }
  189. }

让LTexturePack中的两个精灵进行单挑

多个图像移动:

[java] view plain copy
  1. packageorg.loon.test;
  2. importjava.util.ArrayList;
  3. importorg.loon.framework.javase.game.GameScene;
  4. importorg.loon.framework.javase.game.action.collision.Gravity;
  5. importorg.loon.framework.javase.game.action.collision.GravityHandler;
  6. importorg.loon.framework.javase.game.core.LSystem;
  7. importorg.loon.framework.javase.game.core.geom.RectBox;
  8. importorg.loon.framework.javase.game.core.graphics.Screen;
  9. importorg.loon.framework.javase.game.core.graphics.opengl.GLEx;
  10. importorg.loon.framework.javase.game.core.graphics.opengl.LTexturePack;
  11. importorg.loon.framework.javase.game.core.input.LTouch;
  12. importorg.loon.framework.javase.game.core.input.LTransition;
  13. importorg.loon.framework.javase.game.core.timer.LTimer;
  14. importorg.loon.framework.javase.game.core.timer.LTimerContext;
  15. publicclassLTexturePackTestextendsScreen{
  16. ArrayList<Move>moveList;
  17. //显示用精灵大小
  18. finalintshow_size=64;
  19. //实际精灵大小
  20. finalintreally_size=24;
  21. LTexturePackimagePack;
  22. /**
  23. *建立一个移动对象,用以管理LTexturePack中图像的移动
  24. */
  25. publicclassMove{
  26. RectBoxrect=newRectBox(0,0,show_size,show_size);
  27. LTimertimer=newLTimer(150);
  28. intid;
  29. floatx,y;
  30. intaction=1;
  31. inttype=-1;
  32. publicMove(intid,inttype,floatx,floaty){
  33. this.id=id;
  34. this.type=type;
  35. this.x=x;
  36. this.y=y;
  37. }
  38. publicvoidsetX(floatx){
  39. this.x=x;
  40. rect.setX(x);
  41. }
  42. publicvoidsetY(floaty){
  43. this.y=y;
  44. rect.setY(y);
  45. }
  46. publicfloatgetX(){
  47. returnx;
  48. }
  49. publicfloatgetY(){
  50. returny;
  51. }
  52. publicbooleanintersects(Movem){
  53. returnrect.intersects(m.rect);
  54. }
  55. publicvoidupdate(){
  56. if(timer.action(elapsedTime)){
  57. action++;
  58. if(action>4){
  59. action=1;
  60. }
  61. }
  62. }
  63. }
  64. publicLTransitiononTransition(){
  65. returnLTransition.newCrossRandom();
  66. }
  67. publicvoidonLoad(){
  68. imagePack=newLTexturePack();
  69. //加载小图到LTexturePack
  70. intheroImgId=imagePack.putImage("assets/h_a.png");
  71. intenemyImgId=imagePack.putImage("assets/e_a.png");
  72. //宣布所有图像加载完毕(如果调用此函数,则释放所有已加载的资源,仅保留一块主纹理;如果不调用此函数,
  73. //LTexturePack将允许动态增减图像,但是已加载的小图资源不会自动释放(可手动释放,或者dispose全部清空))
  74. imagePack.packed();
  75. //构建一个Move集合,用以控制图像移动与显示
  76. this.moveList=newArrayList<Move>(10);
  77. moveList.add(newMove(heroImgId,0,0,32));
  78. moveList.add(newMove(heroImgId,0,0,136));
  79. moveList.add(newMove(heroImgId,0,0,220));
  80. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,32));
  81. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,136));
  82. moveList.add(newMove(enemyImgId,1,getWidth()-show_size,220));
  83. /**
  84. *获得一个内置的重力管理器
  85. *
  86. *PS:所有具备setX、setY函数的公有类(必须公有,否则反射不到……),都可以被GravityHandler绑定
  87. */
  88. finalGravityHandlergravityHandler=getGravityHandler();
  89. //批量载入重力控制
  90. for(Movem:moveList){
  91. Gravityg=newGravity(m);
  92. if(m.type==0){
  93. g.setVelocityX(LSystem.getRandom(50,80));
  94. }elseif(m.type==1){
  95. g.setVelocityX(-LSystem.getRandom(50,100));
  96. }
  97. gravityHandler.add(g);
  98. }
  99. //构建重力监控
  100. GravityHandler.Updateupdate=newGravityHandler.Update(){
  101. publicvoidaction(Gravityg,floatx,floaty){
  102. synchronized(moveList){
  103. Movesrc=(Move)g.getBind().ref();
  104. //仅让我方与敌人产生碰撞
  105. if(src.type==0&&src.action!=5){
  106. for(Moveobj:moveList){
  107. if(src.type!=obj.type&&!src.equals(obj)
  108. &&src.intersects(obj)){
  109. src.action=5;
  110. obj.action=6;
  111. }
  112. }
  113. }
  114. if(src.action<5){
  115. //让移动有一定几率上下浮动(比较贴近真实行走)
  116. g.setVelocityY(LSystem.getRandom(-100,100));
  117. }else{
  118. //打人或挨打时不能上下浮动
  119. g.setVelocityY(0);
  120. }
  121. //让当前重力控制触边实效(更上例不同,此方式仅暂停重力控制,而非删除,这意味着可以唤醒)
  122. if(x<0){
  123. g.setEnabled(false);
  124. }
  125. if(x>getWidth()-show_size){
  126. g.setEnabled(false);
  127. }
  128. }
  129. }
  130. };
  131. //添加监控(每次Gravity对象坐标发生变更时生效)
  132. gravityHandler.onUpdate(update);
  133. }
  134. publicvoidalter(LTimerContexttimer){
  135. }
  136. publicvoiddraw(GLExg){
  137. if(isOnLoadComplete()){
  138. synchronized(moveList){
  139. //当执行glBegin后,将在GLEx触发一个渲染批处理事件,仅在执行glEnd后提交
  140. //渲染内容到窗体。如果不调用此函数,则LTexturePack依旧可以执行,但是效率
  141. //可能会受到一定影响(每次渲染都单独提交)。
  142. imagePack.glBegin();
  143. for(Moveo:moveList){
  144. switch(o.type){
  145. case0:
  146. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  147. (o.action-1)*really_size,0,o.action
  148. *really_size,really_size);
  149. break;
  150. case1:
  151. imagePack.draw(o.id,o.x,o.y,show_size,show_size,
  152. o.action*really_size,0,(o.action-1)
  153. *really_size,really_size);
  154. break;
  155. }
  156. o.update();
  157. }
  158. //提交渲染结果到游戏画面
  159. imagePack.glEnd();
  160. }
  161. }
  162. }
  163. publicvoidtouchDown(LTouche){
  164. }
  165. publicvoidtouchDrag(LTouche){
  166. }
  167. publicvoidtouchMove(LTouche){
  168. }
  169. publicvoidtouchUp(LTouche){
  170. }
  171. publicvoiddispose(){
  172. if(imagePack!=null){
  173. imagePack.dispose();
  174. imagePack=null;
  175. }
  176. }
  177. publicstaticvoidmain(String[]args){
  178. GameScenegame=newGameScene("LTexturePackTest",480,320);
  179. game.setShowFPS(true);
  180. game.setShowLogo(false);
  181. game.setScreen(newLTexturePackTest());
  182. game.showScreen();
  183. }
  184. }

让单独纹理中的多个精灵进行混战



——————————

除了动态加载小图为统一纹理外,LTexturePack工具也允许根据XML设定来分解单独的大图为指定格式小图。

以上例为准,当我们执行下列代码:

System.out.println(imagePack.toString());

将可以在控制台见到如下输出:

<?xml version="1.0" standalone="yes" ?>
<pack file="null">
<block id="0" name="assets/h_a.png" left="0" top="0" right="144" bottom="24"/>
<block id="1" name="assets/e_a.png" left="0" top="24" right="144" bottom="48"/>
</pack>


这一输出,其实就是LTexturePack工具的XML文档解析格式。如果有单独的复合素材图(所有小图合成一张大图的那种),只要我们构建一个符合上述格式的XML文档,就能直接导入LTexturePack中使用。具体来说,<pack file="null">这项必须存在,其中file需要填写为素材图所在路径;id、left、top、right、bottom这五项也必须存在,否则无法定位和获取小图;name项如果想根据name取小图时必须存在,如果无此要求可不填。

另外,在LAE和LSE包中并无此工具类及类似工具存在。原因在于,使用LTexturePack工具虽然可以有效的节约图像资源,可惜调用方法不够直观,与LAE和LSE包的Easy特性并不相符。而且在Bitmap分图时,效率损耗要大于Texture,虽然能节约一定的显存空间,却会使本就不快的Canvas绘图变得更慢。因此,没有为LAE和LSE包提供相关扩展。

____________________

示例中用到了一些MD版梦幻模拟战的素材,资源在此(用什么图原理都一样):

http://115.com/file/dnr4wd6b#


临时想到的一些杂项:

1、关于LGame屏幕设置:

LGame默认提供有的Activity子类LGameAndroid2DActivity,只要继承该类的Activity就可以获得onMain、onGamePaused、onGameResumed三个接口。通常来说,在onMain中就足以完成我们所有的游戏初始化设置。

下面是一个最典型的基本设置:

[java] view plain copy
  1. publicvoidonMain(){
  2. //横屏,全屏显示
  3. this.initialization(true,LMode.Fill);
  4. //不显示logo
  5. this.setShowLogo(false);
  6. //显示实际fps
  7. this.setShowFPS(true);
  8. //注入游戏Screen
  9. this.setScreen(newMyScreen());
  10. //显示画面
  11. this.showScreen();
  12. }

如果我们设置initialization(true),这时游戏屏幕为横屏显示,而initialization(false)为竖屏显示,在布尔值后还可追加一项LMode,通过该类可以设定屏幕的显示方式,如全屏、自适屏、默认大小等等。而在调用initialization之前,我们可以调用maxScreen函数设定默认的屏幕大小,屏幕缩放以此作为依据,如果不进行设置,则默认游戏屏幕大小为480x320。

2、怎样提高游戏速度:

单以效率论,除了能起到缓存(或跳过冗余步骤)的模块外,绝大多数Java类在游戏开发中只能起到减速作用,游戏模块越多,意味着速度被放缓的可能性也就越大。所以游戏引擎也并不一定在所有场景都是快速的,因使用者不同,引擎即可能成为游戏加速的工具,也可能沦为游戏减速的利器。

仅以小弟愚见,提高速度的最简便诀窍在于——“能够执行一次的地方,就绝不给他第二次执行的机会”,真能做到这样,足矣。 cping1982原文: http://blog.csdn.net/cping1982/article/details/7002541
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值