Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

「釣り★スタ」でのCocos2d-JSを使ってのアプリアップデート事例 (1)

5,874 views

Published on

Cocos2d-x Talks #2(2015/3/13)発表資料
https://atnd.org/events/62594

グリー株式会社 Wright Flyer Studios部 中 貴弘
グリー株式会社 Web Game Studio部 / 釣りスタグループ 和田孝尚

日本最初のモバイルソーシャルゲームである「釣り★スタ」
フィーチャーフォンの時代から存在するゲームをCocos2d-JSを使ってのアプリ作成。
既に稼働中のサービスに対して行うアプリアップデート、その中で一番重視したことは実現できたのか。実際にプレイしたユーザからの反応等も交えて開発の事例を紹介できればと思います。

Published in: Technology
  • Login to see the comments

「釣り★スタ」でのCocos2d-JSを使ってのアプリアップデート事例 (1)

  1. 1. 釣り★スタ グリー株式会社 Web Game Studio部 釣りスタグループ 和田孝尚 COCOS2D-JS アプリアップデート事例 GL verts: 36 GL calls: 6 57.91 / 0.003
  2. 2. 和田孝尚 ショウカイ エンジニア アプリ実装を主に担当 レベル:  38  HP: 166  MP:  63 2011年 グリー入社 2013年 釣り★スタチームへ これが初のCOCOS2D-X GL verts: 192 GL calls: 8 57.82 / 0.004
  3. 3. 釣り★スタ GL verts: 6 GL calls: 1 60.00 / 0.004
  4. 4. • 釣り★スタ 2007年5月サービス開始 セツメイ • 世界初のモバイルソーシャルゲーム • アプリは2011年から提供 GL verts: 66 GL calls: 3 59.94 / 0.004
  5. 5. ガメン GL verts: 18 GL calls: 3 58.81 / 0.008
  6. 6. ギモン ブラウザゲームじゃないの? GL verts: 12 GL calls: 2 58.65 / 0.002
  7. 7. • HTMLやらFlashLiteで構成 レキシ • SP対応時当初はHTML5(Canvasとか) • 2013年後半LWFに対応 GL verts: 72 GL calls: 4 59.71 / 0.008 ※LWF(LightWeightSWF)とはGREEが開発しているオープンソース(zlib License)のフレームワークです。
  8. 8. ケツロン WebViewの限界 GL verts: 12 GL calls: 2 59.58 / 0.004
  9. 9. ケンショウ GL verts: 18 GL calls: 3 58.65 / 0.009
  10. 10. • 一部機種でタップ遅延が発生する チョウサ • アニメーション再生は許容範囲 • 釣りはアクションゲーム GL verts: 66 GL calls: 3 59.94 / 0.007
  11. 11. モクヒョウ すべてのユーザ に等しい体験を GL verts: 12 GL calls: 2 60.00 / 0.004
  12. 12. ならば GL verts: 6 GL calls: 1 59.98 / 0.006
  13. 13. ネイティブ化 GL verts: 6 GL calls: 1 59.24 / 0.005
  14. 14. • 基本はWebViewをベース ヨウキュウ • Android2.2以上 / iOS4.3以上 • 端末間の差が発生しにくい GL verts: 66 GL calls: 3 59.94 / 0.009
  15. 15. 選ばれたのは GL verts: 6 GL calls: 1 59.24 / 0.006
  16. 16. COCOS2D-JS GL verts: 6 GL calls: 1 58.79 / 0.006
  17. 17. • 2系なら対象OSは問題無し ジョウキョウ • 3系だと一部切り捨て(当時β • GREE-SDK非対応 作るしかない GL verts: 66 GL calls: 3 57.56 / 0.007
  18. 18. ヨウキュウ サポート範囲 は既存のまま GL verts: 12 GL calls: 2 59.62 / 0.004
  19. 19. • COCOS2D-X 2.2系を採用 サイヨウ • COCOS2D-X 3系以降は独立する • リソース更新で無限の可能性 GL verts: 66 GL calls: 3 57.46 / 0.008
  20. 20. • UI周りはCOCOS2D-JS コウセイ • 固有の処理はJavaScriptBinding • GREE-SDKをJavaScriptから制御 GL verts: 66 GL calls: 3 58.13 / 0.004
  21. 21. カンケイ COCOS2D-JS JavaScriptJSB Objective-C iOS Android JavaC++ COCOS2D-X Library GREE-SDK JSB GL verts: 510 GL calls: 15 59.04 / 0.011
  22. 22. 画面を作ろう GL verts: 6 GL calls: 1 59.24 / 0.006
  23. 23. • 背景等は固定画像 ガメン • アイテム類は可変画像 • フルスクリーン表示 GL verts: 72 GL calls: 4 58.16 / 0.008
  24. 24. ガゾウ var bgLayer = cc.Sprite.create("RaidBattle/bgselect.jpg"); bgLayer.setPosition( cc.p(layerSize.width*.5, layerSize.width*.5)); this.addChild(bgLayer); • Sprite(CCSprite)で画像表示 • 1枚画像なんかは 基本これのみ • リソースパス等あれば初期化時に設定する GL verts: 126 GL calls: 5 57.89 / 0.009
  25. 25. GL verts: 72 GL calls: 4 57.56 / 0.007 ギョエイ • DrawNode(CCDrawNode)を利用してみてる • 図形描画でアニメーション等検討 • ゲーム中の標的でアニメーションが必要
  26. 26. シヨウ JS_FN("drawDot", js_cocos2dx_CCDrawNode_drawDot, 3, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("drawSegment", js_cocos2dx_CCDrawNode_drawSegment, 4, JSPROP_PERMANENT | JSPROP_ENUMERATE), • 2系だと描画命令が少ない • 3系だともう少し増える • 2系と3系で機能が違うものも多々ある GL verts: 126 GL calls: 5 57.56 / 0.006
  27. 27. タイオウ JS_FN("drawDot", js_cocos2dx_CCDrawNode_drawDot, 3, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("drawSegment", js_cocos2dx_CCDrawNode_drawSegment, 4, JSPROP_PERMANENT | JSPROP_ENUMERATE), • 2系だと描画命令が少ない • 3系だともう少し増える • 2系と3系で機能が違うものも多々ある var fishSp = cc.Sprite.create("RaidBattle/fish_sprite.png"); var fishBody = cc.Sprite.create(); var animeCache = cc.AnimationCache.getInstance(); var fishAnime = animeCache.getAnimation("raidfish"); if(fishAnime == null){ var fish1 = cc.SpriteFrame.createWithTexture( fishSp.getTexture(), cc.rect(0, 0, 200, 100)); var fish2 = cc.SpriteFrame.createWithTexture( fishSp.getTexture(), cc.rect(0, 100, 200, 100)); var animFrames = []; animFrames.push(fish1); animFrames.push(fish2); fishAnime = cc.Animation.create(animFrames, 0.05); animeCache.addAnimation(fishAnime, "raidfish"); } fishBody.runAction( cc.RepeatForever.create(cc.Animate.create(fishAnime))); GL verts: 186 GL calls: 7 57.94 / 0.008
  28. 28. JS_FN("drawDot", js_cocos2dx_CCDrawNode_drawDot, 3, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("drawSegment", js_cocos2dx_CCDrawNode_drawSegment, 4, JSPROP_PERMANENT | JSPROP_ENUMERATE), • 2系だと描画命令が少ない • 3系だともう少し増える • 2系と3系で機能が違うものも多々ある var fishSp = cc.Sprite.create("RaidBattle/fish_sprite.png"); var fishBody = cc.Sprite.create(); var animeCache = cc.AnimationCache.getInstance(); var fishAnime = animeCache.getAnimation("raidfish"); if(fishAnime == null){ var fish1 = cc.SpriteFrame.createWithTexture( fishSp.getTexture(), cc.rect(0, 0, 200, 100)); var fish2 = cc.SpriteFrame.createWithTexture( fishSp.getTexture(), cc.rect(0, 100, 200, 100)); var animFrames = []; animFrames.push(fish1); animFrames.push(fish2); fishAnime = cc.Animation.create(animFrames, 0.05); animeCache.addAnimation(fishAnime, "raidfish"); } fishBody.runAction( cc.RepeatForever.create(cc.Animate.create(fishAnime))); ヨウテン • Animation(CCAnimation)やAction類の利用 • 1画面内で使う画像などは1枚にまとめる • 既存の素材を再編集して使い回し GL verts: 246 GL calls: 8 58.23 / 0.014
  29. 29. モジ GL verts: 12 GL calls: 2 58.61 / 0.009
  30. 30. テイギ common lineHeight=32 base=0 scaleW=1 scaleH=1 pages=1 packed=0 page id=0 file="raid_font.png" chars count=28 char id=48 x=5 y=0 width=50 height=64 xoffset=0 yoffset=0 xadvance=50 page=0 chnl=0 // 0 (中略) char id=19975 x=192 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 万 char id=33021 x=256 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 能 GL verts: 66 GL calls: 3 59.02 / 0.007
  31. 31. リヨウ common lineHeight=32 base=0 scaleW=1 scaleH=1 pages=1 packed=0 page id=0 file="raid_font.png" chars count=28 char id=48 x=5 y=0 width=50 height=64 xoffset=0 yoffset=0 xadvance=50 page=0 chnl=0 // 0 (中略) char id=19975 x=192 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 万 char id=33021 x=256 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 能 var rod_status = cc.LabelBMFont.create(“万能","raid_font.fnt"); rod_status.setPosition(cc.p(160, 365)); rod_status.setZOrder(1); this.addChild(rod_status); GL verts: 126 GL calls: 4 58.59 / 0.007
  32. 32. ヨウテン common lineHeight=32 base=0 scaleW=1 scaleH=1 pages=1 packed=0 page id=0 file="raid_font.png" chars count=28 char id=48 x=5 y=0 width=50 height=64 xoffset=0 yoffset=0 xadvance=50 page=0 chnl=0 // 0 (中略) char id=19975 x=192 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 万 char id=33021 x=256 y=192 width=64 height=64 xoffset=0 yoffset=0 xadvance=64 page=0 chnl=0 // 能 • LabelBMFont(CCLabelBMFont)を利用 • 子要素にアクセスして文字列アニメ等 • 白色で作ると色変更なんかも可能 GL verts: 186 GL calls: 6 58.84 / 0.006
  33. 33. • 背景等は固定画像 ドウグ • アイテム類は可変画像 • フルスクリーン表示 ユーザ所持アイテム イベント毎に増加 GL verts: 138 GL calls: 7 58.44 / 0.010
  34. 34. • 背景等は固定画像 ハイケイ • アイテム類は可変画像 • フルスクリーン表示 ユーザ所持アイテム イベント毎に増加 • アイテムの所持状態に左右される • 総量がかなりの量、7年以上の物量 • 全てをダウンロードするには不向き GL verts: 198 GL calls: 8 59.32 / 0.012
  35. 35. シンジツ JS側にオンラインで 画像取得の手段なし GL verts: 12 GL calls: 2 59.12 / 0.006
  36. 36. チョウサ • XMLHttpRequestとかはある • 扱えてもテキスト程度(エラーを返さない • あらかじめ内包する手段もあるが… GL verts: 66 GL calls: 3 59.37 / 0.004
  37. 37. チョウセン ないなら作れ GL verts: 66 GL calls: 3 59.42 / 0.005
  38. 38. ジッソウ JavaScript-Binding GL verts: 66 GL calls: 3 59.41 / 0.005
  39. 39. テイギ JSClass js_class = { "ImageLoader", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, basic_object_finalize, JSCLASS_NO_OPTIONAL_MEMBERS }; DownloadResource::js_class = js_class • JavaScript側でのクラス定義 • 基本は既存クラスの処理を真似すればいい GL verts: 126 GL calls: 5 57.74 / 0.007
  40. 40. テイギ • JavaScript側でのクラス定義 • 基本は既存クラスの同類の処理を真似Property,function,static_functionの定義 static JSPropertySpec props[] = { {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; static JSFunctionSpec funcs[] = { JS_BINDED_FUNC_FOR_DEF(ImageLoader, loadURL), JS_FS_END }; static JSFunctionSpec st_funcs[] = { JS_FS_END }; GL verts: 246 GL calls: 7 57.98 / 0.006
  41. 41. テイギ static JSPropertySpec props[] = { {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; static JSFunctionSpec funcs[] = { JS_BINDED_FUNC_FOR_DEF(ImageLoader, loadURL), JS_FS_END }; static JSFunctionSpec st_funcs[] = { JS_FS_END }; ImageLoader::js_parent = NULL; ImageLoader::js_proto = JS_InitClass(cx, global, NULL, &ImageLoader::js_class , ImageLoader::_js_constructor, 0, props, funcs, NULL, st_funcs); • 既存クラスの継承等も可能 • サンプル類は豊富にあるので読んで理解 • 2系と3系で微妙に違うので注意 GL verts: 366 GL calls: 9 57.98 / 0.006
  42. 42. テイギ JS_BINDED_CONSTRUCTOR_IMPL(ImageLoader) { ImageLoader* pAuthorizer = new ImageLoader(); pAuthorizer->autorelease(); js_proxy_t *p; jsval out; JSObject *obj = JS_NewObject(cx, &ImageLoader::js_class, ImageLoader::js_proto, ImageLoader::js_parent); if (obj) { JS_SetPrivate(obj, pAuthorizer); out = OBJECT_TO_JSVAL(obj); } JS_SET_RVAL(cx, vp, out); p =jsb_new_proxy(pAuthorizer, obj); JS_AddNamedObjectRoot(cx, &p->obj, "ImageLoader"); return JS_TRUE; } GL verts: 66 GL calls: 3 58.24 / 0.007
  43. 43. JS_BINDED_CONSTRUCTOR_IMPL(ImageLoader) { ImageLoader* pAuthorizer = new ImageLoader(); pAuthorizer->autorelease(); js_proxy_t *p; jsval out; JSObject *obj = JS_NewObject(cx, &ImageLoader::js_class, ImageLoader::js_proto, ImageLoader::js_parent); if (obj) { JS_SetPrivate(obj, pAuthorizer); out = OBJECT_TO_JSVAL(obj); } JS_SET_RVAL(cx, vp, out); p =jsb_new_proxy(pAuthorizer, obj); JS_AddNamedObjectRoot(cx, &p->obj, "ImageLoader"); return JS_TRUE; } テイギ var imageLoader = new ImageLoader(); JavaScript GL verts: 132 GL calls: 5 58.32 / 0.006
  44. 44. テイギ JS_BINDED_FUNC_IMPL(ImageLoader, loadURL) { jsval *arg = JS_ARGV(cx, vp); if (argc == 1) { JSStringWrapper arg0(arg[0]); CCHttpReqest *request = new CCHttpRequest(); request->setUrl(arg0.c_str()); request->setRequestType(CCHttpRequest::kHttpGet); request->setResponseCallback(this, httpresponse_selector(ImageLoader::onLoadCompleted)); CCHttpClient::getInstance()->send(request); request->release(); return JS_TRUE; } return JS_FALSE; } GL verts: 66 GL calls: 3 58.27 / 0.007
  45. 45. テイギ JS_BINDED_FUNC_IMPL(ImageLoader, loadURL) { jsval *arg = JS_ARGV(cx, vp); if (argc == 1) { JSStringWrapper arg0(arg[0]); CCHttpReqest *request = new CCHttpRequest(); request->setUrl(arg0.c_str()); request->setRequestType(CCHttpRequest::kHttpGet); request->setResponseCallback(this, httpresponse_selector(ImageLoader::onLoadCompleted)); CCHttpClient::getInstance()->send(request); request->release(); return JS_TRUE; } return JS_FALSE; } var imageLoader = new ImageLoader(); imageLoader.loadURL(“http://xxx.com/test.png”); JavaScript GL verts: 132 GL calls: 5 58.26 / 0.008
  46. 46. テイギ void ImageLoader::onLoadCompleted(CCHttpClient *client, CCHttpResponse *response) { if (!response->isSucceed()) {return;} std::vector<char> *buffer = response->getResponseData(); CCImage *image = new CCImage(); image->initWithImageData(&(buffer->front()), buffer->size()); /* ~responseから画像生成後~ */ js_proxy_t* p = jsb_get_native_proxy(this); JSContext* cx = ScriptingCore::getInstance()->getGlobalContext(); js_proxy_t *sp = js_get_or_create_proxy<cocos2d::CCTexture2D>(cx, texture); jsval retval; jsval v[] = { v[0] = OBJECT_TO_JSVAL(sp->obj) }; ScriptingCore::getInstance()->executeFunctionWithOwner( OBJECT_TO_JSVAL(p->obj),"imageRequestComplete", 1, v, &retval); image->release(); } GL verts: 66 GL calls: 3 57.97 / 0.004
  47. 47. テイギ void ImageLoader::onLoadCompleted(CCHttpClient *client, CCHttpResponse *response) { if (!response->isSucceed()) {return;} std::vector<char> *buffer = response->getResponseData(); CCImage *image = new CCImage(); image->initWithImageData(&(buffer->front()), buffer->size()); /* ~responseから画像生成後~ */ js_proxy_t* p = jsb_get_native_proxy(this); JSContext* cx = ScriptingCore::getInstance()->getGlobalContext(); js_proxy_t *sp = js_get_or_create_proxy<cocos2d::CCTexture2D>(cx, texture); jsval retval; jsval v[] = { v[0] = OBJECT_TO_JSVAL(sp->obj) }; ScriptingCore::getInstance()->executeFunctionWithOwner( OBJECT_TO_JSVAL(p->obj),"imageRequestComplete", 1, v, &retval); image->release(); } var imageLoader = new ImageLoader(); imageLoader.imageRequestComplete = function(texture) { var t = texture.getContentSize() var loadSprite = getXXXXImageSprite(); loadSprite.setTexture(texture); loadSprite.setTextureRect( cc.rect(0, 0, t.width, t.height)); } imageLoader.loadURL(“http://xxx.com/test.png”); JavaScript GL verts: 132 GL calls: 5 57.75 / 0.005
  48. 48. ホウコク • 基本クラスのJSB見るのが理解早い • Callbackは関数定義のほうが見やすいかも • COCOS2D-X内で完結するものは比較的楽 GL verts: 66 GL calls: 3 58.13 / 0.006
  49. 49. • 背景等は固定画像 ザヒョウ • アイテム類は可変画像 • フルスクリーン表示 基本的にフルスクリーン 高さ分表示を調整したい 基本処理には存在しない GL verts: 138 GL calls: 7 58.31 / 0.011
  50. 50. テイギ float CCDeviceInfo::getStausBarHeight(){ CGRect statusBarRect = [UIApplication sharedApplication].statusBarFrame; CGFloat statusBarHeight = statusBarRect.size.height > statusBarRect.size.width ? statusBarRect.size.width : statusBarRect.size.height; return statusBarHeight; } iOS public static int getStausBarHeight(){ return 0; } Java GL verts: 84 GL calls: 6 58.83 / 0.009
  51. 51. テイギ float CCDeviceInfo::getStausBarHeight(){ CGRect statusBarRect = [UIApplication sharedApplication].statusBarFrame; CGFloat statusBarHeight = statusBarRect.size.height > statusBarRect.size.width ? statusBarRect.size.width : statusBarRect.size.height; return statusBarHeight; } iOS public static int getStausBarHeight(){ return 0; } Java • iOSなら拡張子*.mmにしてC++とObj-C併用 • AndroidはJNI利用して呼び出し GL verts: 144 GL calls: 8 58.82 / 0.007
  52. 52. テイギ CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); CCSize frameSize = pEGLView->getFrameSize(); pDirector->setContentScaleFactor(frameSize.width/320); cocos2d::CCEGLView::sharedOpenGLView()->setDesignResolutionSize( 320, 480, kResolutionFixedWidth); AppDelegate.cpp • 利用する画像の基準でScaleを指定 • 固定サイズで調整するのが簡単(320,480) GL verts: 132 GL calls: 6 58.79 / 0.006
  53. 53. テイギ CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); CCSize frameSize = pEGLView->getFrameSize(); pDirector->setContentScaleFactor(frameSize.width/320); cocos2d::CCEGLView::sharedOpenGLView()->setDesignResolutionSize( 320, 480, kResolutionFixedWidth); AppDelegate.cpp • 利用する画像の基準でScaleを指定 • 固定サイズで調整するのが簡単(320,480) var imgScale = 1/imgDirector.getContentScaleFactor(); var scaleSize = cc.rect(x*imgScale, y*imgScale, width*imgScale, height*imgScale); createWithTexture等:Retina(x2)想定 var imgScale = imgDirector.getContentScaleFactor()/2; imageSprite.setScale(imgScale); Sprite等:Retina(x2)想定 GL verts: 266 GL calls: 10 58.79 / 0.006
  54. 54. イショク GL verts: 12 GL calls: 2 59.33 / 0.006
  55. 55. イショク どうやって移植するの? 目コピで! 無理理に決まってんだろ! GL verts: 90 GL calls: 7 59.65 / 0.005
  56. 56. イショク どうやって移植するの? 目コピで! 無理理に決まってんだろ! • どうせなら新しい作り方に挑戦したい • Flasherさんとかでも扱いやすい環境 • 開発側でも調整ができるように GL verts: 150 GL calls: 9 59.36 / 0.006
  57. 57. コウホ GL verts: 12 GL calls: 2 59.82 / 0.006
  58. 58. コウホ CocosBuilder • Flash風味なインタフェース • アニメーションの細かい制御できない • COCOS2D-JS用の出力が可能 GL verts: 78 GL calls: 5 59.82 / 0.006
  59. 59. コウホ CocosBuilder • Flash風味…か • アニメーションの細かい制御できない • COCOS2D-JS用の出力が可能 公開停止 死亡確認 GL verts: 138 GL calls: 6 59.73 / 0.006
  60. 60. コウホ GL verts: 12 GL calls: 2 59.81 / 0.008
  61. 61. コウホ SpriteBuilder • CocosBuilderの後継? • 公開直後だったのかやたら不安定 • COCOS2D-JS用の出力不能 GL verts: 78 GL calls: 5 59.86 / 0.005
  62. 62. コウホ SpriteBuilder • CocosBuilderの後継? • 公開直後だったのかやたら不安定 • COCOS2D-JS用の出力不能 利用不能 死亡確認 GL verts: 138 GL calls: 6 59.28 / 0.006
  63. 63. コウホ GL verts: 12 GL calls: 2 58.63 / 0.007
  64. 64. コウホ CocoStudio • Windows用しかない • αとかβ • 公式だからアンシーン 利用不能 死亡確認 GL verts: 138 GL calls: 6 59.14 / 0.006
  65. 65. イショク JavaScriptのコードを移植 GL verts: 72 GL calls: 4 59.68 / 0.007
  66. 66. イショク • 相性もあるけど比較的楽な形式だった • アニメーションの計算なんかもそのまま • 旧:30FPS >> 新:60FPS GL verts: 72 GL calls: 4 59.43 / 0.008
  67. 67. サクセイ GL verts: 12 GL calls: 2 58.99 / 0.008
  68. 68. サクセイ 動作が早すぎて無理ゲー GL verts: 72 GL calls: 4 59.44 / 0.007
  69. 69. サクセイ • 全く処理落ちしないので想定より早い • 旧処理と操作回数、ゲーム結果の比較 • 原作のFLasherさんに微調整依頼 GL verts: 72 GL calls: 4 59.42 / 0.007
  70. 70. カンセイ • ひたすら動作確認の日々 • QA実施「もう過去に戻れない」と評価 • 別イベントとして作成して新旧を比較 GL verts: 72 GL calls: 4 59.62 / 0.008
  71. 71. コウカイ まずはAndroid先行 GL verts: 72 GL calls: 4 59.81 / 0.008
  72. 72. コウカイ プレイ後にアンケートを実施 GL verts: 72 GL calls: 4 59.83 / 0.007
  73. 73. シュウケイ プレイ後にアンケートを実施 GL verts: 78 GL calls: 5 59.77 / 0.008 秘境島=COCOS2D-JS 大イカ=LWF
  74. 74. シュウケイ プレイ後にアンケートを実施 GL verts: 78 GL calls: 5 59.68 / 0.007 秘境島=COCOS2D-JS 大イカ=LWF
  75. 75. シュウケイ • 魚の速度は明らかにCOCOS2D-JS • 遊びやすさは僅差でCOCOS2D-JS • 結果のスコアなどは比較的均一化された GL verts: 78 GL calls: 5 59.64 / 0.006
  76. 76. ルイジ iOS版のアンケートもほぼ同じ結果 GL verts: 72 GL calls: 4 59.56 / 0.007
  77. 77. • 処理上の目標は達成できた カンソウ • 今後の処理にも期待が持てる • 新バージョン(3系)も使えそう GL verts: 66 GL calls: 3 58.68 / 0.006
  78. 78. END GL verts: 6 GL calls: 1 58.59 / 0.005
  79. 79. END GL verts: 6 GL calls: 1 58.99 / 0.005
  80. 80. 危険がヤバイ GL verts: 6 GL calls: 1 59.45 / 0.005
  81. 81. カイシ bool AppDelegate::applicationDidFinishLaunching() { // initialize director CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); // turn on display FPS pDirector->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this pDirector->setAnimationInterval(1.0 / 60); ScriptingCore* sc = ScriptingCore::getInstance(); /* ~省略~ */ sc->start(); CCScriptEngineProtocol *pEngine = ScriptingCore::getInstance(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); ScriptingCore::getInstance()->runScript("cocos2d-jsb.js"); return true; } GL verts: 66 GL calls: 3 59.47 / 0.005
  82. 82. bool AppDelegate::applicationDidFinishLaunching() { // initialize director CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); // turn on display FPS pDirector->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this pDirector->setAnimationInterval(1.0 / 60); ScriptingCore* sc = ScriptingCore::getInstance(); /* ~省略~ */ sc->start(); CCScriptEngineProtocol *pEngine = ScriptingCore::getInstance(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); ScriptingCore::getInstance()->runScript("cocos2d-jsb.js"); return true; } カイセキ • JS自体はアプリ内に存在 • runScriptから処理を開始 • 難読化しても読もうと思えば読める GL verts: 126 GL calls: 5 59.78 / 0.005
  83. 83. bool AppDelegate::applicationDidFinishLaunching() { // initialize director CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); // turn on display FPS pDirector->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this pDirector->setAnimationInterval(1.0 / 60); ScriptingCore* sc = ScriptingCore::getInstance(); /* ~省略~ */ sc->start(); CCScriptEngineProtocol *pEngine = ScriptingCore::getInstance(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); ScriptingCore::getInstance()->runScript("cocos2d-jsb.js"); return true; } シボウ 書き換えも可能 GL verts: 126 GL calls: 5 59.25 / 0.005
  84. 84. タイサク 起動時 • 更新頻度低いもの含めてチェック • ファイルのハッシュ値比較 • 問題なければJS実行 GL verts: 72 GL calls: 4 59.16 / 0.006
  85. 85. タイサク 起動時 • 更新頻度低いもの含めてチェック • ファイルのハッシュ値比較 • 問題なければJS実行 通常時 • その時点で必要なもののみチェック • ファイルのハッシュ値比較 • 更新があればスクリプト再起動 GL verts: 138 GL calls: 6 59.07 / 0.006
  86. 86. ソウカツ • 基本はHTMLと同じでJSのソースは丸見え • 見せたくないものはJSB等で隠蔽 • JavaScript上のエラー等も考慮して実装 • デバッグは…習うより慣れろ GL verts: 66 GL calls: 3 58.87 / 0.005
  87. 87. CONTINUE? GL verts: 6 GL calls: 1 58.62 / 0.006
  88. 88. COCOS2D-JS3.3 GL verts: 6 GL calls: 1 59.14 / 0.006
  89. 89. カンキョウ GL verts: 18 GL calls: 3 59.11 / 0.007
  90. 90. ベンリ • Cocos Code IDEでデバッグ実行 • Cocos StudioでUIやアニメーション作成 • Runtimeパス指定で、JSB等の実装もカバー GL verts: 78 GL calls: 5 59.48 / 0.007
  91. 91. ジッコウ • Cocos Code IDEでデバッグ実行 • Cocos StudioでUIやアニメーション作成 • Runtimeパス指定で、JSB等の実装もカバー >cocos run -p web GL verts: 138 GL calls: 7 59.65 / 0.007
  92. 92. ドウサ GL verts: 12 GL calls: 2 59.58 / 0.006
  93. 93. カンキョウ • 動作はそこまで軽くないが確認には十分 • Chrome等ブラウザから確認可能 • 2系のコードほぼそのまま使える GL verts: 72 GL calls: 4 59.53 / 0.006
  94. 94. ヘンコウ var direvtor = cc.Director.getInstance(); var color_a = cc.c4b(0, 0, 0, 255); var color_b = cc.BLACK; var sp_test = cc.Sprite.create(“test.png”); var direvtor = cc.director; var color_a = cc.color(0, 0, 0, 255); var color_b = cc.color.BLACK; var sp_test = new cc.Sprite(“test.png”); Cocos2d-html5 v2.x Cocos2d-JS v3.x GL verts: 84 GL calls: 6 59.37 / 0.008
  95. 95. ヘンコウ var direvtor = cc.Director.getInstance(); var color_a = cc.c4b(0, 0, 0, 255); var color_b = cc.BLACK; var sp_test = cc.Sprite.create(“test.png”); var direvtor = cc.director; var color_a = cc.color(0, 0, 0, 255); var color_b = cc.color.BLACK; var sp_test = new cc.Sprite(“test.png”); Cocos2d-html5 v2.x Cocos2d-JS v3.x• Webもサポートするなら書き方注意 • 基本はそのまま • 旧記述のままだと挙動が変わるケースも GL verts: 144 GL calls: 8 59.48 / 0.008
  96. 96. ヘンコウ this.setTouchMode(cc.TOUCH_ONE_BY_ONE); this.setTouchEnabled(true); this.onTouchBegan = function( touch ) { /*~ TODO:Touch Event ~*/ } cc.eventManager.addListener(cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY_ONE, onTouchBegan:function (touches, event) { /*~ TODO:Touch Event ~*/ } }), this); Cocos2d-html5 v2.x Cocos2d-JS v3.x GL verts: 84 GL calls: 6 59.36 / 0.007
  97. 97. ヘンコウ this.setTouchMode(cc.TOUCH_ONE_BY_ONE); this.setTouchEnabled(true); this.onTouchBegan = function( touch ) { /*~ TODO:Touch Event ~*/ } cc.eventManager.addListener(cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY_ONE, onTouchBegan:function (touches, event) { /*~ TODO:Touch Event ~*/ } }), this); Cocos2d-html5 v2.x Cocos2d-JS v3.x• Touchイベントはcocos2d-xと同様の変更 • WebもやるならMouseイベントも設定 • サンプルにだいたい欲しい処理がある GL verts: 144 GL calls: 8 59.34 / 0.008
  98. 98. コンゴ • COCOS2D-JS自体のバージョンアップ • 開発効率を上げるためのツール導入 • 運用ノウハウの蓄積 GL verts: 66 GL calls: 3 59.82 / 0.008
  99. 99. END GL verts: 6 GL calls: 1 60.00 / 0.005

×