<COCOS2D-X>

3. Admob 연동하기

CodeGrimie 2021. 2. 2. 23:48

20210202. 컴퓨터마다 발생하는 오류가 달라서 계속 수정 중

시작하기에 앞서서 구글은 손들고 벽보고 서있어라.

너네들 Admob Cocos2D-X 가이드 테스트 안 해보고 올린거지?

안 되잖아!!

 

무려 3일간의 삽질 끝에 드디어 애드몹을 연동할 수 있었다.

나처럼 Cocos2D-X에 애드몹을 연동하고 싶지만 구글 공식 가이드를 따라 해도

안 되서 답답한 사람들을 위해서 가이드를 남긴다.

Cocos2D-X 프로젝트 만들기

애드몹(Admob) 자체에 집중하기 위해서 기본 생성 코드를 사용한다.

이 편이 실제로 만든 게임에 적용하기엔 더 참고하기 좋을 것이다.

Cocos2D-X 명령어를 사용해서 새 프로젝트를 만든다.

 

-p(Package) 명령어가 추가되어있다.

cocos new HelloAdmob -l cpp -p com.codegrimie.helloadmob

패키지(Package)는 안드로이드에서 특정 앱을 구분하는 고유 식별자 정도로 이해하면 된다.

보통 { com.(제작자).(앱이름) }의 구성으로 짓는다.

 

안드로이드로 빌드하더라도 Admob을 CPP로 작성하기 때문에 CPP 환경도 미리 설정해준다.

 

▼ CMake 명령어로 비주얼 스튜디오 솔루션을 생성한다.

cmake .. -G "Visual Studio 16 2019" -AWin32

빌드해서 정상적으로 실행되는 것이 확인되면 다음으로 넘어간다.

 

안드로이드 스튜디오에서 해당 프로젝트를 열어서 설정해준다.

자세한 설정 방법은 0. 개발 환경 설정 에서 다루고 있다.

파이어베이스(Firebase) 프로젝트 생성하기

구글 애드몹(Admob)을 사용하기 위해서는 파이어베이스(Firebase) 프로젝트를 먼저 생성해야한다.

파이어베이스 공식 홈페이지 한 가운데에 있기 때문에 찾아다닐 필요조차 없다.

 

▼ 프로젝트 만들기를 누르면 된다.

파이어베이스 프로젝트 생성은 쉽고 간편하게 진행된다.

그냥 시키는대로 3번 설정하면 끝이다.

 

▼ Cocos2D-X 프로젝트 이름과 동일하게 하면 좋다.

계속을 누르면 Google 애널리틱스를 사용하겠냐고 묻는데 무조건 사용해야한다.

 

내 경험담으로 단순히 적힌 내용의 기능들은 안 쓸꺼 같아서 처음 프로젝트 만들 때 사용 해제했었다.

그런데 Admob이 애널리틱스를 사용해야 연동할 수 있어서 다시 수정해줘야만 했다.

 

▼ Google 애널리틱스 사용 설정을 꼭 해야한다.

그다음엔 Google 애널리틱스 계정을 선택하라고 뜨는데 그냥 Default Account for Firebase를 사용하면 된다.

만약 없다면 자동으로 생성해준다.

 

▼ 그냥 프로젝트 만들기 누르면 된다.

잠깐의 기다림 후에 새 프로젝트가 생성되었다고 안내 페이지가 뜬다.

 

▼ 파이어베이스 프로젝트가 정상적으로 생성되었다.

파이어베이스(Firebase) 프로젝트에 앱 추가하기

이제 이 Firebase 프로젝트에 우리가 만들 앱을 추가해야한다.

특별한 일이 없는 한 새 프로젝트가 만들어지면 홈페이지 중앙에 앱을 추가하는 버튼이 생성된다.

 

▼ 가운데에 있는 안드로이드를 누르면 된다.

그러면 몇 가지의 단계를 거쳐서 앱을 추가하게 되는데 차례대로 진행하면 어렵지 않게 진행할 수 있다.

앱 등록을 위한 패키지 이름은 아까 Cocos2D-X 프로젝트 만들 때 사용한 걸 그대로 입력하면 된다.

 

▼ 아까 Cocos2D-X 패키지 명령어와 동일하다.

앱을 등록하고 나면 이제 실제 앱에다가 Firebase를 사용한다고 연동해줘야 한다.

이 부분은 안드로이드에 해당하기 때문에 안드로이드 스튜디오Gradle을 이용해 진행한다.

 

▼ 누가 봐도 내려받고 싶은 버튼을 눌러서 google-services.json을 내려받는다.

Android 앱 모듈 루트 디렉토리로 이동하라는데 그냥 드래그 앤 드랍하라는 의미다.

나처럼 안드로이드 스튜디오가 처음인 사람들이 있을 것이기 때문에 순차적으로 정리한다.

 

▼ 왼쪽 상단의  Android를 클릭하면 프로젝트 표시 방법이 나오는데 여기서 Project를 누른다.

그럼 아래와 같이 뜰 텐데 { [proj] - [proj.android] - [app] } 경로에 google-services.json

드래그 앱 드랍으로 넣어주면 된다.

 

▼ 복잡해보이지만 두 번 밖에 안 타고 들어간다.

Refactor 누르면 된다.

google-services.json을 넣었으니 다음을 눌러서 Firebase SDK를 추가한다.

 

여기서 안드로이드를 개발해본 경험이 없는 사람들은 당황하게 되는데 용어가 처음보기 때문이다.

나 역시 프로젝트 수준, 앱 수준이 대체 뭔 소리냐 하면서 따로 찾아봤어야 했다.

 

이 글에서는 명확하게 어느 위치의 파일을 수정하는 것인지 일일이 알려주기 때문에 따라하기만 하면 된다.

 

먼저 프로젝트 수준build.gradle 을 수정한다.

 

▼ 구글 가이드 코드

프로젝트 수준이 대체 뭔지 몰라서 파일을 찾기 애매한데 먼저 해당 파일을 찾기 쉽도록

Project로 되어있는 프로젝트 표시 방법을 다시 Android로 변경한다.

 

▼ 자주 변경하니 꼭 기억해두자.

여기서 3개의 build.gradle이 있는데 우리가 유심히 보아야 하는 건 따로 있다.

build.gradle 뒤의 () 안에 든 것에 따라 프로젝트 수준, 앱 수준으로 나뉜다.

 

프로젝트 수준

build.gradle (Project: proj.android)

 

▼ 앱 수준

build.gradle (Module: proj.android.HelloAdmob)

 

기본적으로 프로젝트 수준은 Project라고 적혀있기 때문에 구분이 쉽다.

앱 수준은 libcocos2dx가 있어서 헷갈릴 수 있지만 저건 우리가 건드릴 일이 없으니 잊어도 좋다.

 

아무튼 build.gradle (Project: proj.android)을 더블 클릭하면 해당 Gradle 파일을 열어서 수정할 수 있다.

여기에 구글 가이드에 적힌 코드를 복붙하면 된다.

 

▼ 이런 코드가 될 것이다.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.2'
        classpath 'com.google.gms:google-services:4.3.5'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

이렇게 Gradle 파일을 수정하면 우측 상단에 Sync 버튼 팝업이 뜨는데 생길 때마다 항상 눌러주면 된다.

 

▼ 보이면 그냥 냅다 누르면 된다.

 

이제 이어서 앱 수준build.gradle 을 수정한다.

 

▼ 구글 가이드 코드

마찬가지로 build.gradle (Module: proj.android.HelloAdmob)을 더블 클릭하면 수정할 수 있다.

프로젝트 수준에 비해서 훨씬 코드가 많아서 어디를 수정해야 할 지 막막할 수도 있다.

 

쉽게 기억하는 방법은 그냥 가장 마지막 줄에 작성한다고 생각하면 된다.

 

▼ apply pulgin의 위치가 구글과 다르다.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(':libcocos2dx')

    // FIREBASE
    implementation platform('com.google.firebase:firebase-bom:26.4.0')
    implementation 'com.google.firebase:firebase-analytics'
}

apply plugin: 'com.google.gms.google-services'

이 과정이 모두 완료되면 파이어베이스 홈페이지에서는 완료되었다고 안내한다.

하지만 실제로 안드로이드 스튜디오에서 cocos2D-X 프로젝트를 빌드해보면 아래와 같은 에러가 발생한다.

 

▼ 안드로이드X가 누구세요..?

This project uses AndroidX dependencies, but the 'android.useAndroidX' property is not enabled. Set this property to true in the gradle.properties file and retry.

복잡하게 생각할 필요없이 AndroidX 종속성을 사용하는데 활성화가 되어있지 않다고 한다.

gradle.properties에 아래의 두 코드를 포함시켜서 AndroidX를 사용한다고 알려주면 된다.

android.enableHetifier=true
android.useAndroidX=true

그리고 다시 빌드를 해보면 안드로이드 스튜디오도 문제없이 빌드가 된다.

애드몹(Admob)에 새 앱 등록하기

이제 애드몹(Admob)에서 새 앱을 설정한다.

파이어베이스와 마찬가지로 등록하는 것은 매우 쉽고 간단하다.

연동하고 써먹는게 그지 같아서 그렇지.

 

▼ 플랫폼과 앱스토어 등록 여부를 설정한다.

▼ 앱 이름은 Cocos2D-X 프로젝트 이름과 같으면 좋다.

사용자 측정항목은 체크 해제해도 문제없다.

확인을 누르면 앱이 만들어지는데 광고 단위를 바로 붙일 필요는 없다.

 

우선 우리가 만든 파이어베이스 프로젝트와 연결시켜주는 것부터 진행해야 한다.

앱을 만들고 잠깐의 시간이 지나면 FIREBASE 연결 버튼이 활성화 된다.

 

이후의 과정 역시 하라는 대로만 하면 완료된다.

 

▼ 앱 설정에서 연결할 수 있다.

FIREBASE 연결 버튼을 누르면 패키지 이름을 작성해달라고 한다.

 

▼ 우리가 설정한 패키지 이름을 입력한다.

 

▼ 프로젝트를 선택하면 된다.

 

▼ 아래처럼 나온다면 연결이 완료된 것이다.

자, 여기서 한가지 작업을 더해줘야 하는데 다시 파이어베이스로 돌아가야 한다.

우리가 애드몹을 연결하면서 google-services.json 이 업데이트 되었기 때문에 다시 내려받아서 옮겨준다.

 

안드로이드 스튜디오에서 다시 한번 빌드해서 정상적으로 실행이 되는지 확인해보자.

여기 까지 왔다면 이제 Admob을 사용할 사전 준비(!!)가 완료되었다.

이제부터가 진짜 중요하다.

Firebase 코드 추가하기

아마 애드몹 연동 중에서 가장 짜증나는 부분이었다.

Firebase SDK를 내려받아서 압축을 푼다.

 

firebase_cpp_sdk 폴더를 HelloAdmob 프로젝트 폴더 안에 옮겨 넣는다.

 

▼ CMakeLists.txt와 같은 위치에 있어야 한다.

이제 Gralde이 이 firebase_cpp_sdk를 인식하도록 설정해야한다.

 

gradle.properties에서 firebase_cpp_sdk 폴더의 위치를 지정한다.

systemProp.firebase_cpp_sdk.dir=D\:\\Workspaces\\COCOS2D\\HelloAdmob\\firebase_cpp_sdk

이 코드는 Gradle 시스템 변수 firebase_cpp_sdk.dir에 경로를 지정해준다.

Gradle은 \\로 구분하는 것을 조심해야한다.

 

다른 gradle에서도 사용할 수 있도록 정의해두기 위해서 settings.gradle에서 아래의 코드를 추가한다.

def firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')

gradle.ext.firebase_cpp_sdk_dir = "$firebase_cpp_sdk_dir"
includeBuild "$firebase_cpp_sdk_dir"

 

 

build.gradle (Module: proj.android.HelloAdmob)의 마지막에 아래의 코드를 추가한다.

project.ext {
    // Configure the Firebase C++ SDK location.
    firebase_cpp_sdk_dir = System.getProperty('firebase_cpp_sdk.dir')
    if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
        firebase_cpp_sdk_dir = System.getenv('FIREBASE_CPP_SDK_DIR')
        if (firebase_cpp_sdk_dir == null || firebase_cpp_sdk_dir.isEmpty()) {
            if ((new File('firebase_cpp_sdk')).exists()) {
                firebase_cpp_sdk_dir = 'firebase_cpp_sdk'
            }
            else {
                throw new StopActionException( 'firebase_cpp_sdk.dir property or the FIREBASE_CPP_SDK_DIR ' + 'environment variable must be set to reference the Firebase C++ ' + 'SDK install directory. This is used to configure static library ' + 'and C/C++ include paths for the SDK.')
            }
        }
    }

    if (!(new File(firebase_cpp_sdk_dir)).exists()) {
        throw new StopActionException( sprintf('Firebase C++ SDK directory %s does not exist', firebase_cpp_sdk_dir))
    }
}

이제 안드로이드가 CPP 파일을 받아서 빌드할 수 있도록 Android.mk를 만들어줘야 하는데 위치가 정해져있다.

 

{ [app] - [jni] } 안에 만든다.

 

▼ Android.mk 파일에 들어가는 코드

LOCAL_PATH := $(call my-dir)

# The path to the Firebase C++ SDK, in the project's root directory.
FIREBASE_CPP_SDK_DIR := ../../../firebase_cpp_sdk

APP_ABI := armeabi-v7a x86
STL := $(firstword $(subst _, ,$(APP_STL)))
FIREBASE_LIBRARY_PATH := $(FIREBASE_CPP_SDK_DIR)/libs/android/$(TARGET_ARCH_ABI)/$(STL)

include $(CLEAR_VARS)
LOCAL_MODULE := firebase_app
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libapp.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := firebase_feature
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libadmob.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := firebase_database
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libfirebase_database.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := firebase_admob
LOCAL_SRC_FILES := $(FIREBASE_LIBRARY_PATH)/libfirebase_admob.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(FIREBASE_CPP_SDK_DIR)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos/audio/include)

LOCAL_MODULE := MyGame_shared
LOCAL_MODULE_FILENAME := libMyGame

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../../Classes/AppDelegate.cpp \
                   ../../../Classes/HelloWorldScene.cpp 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes

# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END

LOCAL_STATIC_LIBRARIES := cocos2dx_static
LOCAL_STATIC_LIBRARIES += firebase_feature
LOCAL_STATIC_LIBRARIES += firebase_admob
LOCAL_STATIC_LIBRARIES += firebase_database
LOCAL_STATIC_LIBRARIES += firebase_app

# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)

# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END


Admob 테스트 코드 작성

자 이제 드디어 Cocos2D-X에 Admob 테스트 코드를 작성할 차례다.

말이 작성이지 사실은 복붙하는 경우가 맞을 것이다.

 

코드 분석은 개인에게 맡기고 지금은 일단 배너 광고를 하나 띄우는데 집중한다.

CMakeList.txt 파일과 AppDelegate.cpp, GameScene.h, GameScene.cpp를 수정하고

FirebaseHelper.h와 FirebaseHelper.cpp를 새로 작성한다.

 

코드 자체는 구글의 예시 코드를 가져왔지만 전체적으로 안드로이드나 ios 일 때만 빌드하도록 감쌌다.

 

▼ CMakeList.txt 가장 아래에 아래의 코드를 추가한다.

if(ANDROID)
# ADMOB
add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
set(firebase_libs firebase_admob firebase_app)
target_link_libraries(${APP_NAME} "${firebase_libs}" ${ADDITIONAL_LIBS})
endif()

Cocos2D-X는 멀티플랫폼 빌드를 위해서 CMake를 사용한다.

CMake에서 firebase_cpp_sdk 위치를 가져오기 위한 코드다.

 

▼ AppDelegate.cpp 수정

#include "AppDelegate.h"
#include "HelloWorldScene.h"

///////////////////////////////////////////////
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "firebase/app.h"
#include "firebase/admob.h"
#endif
///////////////////////////////////////////////

// ...

///////////////////////////////////////////////
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    // Initialize Firebase for Android.
    firebase::App* app = firebase::App::Create(
        firebase::AppOptions(), JniHelper::getEnv(), JniHelper::getActivity());
    // Initialize AdMob.
    firebase::admob::Initialize(*app, "INSERT_YOUR_ADMOB_ANDROID_APP_ID");
    // Initialize AdMob.
    firebase::admob::Initialize(*app);
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    // Initialize Firebase for iOS.
    firebase::App* app = firebase::App::Create(firebase::AppOptions());
    // Initialize AdMob.
    firebase::admob::Initialize(*app, "INSERT_YOUR_ADMOB_IOS_APP_ID");
    // Initialize AdMob.
    firebase::admob::Initialize(*app);
#endif
///////////////////////////////////////////////

// create a scene. it's an autorelease object
auto scene = HelloWorld::createScene();

// run
director->runWithScene(scene);

위치를 잘 확인하고 복붙하면 된다.

 

▼ FirebaseHelper.h

#ifndef __FIREBASE_HELPER_H__
#define __FIREBASE_HELPER_H__
#include "cocos2d.h"

USING_NS_CC;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

#include "firebase/admob/types.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
extern "C" {
#include <objc/objc.h>
}  // extern "C"
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
firebase::admob::AdParent getAdParent();
#endif

#endif

#endif // __FIREBASE_HELPER_H__


▼ FirebaseHelper.cpp

#include "FirebaseHelper.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "platform/android/jni/JniHelper.h"

USING_NS_CC;

firebase::admob::AdParent getAdParent() {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    // Returns the iOS RootViewController's main view (i.e. the EAGLView).
    return (id)Director::getInstance()->getOpenGLView()->getEAGLView();
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    // Returns the Android Activity.
    return JniHelper::getActivity();
#else
    // A void* for any other environments.
    return 0;
#endif
}

#endif

새로운 소스파일을 추가했기 때문에 CMakeList.txt와 Android.mk를 수정해줘야한다.

 

▼ CMakeList.txt 수정

# add cross-platforms source files and header files 
list(APPEND GAME_SOURCE
     Classes/AppDelegate.cpp
     Classes/HelloWorldScene.cpp
     Classes/FirebaseHelper.cpp
     )
list(APPEND GAME_HEADER
     Classes/AppDelegate.h
     Classes/HelloWorldScene.h
     Classes/FirebaseHelper.h
     )

 

▼ Android.mk 수정

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../../Classes/AppDelegate.cpp \
                   ../../../Classes/HelloWorldScene.cpp \
                   ../../../Classes/FirebaseHelper.cpp

이제 실제로 Admob을 출력 할 HelloWorldScene을 작성한다.

 

▼ HelloWorldScene.h 수정

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "firebase/admob/banner_view.h"
#endif

class HelloWorld : public cocos2d::Scene
{
private:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    firebase::admob::BannerView* banner_view;
#endif

public:
    static cocos2d::Scene* createScene();

    virtual bool init() override;
    virtual void update(float delta) override;
public:
    
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

 

▼ HelloWorldScene.cpp 수정

#include "HelloWorldScene.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

#include "FirebaseHelper.h"

#include "firebase/admob.h"
#include "firebase/admob/types.h"
#include "firebase/app.h"
#include "firebase/future.h"
#include "firebase/admob/banner_view.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <android/log.h>
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif

#endif

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    return HelloWorld::create();
}

// Print useful error message instead of segfaulting when files are not there.
static void problemLoading(const char* filename)
{
    printf("Error while loading: %s\n", filename);
    printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

    if (closeItem == nullptr ||
        closeItem->getContentSize().width <= 0 ||
        closeItem->getContentSize().height <= 0)
    {
        problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
    }
    else
    {
        float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;
        float y = origin.y + closeItem->getContentSize().height/2;
        closeItem->setPosition(Vec2(x,y));
    }

    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
    if (label == nullptr)
    {
        problemLoading("'fonts/Marker Felt.ttf'");
    }
    else
    {
        // position the label on the center of the screen
        label->setPosition(Vec2(origin.x + visibleSize.width/2,
                                origin.y + visibleSize.height - label->getContentSize().height));

        // add the label as a child to this layer
        this->addChild(label, 1);
    }

    // add "HelloWorld" splash screen"
    auto sprite = Sprite::create("HelloWorld.png");
    if (sprite == nullptr)
    {
        problemLoading("'HelloWorld.png'");
    }
    else
    {
        // position the sprite on the center of the screen
        sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

        // add the sprite as a child to this layer
        this->addChild(sprite, 0);
    }

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

#if defined(__ANDROID__)
    // Android ad unit IDs.
    const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
#else
    // iOS ad unit IDs.
    const char* kBannerAdUnit = "ca-app-pub-3940256099942544/6300978111";
#endif

    // Create and initialize banner view.
    //firebase::admob::BannerView* banner_view;
    banner_view = new firebase::admob::BannerView();
    firebase::admob::AdSize ad_size;
    ad_size.ad_size_type = firebase::admob::kAdSizeStandard;
    ad_size.width = 320;
    ad_size.height = 50;
    banner_view->Initialize(getAdParent(), kBannerAdUnit, ad_size);

#endif

    this->scheduleUpdate();

    return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
    Director::getInstance()->end();
}

void HelloWorld::update(float delta)
{
    Node::update(delta);

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

    // Check that the banner has been initialized.
    if (banner_view->InitializeLastResult().status() ==
        firebase::kFutureStatusComplete) {
        // Check that the banner hasn't started loading.
        if (banner_view->LoadAdLastResult().status() ==
            firebase::kFutureStatusInvalid) {
            // Make the banner visible and load an ad.
            CCLOG("Loading a banner.");
            banner_view->Show();
            firebase::admob::AdRequest my_ad_request = {};
            banner_view->LoadAd(my_ad_request);
        }
    }
#endif

}

 

 

 

참고 자료

Cocos2D-X의 사용도가 얼마나 떨어졌는지 알 수 있었던게 자료가 없다.그나마 있는 자료들도 레거시 코드라 지금은 안 되는 것들이 대부분이고 그나마 찾은 것들도 최근 버전에 맞게 수정을 해야 적용되었다.

 

밑의 어마어마한 참고자료를 보면 알겠지만 엄청난 삽질들이 있었다.

 

결론 부터 말하자면 Firebase에 위치하는 CMakeList.txt를 수정해야하는 것이었다..

CMake에 대해서 공부를 안 했던 것이 이렇게 큰 스노우볼이 되어 돌아올 줄이야..제기랄..

 

▼ AndroidManifest.xml에 아래의 광고ID 설정이 추가되어야 한다.

 <!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>

 

이제서야 Admob이 정상적으로 연동이 된 것이다..!

실제 Cocos2D-X에서 사용해보자...

 

Android.mk 파일을 만들어서 아래의 코드를 입력해준다.

 

CMakeList.txt

add_subdirectory(${FIREBASE_CPP_SDK_DIR} EXCLUDE_FROM_ALL)
set(FIREBASE_LIBRARY_PATH ${FIREBASE_CPP_SDK_DIR}/libs/android/arm64-v8a/c++)

target_link_libraries(${APP_NAME} ${FIREBASE_LIBRARY_PATH}/libfirebase_app.a)
target_link_libraries(${APP_NAME} ${FIREBASE_LIBRARY_PATH}/libfirebase_admob.a)
target_link_libraries(${APP_NAME} ${FIREBASE_LIBRARY_PATH}/libfirebase_analytics.a)

 

 

firebase.google.com/docs/cpp/setup?platform=android#analytics-enabled

 

C++ 프로젝트에 Firebase 추가

C++ 프로젝트에 Firebase 추가plat_iosplat_androidplat_cpp iOS 및 Android용 Firebase를 기반으로 C++ 인터페이스를 제공하는 Firebase C++ SDK를 사용하여 C++ 게임을 업그레이드하세요. 플랫폼 네이티브 코드를 작성

firebase.google.com

firebase.google.com/docs/admob/cpp/cocos2d-x?hl=ko

 

Cocos2d-x  |  Firebase

이 가이드에서는 새로 만든 Cocos2d-x 프로젝트에 AdMob과 Firebase를 포함하는 방법을 보여줍니다. 아직 프로젝트가 없다면 기본 요건을 완료하고 다음과 같이 명령줄에서 cocos 프로젝트를 새로 만드

firebase.google.com

qiita.com/pakiakose/items/564c32dbb16638a02607

 

cocos2d-x/AndroidStudio에서 admob사용을 위한 Firebase 도입 1 - Qiita

cocos2d-x 3.17.1 AndroidStudio 3.4.1 공식 가이드 페이지 -> Add Firebase to your C++ project Firebase 프로젝트 추가 후 앱을 추가합니다...

qiita.com

qiita.com/pakiakose/items/954e94413643e7a9fe8e

 

cocos2d-x/Android Studio에서 admob사용을 위한 Firebase 도입 2 - Qiita

cocos2d-x 3.17.1 AndroidStudio 3.4.1 Firebase C++ SDK 다운로드 링크 -> Add Firebase C++ SDKs 다운받은 sdk를 압축을 풀고 아래의 경로...

qiita.com

github.com/FirebaseExtended/cocos2dx-cpp-sample/tree/master/admobgithub.com/FirebaseExtended/cocos2dx-cpp-sample/

 

FirebaseExtended/cocos2dx-cpp-sample

Firebase Cocos2d-x samples. Contribute to FirebaseExtended/cocos2dx-cpp-sample development by creating an account on GitHub.

github.com

discuss.cocos2d-x.org/t/tutorial-integrate-firebase-admob-with-cocos2d-x-c-and-firebase-cpp-sdk/42768

developers.google.com/admob/android/quick-start#update_your_androidmanifestxml

 

시작하기  |  Android  |  Google Developers

Android 앱을 제작 중인 Google AdMob 게시자를 위한 모바일 광고 SDK입니다.

developers.google.com

 

medium.com/androiddevelopers/how-to-integrate-firebase-into-your-native-c-android-game-aa0d76eeba23

 

How to integrate Firebase into your native C++ Android game.

Many games have a core thing in common when you really dig under the surface: there’s almost always a soft nougaty core of C++. Firebase…

medium.com

static-jsony.tistory.com/8

 

cocos2d - firebase (with AndroidStudio)

(각 종속 항목들 버전 확인 -> https://firebase.google.com/docs/android/setup?hl=ko#available_libraries) ▶ project Gradle buildscript { repositories { .... } dependencies { classpath 'com.android.t..

static-jsony.tistory.com

discuss.cocos2d-x.org/t/firebase-admob-crashes/38841/3

 

Firebase Admob crashes

I got the same error… i check whole things… not found a single mistake… are you solve it out @FailingUser can you help me 12-01 00:26:10.746 31219-31256/? E/firebase: Unable to check Google Play services availablity as the com.google.android.gms.comm

discuss.cocos2d-x.org

 

프로젝트 크기 줄이기

Cocos2D-X는 엔진 소스 파일을 모조리 복사하는데 장단점이 있는 방식이다.

 

장점으로는 일단 프로젝트를 만들면 엔진 코드가 있기 때문에 독립적으로 개발할 수 있지만

단점으로는 프로젝트 폴더 크기가 매우 커진다.

 

이를 해결하기 위해서는 심볼릭링크(Symbolic Link)를 사용해서 해결할 수 있다.

간단하게 말하면 바로가기를 사용한 방법이다.

 

우선 프로젝트 폴더에서 cocos2d 폴더를 삭제한다.

이 엔진 코드 폴더가 용량을 많이 먹는 거라서 이걸 삭제하면 조금은 쾌적해진다.

대신 컴파일러가 우리의 게임을 컴파일 하려면 엔진 코드가 필요한데 이걸 엔진 폴더를 직접 연결해줘서 해결한다.

 

프로젝트 폴더 안에서 아래의 명령어를 입력하면 된다.

 

▼ -Name은 현재 만들 폴더 -Target은 엔진 폴더 위치

new-Item -ItemType SymbolicLink -Name cocos2d -Target C:\cocos2d-x-4.0