cocos2d-x
c++
Java
JNI
用户交互这里指的就是用户在手机上的点击,滑动以及晃动手机等行为,从而得到相应的反馈。今天学习Cocos2dx,遇到交互问题,所以就写出来和大家分享一下。我这里是以Android连接为例的,因为目前我只会Android相关的开发。好了,不多说,看下面步骤:
第一步:在Android中,交互操作的入口在SurfaceView或是GLSurfaceView中的onTouchEvent时间中。本例代码所在位置org.cocos2dx.lib---->Cocos2dxGLSurfaceView.java
- publicbooleanonTouchEvent(finalMotionEventpMotionEvent){
-
- finalintpointerNumber=pMotionEvent.getPointerCount();
- int[]ids=newint[pointerNumber];
- float[]xs=float[pointerNumber];
- float[]ys=float[pointerNumber];
-
- for(inti=0;i<pointerNumber;i++){
- ids[i]=pMotionEvent.getPointerId(i);
- xs[i]=pMotionEvent.getX(i);
- ys[i]=pMotionEvent.getY(i);
- }
- switch(pMotionEvent.getAction()&MotionEvent.ACTION_MASK){
- caseMotionEvent.ACTION_POINTER_DOWN:
- intindexPointerDown=pMotionEvent.getAction()>>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- intidPointerDown=pMotionEvent.getPointerId(indexPointerDown);
- floatxPointerDown=pMotionEvent.getX(indexPointerDown);
- floatyPointerDown=pMotionEvent.getY(indexPointerDown);
-
- this.queueEvent(newRunnable(){
- @Override
- voidrun(){
- Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown,xPointerDown,yPointerDown);
- }
- });
- break;
- caseMotionEvent.ACTION_DOWN:
- //thereareonlyonefingeronthescreen
- intidDown=pMotionEvent.getPointerId(0);
- floatxDown=xs[0];
- floatyDown=ys[0];
- this.mCocos2dxRenderer.handleActionDown(idDown,xDown,yDown);
- caseMotionEvent.ACTION_MOVE:
- newRunnable(){
- @Override
- voidrun(){
- Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionMove(ids,xs,ys);
- });
- break;
- caseMotionEvent.ACTION_POINTER_UP:
- intindexPointUp=pMotionEvent.getAction()>>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- intidPointerUp=pMotionEvent.getPointerId(indexPointUp);
- floatxPointerUp=pMotionEvent.getX(indexPointUp);
- floatyPointerUp=pMotionEvent.getY(indexPointUp);
- this.mCocos2dxRenderer.handleActionUp(idPointerUp,xPointerUp,yPointerUp);
- caseMotionEvent.ACTION_UP:
-
- intidUp=pMotionEvent.getPointerId(0);
- floatxUp=xs[floatyUp=ys[this.mCocos2dxRenderer.handleActionUp(idUp,xUp,yUp);
- caseMotionEvent.ACTION_CANCEL:
- this.mCocos2dxRenderer.handleActionCancel(ids,ys);
- returntrue;
- }
第二步:Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown,yDown)等相关语句的方法在org.cocos2dx.lib------>Cocos2dxRender.java,代码如下:
privatestaticnativevoidnativeTouchesBegin(intid,floatx,153); background-color:inherit; font-weight:bold">floaty);
- voidnativeTouchesEnd(floaty);
- voidnativeTouchesMove(int[]ids,153); background-color:inherit; font-weight:bold">float[]xs,153); background-color:inherit; font-weight:bold">float[]ys);
- voidnativeTouchesCancel(float[]ys);
- voidhandleActionDown(floaty){
- Cocos2dxRenderer.nativeTouchesBegin(id,x,y);
- voidhandleActionUp( Cocos2dxRenderer.nativeTouchesEnd(id,153); background-color:inherit; font-weight:bold">voidhandleActionCancel(float[]ys){
- Cocos2dxRenderer.nativeTouchesCancel(ids,ys);
- 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,内容如下:
protectedvoidonLoadNativeLibraries(){
- try{
- ApplicationInfoai=getPackageManager().getApplicationInfo(getPackageName(),PackageManager.GET_META_DATA);
- Bundlebundle=ai.metaData;
- StringlibName=bundle.getString("android.app.lib_name");
- System.loadLibrary(libName);
- }catch(Exceptione){
- e.printStackTrace();
- }
bundle.getString("android.app.lib_name")文件是找出.so文件。和它相关内容在Android工程中AndroidManifest.xml里,内容如下:
<?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="org.cocos.CocosProject4"
- android:versionCode="1"
- android:versionName="1.0"
- android:installLocation="auto">
- uses-sdkandroid:minSdkVersion="9"/>
- uses-featureandroid:glEsVersion="0x00020000"/>
- applicationandroid:label="@string/app_name"
- android:icon="@drawable/icon"
- meta-dataandroid:name="android.app.lib_name"
- android:value="cocos2dcpp"activityandroid:name="org.cocos2dx.cpp.AppActivity"
- android:label="@string/app_name"
- android:screenOrientation="landscape"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:configChanges="orientation"intent-filteractionandroid:name="android.intent.action.MAIN"categoryandroid:name="android.intent.category.LAUNCHER"</>
- activityapplicationsupports-screensandroid:anyDensity="true"
- android:smallScreens="true"
- android:normalScreens="true"
- android:largeScreens="true"
- android:xlargeScreens="true"uses-permissionandroid:name="android.permission.INTERNET"manifest>
第四步:cocos2dcpp.so文件的生成,因为native 方法都在这里面。它的生成在Android工程中的jni文件里么的Android.mk文件(相关内容参考链接)。native方法所在文件路径cocos2d-x-3.6/cocos/platform/android/jni/TouchesJni.cpp,内容如下:
#include"base/CCDirector.h"
- #include"base/CCEventKeyboard.h"
- #include"base/CCEventDispatcher.h"
- #include"platform/android/CCGLViewImpl-android.h"
- #include<android/log.h>
- #include<jni.h>
- usingnamespacecocos2d;
- extern"C"{
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv*env,jobjectthiz,jintid,jfloatx,jfloaty){
- intptr_tidlong=id;
- cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1,&idlong,&x,&y);
- JNIEXPORTvoidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd(JNIEnv*env,jfloaty){
- intptr_tidlong=id;
- cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1,&y);
- voidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesMove(JNIEnv*env,jintArrayids,jfloatArrayxs,jfloatArrayys){
- intsize=env->GetArrayLength(ids);
- jintid[size];
- jfloatx[size];
- jfloaty[size];
- env->GetIntArrayRegion(ids,size,id);
- env->GetFloatArrayRegion(xs,x);
- env->GetFloatArrayRegion(ys,y);
- intptr_tidlong[size];
- for(inti=0;i<size;i++)
- idlong[i]=id[i];
- cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesMove(size,idlong,153); background-color:inherit; font-weight:bold">voidJNICALLJava_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesCancel(JNIEnv*env,jfloatArrayys){
- intsize=env->GetArrayLength(ids);
- jintid[size];
- jfloatx[size];
- jfloaty[size];
- env->GetIntArrayRegion(ids,id);
- env->GetFloatArrayRegion(xs,x);
- env->GetFloatArrayRegion(ys,87); background-color:inherit; font-weight:bold">intptr_tidlong[size];
- inti=0;i<size;i++)
- idlong[i]=id[i];
- 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,内如如下:
voidGLView::handleTouchesBegin(intnum,intptr_tids[],87); background-color:inherit; font-weight:bold">floatxs[],87); background-color:inherit; font-weight:bold">floatys[])
- {
- intptr_tid=0;
- floatx=0.0f;
- floaty=0.0f;
- intunusedIndex=0;
- EventTouchtouchEvent;
- inti=0;i<num;++i)
- id=ids[i];
- x=xs[i];
- y=ys[i];
- autoiter=g_touchIdReorderMap.find(id);
- //itisanewtouch
- if(iter==g_touchIdReorderMap.end())
- {
- unusedIndex=getUnUsedIndex();
- //ThetouchesismorethanMAX_TOUCHES?
- if(unusedIndex==-1){
- CCLOG("ThetouchesismorethanMAX_TOUCHES,unusedIndex=%d",unusedIndex);
- continue;
- Touch*touch=g_touches[unusedIndex]=new(std::nothrow)Touch();
- touch->setTouchInfo(unusedIndex,(x-_viewPortRect.origin.x)/_scaleX,
- (y-_viewPortRect.origin.y)/_scaleY);
- CCLOGINFO("x=%fy=%f",touch->getLocationInView().x,touch->getLocationInView().y);
- g_touchIdReorderMap.insert(std::make_pair(id,unusedIndex));
- touchEvent._touches.push_back(touch);
- if(touchEvent._touches.size()==0)
- CCLOG("touchesBegan:size=0");
- return;
- touchEvent._eventCode=EventTouch::EventCode::BEGAN;
- autodispatcher=Director::getInstance()->getEventDispatcher();
- dispatcher->dispatchEvent(&touchEvent);
- }
第六步:使用。首先要给_eventDispathcer(在CCNote.cpp文件中)添加listener,示例如下:
autolistener=EventListenerTouchAllAtOnce::create();
- listener->onTouchesBegan=CC_CALLBACK_2(ParticleDemo::onTouchesBegan,this);
- listener->onTouchesMoved=CC_CALLBACK_2(ParticleDemo::onTouchesMoved,153); background-color:inherit; font-weight:bold">this);
- 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);
其次就是我们实际操作,使交互产生什么样的变化,代码如下:
voidParticleDemo::onTouchesBegan(conststd::vector<Touch*>&touches,Event*event)
- onTouchesEnded(touches,event);
- voidParticleDemo::onTouchesMoved(returnonTouchesEnded(touches,event);
- voidParticleDemo::onTouchesEnded( autotouch=touches[0];
- autolocation=touch->getLocation();
- autopos=Vec2::ZERO;
- if(_background)
- pos=_background->convertToWorldSpace(Vec2::ZERO);
- if(_emitter!=nullptr)
- _emitter->setPosition(location-pos);
- }
上面代码是ParticleTest中的内容,通过dispathcer将参数最终传递给要变化的_mitter,就是粒子发射器的移动。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|