iOS cocos2d學習筆記 之 iOS View與OpenGL View的那些事

回首一下,故事的背景……


我們依稀記得,iOS View與OpenGL View之間有着不可告人的祕密關係,

有人說,他們呢,就像是天上的牛郎星和織女星,他們的座標原定被手機屏幕隔開在左邊的兩個角落。

iOS View的座標原點位於手機屏幕的左上角,OpenGL View的則位於手機屏幕的左下角,無論凡人們如何將手機來個巴黎鐵塔翻轉再翻轉,也沒可能改變他們悲劇的命運——相隔屏幕兩方,一個左上,一個左下。

但是,凡人都知道,牛郎織女卻會在每年的那麼幾天走在一起……


等等騷年,你逗我玩嗎?你的意思是說iOS View與OpenGL View的座標原點走到了一起!?

我可以很認真,很老實地告訴你:

嗯,有情人終成眷屬。


確實,這種看似不可能的事情讓我碰上了

在寫關於cocos2d座標轉換的一篇筆記當中,通過打印相關座標作爲驗證的時候發現了這個問題,而且還困惑了我那麼一段時間。

在我不懈的努力下,經過了實踐和試驗得出,牛郎和織女是可以走在一起的。大笑

我的意思是:iOS View與OpenGL View的座標原點是可以走在一起的。尷尬


好吧,在開始探討之前,我必須告訴大家一件事,在這一個案例裏面的情況,僅在iOS5以及iOS6之間測試過,只有iOS5或之前版本會出現這樣問題,對於現在已經是iOS7侵略期,這算是就知識吧,有興趣就往下看,沒興趣亦可瞭解一下。


我先貼遇到這樣問題的工程中的一段關鍵代碼:

AppDelegate.mm:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    if (![CCDirector setDirectorType:kCCDirectorTypeDisplayLink])
    {
        // 設置導演類型
        [CCDirector setDirectorType:kCCDirectorTypeDefault];
    }
    
    CCDirector *director = [CCDirector sharedDirector];
    // 取得當前導演
    // 創建一個舞臺
    EAGLView *glView = [EAGLView viewWithFrame:[self.window bounds]pixelFormat:kEAGLColorFormatRGB565 depthFormat:0];
    [director setOpenGLView:glView];// 設置OpenGLView
    if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
    {
        [director setDeviceOrientation:CCDeviceOrientationLandscapeLeft];
        // 設置遊戲方向爲左橫平
    }

    [director setAnimationInterval:1.0f/60.0f];
    // 設置遊戲刷新率爲每秒60真
    [director setDisplayFPS:YES];
    //
    
    RootViewController *rvc = [[RootViewController alloc] init];
    [rvc setView:glView];
    [self.window setRootViewController:rvc];
    [rvc release];
    // 把rvc作爲window作爲根視圖
    
    [self.window makeKeyAndVisible];
    // 屏幕要顯示第一個劇場
    CCScene *sc = [LoadingScene scene];
    [[CCDirector sharedDirector] runWithScene:sc];
    // 讓導演運行劇場
    
    return YES;
}

喲!這不是appdelegate裏面的啓動方法嘛?

沒錯,眼利的童鞋一眼就可以看出來了,牛郎與織女之所以能走到一起,離不開起始的啓動狀態的設置。

我們先通讀一下這個方法的實現過程,瞭解兩人的作案動機(寫得略亂,求大神勿噴,新手勿模仿尷尬

不過,我還是沒有突出最最核心的一句。

那這就來了:

    if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
    {
        [director setDeviceOrientation:CCDeviceOrientationLandscapeLeft];
        // 設置遊戲方向爲左橫平
    }

是的,就是這一句話,讓兩個View的座標原點走在一起的,正是因爲這有條件的一句,讓基情發生在iOS6以前的版本中。


我爲什麼要這樣子寫呢?

現在我們來了解一下兩個因素:

1、iOS6.0的設備與視圖的自動旋轉非常簡單,只需簡單設置plist文件中相應的設置項“Supported interface orientations”即可支持旋轉,但在之前版本則需要通過重寫supportedInterfaceOrientations方法來實現,具體請看文章末尾

2、setDevicOrientation 這個方法很懶只負責將設備轉向,而並沒有將屏幕中的視圖跟着一起旋轉(這個方法在iOS6.0以前才需要執行來設置機械的橫屏)但需要注意的是,重力感應依然有效,設備是真實旋轉過的。


好,我們再來看一下最上面的代碼,看看我做了什麼事?

運行步驟:

1. 創建導演類

2. 以當前畫面配置設置一個EAGLView對象glView(注意這不是我們討論的那個OpenGL View),並把這個對象託付給導演(導演要播的動畫都會在這個視圖上面出現)

3. (iOS6.0以前版本)設備方向設爲左橫屏

4. 創建一個ViewController對象 rvc(這個就是iOS View),並將glView作爲其視圖。

5. 創建一個LoadingScene類劇場 sc(這個則是所討論的OpenGL View),並使用導演將其運作起來。

再附上LoadingScene類在初始化時運作的代碼:

+ (id) scene
{
    CCScene *sc = [CCScene node];
    // 創建空的劇場
    LoadingScene *ls = [LoadingScene node];
    // 創建自己的節目
    [sc addChild:ls];
    // 把節目加到通用劇場尚
    return sc;
}
+ (id) node
{
    return [[[[self class] alloc] init]autorelease];
}

// CCLayer.m

-(id) init

{

if( (self=[super init]) ) {

CGSize s = [[CCDirector sharedDirector] winSize];

anchorPoint_ = ccp(0.5f, 0.5f);

[self setContentSize:s];

self.isRelativeAnchorPoint = NO;

isTouchEnabled_ = NO;

#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED

isAccelerometerEnabled_ = NO;

#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)

isMouseEnabled_ = NO;

isKeyboardEnabled_ = NO;

#endif

}

return self;

}


LoadingScene類繼承於CCLayer類的,於是我們可以通過上面代碼發現,LoadingScene對象在初始化過程中調用到CCLayer的init方法,而其中使用到了導演類的 winSize 方法,並以其作爲setContentSize的參數。

其中winSize方法是獲取當前屏幕CGRect(x,y,width,height)的方法。

那麼,回到最上面的代碼中,設備旋轉過後創建的劇場sc的視圖width = 480,height = 320,橫放,座標原點按照OpenGL View的規格放在左下角。

而在設備旋轉之前、作爲rvc視圖的glView則是使用當時window的長和寬來定義的width =320,height = 480,豎直襬放(相對手機來說),未隨着設備的旋轉自動調整角度,而是跟着設備一起旋轉。所以,座標原點按照iOS View放在左上角,也就是設備正看時的左上角,橫放時的左下角。


好了,說到這裏,這個唯美的故事就這樣發生了,而且已經成爲一歷史了,完。



關於iOS6的屏幕旋轉詳細解說請參考:http://blog.csdn.net/jaywon/article/details/8208991

更多關於用cocos2d編寫《憤怒的小鳥》遊戲的筆記請看 《iOS cocos2d學習筆記》系列

扉頁:http://blog.csdn.net/youngsblog/article/details/9717335



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章