Cocos2d-x-3.6 用户交互原理---------如何通过JNI连接Java和C++

前端之家收集整理的这篇文章主要介绍了Cocos2d-x-3.6 用户交互原理---------如何通过JNI连接Java和C++前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

用户交互这里指的就是用户在手机上的点击,滑动以及晃动手机等行为,从而得到相应的反馈。今天学习Cocos2dx,遇到交互问题,所以就写出来和大家分享一下。我这里是以Android连接为例的,因为目前我只会Android相关的开发。好了,不多说,看下面步骤:

第一步:在Android中,交互操作的入口在SurfaceView或是GLSurfaceView中的onTouchEvent时间中。本例代码所在位置org.cocos2dx.lib---->Cocos2dxGLSurfaceView.java

[java] view plain copy
  1. publicbooleanonTouchEvent(finalMotionEventpMotionEvent){
  2. //thesedataareusedinACTION_MOVEandACTION_CANCEL
  3. finalintpointerNumber=pMotionEvent.getPointerCount();
  4. int[]ids=newint[pointerNumber];
  5. float[]xs=float[pointerNumber];
  6. float[]ys=float[pointerNumber];
  7. for(inti=0;i<pointerNumber;i++){
  8. ids[i]=pMotionEvent.getPointerId(i);
  9. xs[i]=pMotionEvent.getX(i);
  10. ys[i]=pMotionEvent.getY(i);
  11. }
  12. switch(pMotionEvent.getAction()&MotionEvent.ACTION_MASK){
  13. caseMotionEvent.ACTION_POINTER_DOWN:
  14. intindexPointerDown=pMotionEvent.getAction()>>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
  15. intidPointerDown=pMotionEvent.getPointerId(indexPointerDown);
  16. floatxPointerDown=pMotionEvent.getX(indexPointerDown);
  17. floatyPointerDown=pMotionEvent.getY(indexPointerDown);
  18. this.queueEvent(newRunnable(){
  19. @Override
  20. voidrun(){
  21. Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown,xPointerDown,yPointerDown);
  22. }
  23. });
  24. break;
  25. caseMotionEvent.ACTION_DOWN:
  26. //thereareonlyonefingeronthescreen
  27. intidDown=pMotionEvent.getPointerId(0);
  28. floatxDown=xs[0];
  29. floatyDown=ys[0];
  30. this.mCocos2dxRenderer.handleActionDown(idDown,xDown,yDown);
  31. caseMotionEvent.ACTION_MOVE:
  32. newRunnable(){
  33. @Override
  34. voidrun(){
  35. Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionMove(ids,xs,ys);
  36. });
  37. break;
  38. caseMotionEvent.ACTION_POINTER_UP:
  39. intindexPointUp=pMotionEvent.getAction()>>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
  40. intidPointerUp=pMotionEvent.getPointerId(indexPointUp);
  41. floatxPointerUp=pMotionEvent.getX(indexPointUp);
  42. floatyPointerUp=pMotionEvent.getY(indexPointUp);
  43. this.mCocos2dxRenderer.handleActionUp(idPointerUp,xPointerUp,yPointerUp);
  44. caseMotionEvent.ACTION_UP:
  45. @H_404_351@//thereareonlyonefingeronthescreen
  46. intidUp=pMotionEvent.getPointerId(0);
  47. floatxUp=xs[floatyUp=ys[this.mCocos2dxRenderer.handleActionUp(idUp,xUp,yUp);
  48. caseMotionEvent.ACTION_CANCEL:
  49. this.mCocos2dxRenderer.handleActionCancel(ids,ys);
  50. returntrue;
  51. }

第二步:Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown,yDown)等相关语句的方法在org.cocos2dx.lib------>Cocos2dxRender.java,代码如下:

copy
    privatestaticnativevoidnativeTouchesBegin(intid,floatx,153); background-color:inherit; font-weight:bold">floaty);
  1. voidnativeTouchesEnd(floaty);
  2. voidnativeTouchesMove(int[]ids,153); background-color:inherit; font-weight:bold">float[]xs,153); background-color:inherit; font-weight:bold">float[]ys);
  3. voidnativeTouchesCancel(float[]ys);
  4. voidhandleActionDown(floaty){
  5. Cocos2dxRenderer.nativeTouchesBegin(id,x,y);
  6. voidhandleActionUp( Cocos2dxRenderer.nativeTouchesEnd(id,153); background-color:inherit; font-weight:bold">voidhandleActionCancel(float[]ys){
  7. Cocos2dxRenderer.nativeTouchesCancel(ids,ys);
  8. voidhandleActionMove( Cocos2dxRenderer.nativeTouchesMove(ids,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> }


第三步: private static native void nativeTouchesBegin(final int id,final float x,final float y)这是本地方法调用c++内容的语句。而这些内容被打包在Android工程中的libs/armeabi/cocos2dcpp.so文件中。所以我们在使用这些方法时一定要加载这个.so文件代码位置在org.cocos2dx.lib--->Cocos2dxActivity.java,内容如下:

copy
    protectedvoidonLoadNativeLibraries(){
  1. try{
  2. ApplicationInfoai=getPackageManager().getApplicationInfo(getPackageName(),PackageManager.GET_Meta_DATA);
  3. Bundlebundle=ai.MetaData;
  4. StringlibName=bundle.getString("android.app.lib_name");
  5. System.loadLibrary(libName);
  6. }catch(Exceptione){
  7. e.printStackTrace();
  8. }
bundle.getString("android.app.lib_name")文件是找出.so文件。和它相关内容在Android工程中AndroidManifest.xml里,内容如下:

[html] copy
    <?xml@H_502_624@version="1.0"@H_502_624@encoding="utf-8"?>
  1. <manifest@H_502_624@xmlns:android="http://schemas.android.com/apk/res/android"
  2. @H_502_624@package="org.cocos.CocosProject4"
  3. @H_502_624@android:versionCode="1"
  4. @H_502_624@android:versionName="1.0"
  5. @H_502_624@android:installLocation="auto">
  6. uses-sdk@H_502_624@android:minSdkVersion="9"/>
  7. uses-feature@H_502_624@android:glEsVersion="0x00020000"/>
  8. application@H_502_624@android:label="@string/app_name"
  9. @H_502_624@android:icon="@drawable/icon" <!--TellCocos2dxActivitythenameofour.so-->
  10. Meta-data@H_502_624@android:name="android.app.lib_name"
  11. @H_502_624@android:value="cocos2dcpp"activity@H_502_624@android:name="org.cocos2dx.cpp.AppActivity"
  12. @H_502_624@android:label="@string/app_name"
  13. @H_502_624@android:screenOrientation="landscape"
  14. @H_502_624@android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
  15. @H_502_624@android:configChanges="orientation"intent-filteraction@H_502_624@android:name="android.intent.action.MAIN"category@H_502_624@android:name="android.intent.category.LAUNCHER"</>
  16. activityapplicationsupports-screens@H_502_624@android:anyDensity="true"
  17. @H_502_624@android:smallScreens="true"
  18. @H_502_624@android:normalScreens="true"
  19. @H_502_624@android:largeScreens="true"
  20. @H_502_624@android:xlargeScreens="true"uses-permission@H_502_624@android:name="android.permission.INTERNET"manifest>

第四步:cocos2dcpp.so文件生成,因为native 方法都在这里面。它的生成在Android工程中的jni文件里么的Android.mk文件(相关内容参考链接)。native方法所在文件路径cocos2d-x-3.6/cocos/platform/android/jni/TouchesJni.cpp,内容如下:

[cpp] copy
    #include"base/CCDirector.h"
  1. #include"base/CCEventKeyboard.h"
  2. #include"base/CCEventDispatcher.h"
  3. #include"platform/android/CCGLViewImpl-android.h"
  4. #include<android/log.h>
  5. #include<jni.h>
  6. usingnamespacecocos2d;
  7. extern"C"{
  8. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv*env,jobjectthiz,jintid,jfloatx,jfloaty){
  9. intptr_tidlong=id;
  10. cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1,&idlong,&x,&y);
  11. JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd(JNIEnv*env,jfloaty){
  12. intptr_tidlong=id;
  13. cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1,&y);
  14. voidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesMove(JNIEnv*env,jintArrayids,jfloatArrayxs,jfloatArrayys){
  15. intsize=env->GetArrayLength(ids);
  16. jintid[size];
  17. jfloatx[size];
  18. jfloaty[size];
  19. env->GetIntArrayRegion(ids,size,id);
  20. env->GetFloatArrayRegion(xs,x);
  21. env->GetFloatArrayRegion(ys,y);
  22. intptr_tidlong[size];
  23. for(inti=0;i<size;i++)
  24. idlong[i]=id[i];
  25. cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesMove(size,idlong,153); background-color:inherit; font-weight:bold">voidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesCancel(JNIEnv*env,jfloatArrayys){
  26. intsize=env->GetArrayLength(ids);
  27. jintid[size];
  28. jfloatx[size];
  29. jfloaty[size];
  30. env->GetIntArrayRegion(ids,id);
  31. env->GetFloatArrayRegion(xs,x);
  32. env->GetFloatArrayRegion(ys,87); background-color:inherit; font-weight:bold">intptr_tidlong[size];
  33. inti=0;i<size;i++)
  34. idlong[i]=id[i];
  35. cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesCancel(size,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> }

第五步:cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1,&y)这个方法是如何起作用的呢,文件位置在 cocos2d-x-3.6/cocos/platform/CCGLView.cpp,内如如下:

copy
    voidGLView::handleTouchesBegin(intnum,intptr_tids[],87); background-color:inherit; font-weight:bold">floatxs[],87); background-color:inherit; font-weight:bold">floatys[])
  1. {
  2. intptr_tid=0;
  3. floatx=0.0f;
  4. floaty=0.0f;
  5. intunusedIndex=0;
  6. EventTouchtouchEvent;
  7. inti=0;i<num;++i)
  8. id=ids[i];
  9. x=xs[i];
  10. y=ys[i];
  11. autoiter=g_touchIdReorderMap.find(id);
  12. //itisanewtouch
  13. if(iter==g_touchIdReorderMap.end())
  14. {
  15. unusedIndex=getUnUsedIndex();
  16. //ThetouchesismorethanMAX_TOUCHES?
  17. if(unusedIndex==-1){
  18. CCLOG("ThetouchesismorethanMAX_TOUCHES,unusedIndex=%d",unusedIndex);
  19. continue;
  20. Touch*touch=g_touches[unusedIndex]=new(std::nothrow)Touch();
  21. touch->setTouchInfo(unusedIndex,(x-_viewPortRect.origin.x)/_scaleX,
  22. (y-_viewPortRect.origin.y)/_scaleY);
  23. CCLOGINFO("x=%fy=%f",touch->getLocationInView().x,touch->getLocationInView().y);
  24. g_touchIdReorderMap.insert(std::make_pair(id,unusedIndex));
  25. touchEvent._touches.push_back(touch);
  26. if(touchEvent._touches.size()==0)
  27. CCLOG("touchesBegan:size=0");
  28. return;
  29. touchEvent._eventCode=EventTouch::EventCode::BEGAN;
  30. autodispatcher=Director::getInstance()->getEventDispatcher();
  31. dispatcher->dispatchEvent(&touchEvent);
  32. }

第六步:使用。首先要给_eventDispathcer(在CCNote.cpp文件中)添加listener,示例如下:

copy
    autolistener=EventListenerTouchAllAtOnce::create();
  1. listener->onTouchesBegan=CC_CALLBACK_2(ParticleDemo::onTouchesBegan,this);
  2. listener->onTouchesMoved=CC_CALLBACK_2(ParticleDemo::onTouchesMoved,153); background-color:inherit; font-weight:bold">this);
  3. listener->onTouchesEnded=CC_CALLBACK_2(ParticleDemo::onTouchesEnded,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> _eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,153); background-color:inherit; font-weight:bold">this);
其次就是我们实际操作,使交互产生什么样的变化,代码如下:

copy
    voidParticleDemo::onTouchesBegan(conststd::vector<Touch*>&touches,Event*event)
  1. onTouchesEnded(touches,event);
  2. voidParticleDemo::onTouchesMoved(returnonTouchesEnded(touches,event);
  3. voidParticleDemo::onTouchesEnded( autotouch=touches[0];
  4. autolocation=touch->getLocation();
  5. autopos=Vec2::ZERO;
  6. if(_background)
  7. pos=_background->convertToWorldSpace(Vec2::ZERO);
  8. if(_emitter!=nullptr)
  9. _emitter->setPosition(location-pos);
  10. }
上面代码是ParticleTest中的内容,通过dispathcer将参数最终传递给要变化的_mitter,就是粒子发射器的移动。 原文链接:https://www.f2er.com/cocos2dx/341864.html

猜你在找的Cocos2d-x相关文章