顯示具有 ios 標籤的文章。 顯示所有文章
顯示具有 ios 標籤的文章。 顯示所有文章

[cocos2dx-IOS篇]在Xcode中,替Cocos2D-X專案添加Admob廣告

文章撰寫日期︰2014/01/04 12:36
cocos2d-x使用版本︰2.1.4

一、前言

廣告是app開發商的獲利方式之一,
Google的Admob更是眾多開發者的選擇。
因此學會如何串接Admob也變得非常重要。

二、文章開始

第1步 下載ios-Admob套件

先到Google Admob網站下載Admob


第2步 添加Admob Library檔至遊戲專案

我們將下載後的檔案解壓縮,
放在常收納套件的收藏資料夾底下。
(我放在ios/third-party/目錄底下)
解壓縮下載完後的Admob套件
在Xcode的遊戲專案,
按右鍵,選擇Add Files to "您的專案"。
選擇Admob套件剛才存放的地方
新增後,在專案資料夾就看到Admob的套件檔添加進來了。

第3步 添加Admob需要用到的Framework

依照Admob官方的說明,
在使用Admob我們需要下列這些Framework
  • AdSupport
  • AudioToolbox
  • AVFoundation
  • CoreGraphics
  • MessageUI
  • StoreKit
  • SystemConfiguration
添加Framework的方式

第4步 設定-ObjC屬性

  1. In Xcode's project navigator, press the blue top-level project icon.
  2. Click on your target, then the Build Settings tab.
  3. Under Other Linker Flags, add -ObjC to both Debug and Release.

第5步 添加Admob code到程式裡

如果你接下來想照著官方教學繼續這麼做,
我會建議不要。

為什麼?
如果你剛才一直照著我說的,
跟著官方step by step加入Admob,
那麼你現在可以試看看按Run來啟動專案。

第6步 error解除

啟動後,
Shit!無法執行!
 
你會發現編譯器告訴你︰
Admob裡有一個叫GoogleAnalytics的東西,
main.m檔要求compiler在編譯這份文件時,
這個m檔需要使用ios的ARC機制!

我的經驗是不要干脆不要使用GoogleAnalytics,
因為我花了一天還是處理不完,
沒完沒了。
所以就把它刪掉了。
再次執行,
仍然無法編譯成功。
這次的錯誤是找不到Library。

第7步 重設並整理Library路徑

Target選擇我們的專案,
選擇[Build Settings] 找到Search Paths後,
在Debug列表點擊2下。
發現原本的路徑全跑掉了,
只好重設。
因為我是用Javasript來寫cocos2d-x,
因此上面的library看的到有使用spidermonkeyscripting/javascript/spidermonkey-ios/lib\。 將上面3個路徑改到實体路徑
\"$(SRCROOT)/../../../scripting/javascript/spidermonkey-ios/lib\"
變成
/Users/lp43/cocos2d-x/cocos2d-x2.1.4/scripting/javascript/spidermonkey-ios/lib
依此類推。

然後,
因為剛才我們已經將Google Analytics(Google追蹤)套件拿掉了,
因此上面紅框的部份都可以刪掉。

第8步 確認專案已修復並可執行

這時候再重新run一次專案,
發現專案又復活了,可以正常執行。

第9步 添加Admob code

現在可以回到官方的admob教學流程了,
在RootViewController.h添加code如下
#import 

#import "GADBannerViewDelegate.h"//加入這行
@class GADBannerView;//加入這行
@class GADRequest;//加入這行

@interface RootViewController : UIViewController//加入這個Delegate
- (void) SampleSelector:(NSObject *)prms;

@property(nonatomic, strong) GADBannerView *adBanner;//加入這行
- (GADRequest *)request;//加入這行
@end

然後, 在RootViewController.mm加入
#import "RootViewController.h"
#include "IOSNDKHelper.h"

#import "GADBannerView.h"//加入這行
#import "GADRequest.h"//加入這行

@implementation RootViewController

// Override to allow orientations other than the default portrait orientation.
// This method is deprecated on ios6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return UIInterfaceOrientationIsLandscape( interfaceOrientation );
}

// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (NSUInteger) supportedInterfaceOrientations{
#ifdef __IPHONE_6_0
    return UIInterfaceOrientationMaskAllButUpsideDown;
#endif
}

- (BOOL) shouldAutorotate {
    return YES;
}

//fix not hide status on ios7
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        
        // 告訴NDKHelper說 RootViewController會回應來自C++的message
        [IOSNDKHelper SetNDKReciever:self];
        
    }
    return self;
}
- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"Objective-C端的SampleSelector被呼叫了");
    //加入底下
    // Initialize the banner at the bottom of the screen.
    self.adBanner = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
    // Note: Edit SampleConstants.h to provide a definition for kSampleAdUnitID before compiling.
    self.adBanner.adUnitID = @"填上你的admob_id";
    self.adBanner.delegate = self;
    self.adBanner.rootViewController = self;
    [self.view addSubview:self.adBanner];
    [self.adBanner loadRequest:[self request]];
}
//加入底下函式
- (GADRequest *)request {
    GADRequest *request = [GADRequest request];
    
    // Make the request for a test ad. Put in an identifier for the simulator as well as any devices
    // you want to receive test ads.
    request.testDevices = @[
                            // TODO: Add your device/simulator test identifiers here. Your device identifier is printed to
                            // the console when the app is launched.
                            GAD_SIMULATOR_ID,
                            @"如果你要在實機上測試admob,從console裡會有一串實機的編碼,填進這裡"
                            ];
    return request;
}
@end

完成了!

重新執行專案,
會發現Admob完美的岀現在我們cocos2dx的專案上。

三、結論

由於Admob套件裡的Google Analytics使用了ARC機制,
而cocos2d-x專案預設是沒有ARC的,
為了避免ARC與您的專案間改寫與設定上的麻煩,
我直接將Google Analytics套件從Admob中拆掉。

上面的教學我個人覺得已經是最快實作Admob的途徑,
也將整個步驟鉅細靡疑的交待岀來。
希望在看這篇文章的您從中受益,
縮短冤枉的時間。

謝謝您的閱讀。

[cocos2d-x / ios篇]教學1︰在Xcode專案裡使用EasyNDK

文章撰寫日期︰2013/12/29 16:10
cocos2d-x使用版本︰2.1.4

一、前言

Cocos2D-x使用C++語言來攢寫遊戲,
但由於編譯器的不同,
因此不能直接在.cpp檔裡直接使用Objective-C的程式。
(當然,你可以建立一個.mm檔實作C++的.h檔來使用Objective-c)

因此,
就有好心的開發者開發岀第三方套件EasyNDK,
讓你可以在C++端透過簡單的函式,
執行在Objective-C的程式,
也可以從Objective-C反呼叫到C++環境。
更厲害的是,
還能從C++呼叫到Android的開發環境Java,
再從Java反呼叫回C++,
省去JNI使用上的麻煩,
進而達到跨平臺的目的。

二、文章開始


第1步 下載EasyNDK套件

在使用EasyNDK前,
需要先到GitHub下載這套Cocos2D-X的第三方套件。

開啟Terminal(終端機),
在cocos2dx目錄底下輸入
$git clone https://github.com/aajiwani/EasyNDK-for-cocos2dx.git

因為是第三方套件,
我選擇將它放在cocos2dx的tools資料夾底下。

第2步 在您的專案中添加EasyNDK套件

首先,我們準備好一個全新的cocos2d-x空專案,
命名為TestEasyNDK,
並為其它添加EasyNDK套件。

記得選成Create groups for any added folders

添加完後,
就能在專案目錄裡看到這三個資料夾。

三、結論

將EasyNDK套件初始化後,
就可以開始使用它囉!

請見下篇︰
使用EasyNDK從C++呼叫Objective-C。

相關文章

1. 官方教學

[cocos2d-x / ios篇]教學2︰使用EasyNDK從C++呼叫Objective-C

文章撰寫日期︰2013/12/29 16:40
cocos2d-x使用版本︰2.1.4

一、前言

繼上一篇我們在Xcode專案初始化EasyNDK環境後,
這篇就要繼續來說明怎麼從C++呼叫Objective-C

二、文章開始

底下示例從 C++ 叫岀 IOS 的 UIAlertView彈跳視窗。

實作C++端

在Classes\HelloWorldScene.cpp開始處宣告
#include "NDKHelper.h"

然後修改關閉按鈕觸發後的事件如下
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCLog(__FUNCTION__);
    
    // 在C++中呼叫Objective-C的函式︰SampleSelector
    SendMessageWithParams(string("SampleSelector"), NULL);
}

實作Objective-C端

在ios\RootViewController.h宣告即將從C++呼叫的函式SampleSelector

在RootViewController.mm裡匯入EasyNDK套件
#include "IOSNDKHelper.h"

添加底下函式讓Objective-C端註冊IOSNDKHelper,
目的是讓RootViewController.mm有能力監聽從C++端傳來的呼叫
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {

        // 告訴NDKHelper說 RootViewController會回應來自C++的message
        [IOSNDKHelper SetNDKReciever:self];
        
    }
    return self;
}

實作SampleSelector函式
- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"Objective-C端的SampleSelector被呼叫了");
    
    // Show a bogus pop up here
    UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Hello World!"
                                                      message:@"This is a sample popup on iOS"
                                                     delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
    [message show];
}

成功了!

執行專案,
此時看到ios simulator跳岀畫面如下
從C++呼叫岀來的UIAlertView彈跳視窗

三、結論

從上面的教學來看,
從C++呼叫Objective-C一點也不難。
只要將EasyNDK專案匯入遊戲專案,
然後在.cpp和.mm檔引用套件並使用EasyNDK的函式SendMessageWithParams,
便能輕易地與Objecitve-C溝通。

這篇教學文的目的是簡單易懂,
如果您還有進階的需求,
像是想用SendMessageWithParams傳送Object給Objective-C,
或者希望從Objective-C呼叫回C++端,
可以參考官方教學使用CCDictionary的方式或者下一篇。

[IOS篇]Xcode cannot run using the selected device.錯誤

cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天在運行Xcode時,遇到了一個Xcode cannot run using the selected device.的錯誤。


二、解決辦法

上網爬文,很多人都說是運行版本的設置不一致而產生該問題(見下圖)

但筆者在實際實作時,
發現是因為擅自更改專案相關目錄名稱造成的問題。

如果以上辦法無法改善,
建議直接將整個專案砍掉重新建置了。

[IOS篇]Cocos2dX-IOS 直向開發的設定方式

cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1
在RootViewController.mm裡,
- (BOOL)shouldAutorotateToInterfaceOrientation:
函式的return值改回傳為return UIInterfaceOrientationIsPortrait( interfaceOrientation );
 
最後的樣子會變成︰
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return UIInterfaceOrientationIsPortrait( interfaceOrientation );
}