注:以下资料在实际写代码过程中都不如看quick源代码来得直接有效!
quick官网,主要用于下载,教程有一定参考价值: http://cn.cocos2d-x.org/?v=CN
quick-cocos2d-x 文档,很全面,配置环境时需要参考: http://quick.cocoachina.com/wiki/doku.php?id=zh_cn
quick-cocos2d-x API 文档,有一定参考价值: http://quick.cocoachina.com/wiki/doku.php?id=zh_cn:api
Quick-Cocos2d-X 捋一捋框架流程,说了一些重点需要注意的框架方面的问题: http://www.cocos2dev.com/?p=535
quick github: https://github.com/chukong/quick-cocos2d-x
luaj是这个博主写的: http://dualface.github.io
Quick-Cocos2d-x 加密: http://cn.cocos2d-x.org/tutorial/show?id=1447 http://cn.cocos2d-x.org/tutorial/show?id=1507
Quick在Cocos Code IDE中实现代码提示: http://cn.cocos2d-x.org/tutorial/show?id=1715
Android FATAL 11无堆栈信息调试方法:
cd $ANDROID_NDK_ROOT
adb logcat | ./ndk-stack -sym /Users/hellosure/Develop/pincollage/branches/wallet_1-1-6-BRANCH/frameworks/runtime-src/proj.android/obj/local/armeabi/
动态更新: http://my.oschina.net/SunLightJuly/blog/180639 https://groups.google.com/forum/#!topic/quick-x/ni6Nf50jzfo http://my.oschina.net/u/1785418/blog/283043 http://zengrong.net/post/2131.htm https://github.com/chukong/quick-cocos2d-x/tree/master/samples/2048
quick-cocos2d-x 多分辨率适配详解: http://quick.cocoachina.com/?p=1436
animation的效果,很容易通过transition.lua实现
Lua Style Guide,编程风格: https://github.com/Olivine-Labs/lua-style-guide
Lua 5.1 参考手册,用的不多,需要知道什么写法直接google再终端试一下即可: http://www.codingnow.com/2000/download/lua_manual.html
Lua的点号和冒号 用lua进行面向对象的编程,声明方法和调用方法统一用冒号,对于属性的调用全部用点号。
Lua 中关于函数稍微难以理解的是函数也可以没有名字,匿名的。当我们提到函数 名(比如 print),实际上是说一个指向函数的变量,像持有其他类型值的变量一样:
a = {p = print}
a.p("Hello World") --> Hello World
print = math.sin -- `print' now refers to the sine function
a.p(print(1)) sin = a.p sin(10,20)
--> 0.841470
-- `sin' now refers to the print function -->10 20
cocos2dx文档,没怎么看过: http://cn.cocos2d-x.org/doc/cocos2d-x-3.0/index.html
parse文档,主要就是看这个: https://www.parse.com/docs
Fyber: http://developer.fyber.com/content/android/offer-wall/offer-api/
SponsorPay: https://github.com/SponsorPay/mobile-sdk
TapJoy: https://github.com/kalpeshhpatel/cordova-tapjoy-plugin
Aarki: https://portal.aarki.com/account/library https://portal.aarki.com/docs/webapi/
Adcolony: https://github.com/AdColony/AdColony-Android-SDK/wiki/API-Details
develop console https://play.google.com/apps/publish/?dev_acc=00903166301840771912#AppListPlace
crash https://play.google.com/apps/publish/?dev_acc=00903166301840771912#ErrorClusterDetailsPlace:p=gift.wallet&et=CRASH&sh=false&lr=LAST_7_DAYS&ecn=Native+crash&tf=unknown&tc=unknown&tm=unknown&nid=251b7bf0b0d31bd2&an&c&s=new_status_desc
emulator: http://stackoverflow.com/questions/2799097/how-can-i-detect-when-an-android-application-is-running-in-the-emulator
"google_sdk".equals(Build.PRODUCT) || "sdk".equals(Build.PRODUCT) || "sdk_x86".equals(Build.PRODUCT) || "vbox86p".equals(Build.PRODUCT)
Build.FINGERPRINT.contains("generic")
Installing ARM Translation and GApps http://forum.xda-developers.com/showthread.php?t=2528952
https://www.woorank.com
http://www.appannie.com/apps/google-play/app/gift.wallet/?account_id=222547
用来将多张图打包成一张大图plist
这种技术叫做CSS Sprite,本质是:
这种技术有好处也有坏处,好处是由于图片都放在一起,请求时只需请求一张图片,减少了与服务器的交互次数,提高了页面性能是它最大的好处,还可以解决hover延迟加载的问题。能减少图片的字节,曾经比较过多次3张图片合并成1张图片的字节总是小于这3张图片的字节总和。还有就是更换风格方便,只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变。维护起来更加方便。
坏处就是不好控制,扩展性不太好,以后有改动,可谓是牵一发而动全身,而且有时会因为屏幕分辨率不同出现背景断裂现象。CSS Sprites在开发的时候比较麻烦,你要通过photoshop或其他工具测量计算每一个背景单元的精确位置,这是针线活,没什么难度,但是很繁琐;幸好腾讯的鬼哥用ADOBE AIR开发了一个CSS Sprites 样式生成工具,虽然还有一些使用上的不灵活,但是已经比photoshop测量来的方便多了,而且样式直接生成,复制,拷贝就OK!
最开始想参考的是FeaturePoint,它是用hybrid app的方式做的,因此调研了一些关于hybrid app的知识。
hybrid app 的技术选型包括两个方面:
主流选用cordova,而titanium相对而言不够成熟,学习曲线高。
在整个系统中,服务提供方为backend,1位于middle,2位于frontend。
对于前端技术选型,可选的方案有:
(1) ionic
ionic提供了ui,mvx集成了angular。
虽然angular做spa有天然优势,不过上手没有jquery快,而且更适合做更复杂的应用,另外angular对代码侵入性较大如果未来想把它换掉那基本上只能重新开发。再就是感觉ionic的document不是非常详细,ui也没有感受到太多优势,ionic creator对html原型快速搭建有用不过没有必要使用它,另外对于它宣称的性能优势这方面估计并不能对咱们应用带来多少实际好处。
(2) sencha touch
定制化比较高,对于当前应用来说稍显重。
(3) jquery mobile
jqm被诟病较多的在于两个方面,一是webapp中不能忍它库文件太重,二是ui模版味太重。对于第一点在hybridapp中可以避免,对于第二点可以借助bootstrap等ui框架来优化。
另外,jquery mobile和ionic都提供builder工具快速drag-and-drop,export可以快速得到html,可以减轻页面初期开发工作量。
(1) jquery mobile
codiqa,另外可导入用themeroller自定义的theme http://themeroller.jquerymobile.com
(2) ionic
ionic-creator https://creator.ionic.io
hybrid app的选型结果:
cordova + jquery mobile + bootstrap
但是后来把hybrid app方案毙掉的原因是: hybrid app有个最大的问题就是:安全性。hacker是可以从apk中获取并反编译得到源代码的,这个太恐怖了。可能被很快的复制,也可能被钓鱼。在产品角度又想跨平台,因此采用lua来做,lua通过xxtea算法加密,再就是lua有动态更新这点很爽。
bybrid app用来自己做app快速上线,还有有点用处的,但是实际项目还是谨慎。
http://rensanning.iteye.com/category/305123
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(mActivity)
.setMessage("Google play services out of date.")
.setPositiveButton("Update", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mActivity.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("market://details?id=com.google.android.gms")));
}
}).show();
}
});
java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare() android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 解决方式都是放到ui线程中:
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
myDialog = ProgressDialog.show(mActivity, "title", "body", true);
}
});
另外,handler是用来在UI线程中修改界面的。
class MyTask extends AsyncTask {
ProgressDialog pd;
@Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("loading");
pd.show();
}
@Override
protected Void doInBackground(Void... params) {
// Do your request
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pd != null)
{
pd.dismiss();
}
}
}
lua中cc.httprequest在模拟器中是会到CCHTTPRequest.cpp 但是在安卓真机上会到CCHTTPRequestAndroid.cpp 然后它里面会调用框架的QuickHTTPInterface.java
从CCHTTPRequestAndroid.cpp的start方法中可以看到,比如对于header的处理,必须用=分割: int pos = val.find(‘=‘); 然后去调用addRequestHeaderJava,这个也就是QuickHTTPInterface.java中的addRequestHeader方法
最终达到的效果就是CCHTTPRequestAndroid.cpp和QuickHTTPInterface.java都不改,在lua中迎合它代码的逻辑。
注意,CCHTTPRequest.cpp和CCHTTPRequestAndroid.cpp对HTTP的处理逻辑是不同的,以后直接在真机中调试比较好。
发现对https的api发送接收有问题。 解决方案应该是把ssl关掉: 比如python中
httpClient = httplib2.Http(disable_ssl_certificate_validation=True)
promoeUrl = "https://api.zhaowowa.com/api/v1/promote"
这个问题的最终解决方法是: 官网上说明是 https://developer.android.com/training/articles/security-ssl.html 实际解决是信任所有Https: http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/
getfollow那里实现方式是改了quick cocos2dx框架底层的c++配置,这种方式简单,但是不可扩展。
在一个分辨率中摆放东西是很简单的。但是放到多设备上就会有各种问题。
按比例放置在640*1136,然后放到安卓大设备就会和设计图有点出入,然后图片会模糊一点,这是这种方案的缺点。 getlikes当时是这种方案做的。
在1440*2560中按比例放置,或者按绝对坐标放置。然后这是在一个layer中放sprite,因为这个分辨率是最大的了,放到其他分辨率的时候,就把这个layer整体scale缩放,这样就不会有1的那种和设计图不一致的问题,但是有另外的一个问题就是:可能有黑边、或者界面在一个方向上出去了。 因为缩放是按照宽或者高来的,如果按照宽来,那么在不同的设备上,高就有可能黑边或者出去。反之如果按照高来,那么在不同设备上,宽就可能黑边或者出去。 getfollows是这种方案做的,贴边的工作非常烦人,最好能避免。 这里还有一个技巧,就是底部的一排按钮肯定必须完美占满,所以这排按钮是在缩放的layer之上的,就是layer不管怎么缩放,在layer缩放完了之后再把底部一排按钮加上去。
no border的方案,这种团队里还没有采用过,就是设计的时候,就在一个方向上给出余量,比如在高上给出余量,那么在缩放以宽为基准就是把宽完美填满时,高可以满足各种设备:都不会出现黑边,且就算超过了也不会影响效果。 这种需要设计师来考虑怎么设计比较合适。 游戏中很多是这样做的,因为游戏的背景出去一点没有什么关系。
在代码的组织上,先放一个layer,然后在上面放置各种sprite,这些sprite可以把一些有关联的封装在一起,这样缩放时就是一个整体了。 在addchild时可以在第二个参数设置是哪个层级。
坐标原点肯定是在左下角,但是锚点可以放置在不同的位置,比如放置在最上方的中间位置。这样就算缩放,两边的黑边是一样宽的。
一组组件封装在一起,其坐标是组件内部的坐标系来定位。然后再把组件群一起调价到layer中。
lua其实就是把c++代码封装了一下,在quick2.2的版本中,可以看得很清楚,比如display.lua中的 function display.newLayer() 就是调用的c++代码CCLayer,把它创建了一下然后返回一个CCLayer对象,然后在使用的时候就可以根据这个创建出的对象来调用CCLayer.h中提供的方法,比如: local layer = display.newLayer() layer:setColor(xxx) 注意,要用冒号,另外setColor必须在CCLayer.h中提供。
然后在quick3.2版本中,framework本身的封装更复杂了,比如: function display.newLayer() return cc.Layer:create() end 那么这个cc.Layer是什么呢? 在quick/lib/lua_bindings/auto/lua_cocos2dx_auto.cpp中:
int lua_cocos2dx_Layer_create(lua_State* tolua_S)
{
int argc = 0;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.Layer",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(tolua_S) - 1;
if (argc == 0)
{
if(!ok)
return 0;
cocos2d::Layer* ret = cocos2d::Layer::create();
object_to_luaval(tolua_S, "cc.Layer",(cocos2d::Layer*)ret);
return 1;
}
CCLOG("%s has wrong number of arguments: %d, was expecting %d\n ", "create",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Layer_create'.",&tolua_err);
#endif
return 0;
}
那么可以看到,创建的是cocos2d::Layer
在cocos2d.h中引入了cocos2d所有的c++代码。
core中提供data存储/config配置 push中提供消息推送 analytics中提供统计展示 按照document中说的去做就可以。
比如首页中的操作按钮等这些信息都可以作为config在parse中配置: 在lua中通过parse.lua中的getStringConfig(key)等三个get方法来获取。
统计也可以在parse中方便的统计,需要在代码中进行打点:Parse.trackEvent(‘ClickOperate’, {target = name})
另外,对于config,lua中放默认值,以免用户网络不好的情况下取不到数据。然后最新的数据可以从parse中getStringConfig(“OperateList”)获取。
应用初始化的时候parse用户登录,如果登陆了说明是个原来有的用户(可能是匿名的也可能是实名的,其实两者没有本质区别,都有parseuserid)。 如果登陆了parse,然后看是否在ifun中注册过,如果注册过就通过parseuserid去parse中获取name/email再去ifun中login。 如果没有注册过,就去ifun中signup,name/email通过parseuserid构造。
如果没有登录parse,就构造匿名用户登录parse,这样在parse的user表中就有了一条记录,然后就可以获取到parseuserid,然后同样的用它来构造name/email去ifun中signup(signup之后都自动login了)。
chrome中的getpost工具
整个应用的入口是wallet.onCreate(java)—> SPHelper.init(java)—> 开始load lua代码,入口是MyApp.run(lua)—> SPHelper.init(lua)—> SPHelper.initWithOptions(java)并且这里会指出如果积分墙被点击了需要回调的lua方法是谁(这个会在第3步被调用)
当界面中的list item被点击时,会触发SPHelper.showOfferwall(lua),然后它会调用SPHelper.showSponsorPay(java)起一个ui线程显示出积分墙。
当积分墙中的项目被点击实现后,触发java中的listener,然后调用lua中第1步中提到的回调方法
在分析这个流程的时候,要注意一点是,积分墙界面是java sdk所以是java环境,其他界面是lua环境,所以存在java和lua跳来跳去的情况。
-EOF-