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

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

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

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

第一步:在AndroID中,交互 *** 作的入口在SurfaceVIEw或是GLSurfaceVIEw中的ontouchEvent时间中。本例代码所在位置org.cocos2dx.lib---->Cocos2dxGLSurfaceVIEw.java

public boolean ontouchEvent(final MotionEvent pMotionEvent) {        // these data are used in ACTION_MOVE and ACTION_CANCEL        final int pointerNumber = pMotionEvent.getPointerCount();        final int[] IDs = new int[pointerNumber];        final float[] xs = new float[pointerNumber];        final float[] ys = new float[pointerNumber];        for (int i = 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) {            case MotionEvent.ACTION_POINTER_DOWN:                final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;                final int IDPointerDown = pMotionEvent.getPointerID(indexPointerDown);                final float xPointerDown = pMotionEvent.getX(indexPointerDown);                final float yPointerDown = pMotionEvent.getY(indexPointerDown);                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionDown(IDPointerDown,xPointerDown,yPointerDown);                    }                });                break;            case MotionEvent.ACTION_DOWN:                // there are only one finger on the screen                final int IDDown = pMotionEvent.getPointerID(0);                final float xDown = xs[0];                final float yDown = ys[0];                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionDown(IDDown,xDown,yDown);                    }                });                break;            case MotionEvent.ACTION_MOVE:                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionMove(IDs,xs,ys);                    }                });                break;            case MotionEvent.ACTION_POINTER_UP:                final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;                final int IDPointerUp = pMotionEvent.getPointerID(indexPointUp);                final float xPointerUp = pMotionEvent.getX(indexPointUp);                final float yPointerUp = pMotionEvent.getY(indexPointUp);                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionUp(IDPointerUp,xPointerUp,yPointerUp);                    }                });                break;            case MotionEvent.ACTION_UP:                // there are only one finger on the screen                final int IDUp = pMotionEvent.getPointerID(0);                final float xUp = xs[0];                final float yUp = ys[0];                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionUp(IDUp,xUp,yUp);                    }                });                break;            case MotionEvent.ACTION_CANCEL:                this.queueEvent(new Runnable() {                    @OverrIDe                    public voID run() {                        Cocos2dxGLSurfaceVIEw.this.mCocos2dxRenderer.handleActionCancel(IDs,ys);                    }                });                break;        }            return true;    }

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

    private static native voID nativetouchesBegin(final int ID,final float x,final float y);    private static native voID nativetouchesEnd(final int ID,final float y);    private static native voID nativetouchesMove(final int[] IDs,final float[] xs,final float[] ys);    private static native voID nativetouchesCancel(final int[] IDs,final float[] ys);       public voID handleActionDown(final int ID,final float y) {        Cocos2dxRenderer.nativetouchesBegin(ID,x,y);    }    public voID handleActionUp(final int ID,final float y) {        Cocos2dxRenderer.nativetouchesEnd(ID,y);    }    public voID handleActionCancel(final int[] IDs,final float[] ys) {        Cocos2dxRenderer.nativetouchesCancel(IDs,ys);    }    public voID handleActionMove(final int[] IDs,final float[] ys) {        Cocos2dxRenderer.nativetouchesMove(IDs,ys);    }


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

 protected voID onLoadNativelibrarIEs() {        try {            ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackagename(),PackageManager.GET_Meta_DATA);            Bundle bundle = ai.MetaData;            String libname = bundle.getString("androID.app.lib_name");            System.loadlibrary(libname);        } catch (Exception e) {            e.printstacktrace();        }    }
bundle.getString("androID.app.lib_name")文件是找出.so文件。和它相关内容在AndroID工程中AndroIDManifest.xml里,内容如下:

<?xml version="1.0" enCoding="utf-8"?><manifest xmlns:androID="http://schemas.androID.com/apk/res/androID"      package="org.cocos.CocosProject4"      androID:versionCode="1"      androID:versionname="1.0"      androID:installLocation="auto">    <uses-sdk androID:minSdkVersion="9"/>    <uses-feature androID:glEsversion="0x00020000" />    <application androID:label="@string/app_name"                 androID:icon="@drawable/icon">					         <!-- Tell Cocos2dxActivity the name of our .so -->        <Meta-data androID:name="androID.app.lib_name"	              androID:value="cocos2dcpp" />        <activity androID:name="org.cocos2dx.cpp.AppActivity"                  androID:label="@string/app_name"                  androID:screenorIEntation="landscape"                  androID:theme="@androID:style/theme.NoTitlebar.Fullscreen"                  androID:configChanges="orIEntation">            <intent-filter>                <action androID:name="androID.intent.action.MAIN" />                <category androID:name="androID.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application>    <supports-screens androID:anyDensity="true"                      androID:smallScreens="true"                      androID:normalScreens="true"                      androID:largeScreens="true"                      androID:xlargeScreens="true"/>    <uses-permission androID: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>using namespace cocos2d;extern "C" {    JNIEXPORT voID JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativetouchesBegin(jnienv * env,jobject thiz,jint ID,jfloat x,jfloat y) {        intptr_t IDlong = ID;        cocos2d::Director::getInstance()->getopenGLVIEw()->handletouchesBegin(1,&IDlong,&x,&y);    }    JNIEXPORT voID JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativetouchesEnd(jnienv * env,jfloat y) {        intptr_t IDlong = ID;        cocos2d::Director::getInstance()->getopenGLVIEw()->handletouchesEnd(1,&y);    }    JNIEXPORT voID JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativetouchesMove(jnienv * env,jintArray IDs,jfloatArray xs,jfloatArray ys) {        int size = env->GetArrayLength(IDs);        jint ID[size];        jfloat x[size];        jfloat y[size];        env->GetIntArrayRegion(IDs,size,ID);        env->GetfloatArrayRegion(xs,x);        env->GetfloatArrayRegion(ys,y);        intptr_t IDlong[size];        for(int i = 0; i < size; i++)            IDlong[i] = ID[i];        cocos2d::Director::getInstance()->getopenGLVIEw()->handletouchesMove(size,IDlong,y);    }    JNIEXPORT voID JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativetouchesCancel(jnienv * env,y);        intptr_t IDlong[size];        for(int i = 0; i < size; i++)            IDlong[i] = ID[i];        cocos2d::Director::getInstance()->getopenGLVIEw()->handletouchesCancel(size,y);    }       }

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

voID GLVIEw::handletouchesBegin(int num,intptr_t IDs[],float xs[],float ys[]){    intptr_t ID = 0;    float x = 0.0f;    float y = 0.0f;    int unusedindex = 0;    Eventtouch touchEvent;        for (int i = 0; i < num; ++i)    {        ID = IDs[i];        x = xs[i];        y = ys[i];        auto iter = g_touchIDReorderMap.find(ID);        // it is a new touch        if (iter == g_touchIDReorderMap.end())        {            unusedindex = getUnUsedindex();            // The touches is more than MAX_touches ?            if (unusedindex == -1) {                cclOG("The touches is more than MAX_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 = %f y = %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;    auto dispatcher = Director::getInstance()->getEventdispatcher();    dispatcher->dispatchEvent(&touchEvent);}

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

 auto Listener = EventListenertouchAllAtOnce::create();    Listener->ontouchesBegan = CC_CALLBACK_2(ParticleDemo::ontouchesBegan,this);    Listener->ontouchesMoved = CC_CALLBACK_2(ParticleDemo::ontouchesMoved,this);    Listener->ontouchesEnded = CC_CALLBACK_2(ParticleDemo::ontouchesEnded,this);    _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener,this);
其次就是我们实际 *** 作,使交互产生什么样的变化,代码如下:

voID ParticleDemo::ontouchesBegan(const std::vector<touch*>& touches,Event  *event){    ontouchesEnded(touches,event);}voID ParticleDemo::ontouchesMoved(const std::vector<touch*>& touches,Event  *event){    return ontouchesEnded(touches,event);}voID ParticleDemo::ontouchesEnded(const std::vector<touch*>& touches,Event  *event){    auto touch = touches[0];    auto location = touch->getLocation();    auto pos = Vec2::ZERO;    if (_background)    {        pos = _background->convertToWorldspace(Vec2::ZERO);    }    if (_emitter != nullptr)    {        _emitter->setposition(location -pos);    }}

上面代码是ParticleTest中的内容,通过dispathcer将参数最终传递给要变化的_mitter,就是粒子发射器的移动。


好了,以上就是这个过程,当然,要想完全理解,那就要修炼内功了,怎么做,你懂的~

总结

以上是内存溢出为你收集整理的Cocos2d-x-3.6 用户交互原理---------如何通过JNI连接Java和C++全部内容,希望文章能够帮你解决Cocos2d-x-3.6 用户交互原理---------如何通过JNI连接Java和C++所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1066817.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存