Wednesday, March 11, 2015

Cocos2d-x: Tích hợp quảng cáo Admob vào Game (Phần 1)


Hôm nay chúng ta sẽ cùng tìm hiểu về chủ đề "Tích hợp quảng cáo Admob vào Game".
Ngày nay, đại đa số các bạn làm game đều chủ yếu là phát triển các game Free, sau đó gắn quảng cáo dưới dạng Banner hoặc là Interstitial (Full screen).
Vì quảng cáo Admob của Google không có thư viện riêng cho C++ nói chung hay Cocos2d-x nói riêng, nên chúng ta sẽ tiếp cận việc tích hợp này theo hướng Native Code, tức là tích hợp theo từng nền tảng.
Do đó bài viết này sẽ có 2 phần:
- Phần 1: tích hợp Admob trên nền tảng iOS
- Phần 2: tích hợp Admob trên nền tảng Android.

Giả sử đến giai đoạn này chúng ta đã xây dựng xong được một game theo ý của mình, và chúng ta muốn tích hợp quảng cáo vào game. Chúng ta sẽ đi qua các bước như sau:
1. Tạo thông tin game trong tài khoản Admob của mình
    Tạo các ID cho Banner và Interstital mong muốn
2. Tải bản SDK phù hợp (iOS, Android), tích hợp vào dự án
3. Viết code để hiển thị quảng cáo, điều khiển ẩn hiện quảng cáo theo ý muốn.


Chúng ta bắt đầu đi chi tiết từng bước trên phiên bản iOS

1. Tạo thông tin game và các ID



Với bước này mình nghĩ các bạn sẽ có thể tự thao tác được :)

2. Tải bản SDK Admob dành cho iOS, tích hợp vào Xcode

. Link tải SDK của Admob
. Hướng dẫn tích hợp vào Xcode

3. Hiển thị quảng cáo trong game iOS

Chúng xem xét các trường hợp hiển thị quảng cáo như sau
a. Hiển thị Banner ở trên hoặc dưới mỗi màn hình của game
b. Hiển thị Interstital Ads khi bắt đầu hoặc kết thúc một lần chơi game
c. Ẩn Banner ở một số màn hình game nào đó, ví dụ: About Scene

Do Admob SDK iOS là thư viện native code dành cho bản iOS, nên chúng ta gần như phải viết code bằng Objective-C để hiển thị quảng cáo như bài hướng dẫn tích hợp ở trên.

Chúng ta cùng xem lại cấu trúc của 1 game Cocos2d-x trên iOS. Về mặt logic, game của chúng ta đơn giản chỉ là các Scene được vẽ trên một view duy nhất của ứng dụng iOS, view đó được "control" bởi RootViewController


Như vậy, ý tưởng của chúng ta là: mọi thao tác liên quan đến banner quảng cáo ta sẽ thực hiện trên cái view duy nhất này, ở đây sẽ thực hiện add Banner ở trên, hoặc hiển thị Interstitial, ẩn Banner đã add...
Và việc tiếp theo là trong RootViewController này sẽ định nghĩa các phương thức để điều khiển việc hiện, ẩn, hiển thị này, các phương thức này sẽ được gọi từ các màn hình game của chúng ta, tùy vào sự kiện cụ thể mà điều khiển các quảng cáo này. Và dĩ nhiên, mã nguồn viết trên RootViewController là bằng Objective-C, trong khi game của chúng ta, các màn hình game, đối tượng... được viết bằng C++, vậy thì sao?
Vâng, chúng ta sẽ phải có cái gì đó hỗ trợ gửi lời từ lớp C++ sang lớp Objective-C để game của chúng ta có thể điều khiển được quảng cáo qua việc gọi các hàm...

Lúc này đây, chúng ta sẽ làm quen với bộ thư viện EasyNDK, nó sẽ giúp chúng ta làm được công việc nhập nhằng ở trên.

Link tải EasyNDK tại đây

Sau đó ta thực hiện thêm bộ thư viện này vào Xcode:
- Phần một: thư viện C++


- Phần hai: thư viện Objective-C


Sau khi xong xuôi, chúng ta bắt đầu viết code.

a. Viết code add Banner và hiển thị Interstitial

Đầu tiên chúng ta kiểm tra lớp AppController.
 // Init the CCEAGLView
    CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]
                                         pixelFormat: (NSString*)cocos2d::GLViewImpl::_pixelFormat
                                         depthFormat: cocos2d::GLViewImpl::_depthFormat
                                  preserveBackbuffer: NO
                                          sharegroup: nil
                                       multiSampling: NO
                                     numberOfSamples: 0 ];
    // Use RootViewController manage CCEAGLView
    _viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
    _viewController.wantsFullScreenLayout = YES;
    _viewController.view = eaglView;
Đây chính là đoạn khởi tạo view "duy nhất" mà chúng ta nói ở trên, sau khi khởi tạo view thành công, nó được gán trực tiếp vào viewcontroller điều khiển.
Như vậy là chúng ta không thể can thiệp gì vào cái view duy nhất này nữa, không add banner, không hiển Interstitial.
Chúng sẽ cần sửa lại, không tạo view này ở AppDelegate nữa mà sẽ giao việc này lại cho ViewController, vì như vậy chúng ta mới có thể can thiệp được vào ViewController

Trong AppController chỉnh sửa lại như sau

// Init the CCEAGLView
    /*CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]
                                         pixelFormat: (NSString*)cocos2d::GLViewImpl::_pixelFormat
                                         depthFormat: cocos2d::GLViewImpl::_depthFormat
                                  preserveBackbuffer: NO
                                          sharegroup: nil
                                       multiSampling: NO
                                     numberOfSamples: 0 ];*/


    // Use RootViewController manage CCEAGLView
    _viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
    _viewController.wantsFullScreenLayout = YES;
//    _viewController.view = eaglView;

Trong ViewController, chúng ta sẽ khởi tạo view

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
        CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [[UIScreen mainScreen] bounds]
                                             pixelFormat: kEAGLColorFormatRGBA8
                                             depthFormat: GL_DEPTH24_STENCIL8_OES
                                      preserveBackbuffer: NO
                                              sharegroup: nil
                                           multiSampling: NO
                                         numberOfSamples: 0];
       
        self.view = eaglView;
    return self;
}

Khai báo các đối tượng phục vụ cho việc hiển thị quảng cáo
Trong ViewController.h

#import <UIKit/UIKit.h>
#import "GADBannerView.h"
#import "GADInterstitial.h"

@interface RootViewController : UIViewController<GADInterstitialDelegate, AdBuddizDelegate> {
    GADBannerView         *_gadBannerView;
    GADInterstitial             *_gadInterstitial;
}
- (BOOL) prefersStatusBarHidden;
            - (void)showIntertistitalAds:(NSObject *)prms;
@end
Khởi tạo Banner quảng cáo
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        ...........
        CGSize screenSize = [UIScreen mainScreen].bounds.size;
       
        if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
        {
            _gadBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeLeaderboard];
            _gadBannerView.frame    = CGRectMake(24, 0, 720, 90);
        } else {
            _gadBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
            _gadBannerView.frame    = CGRectMake(0, 0, screenSize.width, 50);
        }
       
       
        _gadBannerView.adUnitID = @"ca-app-pub-xxxxxxxxxxx";
        _gadBannerView.rootViewController = self;
       
        GADRequest *request = [GADRequest request];
        request.testDevices = @[ GAD_SIMULATOR_ID ];
        [_gadBannerView loadRequest:request];
       
        [self.view addSubview:_gadBannerView];
        _gadInterstitial = nil;
        GADInterstitial *interstitial = [[GADInterstitial alloc] init];
        interstitial.adUnitID = @"ca-app-pub-xxxxxxxxxxxxxxxxxx";
        interstitial.delegate = self;
        [interstitial loadRequest:request];
   
        return self;
}
Nếu đến đây chúng ta build và run code trên Simulator là đã thấy có banner được add bên trên


Để hiển thị Interstital sau mỗi lần kết thúc 1 sự kiện chơi game, chúng ta cần viết thêm mã cho việc hiển thị Interstial

- (void)showIntertistitalAds:(NSObject *)prms
{
    if (_gadInterstitial) {
        [_gadInterstitial presentFromRootViewController:self];
    }
}

b. Gọi hàm điều khiển quảng cáo từ các lớp C++

Để C++ có thể gọi được hàm showIntertistitalAds của ViewController, thì ViewController cần đăng ký nó là một bộ nhận (receiver) với EasyNDK

#import "IOSNDKHelper.h"
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        ...........
        [IOSNDKHelper setNDKReceiver:self];
    }
    return self;
}
 Giả sử trong IngameScene.cpp, chúng ta sẽ gọi hàm này như sau

#include "NDKHelper.h"

void IngameScene::showAds()
{
    sendMessageWithParams("showIntertistitalAds", Value());
}



Như vậy là chúng ta đã cùng tìm hiểu cách thức hiển thị quảng cáo Admob trong Game được xây dựng bằng Cocos2d-x C++ trên nền tảng iOS

Chúng ta sẽ tiếp tục tìm hiểu trên nền tảng Android ở phần tiếp theo.

No comments:

Post a Comment