博客

  • Gradle中ProGuard的配置

    好久没有写博客了…元旦前赶紧写一篇吧…

    这些日子琢磨了一下gradle。对比起maven确实在配置上灵活很多,对groovy的支持可以更容易的自定义任务。

    由于最近的几个项目中都使用到了moco这个开源项目,它使用gradle管理,使用命令gradle uberjar可以生成一个独立运行包,这个包有8M大。我使用的环境比较特殊…8M有点大了,就琢磨这使用ProGuard给它瘦个身,效果不错,简单配置以后大小变成了4.6M,只有原来的57%了。

    在配置的过程中遇到了很多难题,google之后都没有什么中文参考,故记录下了这次尝试,分享给大家。

    ProGuard简介

    ProGuard是一个压缩、优化和混淆Java 字节码文件的软件。它可以删除无用的类、字段、方法和属性。还可以删除没用的注释,优化 字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。

    我最开始接触ProGuard是在Android的开发中,这个工具已经成为标配了。其实ProGuard一样可以用于一般的Java项目。它的主要功能有三块:压缩,优化,混淆。其中压缩是删除没有用到的类等,当你的项目使用到了大量开源库的时候这个功能尤其明显。这也是本文主要用到的功能。优化可以去除一些无用参数,还可以进行一些代码内联。混淆功能是将包名、类名、方法名等等用无意义的字符替换掉,可以增加反编译的难度,保护你的代码。混淆也可以减少包的大小,但是混淆后不利于调试。

    ProGuard的配置

    大部分的工具都有配置,如果你没有太大的需求,一般可以直接使用。而ProGuard的配置是不可缺少的,特别是刚刚接触这个工具的时候,我觉得这个配置完全是自己写不出来的,我是针对每一个用到的包去搜索复制相关配置。后面慢慢发现其实还好,了解了原理以后就可以自己配置了。

    ProGuard会从你给出的入口点切入开始分析,一般是程序的main方法,如果某个类或者方法没有时候就会被去除。然而有时候程序中用到了某些类是通过配置文件或者反射等方法得到的,这种情况ProGuard可能就会误删。虽然目前ProGuard可以分析一些简单的情况,但是更多的时候还是需要自己配置。

    在Gradle中使用ProGuard

    ProGuard提供了Gradle插件,这样我们可以更方便的将ProGuard集成进来了。当前最新版是4.10。

    这个插件的介绍页面我死活打不开了…主要的参考也是其他项目的配置。

    先来看看如果在Gradle中生成一个独立包。这个包需要包含自身的源码、资源还有所有的第三方依赖。如果你的项目是一个多项目,那么你的独立包还应该其他需要的子项目,一般情况下配置如下:

    task uberjar(type: Jar, dependsOn: jar) {
    classifier ='standalone'
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    fromconfigurations.runtime.asFileTree.files.collect { zipTree(it) }
    
    manifest {
    attributes'Main-Class': YOUR MAINCLASS,
    
  • maven和libGDX

    maven和libGDX

    这一篇是关于maven和libgdx的。本来我准备用gradle(现已有gradle模板了),不过暂时有点小问题,而同时libgdx官方提供了maven支持,为了快速上手还是选用maven了。

    为什么要用maven

    其实原因很简单…我讨厌每次新建项目结构。

    从最开始接触libgdx手动建立Java项目和对应的Android项目到后面的使用setup-ui工具。

    手动建立不说了…这个建立步骤甚至挡住了一些人使用libgdx的步伐。

    setup-ui的确很棒,但是每次重复工作还是很麻烦,特别是需要一个完整的zip包…我本地一般不保存,所以每次都要下载。

    对我而言,在用libgdx开发游戏的时候用maven有三个优点:

    • 不需要去下载相关的包,不管是libgdx本身的,还是你自己使用的第三方包。

    • 省去了建立初始项目结构的麻烦,一个mvn archetype:generate就搞定了。

    • 各种环境不需要配置了,特别是GWT那个。

    虽然很多人觉得maven老了,但是我觉得能用就行了。

    不说多了,直接开始动手吧。这个系列都是以我最近在做的一个东西为例子,名字叫单词泡泡,大概是一个陪单词的(不要在意细节)。

    安装libgdx-maven-archetype

    刚才说到libgdx官方有支持,地址是:https://github.com/libgdx/libgdx-maven-archetype

    先把它clone下来,命令

    git clone git://github.com/libgdx/libgdx-maven-archetype.git

    进入目录,运行

    mvn install

    运行效果:

    安装好了就可以删除clone下来的文件了,我这里安装的是0.99版本。

    然后进入你的工作目录,

    mvn archetype:generate -DarchetypeGroupId=com.badlogic.gdx -DarchetypeArtifactId=gdx-archetype -DarchetypeVersion=0.9.9-SNAPSHOT

    然后输入一些信息,比如groupId,artifactId啥的,最后建立完成,目录结构如下:

    一些小修改

    建立工作就完成了…但是很遗憾,要让它正常工作还需要修改一下小配置。

    主要的问题集中在android项目上,桌面问题不大。

    尝试运行命令:

    mvn integration-test

  • 如何使用libgdx编写一个简单的游戏(三)— 人性化

    如何使用libgdx编写一个简单的游戏(三)— 人性化

    这一篇主要是添加一些让游戏更人性化的东西,比如音效和加载画面,菜单等等。

    这其中用到了很多资源,主要出自以下几个网站,大家有需要也可以去上面寻找。

    http://www.freesound.org/

    添加音效

    首先是飞镖发出时候的音效,我希望是类似”bing”的一声,要短小精炼。

    我使用的是http://www.freesound.org/people/BMacZero/sounds/96132/

    libgdx支持的音频主要是WAV, MP3和OGG,其他的支持需要扩展支持。

    libgdx中的音频有两种,一种是sound,一种是music。

    一般所谓的音效使用sound,而音乐就使用music。

    在DartController中添加属性

    Sound bing;

    在实例化方法中添加

    this.bing = Gdx.audio.newSound(Gdx.files.internal("audio/bing.wav"));

    在AddDart方法中添加

    bing.play();

     

    在怪兽被消灭的时候的音效我选用http://www.freesound.org/people/yottasounds/sounds/174465/

    在TargetController中添加

    great = Gdx.audio.newSound(Gdx.files.internal("audio/great.wav"));

    最后添加一个背景音乐。我使用的是http://www.freesound.org/people/Setuniman/sounds/167453/

    大小为5.7M,个人感觉有点大。

    而且我需要循环播放,这就意味着末尾的这个部分的我不需要。

    使用在线转换器截取并转化成ogg。

    转化以后大小变成465kb了。仔细听一下,感觉很多部分是重复,所以再一次截取,只要前4秒的。

    转化好以后在主类添加

    backgroundMusic = Gdx.audio.newMusic(Gdx.files
    .internal("audio/background.ogg"));
    
  • 如何使用libgdx编写一个简单的游戏(二)— 完善

    如何使用libgdx编写一个简单的游戏(二)— 完善

    上一篇介绍游戏雏形的编写,这一篇将完善部分逻辑并添加更多效果。

    例子代码在https://github.com/htynkn/DartsShaSha,如有需要请自行在tag中下载对应部分。

    完善飞镖逻辑

    现在的飞镖可以旋转可以飞行了,但是有一个问题却没有解决。

    首先飞镖的速度,如果用户触摸位置很靠近左侧,那么飞镖的速度就很慢了。

    其次,如果用户触摸中间位置,默认情况下飞镖应该是朝那个方向飞行,而不是飞到触摸位置就消失了。

    这里的处理办法很简单,就是根据用户触摸位置,算出一个X为480的值,这样飞镖就可以飞到最右侧,同时保持相当的速度。

    在createProjectile方法中添加

    float r = (target.y - image.getY()) / (target.x - image.getX());//获取斜率
    float detY = r *480;//获取Y的变动量
    image.addAction(Actions.moveTo(480 + image.getX(), detY + image.getY(),
    2f));// 设置飞镖的移动

    这样基本就解决了问题。

    接下来来思考飞镖的数量和相应位置。

    首先飞镖的速度一定要得到限制,不然满屏幕飞镖有什么意思。这里限制飞镖的数量为5个。

    在touchDown的最开始添加

    if (projectiles.getChildren().size >=5) 
  • 如何使用libgdx编写一个简单的游戏(一)— 雏形

    如何使用libgdx编写一个简单的游戏(一)— 雏形

    写这几篇文章主要是看了这个系列的文章:http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial

    这个系列主要讲述了如何使用Cocos2D编写简单的游戏。稍微读读感觉不错,所以想写个libgdx版本的。

    本篇文章主要讲述基本内容的编写,包括显示人物、怪兽和飞镖。

    最终效果如下图:

    01_thumb1

    获取libgdx

    你可以从libgdx的官网下载打包好的代码,我下载的是0.98版本。

    02_thumb4

    当然,你也可以从git代码仓库获取最新的版本的,或者你习惯使用的以前版本,比如0.97。

    创建项目

    libgdx项目的创建可以有多种方式,我推荐使用setup-ui。方便易用还可以省去很多麻烦,特别是ADT升级以后的ClassNotFound问题。

    如果是下载打包好的,那么就默认包含了gdx-setup-ui,双击就可以打开。

    03_thumb1

    填写一些基本信息,然后选中你下载的0.98.zip那个压缩文件。这里我只生成一个桌面项目和Android项目。

    桌面项目是方便调试,而Android项目是最后发布的。在整个开发中我始终用桌面项目调试,因为速度快,容易排错。同时周期性的在Android真机上测试。

    04_thumb1

    点击生成项目,然后在Eclipse中导入。

    05_thumb1

    一般导入进去以后Android项目会有一些问题,修改project.properties文件和AndroidManifest.xml配置文件。

    运行效果如下:

    06_thumb1

    准备工作

    本例子中用到的图片如下:

    Player_thumb Projectile_thumb Target_thumb

    用gdx-texturepacker打包成一张大图。

    07_thumb1

    我整个例子都是用的是Stage模式。所以它的坐标原点在左下角,如果是一般用Spirte直接绘制,那么原点在右上角。

    首先将打包好的图册复制到assets中新建的pack文件夹。

    然后我们开始动工了,首先删除setup-ui生成的多余代码,整理DartsShaSha.java文件如下:

    package com.cnblogs.htynkn;
    
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.GL10;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    
    publicclass DartsShaSha extends ApplicationAdapter {
    Stage 
  • android游戏开发框架libgdx的使用(完)—杂谈Libgdx

    写在最前面

    仔细看看,上一篇博文是10月5号了,有很长的时间没有写博客了。

    libgdx这个系列的文章开篇一年有余了,期间得到了很多朋友的鼓励和意见,总的来说感觉还是蛮不错的。

    想了很久,我决定给这个系列的文章画上一个句号。

    就原因来说是多方面的:

    第一是libgdx的版本从0.92到了今天的0.97版本,虽然总体架构变化不大,但是细节上的接口还是有很多差异了,早期的一些文章的实例代码可能无法直接运行了,我又没有精力细细检查和修改,可能新入手的朋友们会遇到一些问题。

    第二就是这个系列本身的问题,我开始写的时候也没有想什么具体的东西,就是有一篇写一篇的,整个系列来看没有一种整体的驾驭性,继续写下去我感觉意义不大。

    第三就是个人原因了,我其实并没有做过太多的游戏开发,当初接触libgdx也是相当偶然的原因。一些对于游戏开发更深入的东西我没有研究,不敢随意写出来。

    文章接下来的内容是一些极为零碎的东西,希望能够有所用处。

    Libgdx是什么

    我最感到庆幸的就是这个系列的文章的标题【android游戏开发框架libgdx的使用】,虽然最开始了解不深入,但是这个标题却是正确的。

    Libgdx是一个游戏开发框架,它不是一个游戏引擎。

    它的主要代码是java,其中对于效率要求较高的部分是由C和C++写成的。

    它是跨平台的,支持Windows、Mac OS、Linux、Android(1.5+)、GWT,它对IOS的支持是基于MonoTouchIKVM

    它是免费的,基于Apache License 2.0协议。

    Libgdx的优势是什么?我为什么选择它?

    说实话,现在的游戏框架和引擎有很多,选择的面也很广。比如庞大的cocos2d家族。

    如果你的主要语言是Java,那么推荐你使用Libgdx。

    如果你主要涉足Android游戏领域,那么推荐你使用Libgdx。它可以方便的在桌面环境调试你的游戏逻辑,你可以轻松地和那个缓慢的模拟器说拜拜了。

    如果你希望更自由的开发,你希望控制和掌握你的代码,那么推荐你使用Libgdx。它的封装比较低级,你可以基于它开发自己的游戏引擎,而不是接受其他引擎的那套模式和理论。当然你不想太底层但又希望一定的自由,2D的UI库和Stage给出了一套简单的解决方法。

    如果你追求高效,那么推荐你使用Libgdx。也许你带着有色的眼光…这货是Java的吧!好吧,我也没有做过相关的测试,不过推荐你看看这篇文章,它比较了主流的游戏框架的方方面面。

    Libgdx好用吗?比起XX怎么样?

    我经常在QQ和Email里面看到这样的询问,说实话,我觉着这种问题意义不大。首先我没有深入的研究过其他的游戏框架和引擎,不敢断言。其次个人的喜欢和需求是不同的,也许你喜欢Libgdx的这套API设计,也许你就是看不惯某种设计模式,这种问题很难有标准的答案,甚至常常引起争端。

    如果你想知道哪款开发框架或引擎适合你,你可以都试试再做出选择。如果你觉得没有时间或者这个功夫,那就双眼一闭,随便选一个吧。

    Libgdx的使用广吗?有哪些游戏使用了它?

    我清楚问这个问题的人的意思和顾虑。但是我觉得一款游戏的好坏和它使用什么技术手段开发没有大的关系。游戏的美工,构思设计还有宣传等等都会有很大的影响。

    当然使用广泛与否一定程度上关系着反馈的快捷和获取帮助的难易程度。我只能告诉你社区很活跃,任何问题都不会拖过半天(起码我遇到的情况是这样的)。我原来看过一个国外的网站,它统计了市场中的游戏使用了第三方库的情况,Libgdx的排名在20位以内,具体的数据和网址我记不清楚了。

    如果你想知道什么游戏使用了Libgdx,你可以去社区看看,有一个列表专门收集基于Libgdx的游戏。如果你硬要我举个例子,不知道Google最近吸引不少眼球的Ingress能不能满足你的心理期待。

    Libgdx支持中文吗?

  • 在stacklab上搭建Hadoop平台

    在stacklab上搭建Hadoop平台

    什么是stacklab

    stacklab是中国开源云联盟(COSCL)和中国OpenStack用户组(COSUG)联合成立OpenStack实验室,简单的来说就是一个免费申请和使用OpenStack的平台,和国外的那个TryOpenstack有点像,不过stacklab没有门槛,不需要邀请码什么的就可以申请使用。稍微试用了一下感觉很爽,特意和大家分享一下。

    在stacklab建立镜像

    网址:http://stacklab.org/

    点击Register注册,验证完邮箱以后登录。

    在建立镜像以前先配置好Keypairs。

    点击Create Keypair,名字随便填写就行了。完成可以得到一个pem文件。

    在Security Groups中添加一个22端口的许可(起初是为了添加对ssh的许可,后来我发现好像不加也没有关系…这里大家随意吧)

    在Images and Snapshots中选择一个喜欢的镜像,我这里选择的是CentOS6.2_x64,点击Launch。

    这里的Keypair选择我们刚才创建的那个,其他的随便填写。

    我创建了hmaster和hsalve两个镜像。

    注意一下中间的Size里面Disk是0,这个没有关系,可以使用的。点击Public Domain可以看到连接命令。

    比如

    ssh -i hmaster.pem -p11011 [email protected]

    第一次登录输入一个yes接受ssh的证书。

    登录以后输入passwd修改密码,这样就可以通过VNC登录了。

    网页上的那个VNC经常失灵…最好还是用ssh吧。如果是用putty,先把pem转成ppk就行了。

    使用CDH4搭建Hadoop

    CDH4使用很方便,参考:https://ccp.cloudera.com/display/CDH4DOC/CDH4+Installation

    先看一下主机名称和对应的IP,修改一下host。

    执行

    wgethttp://archive.cloudera.com/cdh4/one-click-install/redhat/6/x86_64/cloudera-cdh-4-0.noarch.rpm

    然后

    yum--nogpgchecklocalinstallcloudera-cdh-4-0.noarch.rpm

    再把Key加上

    rpm --import http://archive.cloudera.com/cdh4/redhat/6/x86_64/cdh/RPM-GPG-KEY-cloudera

    在hmaster上安装hadoop-yarn-resourcemanager…

  • android游戏开发框架libgdx的使用(二十四)—physics-body-editor配合Box2D加快开发

    android游戏开发框架libgdx的使用(二十四)—physics-body-editor配合Box2D加快开发

    Box2d是一个很出名的2d物理引擎,有C++、Java等等版本。libgdx对Box2D进行了很高效的封装,极大的降低了学习和使用成本。

    但是我觉得和Libgdx的UI库比起来,Box2D的使用始终比较复杂,单纯的物体降落什么的还好说,要是遇上一个特别复杂的物体,有时候就有点繁琐了。

    在网上游荡时发现了physics-body-editor,绝对堪称神器。

    physics-body-editor

    项目主页:http://code.google.com/p/box2d-editor/

    libgdx-box2d-1

    复杂对象的创建只需要用鼠标点点就行了。

    工具可以到处Json格式的文件,还可以用于其他环境中。

    对于Libgdx而言,该项目有一个专门的loader可供使用。

    第一个小瓶子

    我想了半天都没有找到一个合适的例子可以用做演示,干脆就用官方提供了那个瓶子的图片做演示。

    启动编辑器,新建一个项目,导入我们要的图片。

    libgdx-box2d-2

    点点鼠标把边描绘出来。

    libgdx-box2d-4

    编辑器还可以进行测试,点击鼠标拖动就可以出现不同大小和速度的小球。

    libgdx-box2d-3

    保存项目,你可以获得一个Json格式的文件。

    将压缩包中的loader引入项目。

    使用

    BodyEditorLoader loader =new BodyEditorLoader(Gdx.files.internal("box2d/b.json"));

    读入配置文件。然后创建一个动态对象:

    BodyDef bd =new BodyDef();
    bd.type = BodyType.DynamicBody;

    指定密度等等

    FixtureDef fd =new FixtureDef();
    fd.density =1;
    fd.friction =0.5f;
    fd.restitution =0.3f;
  • android游戏开发框架libgdx的使用(二十三)—使用Universal Tween Engine实现动画效果

    android游戏开发框架libgdx的使用(二十三)—使用Universal Tween Engine实现动画效果

    libgdx的ui库可以实现一些动画效果,但是做游戏来说可能有些不足。Universal Tween Engine是一个纯java实现的动画库。

    地址:http://code.google.com/p/java-universal-tween-engine/

    只要能够用float表示的一切java对象它可以让它动画化,可以使用于Libgdx、Android、Swing等等。

    Universal Tween Engine使用一般流程

    使用Universal Tween Engine最重要的一个步骤就是实现TweenAccessor接口,这个接口定义了getValues和setValues方法。

    然后Engine中注册对应的接口。然后定义一些动画效果并添加到管理器中。最后用update方法更新时间。

    具体的可以参考一下Wiki:http://code.google.com/p/java-universal-tween-engine/wiki/GetStarted

    在libgdx中实现简单动画

    我比较喜欢使用Stage,所以下面的例子都是Stage中的。

    首先实现TweenAccessor接口,我没有区分对待,比如给Image写一个,再给Button写个啥的。我直接给Actor写了一个,这样都可以用。

    getValues和setValues中我定义了3中操作:只修改X值;只修改Y值;修改X和Y值。

    publicstaticfinalint POSITION_X =1;
    publicstaticfinalint POSITION_Y =2;
    publicstaticfinalint POSITION_XY =3;

     

    这里注意一下getValues的返回值,你修改或者操作了几个值就返回几。

    代码如下:

    package com.cnblogs.htynkn;
    
    import aurelienribon.tweenengine.TweenAccessor;
    
    import com.badlogic.gdx.scenes.scene2d.Actor;
    
    publicclass 
  • android游戏开发框架libgdx的使用(二十二)—利用TABLELAYOUT进行布局

    android游戏开发框架libgdx的使用(二十二)—利用TABLELAYOUT进行布局

    前面有一篇文章介绍了用TWL进行布局,最近做其他java的东西接触到了table-layout,用着很不错,仔细看来一下文档,原来还支持libgdx。

    简单试用了一下,比TWL好使多了。

    TABLELAYOUT简介

    tablelayout-logo

    TABLELAYOUT是一个轻量级的UI组件布局库。使用表格实现,有点像HTML的TABLE。

    它支持libgdx, Swing, Android和TWL。支持Java API和配置文件两种方式。

    同时有个配套的编辑器http://table-layout.googlecode.com/svn/wiki/jws/editor.jnlp

    使用配置文件

    其实最好的方法应该是使用配置文件,这样便于修改,还可以利用工具进行可视化编辑。但是libgdx对于配置文件的支持好像没有很到位(或者是版本修改等等问题)。

    所以先介绍配置文件方式。配置文件的具体书写格式请参考table-layout主页。

    打开编辑器,绘制一个简单的游戏界面,包含一个开始按钮和设置按钮。

    libgdx-layout-1

    配置文件如下:

    debug
    *spacing:12 padding:5 align:center
    
    ---
    [StartButton] width:200 height:60
    ---
    [PrefButton] width:200 height:60

    那个debug是显示边框的,方便调试。空间以对应的类型为结尾,比如StartButton就是按钮。

    第二行定义的是全局样式。还有很多其他样式可以定义,我个人觉得很Css盒子模型很接近。

    将文件保存为main.layout。

    因为TableLayout是在Stage中使用的,所以很其他的Actor的用法雷同。先添加一个table,在从table中获取TableLayout。然后定义控件,并和配置文件中的名字一一对应注册进去,最后加载配置文件。

    先新建一个table并添加到stage中

    Table table =new Table(skin);