#Testin杯#Mkey libgdx游戏引擎教程实战篇(二)移植俄罗斯方块(附源码)

71
回复
569079
查看
  [复制链接]

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2012-7-10 21:21:29 | 显示全部楼层 |阅读模式
本帖最后由 耒佲請ぁ留埗 于 2012-7-26 17:27 编辑

本文参与:Testin—安卓巴士Android开发原创教程大赛


以下系列教程按讲课顺序排列,也是推荐阅读的顺序

第一讲:libgdx游戏引擎教程(一)性能优良的游戏引擎—libgdx http://www.apkbus.com/android-57355-1-1.html

第二讲: libgdx游戏引擎教程(二) ApplicationListener,着手第一个程序http://www.apkbus.com/android-57372-1-1.html

第三讲:libgdx游戏引擎教程()libgdx粒子系统的使用 http://www.apkbus.com/android-57456-1-1.html

外篇一:libgdx游戏引擎教程外篇(一)优美的自定义进度条(附源码) http://www.apkbus.com/android-57523-1-1.html

第四讲:libgdx游戏引擎教程(四) 游戏正式开始,资源异步加载(附源码)http://www.apkbus.com/android-57716-1-1.html

第五讲 libgdx游戏引擎教程(五)多游戏界面的实现(一)附源码 http://www.apkbus.com/android-57936-1-1.html

第六讲 libgdx游戏引擎教程(六)多游戏界面的实现(二)附源码 http://www.apkbus.com/android-57991-1-1.html  

第七讲 libgdx游戏引擎教程(七) 在libgdx中拦截Android按键事件 http://www.apkbus.com/android-58030-1-1.html  

外篇二: libgdx游戏引擎教程外篇(二)libgdx移植俄罗斯方块(附源码) http://www.apkbus.com/android-58102-1-1.html   

实战一:libgdx游戏引擎教程实战篇(一)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58404-1-1.html  

实战二:libgdx游戏引擎教程实战篇(二)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58408-1-1.html  

实战三:libgdx游戏引擎教程实战篇(三)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58414-1-1.html  

实战四:libgdx游戏引擎教程实战篇(四)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58418-1-1.html  

实战五:libgdx游戏引擎教程实战篇(五)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58419-1-1.html

实战六:libgdx游戏引擎教程实战篇(六)移植俄罗斯方块(附源码) http://www.apkbus.com/android-58760-1-1.html

第八讲 libgdx游戏引擎教程(八) libgdx中的用户手势识别(一)附源码 http://www.apkbus.com/android-58933-1-1.html

第九讲 libgdx游戏引擎教程(九) libgdx中的用户手势识别(二)附源码 http://www.apkbus.com/android-59152-1-1.html

外篇三: libgdx游戏引擎教程外篇(三) 优美的自定义对话框(附源码) http://www.apkbus.com/android-59654-1-1.html  

第十讲:  libgdx游戏引擎教程(十)演员类的复杂动画(一)(附源码) http://www.apkbus.com/android-59998-1-2.html

第十一讲:libgdx游戏引擎教程(十一)演员类的复杂动画(二)(附源码) http://www.apkbus.com/android-60053-1-1.html

第十二讲:libgdx游戏引擎教程(十二)演员类的复杂动画(三)(附源码) http://www.apkbus.com/android-60194-1-1.html   

第十三讲: libgdx游戏引擎教程(十三)演员类的用户交互功能详解(附源码)  http://www.apkbus.com/android-60457-1-1.html

第十四讲:libgdx游戏引擎教程(十四)libgdx中常用的控件(附源码) http://www.apkbus.com/android-60569-1-1.html

最新更新 第十五讲 :libgdx游戏引擎教程(十五)在Libgdx中仿微信帮助滑动效果(附源码) http://www.apkbus.com/android-60822-1-1.html

SDK版本源码下载(是我们移植的素材):



    既然我们是要用libgdx移植这个游戏,我们很显然要让UiActvity从直接继承Activity改成继承AndrodApplication, 并且我们用到了多界面,那么按照我在第五,第六,第七讲三讲中讲的,我们要有两个继承自Screen的界面,分别叫UiScreen,GameScreen,并且有一个管理这两个Screen的继承自Game类的类,我们叫它TetrisGame好了。

    接着实战篇的第一讲,我们开始新建上面提到的这些类,便于从SDK版本中移植。

   先创建一个新类TetrisGame,继承自Game:
  1. public class TetrisGame extends Game {
  2.         Screen screen;
  3.         @Override
  4.         public void create() {
  5.                 // TODO Auto-generated method stub
  6.                 setScreen(screen);
  7.         }
  8.         public TetrisGame(Screen screen) {
  9.                 super();
  10.                 // TODO Auto-generated constructor stub
  11.                 this.screen=screen;
  12.         }
  13.         

  14. }
复制代码
     我们在构造这个Game的时候,同时传入了一个Screen,内部有一个变量保存这个引用,并在这个Game被AndroidApplication调用initialize()方法的时候(Game则调用create())的时候将Game的默认屏幕变为这个传入的Screen。

     

   这个类其实就算写完了,传入一个Screen,并在创建的时候将这个Screen设置为当前界面。

    然后是新建两个Screen, UiScreenGameScreen,分别代表主界面和游戏界面。




目前这两个类也是空的,什么都没有。很简单,直接实现Screen接口就可以了,所以就不贴代码了。

   然后我们进行一个初始阶段比较重要的操作。修改UiActivity让其继承自AndroidApplication


      UiActivity.java:
  1. public class UiActivity extends AndroidApplication {
  2.         TetrisGame tg;
  3.         UiScreen us;
  4.         GameScreen gs;
  5.     @Override
  6.     public void onCreate(Bundle savedInstanceState) {
  7.         super.onCreate(savedInstanceState);
  8.         requestWindowFeature(Window.FEATURE_NO_TITLE);
  9.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  10.                         WindowManager.LayoutParams.FLAG_FULLSCREEN);
  11.         gs=new GameScreen();
  12.         us=new UiScreen();
  13.         tg=new TetrisGame(us);
  14.         initialize(tg, true);
  15.     }   
  16. }
复制代码
    然后我们运行一下,程序能正常启动,不过是是一个全黑的屏幕,这很正常,因为我们没有做任何操作。

       然后我们修改UiScreen,画出基本图像,不过我们这里先不加入难度设置,并且游戏开始用一个按钮表示,最后我们会尝试将用SDK实现的滑动开始的效果和RatingBar的效果用自定义Libgdx实现

      还记得SDK版本的主界面是怎样的吗?我们回忆一下,哈哈,贴张图,然后好做对比。




           当然现在我们要用Libgdx来实现它。

       我们将需要的素材从SDK版本中拿过来放心,这两个版本都是我自己写的所以没有版权问题哈==

         将三张背景图片放在asset文件夹下,这里我们为了追求简单,只对320*240480*320800*480的分辨率进行适配。所以其他机型可以显示,但可能有显示的问题,比如图片拉伸的问题。

        我们先修改UiScreen,这个界面修改好后将成为游戏的开始界面。

        注意,这里有一个非常 非常 非常 非常 非常 非常 非常 非常 非常 非常重要的问题。 libgdx中的图片的边长只能是2的幂次,如2*432*64等等,但是图片不满足这个要求怎么办呢?我们可以用libgdx中的工具TextruePacker,具体使用方法可以看:

android游戏开发框架libgdx的使用(十六)

http://www.apkbus.com/android-44510-1-1.html

   也可以使用将图片修改成2的幂次的边长(多余的部分可以是白色或者任意颜色)我们在绘制的时候用TextureRegion封装Textrue并且只将有用的部分绘制出来就可以了。下面我用的就是这种方法。
      
      我们将图片做一些调整,让边长满足2的幂次的条件。多余的部分我们在绘制的时候不画出就可以了。修改后的图片如下,我们可以很清楚的看见有红色的部分,这都是不会被画出的。

这些图我改成了边长为2的幂次的:




为了醒目,让大家明白多余的部分是不会被画出的,我用了醒目的红色。


UiScreen.java(接下来还会修改,一步步来嘛)

请大家务必看一下注释,很多问题就不便一一讲,但是又非常重要,所以我在注释中都写出来了。
  1. public class UiScreen implements Screen {
  2.         Texture texture;
  3.         TextureRegion background;
  4.         boolean hasini;
  5.         SpriteBatch batch;
  6.         Stage stage;
  7.         Button start;
  8.         int width;
  9.         int height;
  10.         //边长的最大值和最小值
  11.         int max;
  12.         int min;
  13.         Texture tx1;
  14.         Texture tx2;
  15.         Texture tx3;
  16.         @Override
  17.         public void dispose() {
  18.                 // TODO Auto-generated method stub

  19.         }

  20.         @Override
  21.         public void hide() {
  22.                 // TODO Auto-generated method stub
  23.         }

  24.         @Override
  25.         public void pause() {
  26.                 // TODO Auto-generated method stub

  27.         }

  28.         @Override
  29.         public void render(float arg0) {
  30.                 // TODO Auto-generated method stub
  31.                 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
  32.                 Gdx.gl.glClearColor(0f,0f,0f,0f);
  33.                
  34.                 batch.begin();
  35.                 batch.draw(background,0,0,min,max);
  36.                 batch.end();
  37.                
  38.                 //舞台绘制要在背景绘制之后,不然背景会覆盖在按钮表面,我们就看不到按钮了
  39.                 stage.act(Gdx.graphics.getDeltaTime());
  40.                 stage.draw();
  41.         }

  42.         @Override
  43.         public void resize(int arg0, int arg1) {
  44.                 // TODO Auto-generated method stub

  45.         }

  46.         @Override
  47.         public void resume() {
  48.                 // TODO Auto-generated method stub

  49.         }
  50.         

  51.         @Override
  52.         public void show() {
  53.                 // TODO Auto-generated method stub
  54.                
  55.                 //做一个简单的适配。这里解释一下为什么不直接令max=height,原因在于有时候我们从锁屏回到游戏,
  56.                 //从横屏切换到竖屏或者从竖屏切换到横屏的时候,libGdx有时候会来不及切换,也就是说我们可能
  57.                 //getWidth得到的是实际的height值,getHeight得到的是实际的width值,所以这里增加一个长宽哪一个
  58.                 //更大的语句,这样就不会出错了
  59.                 width=Gdx.graphics.getWidth();
  60.                 height=Gdx.graphics.getHeight();
  61.                 max=width>height?width:height;
  62.                 min=width>height?height:width;
  63.                 //再做一个简单的适配
  64.                 if(max>=320&&max<480)
  65.                         max=320;
  66.                 if(max>=480&&max<800)
  67.                         max=480;
  68.                 if(max>=800)
  69.                         max=800;
  70.                 if(!hasini){
  71.                 batch=new SpriteBatch();
  72.                 stage=new Stage(min,max,true);
  73.                 texture=new Texture(Gdx.files.internal("background"+max+".jpg"));
  74.                
  75.                 //新建一个Button
  76.                
  77.                 tx2 = new Texture(Gdx.files.internal("button1.png"));
  78.                 tx1 = new Texture(Gdx.files.internal("button2.png"));
  79.                 tx3 = new Texture(Gdx.files.internal("button3.png"));
  80.                 NinePatch n1 = new NinePatch(tx1, 14, 14, 18, 18);
  81.                 NinePatch n2 = new NinePatch(tx2, 14, 14, 18, 18);
  82.                 NinePatch n3 = new NinePatch(tx3, 14, 14, 18, 18);         
  83.                 start= new Button( new ButtonStyle(n1, n2, n3, 0f, 0f, 0f, 0f), "Start");
  84.                
  85.                 //让按钮的位置处在正中间
  86.                 start.x=(min-tx2.getWidth())/2;
  87.                 stage.addActor(start);
  88.                
  89.                 //重点在这条语句,我们只取了texture的一部分,红色的多余部分我们没有取
  90.                 background=new TextureRegion(texture, 0, 0, min, max);
  91.                 hasini=true;
  92.                 }
  93.                 //这句话是必须的,而且在if(hasini)之外,无论资源是否加载完成,每次显示的时候我们都养将当前屏幕
  94.                 //设置能够接受用户输入
  95.                 Gdx.input.setInputProcessor(stage);
  96.         }
  97. }
复制代码

        咩哈哈,老样子,我胆子比较小,学习Mars老师的,写一点就运行一下,一是可以看看小效果给自己一点信心,二是防止错误往下面积累,后面出错不好锁定错误的位置。运行一下,显示效果应该是这样的,按钮按下没有任何变化..



     然后我们就开始移植最重要的部分,游戏界面,GameScreen,我们将需要移植的工程的GameView里面的一些变量都复制过来,并做一些相应的修改,比如SDK中用来保存方块图片的Bitmap数组我们用libgdx中的Textrue来代替之类的。

     这次的教程写的实在是太长了...我还是放在下一讲继续写...word文档摆了50页...伤不起啊


Testin ID:ilovemkey@gmail.com 总的而言这个平台真的非常好用!我正是用这个平台发现了现在写的这个应用的一些内存管理方面的问题。另外建议能够在测试报告中看到某一台机型在整个执行过程中的cpu和内存占用的变化情况,这样可以更快地锁定问题。感谢Itestin让测试变得轻松了太多太多!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
君见一叶舟,出没风波里

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-16 15:25:51 | 显示全部楼层
其实学习过程和思想才是最重要的啊,为什么大家只看有源码的呢....
君见一叶舟,出没风波里

0

主题

10

帖子

31

安币

初级码农

Rank: 1

发表于 2012-7-17 11:26:36 | 显示全部楼层
{:Pin:}问个问题  actor怎么进行缩放适应屏幕?   否则不同设备  自适应问题不好弄

30

主题

350

帖子

1089

安币

Android大神

Rank: 6Rank: 6

QQ达人

 楼主| 发表于 2012-7-17 12:41:37 | 显示全部楼层
gejw0623 发表于 2012-7-17 11:26
问个问题  actor怎么进行缩放适应屏幕?   否则不同设备  自适应问题不好弄 ...

定义一个变量power,根据不同的屏幕大小附上不同的值,在actor的draw函数中,将绘图中各个参数(如长度,高度,x,y)的值乘上这个值就可以了
君见一叶舟,出没风波里

0

主题

10

帖子

31

安币

初级码农

Rank: 1

发表于 2012-7-18 13:04:38 | 显示全部楼层
耒佲請ぁ留埗 发表于 2012-7-17 12:41
定义一个变量power,根据不同的屏幕大小附上不同的值,在actor的draw函数中,将绘图中各个参数(如长度, ...

好的  谢谢{:Snicker:}

0

主题

37

帖子

25

安币

初级码农

Rank: 1

发表于 2012-7-19 14:06:31 | 显示全部楼层
学习了、、

0

主题

455

帖子

9651

安币

码皇(巴士元老)

Rank: 8Rank: 8

发表于 2012-7-19 19:57:15 | 显示全部楼层
谢谢分享

0

主题

28

帖子

20

安币

程序猿

Rank: 2

发表于 2012-7-23 22:42:51 | 显示全部楼层
楼主,我有个问题:你在UiScreen中用了一个SpriteBatch专门在render()里面画背景,这样做有什么好处?能不能也将其看成一个Actor放在Stage里面?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )