2015年04月12日

cocos2d-xでAdMobメディエーションの実装

今週は広告表示の実装をしました。広告会社は傾撃の時と同じでAppBankNetwork、iAd、AdMobをAdMobメディエーションで切り替える感じです。アイコン型とかウォール型の広告にも興味があるのですがリジェクトされるという噂もあるので、とりあえずバナー型とインタースティシャル型だけで。

各Webサイト側での設定は以前に済ませていたようで全く覚えていないのでプログラム側だけメモ書きです。

  1. 次のファイルをダウンロードしてプロジェクトに追加。
    • GoogleMobileAds.freamwork
    • libAdapterIAd.a
    • NendSDKのNendAdフォルダ
    • NendSDKのlibAdapterNend.a
  2. 次のフレームワークを追加。
    • AdSupport
    • AudioToolbox
    • AVFoundation
    • CoreGraphics
    • CoreTelephony
    • EventKit
    • EventKitUI
    • MessageUI
    • StoreKit
    • SystemConfiguration
    • UIKit
    • CoreMedia
    • Security
    • iAd
  3. RootViewControllerに広告ビューのインスタンスと作成、表示処理を追加。
    • RootViewController.h
    • #import "GoogleMobileAds/GADBannerView.h"
      #import "GoogleMobileAds/GADInterstitial.h"
      
      @interface RootViewController : UIViewController {
          GADBannerView *bannerView_;
          GADInterstitial *interstitialView_;
      }
      
      @property (nonatomic, retain)GADBannerView *bannerView;
      @property (nonatomic, retain)GADInterstitial *interstitialView;
      
      - (void)createAdBanner;
      - (void)deleteAdBanner;
      - (void)createAdInterstitial;
      - (void)viewAdInterstitial;
      
      @end
      
    • RootViewController.mm
    • - (void)createAdBanner
      {
          // すでに作成済みの場合は処理しない
          if (self.bannerView != nil) {
              return;
          }
          
          // 画面下部に標準サイズのビューを作成する
          self.bannerView = [[[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner] autorelease];
          
          // 広告のユニットIDを指定する
          self.bannerView.adUnitID = UNIT_ID;
          
          // ユーザーに広告を表示した場所に後で復元する UIViewController をランタイムに知らせて
          // ビュー階層に追加する。
          self.bannerView.rootViewController = self;
          [self.view addSubview:self.bannerView];
          
          // 広告リクエストを作成する
          GADRequest *request = [GADRequest request];
          
          // テスト広告のリクエストを行う。
          request.testDevices = [NSArray arrayWithObjects:TEST_DEVICE_ID, nil];
          
          // リクエストを行って広告を読み込む
          [self.bannerView loadRequest:request];
      }
      
      - (void)deleteAdBanner
      {
          // バナーを取り除く
          [self.bannerView removeFromSuperview];
          
          // バナーを削除する
          self.bannerView = nil;
      }
      
      - (void)createAdInterstitial
      {
          // インタースティシャル広告を作成する
          self.interstitialView = [[[GADInterstitial alloc] init] autorelease];
          
          // 広告のユニットIDを指定する。
          self.interstitialView.adUnitID = UNIT_ID;
          
          // デリゲートを設定する
          self.interstitialView.delegate = self;
          
          // 広告リクエストを作成する
          GADRequest *request = [GADRequest request];
          
          // テスト広告のリクエストを行う。
          request.testDevices = [NSArray arrayWithObjects:TEST_DEVICE_ID, nil];
          
          // リクエストを行って広告を読み込む
          [self.interstitialView loadRequest:request];
      }
      
      - (void)viewAdInterstitial
      {
          // インタースティシャル広告を表示する準備ができている場合、
          // 広告を表示する。
          if ([self.interstitialView isReady]) {
              [self.interstitialView presentFromRootViewController:self];
          }
      }
      
      - (void)interstitialDidDismissScreen:(GADInterstitial *)ad
      {
          // インタースティシャル広告の表示が終了した時に、
          // 再度作成を行う。
          [self createAdInterstitial];
      }
      
  4. C++からネイティブコードを呼び出すためのクラスを作成する。ここではクラス名はAdvertisementとした。
    • Advertisement.h
    • class Advertisement {
      public:
          static void viewBanner();
          static void hideBaaner();
          static void viewInterstatial();
      };
      
    • Advertisement.mm
    • void Advertisement::viewBanner()
      {
          UIWindow *window = [UIApplication sharedApplication].keyWindow;
          if (window == nil) {
              window = [[UIApplication sharedApplication].windows objectAtIndex:0];
          }
      
          if ([window.rootViewController isKindOfClass:[RootViewController class]]) {
              RootViewController *rootViewController = (RootViewController *)window.rootViewController;
              [rootViewController createAdBanner];
          }
      }
      
      void Advertisement::hideBaaner()
      {
          UIWindow *window = [UIApplication sharedApplication].keyWindow;
          if (window == nil) {
              window = [[UIApplication sharedApplication].windows objectAtIndex:0];
          }
          
          if ([window.rootViewController isKindOfClass:[RootViewController class]]) {
              RootViewController *rootViewController = (RootViewController *)window.rootViewController;
              [rootViewController deleteAdBanner];
          }
      }
      
      void Advertisement::viewInterstatial()
      {
          UIWindow *window = [UIApplication sharedApplication].keyWindow;
          if (window == nil) {
              window = [[UIApplication sharedApplication].windows objectAtIndex:0];
          }
          
          if ([window.rootViewController isKindOfClass:[RootViewController class]]) {
              RootViewController *rootViewController = (RootViewController *)window.rootViewController;
              [rootViewController viewAdInterstitial];
          }
      }
      
ラベル:とりとま AdMob
posted by かねだ at 21:54| Comment(0) | 開発記録 | このブログの読者になる | 更新情報をチェックする

2015年04月05日

cocos2d-xでのGame Center対応

傾撃でもGame Centerに対応していたのですが、iOSのバージョンアップやらcocos2dからcocos2d-xへの変更やらで作り直しをしました。

iTunes Connectにはすでにアプリを登録していたのですが、長いこと放置していたら削除されてしまったので登録からやり直しです。

特に迷うところもないのですが、念のため忘れ防止にメモ書きしておきます。ただ、プログラム周りはあんまり理解せずにググって出てきたものを真似して作ってるところもあるので、もしかするとあんまり正しいやり方じゃないかもしれません。

iTunes Connectでのアプリ登録とGame Centerの設定

  1. iTunes Connectにログイン。
  2. 左上のマイAppのアイコンをクリック。
  3. 左上の+のボタンをクリックして、表示される"新規 iOS App"をクリック。
  4. 以下の設定を入力して"作成"ボタンをクリック。(1作目なのにToritoma2なのはToritomaで作成して放置してたのが削除されて同じ名前が使えなくなったため)
    • 名前 : Toritoma2
    • プライマリ言語 : English
    • バンドルID : com.monochrom-soft.Toritoma2
    • バージョン : 1.0
    • SKU : Toritoma2
  5. 作成されたアプリを選択して、画面真ん中あたりの"Game Center"をクリック。
  6. "シングルゲーム向けに有効化"を選択。
  7. "Leaderboardの追加"をクリック。
  8. シングルLeaderboardの方の"選択する"ボタンをクリック。
  9. 以下の項目を入力。
    • Leaderboardの参照名 : toritomascore
    • Leaderboard ID : toritomascore
    • スコアのフォーマットタイプ : Integer
    • スコア送信タイプ : ベストスコア
    • 並び替えの順序 : 降順
    • スコアの範囲 : (空欄のまま)
  10. "言語を追加"をクリック。
  11. 以下の項目を入力して"Save"をクリック。
    • 言語 : English
    • 名前 : High Score
    • スコアのフォーマット : Integer (100,000.123)
    • スコアのフォーマットサフィックス : (空欄のまま)
    • スコアのフォーマットサフィックス(... : (空欄のまま)
    • 画像 : 1024x1024のアイコンを指定
  12. 右下の"Save"をクリック。
  13. 右下の"Done"をクリック。

プロジェクトにGameKit.frameworkを追加

  1. Xcodeの左側のNavigatorでプロジェクトを選択。
  2. TARGETSの"xxx iOS"を選択。
  3. "Build Phases"を選択。
  4. "Link Binary With Libraries"の中身を表示して、+のボタンをクリックして、GameKit.frameworkを追加する。

RootViewControllerにGKGameCenterControllerDelegateを実装する

RootViewController.hにてGameKit.hをimportしてGKGameCenterControllerDelegateのプロトコルを実装する。

#import <GameKit/GameKit.h>

@interface RootViewController : UIViewController<GKGameCenterControllerDelegate> {

RootViewContoller.mmにgameCenterViewControllerDidFinishを実装する。

- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

Game Centerアクセス用のクラスを作成

今回はc++とネイティブコードの橋渡しをするクラスをOnlineScore、Game Center呼び出しを行うクラスをGameCenterHelperとしました。まだ作ってないですがAndroidでSCOREBOARDに対応するときはScoreBoardHelperとか作ろうかと思っています。

OnlineScore.h

class OnlineScore {
public:
    static void login();
    static void openRanking();
    static void postHighScore(int score);
};

OnlineScore.mm

void OnlineScore::login()
{
    [GameCenterHelper login];
}

void OnlineScore::openRanking()
{
    [GameCenterHelper openRanking];
}

void OnlineScore::postHighScore(int score)
{
    [GameCenterHelper postHighScore:[NSNumber numberWithInt:score]];
}

GameCenterHelper.h

#import <Foundation/Foundation.h>
#import <GameKit/GameKit.h>

@interface GameCenterHelper : NSObject

+(void)login;
+(void)openRanking;
+(void)postHighScore:(NSNumber *)score;

@end

GameCenterHelper.m

#import "GameCenterHelper.h"
#import "RootViewController.h"

static NSString* const LEADERBORD_ID = @"toritoma_score";

@implementation GameCenterHelper

+(void)login
{
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
        if (viewController != nil) {

            UIWindow *window = [UIApplication sharedApplication].keyWindow;
            if (window == nil) {
                window = [[UIApplication sharedApplication].windows objectAtIndex:0];
            }
            [window.rootViewController presentViewController:viewController animated:YES completion:nil];
        }
    };
}

+(void)openRanking
{
    GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
    if (gameCenterController != nil) {

        UIWindow *window = [UIApplication sharedApplication].keyWindow;
        if (window == nil) {
            window = [[UIApplication sharedApplication].windows objectAtIndex:0];
        }

        if ([window.rootViewController isKindOfClass:[RootViewController class]]) {

            RootViewController *rootViewController = (RootViewController *)window.rootViewController;

            gameCenterController.gameCenterDelegate = rootViewController;
            gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
            gameCenterController.leaderboardTimeScope = GKLeaderboardTimeScopeToday;
            gameCenterController.leaderboardCategory = LEADERBORD_ID;
            [rootViewController presentViewController: gameCenterController animated: YES completion:nil];
        }
    }
}

+(void)postHighScore:(NSNumber *)score
{
    GKScore *scoreReporter = [[GKScore alloc] initWithLeaderboardIdentifier:LEADERBORD_ID];
    scoreReporter.value = score;
    scoreReporter.context = 0;

    NSArray *scores = @[scoreReporter];
    [GKScore reportScores:scores withCompletionHandler:^(NSError *error) {
        //Do something interesting here.
    }];
}

@end

呼び出し部分の作成

AppDelegate::applicationDidFinishLaunching()にOnlineScore::login()を呼び出す処理を追加して、ゲームオーバー時にOnlineScore::postHighScore()を、ランキング表示ボタンをタップした時の処理にOnlineScore::openRanking()を呼び出す処理を追加して終わりです。

実機での実行

iPhoneでテスト実行する際にはあらかじめ"設定"の"Game Center"から"サンドボックス"を有効にしておく必要があります。

posted by かねだ at 22:57| Comment(0) | 開発記録 | このブログの読者になる | 更新情報をチェックする

2015年03月29日

ほぼ1年ぶりに更新。

仕事の忙しさにかまけ、反動でスカイリムにハマっていたら、気が付けば10ヶ月もアプリ開発をほっぽってしまっていました。ぼちぼち開発再開していこうと思います。と言っても4月中旬から末まで出張があるのでまたちょっと間が空いてしまうのですが。

どこまで作ってたのか完全に忘れてしまっていたのですが、ソースとかToDoリストとか見てみるとどうやらゲームバランスの調整をやっていたみたいです。細かいことを気にしていると永遠に終わりそうにないので、とりあえず現状でOKとすることにしました。まだ自分でもクリアできてないけど。

あと、エンディングをどうしようか悩んでいたんですが、面倒くさいのでもう昔のファミコンのゲームのごとくラスボス倒したらそのまま2周目に入ることにしました。2周目は難易度上げないとアレなので、手っ取り早く、自機の攻撃力ダウン、雑魚が死んだ時に弾発射、ボスの攻撃に追加で定期的に弾発射、としてみました。試しに残機を90からスタートするようにしてテストプレイして見た結果、クリアする頃には残り40機まで減ってたので普通の条件だと到底クリアできそうにないですが、とりあえずリリース優先でこれもこのままで。(若干なげやり)

これでゲームプレイ部分は大体できたことになるので、あとは広告などの周辺機能とバグの修正など。できれば出張前にリリース出来ると良いんですが、今までのペースでいくと無理っぽい。でも5月にはリリースしたいです。
ラベル:とりとま
posted by かねだ at 23:11| Comment(0) | 開発記録 | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。