這篇文章將為大家詳細(xì)講解有關(guān)cocos2d-x中回調(diào)函數(shù)的按鍵回調(diào)是怎樣的,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
目前創(chuàng)新互聯(lián)公司已為上千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、西青網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
回調(diào)函數(shù)是界面交互和接入各種第三方SDK的關(guān)鍵所在,因?yàn)榛卣{(diào)函數(shù)的C++代碼是不能自動(dòng)生成的,一切的一切,都需要手寫完成。
比較不錯(cuò)的是,Cocos2d-x引擎對(duì)于回調(diào)函數(shù)提供了完整的包裝機(jī)制。我們所需要做的就是了解這個(gè)機(jī)制,并使用他。學(xué)習(xí)引擎自己的代碼例子,可以比較快速準(zhǔn)確的上手這一機(jī)制。
首先,我們?cè)贑ocos2d-x 3.0 beta版中,使用他自帶的工程創(chuàng)建工具,新建一個(gè)跨平臺(tái)的JS項(xiàng)目。按照慣例,這是一個(gè)helloworld項(xiàng)目。在XCode運(yùn)行時(shí),我們可以看到右下角的回調(diào)按鈕。我們來(lái)看看他是怎么實(shí)現(xiàn)的。分成兩個(gè)過(guò)程來(lái)做:
一、綁定回調(diào)函數(shù)過(guò)程
首先,我們要去找回調(diào)函數(shù)JS的綁定代碼,在myApp.js中,init函數(shù)里面,可以看到如下代碼:
1 2 3 4 5 6 7 8 9 10 11 12 | // var closeItem "res/CloseNormal.png" , "res/CloseSelected.png" , function () cc.log( "close ); }, this ); closeItem.setAnchorPoint(cc.p(0.5, var menu menu.setPosition(cc.p(0, this .addChild(menu, closeItem.setPosition(cc.p(size.width |
cc.MenuItemImage.create函數(shù)的第三個(gè)參數(shù),綁定了匿名回調(diào)函數(shù)。第四個(gè)參數(shù),傳入的是回調(diào)函數(shù)調(diào)用時(shí)的this(如果不理解JS的this機(jī)制,請(qǐng)先閱讀一些JS的資料)。這些都是意圖和作用很明顯的JS代碼,不用細(xì)說(shuō)。
然后,我們?nèi)タ吹讓訉?duì)應(yīng)執(zhí)行的C++代碼。在cocos2d_specifics.cpp文件中,找到j(luò)s_cocos2dx_CCMenuItemImage_create函數(shù)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | // // JSBool { if (argc jsval JSStringWrapper JSStringWrapper JSStringWrapper bool thirdArgIsString true ; jsval jsval int last if (argc thirdArgIsString if (thirdArgIsString) arg2.set(argv[2], last } } cocos2d::MenuItemImage* if (argc if (!thirdArgIsString) //cc.MenuItemImage.create( jsCallback if (argc jsThis } } else { //cc.MenuItemImage.create( if (argc jsCallback if (argc jsThis } } } } JSObject JS_SET_RVAL(cx, return JS_TRUE; } JS_ReportError(cx, "Invalid ); return JS_FALSE; } |
因?yàn)樵贑++層,這是一個(gè)重載過(guò)的函數(shù),所以他的實(shí)現(xiàn)里面有很多參數(shù)個(gè)數(shù)的判斷(關(guān)于重載問(wèn)題請(qǐng)參考之前的章節(jié))。過(guò)濾掉很多代碼,我們直接看關(guān)鍵部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if (argc if (!thirdArgIsString) //cc.MenuItemImage.create( jsCallback if (argc jsThis } } else { //cc.MenuItemImage.create( if (argc jsCallback if (argc jsThis } } } } |
在這里我們從參數(shù)中取出回調(diào)函數(shù)和this,分別賦值給jsCallback和jsThis。
1 | JSObject |
由這句模板函數(shù)來(lái)實(shí)現(xiàn)回調(diào)的綁定,四個(gè)參數(shù)依次是,JS上下文,cc.MenuItemImage對(duì)應(yīng)的C++對(duì)象,回調(diào)函數(shù),和回調(diào)函數(shù)調(diào)用時(shí)的this。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | template < class T> JSObject* js_proxy_t if (p) addCallBackAndThis(p->obj, return p->obj; } else { js_type_class_t assert (classType); JSObject // js_proxy_t JS_AddNamedObjectRoot(cx, typeid (*nativeObj).name()); addCallBackAndThis(tmp, return tmp; } } |
繼續(xù)看bind_menu_item的實(shí)現(xiàn)。簡(jiǎn)單說(shuō)一下,因?yàn)榻壎ǖ氖且粋€(gè)JS函數(shù),所以實(shí)際上,需要在SpiderMonkey里面做這個(gè)綁定操作。傳進(jìn)來(lái)的是一個(gè)C++對(duì)象(CCMenuItemImage類型),首先找到和這個(gè)C++對(duì)象對(duì)應(yīng)的JS對(duì)象。如果找不到,就新建立一個(gè)。然后通過(guò)函數(shù)addCallBackAndThis執(zhí)行綁定。
1 2 3 4 5 6 7 8 9 | static { if (callback ScriptingCore::getInstance()->setReservedSpot(0, } if (thisObj ScriptingCore::getInstance()->setReservedSpot(1, } } |
1 2 3 4 | JSBool JS_SetReservedSlot(obj, return JS_TRUE; } |
最終我們看到,存儲(chǔ)回調(diào)函數(shù)的方法是通過(guò)SpiderMonkey的ReservedSlot機(jī)制。0位存放的是回調(diào)函數(shù),1位存放的是回調(diào)函數(shù)對(duì)應(yīng)的this。
好,到此為止,回調(diào)函數(shù)的綁定全部結(jié)束。
二、調(diào)用回調(diào)函數(shù)過(guò)程
現(xiàn)在我們看從C++層啟動(dòng)JS回調(diào)的過(guò)程。我們省略掉事件派發(fā)機(jī)制,直接看按鍵事件發(fā)生時(shí)的調(diào)用代碼。在按鍵事件發(fā)生時(shí),會(huì)調(diào)用MenuItemImage的父類MenuItem中的activate函數(shù)。該函數(shù)在CCMenuItem.cpp中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | void MenuItem::activate() { if (_enabled) { if ( { _callback( this ); } if (kScriptTypeNone { BasicScriptData this ); ScriptEvent ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent); } } } |
非常簡(jiǎn)單,首先判斷按鍵是否可用。然后如果有C++層回調(diào)就調(diào)用。如果有腳本層(JS或lua)回調(diào),就包裝一個(gè)kMenuClickedEvent事件,然后向?qū)?yīng)的腳本引擎發(fā)送該事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | int { if (NULL return 0; JSAutoCompartment switch (evt->type) { case kNodeEvent: { return handleNodeEvent(evt->data); } break ; case kMenuClickedEvent: { return handleMenuClickedEvent(evt->data); } break ; case kTouchEvent: { return handleTouchEvent(evt->data); } break ; case kTouchesEvent: { return handleTouchesEvent(evt->data); } break ; case kKeypadEvent: { return handleKeypadEvent(evt->data); } break ; case kAccelerometerEvent: { return handleAccelerometerEvent(evt->data); } break ; default : break ; } return 0; } |
JS通過(guò)ScriptingCore::sendEvent進(jìn)行事件分發(fā)。kMenuClickedEvent事件派發(fā)給handleMenuClickedEvent函數(shù)來(lái)處理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | int { if (NULL return 0; BasicScriptData* if (NULL return 0; MenuItem* js_proxy_t if (!p) return 0; jsval jsval js_proxy_t dataVal executeJSFunctionFromReservedSpot( this ->_cx, return 1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | static void executeJSFunctionFromReservedSpot(JSContext jsval jsval if (func return ; jsval JSAutoCompartment if (thisObj JS_CallFunctionValue(cx, } else { assert (!JSVAL_IS_PRIMITIVE(thisObj)); JS_CallFunctionValue(cx, } } |
再次通過(guò)SpiderMonkey的ReservedSlot機(jī)制,取回相應(yīng)的參數(shù),最后通過(guò)JS_CallFunctionValue函數(shù)完成JS層回調(diào)函數(shù)的調(diào)用。
關(guān)于cocos2d-x中回調(diào)函數(shù)的按鍵回調(diào)是怎樣的就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
當(dāng)前標(biāo)題:如何通過(guò)JS_CallFunctionValue函數(shù)完成JS層回調(diào)函數(shù)的調(diào)用。
分享地址:http://m.newbst.com/article8/jeehop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)公司、標(biāo)簽優(yōu)化、動(dòng)態(tài)網(wǎng)站、品牌網(wǎng)站制作、定制開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
營(yíng)銷型網(wǎng)站建設(shè)知識(shí)