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

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

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


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

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

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

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

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

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

copy @H_403_1425@
    autolistener=EventListenerTouchAllAtOnce::create();@H_403_40@
  1. listener->onTouchesBegan=CC_CALLBACK_2(ParticleDemo::onTouchesBegan,this);@H_403_40@
  2. listener->onTouchesMoved=CC_CALLBACK_2(ParticleDemo::onTouchesMoved,153); background-color:inherit; font-weight:bold">this);@H_403_40@
  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);@H_403_40@
其次就是我们实际操作,使交互产生什么样的变化,代码如下:

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

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