0

I am looking for a way to detect if the device orientation changed from landscape to portrait or the other way around, for a cocos2dx 2.2.3 app.

I googled this topic for hours now, but to no avail.

I want to detect the orientation changed event in a CCScene. Is there an event I can subscribe to?

I am interested how you can do this for Android, but iOS and Windows is welcomed to!

Thank you!

psu
  • 379
  • 1
  • 5
  • 15
  • I googled this and found no less than 3 answers on Stackoverflow related to this: http://stackoverflow.com/questions/5726657/how-to-detect-orientation-change-in-layout-in-android http://stackoverflow.com/questions/5112118/how-to-detect-orientation-of-android-device http://stackoverflow.com/questions/8248274/android-detect-orientation-changed You may want to work on your google-skills. ;) All I did was enter: "detect device orientation change android" – CodeSmile Jul 29 '14 at 11:58
  • And how can I capture those events inside a cocos 2d x CCScene? I need to detect the screen orientation change in cocos2d x on an android device. read the entire post... – psu Jul 29 '14 at 12:00
  • Not sure since I only know about iOS, but there you got a central app class (AppDelegate) that receives such events. If you need this on the scene, forward it to the scene. The active scene in ObjC is [CCDirector sharedDirector].runningScene (there ought to be a C++ equivalent in CCDirector). – CodeSmile Jul 29 '14 at 13:38
  • @LearnCocos2D: You should improve your reading skills, it says cocos2d-x, and not android native. Both of your links give answers for Android native. – user18853 May 06 '17 at 04:52

2 Answers2

1

I found a solution, but it is not great as you have to modify the lib. Anyway

1.Go to cocos2dx/platform/android/java/src/org/cocos2dx/lib

2.In Cocos2dxRenderer.java add the following to the onSurfaceChanged method

@Override
public void onSurfaceChanged(final GL10 pGL10, final int pWidth, final int pHeight) {
    nativeInit(pWidth, pHeight);
}

3.Go to your project folder and in proj.android/jni/[prjcpp]/main.cpp modify the Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit method

void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*  env, jobject thiz, jint w, jint h)
{
    if (!CCDirector::sharedDirector()->getOpenGLView())
    {
        //...
    }
    else
    {
        //...
        CCEGLView *view = CCEGLView::sharedOpenGLView();        
        if (view->getFrameSize().width != w || view->getFrameSize().height != h) {
            view->setFrameSize(w, h);
            view->setDesignResolutionSize(w, h, kResolutionShowAll);
            CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_ORIENTATION_CHANGED, NULL);
        }   
    }
}

4.Before you can subscribe to the EVENT_ORIENTATION_CHANGED you must declare it in CCEventType.h:

#define EVENT_ORIENTATION_CHANGED  "event_orientation_changed"

5.You can subscribe to the event:

CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(Scene::orientationChangedCallback), EVENT_ORIENTATION_CHANGED, NULL);

You can avoid using the event by checking the orientation in the update method of any CCScene or CCLayer object. I did it by comparing the width and height of the screen:

bool Scene::isLandscape()
{
    CCSize _screenSize = CCDirector::sharedDirector()->getWinSize();
    if (_screenSize.width > _screenSize.height)
        return true;
    return false;
}

There has to be a better solution! Please share!

psu
  • 379
  • 1
  • 5
  • 15
0

Caveat:

I haven't looked in the cocos2x 2.x api for an official implementation (they may have one already?).

If you have to implement it yourself, the cleanest solution I can think of is using the JNI. Full explanation of the JNI is outside the scope of this answer. Here is an example of how it works with cocos2d-x.

Implementation:

  1. Write a native C++ function that Java can call out to using the JNI.
  2. Detect orientation changes on the Java side like you would any Android app.
  3. On orientation change, fire native C++ method from Java passing any extra information you require ("landscape", "portrait", etc.). For simplicity, you can use two void methods instead.
  4. Handle appropriate callback in the definition the C++ side.

Tips:

  1. Don't bother writing the corresponding fully-qualified function names (Java_com_mycompany_mygame_MyGame) yourself: use javah to generate it for you automatically; The JNI can be very error-prone and hard to debug, especially for the uninitiated.
  2. Sprinkle log statements liberally to aid debugging.

Bonus points: For extra flexibility and code reuse, detach game-specific callback from C++ definition and instead use the subscriber model (just like you have in your answer).

This way you don't have to make modifications to the engine.

Community
  • 1
  • 1
Justin Godesky
  • 1,019
  • 1
  • 10
  • 17