日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lua 使用 spine 的一些问题

發布時間:2025/4/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lua 使用 spine 的一些问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文轉自http://blog.csdn.net/dinko321/article/details/44176041

?

一、基本使用:

?

[plain]?view plaincopy
  • self.skeletonNode?=?sp.SkeletonAnimation:create("sptest/spineboy.json",?"sptest/spineboy.atlas",?0.3)??
  • ?self.skeletonNode:setAnimation(0,?"walk",?true)??
  • ???
  • ?self.skeletonNode:setMix("walk",?"jump",?0.2)??
  • ?self.skeletonNode:setMix("jump",?"run",?0.2)??
  • ???
  • ?self.skeletonNode:setAnimation(0,?"walk",?false)??
  • ?self.skeletonNode:addAnimation(0,?"hit",?false)??
  • ????
  • ?self.skeletonNode:setDebugBonesEnabled(true)??
  • ??
  • ?self.skeletonNode:registerSpineEventHandler(function?(event)??
  • ?????print(string.format("[spine]?%d?start:?%s",?event.trackIndex,event.animation))??
  • ?end,?sp.EventType.ANIMATION_START)??
  • ?

    ?

    1、一開始,要set一個animation,第一個參數是track(后面細說)。

    2、播放其他動畫是用add

    3、當set的動畫播放完畢停止之后(非循環),再add動畫是不會動的。

    4、mix 就是讓2個動畫直接的銜接更平滑,最后一個參數是過渡時間

    ?

    二、track的概念

    做音頻的有個概念,叫音軌,就是track,基本比如錄歌,有個主唱,有和聲,有吉他,有貝斯。那么把這些分別錄制,再一起放出來,就是一首歌,分別錄制的這些,就是一個個獨立的音軌,一起放出來就是我們最后聽到的歌曲。

    對比PS,這個概念叫圖層。

    所以其實可以把不同的動作放到不同的track中去做。

    ?

    三、回調中的處理以及bug

    1、回調

    正常情況下,都會對一個動畫的完結做一些處理。比如我需要的就是,當動作A完成后,播放動作C。基本寫法如下:

    ?

    [plain]?view plaincopy
  • self.skeletonNode:registerSpineEventHandler(function?(event)?????
  • ????if?event.animation?==?"hit"?then??
  • ????????print("======?hit?end?====")??
  • ????end??
  • end,?sp.EventType.ANIMATION_END)??
  • 現在的問題是,我需要skeletonNode才能播放這個動畫。怎么才能拿到這個skeletonNode,想當然的以為應該這么寫

    ?

    ?

    [plain]?view plaincopy
  • self.skeletonNode:registerSpineEventHandler(function?(event)??
  • ????if?event.animation?==?"hit"?then??
  • ????????self.skeletonNode:setAnimation(0,?"hit",?false)??
  • ????end????
  • end,?sp.EventType.ANIMATION_END)??
  • 試驗發現可行,但是依據是什么呢?追蹤發現,這個地方是調用的一個Cpp的綁定,找到lua_cocos2dx_spine_manual.cpp如下

    [cpp]?view plaincopy
  • int?tolua_Cocos2d_CCSkeletonAnimation_registerSpineEventHandler00(lua_State*?tolua_S)??
  • {??
  • ????{??
  • ????????LuaSkeletonAnimation*?self????=?(LuaSkeletonAnimation*)??tolua_tousertype(tolua_S,1,0);??
  • ????????if?(NULL?!=?self?)?{??
  • ????????????int?handler?=?(??toluafix_ref_function(tolua_S,2,0));??
  • ????????????spEventType?eventType?=?static_cast<spEventType>((int)tolua_tonumber(tolua_S,?3,?0));??
  • ??????????????
  • ????????????switch?(eventType)?{??
  • ????????????????case?spEventType::SP_ANIMATION_END:??
  • ????????????????????{??
  • ????????????????????????self->setEndListener([=](int?trackIndex){??
  • ????????????????????????????executeSpineEvent(self,?handler,?eventType,?trackIndex);??
  • ????????????????????????});??
  • ????????????????????????ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self,?handler,?ScriptHandlerMgr::HandlerType::EVENT_SPINE_ANIMATION_END);??
  • ????????????????????}??
  • ????????????????????break;??
  • ????????????????default:??
  • ????????????????????break;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • 代碼舍棄了一些無關緊要的細節。然后就會發現,這里取了3個值,一個是self,一個是handler,就是我們傳入的回調函數,還有一個eventType,然后用Cpp注冊了這個回調,回調觸發的時候,執行了executeSpineEvent,此函數如下:

    ?

    ?

    [cpp]?view plaincopy
  • int?executeSpineEvent(LuaSkeletonAnimation*?skeletonAnimation,?int?handler,?spEventType?eventType,?int?trackIndex?,?int?loopCount?=?0,?spEvent*?event?=?nullptr?)??
  • {??
  • ????int?ret?=?0;??
  • ??????
  • ????spTrackEntry*?entry?=?spAnimationState_getCurrent(skeletonAnimation->getState(),?trackIndex);??
  • ????std::string?animationName?=?(entry?&&?entry->animation)???entry->animation->name?:?"";??
  • ????std::string?eventTypeName?=?"";??
  • ??????
  • ????switch?(eventType)?{??
  • ????????case?spEventType::SP_ANIMATION_END:??
  • ????????????{??
  • ????????????????eventTypeName?=?"end";??
  • ????????????}??
  • ????????????break;??
  • ????????default:??
  • ????????????break;??
  • ????}??
  • ??????
  • ????LuaValueDict?spineEvent;??
  • ????spineEvent.insert(spineEvent.end(),?LuaValueDict::value_type("type",?LuaValue::stringValue(eventTypeName)));??
  • ????spineEvent.insert(spineEvent.end(),?LuaValueDict::value_type("trackIndex",?LuaValue::intValue(trackIndex)));??
  • ????spineEvent.insert(spineEvent.end(),?LuaValueDict::value_type("animation",?LuaValue::stringValue(animationName)));??
  • ????spineEvent.insert(spineEvent.end(),?LuaValueDict::value_type("loopCount",?LuaValue::intValue(loopCount)));??
  • ??????
  • ????stack->pushLuaValueDict(spineEvent);??
  • ????ret?=?stack->executeFunctionByHandler(handler,?1);??
  • ????return?ret;??
  • }??
  • 然后結合quick里面關于handler的實現,類似cocos2dx在C++11以前的實現,所以這個地方是obj:function()的調用方法,這個obj就是self。所以其實回調的寫法完整的應該是:

    [plain]?view plaincopy
  • self.skeletonNode:registerSpineEventHandler(handler(self,function?(self,event)??
  • ????if?event.animation?==?"hit"?then??
  • ????????self.skeletonNode:setAnimation(0,?"walk",?true)??
  • ????end??????
  • end),?sp.EventType.ANIMATION_END)??
  • ?

    至于怎么隱式轉換實現的這個function到handler,我還不知道。。。。。。希望知道的告知。。。。


    2、bug
    然后就會發現,這么寫,程序會掉,回調會不停的觸發。這么寫,指的是在回調里面setAnimation。后面面會說解法,此部分可以直接跳過。

    從lua是找不出問題了,直接去C++。

    在C++里面寫一個類似的程序,在回調里面調用setAnimation,會發現如下調用關系。

    回調調用set:

    [cpp]?view plaincopy
  • skeletonNode->setEndListener(?[this]?(int?trackIndex)?{??
  • ???????spTrackEntry*?entry?=?spAnimationState_getCurrent(skeletonNode->getState(),?trackIndex);??
  • ???????const?char*?animationName?=?(entry?&&?entry->animation)???entry->animation->name?:?0;??
  • ???????if?(strcmp(animationName,?"hit")==0)??
  • ???????{??
  • ???????????skeletonNode->setAnimation(0,?"hit",?false);??
  • ???????}??
  • });??
  • node的set的實現:

    ?

    ?

    [cpp]?view plaincopy
  • spTrackEntry*?SkeletonAnimation::setAnimation?(int?trackIndex,?const?std::string&?name,?bool?loop)?{??
  • ????spAnimation*?animation?=?spSkeletonData_findAnimation(_skeleton->data,?name.c_str());??
  • ????if?(!animation)?{??
  • ????????log("Spine:?Animation?not?found:?%s",?name.c_str());??
  • ????????return?0;??
  • ????}??
  • ????return?spAnimationState_setAnimation(_state,?trackIndex,?animation,?loop);??
  • }??
  • 上面那個是通過名字取了動畫,然后進入下一級調用:

    ?

    ?

    [cpp]?view plaincopy
  • spTrackEntry*?spAnimationState_setAnimation?(spAnimationState*?self,?int?trackIndex,?spAnimation*?animation,?int/*bool*/loop)?{??
  • ????_spAnimationState*?internal?=?SUB_CAST(_spAnimationState,?self);??
  • ??
  • ????spTrackEntry*?entry;??
  • ????spTrackEntry*?current?=?_spAnimationState_expandToIndex(self,?trackIndex);??
  • ????if?(current)?_spAnimationState_disposeAllEntries(self,?current->next);??
  • <span?style="white-space:pre">????</span>...?...??
  • }??
  • 后面的選擇性忽略了,因為在if這里就蹦了,然后一路追下去,會發現是最后在free的時候,free了一個沒有alloc的指針,這個指針就是上面的current->next 。

    這個bug,從目前的情況看,大概就是,set新的animation的時候,會把當前的animation做清理,清理的是current的next,因為current已經播放,結果這個next空了。

    ?

    至于為什么空,不知道,太麻煩了,空了看。。。

    ?

    3、關于2的解法

    利用前面說的track,換一個track。

    之前說了,bug的主要原因是當前的track的動畫需要做清理,只要不在已經setAnimation的track上set新的就行了。

    換個track,set或者add都可以。

    ?

    4、補充解法:

    又跟了一下,發現現象很詭異,

    不過如果在end回調里面,用定時器,把操作延時0.001秒或者隨便多少反正就是延時到下一幀去做,就可以正常。

    ?

    ?

    未驗證問題,還沒弄清楚的:

    1、不同的track動畫直接的的mix效果

    2、function到handler的隱式轉化

    3、spine的free的next的錯誤的根源

    轉載于:https://www.cnblogs.com/liuqing0328/p/4900884.html

    總結

    以上是生活随笔為你收集整理的lua 使用 spine 的一些问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 师生出轨h灌满了1v1 | 国产一区二区不卡视频 | 中文字幕日韩精品在线观看 | 亚洲激情婷婷 | 污污网址在线观看 | 亚洲激情视频网 | 91人人看 | 影音先锋亚洲一区 | 国产日韩高清在线 | 久久逼逼| 国产超碰人人 | 求免费黄色网址 | 久久九九爱 | 欧美激情性生活 | 操她视频网站 | 久国久产久精永久网页 | 精国产人伦一区二区三区 | 成人毛片18女人毛片 | 深夜影院深a | 91大神在线观看视频 | 成人福利网站在线观看 | bt天堂新版中文在线地址 | 精品乱子伦一区二区 | 成人毛片软件 | r级无码视频在线观看 | 日本丰满少妇裸体自慰 | 久久亚洲美女 | 黄色正能量网站 | 国产成人综合在线视频 | 真实乱视频国产免费观看 | 日本a√在线观看 | 91成人久久 | 一区二三区 | 亚洲码中文 | 13日本xxxxxⅹxxx20| 日韩激情一区二区 | 欧美熟女一区二区 | 亚洲专区欧美专区 | 美女网站视频在线观看 | av高清在线观看 | 国产精品视频久久久久 | 亚洲高清网| 天天狠天天透 | 午夜丁香网 | 欧美日韩在线观看一区二区三区 | 小敏的受孕日记h | 91亚洲国产成人久久精品网站 | 久久国产日韩欧美 | 91中文在线 | 国产欧美久久久精品免费 | 欧美日韩精品一区二区在线播放 | 精品成人一区二区三区久久精品 | www.国产区 | 好吊色欧美一区二区三区视频 | 亚洲人妻一区二区三区 | 91色视频 | 亚洲一区日本 | 二区在线观看 | 欧洲成人一区二区三区 | 国产丝袜在线视频 | 性网爆门事件集合av | 亚洲av永久中文无码精品综合 | 狠狠操一区二区 | 日本午夜一区二区 | 四虎影院在线免费播放 | 欧美精品黄色 | 综合亚洲色图 | 亚洲精品国产精品乱码不99热 | 日本肉体xxxx裸体137大胆图 | 乱短篇艳辣500篇h文最新章节 | 少妇裸体性生交 | 国产资源视频 | 久久久久免费精品 | 久久精品国产亚洲av香蕉 | 2020av视频| 香蕉久久国产av一区二区 | 久久露脸| 亚洲一区二区三区观看 | 好男人www日本 | 最近中文字幕在线免费观看 | 亚洲黄色激情视频 | 天堂色在线 | www.精品国产| 日韩一区二区精品视频 | 一区二区三区欧美在线 | 国产三级三级三级 | 亚洲免费高清 | 丁香六月激情 | 天堂成人 | 国产一区二区三区在线观看视频 | 亚洲中文字幕97久久精品少妇 | 欧美日韩在线播放三区四区 | 日韩成人高清视频在线观看 | 日本一级淫片1000部 | 最新中文字幕免费 | 成人免费在线视频观看 | 国产在线视频一区二区三区 | 毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 欧美日韩免费一区二区 |