Search…

Phát Triển Game Funny Halloween Pumpkins với Cocos2d-x - Phần 2

21/09/20208 min read
Bài viết hướng dẫn các bạn mới muốn học làm game bằng Cocos2d-x. Thông qua bài viết này, các bạn có thể biết đuợc một số kiến thức về xử lý cũng như cách bố trí cấu trúc của game để có thể tự làm game cho mình.

Giới thiệu

Bài viết trước hiện thực StateGamePlay, bài viết này tiếp tục hiện thực StateEndGame.

StateEndgame

End game scene

StateEndGame.h

#ifndef __STATE_ENDGAME__H__
#define __STATE_ENDGAME__H__

#include "cocos2d.h"

USING_NS_CC;

class StateEndGame : public cocos2d::Layer
{
public:
	// there's no 'id' in cpp, so we recommend returning the class instance pointer
	static cocos2d::Scene* createScene();

	// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
	virtual bool init();
	// implement the "static create()" method manually
	CREATE_FUNC(StateEndGame);

	void update(float dt);
	void gotoMainMenu();          // thoat ra mainmenu
	void rateGame();              // danh gia game
	void shareFaceBook();         // share facebook
	void playAgain();            // choi lai
	void UpdateAdsBanner();
	void showInterstitial();     
	void afterCaptured(bool succeed, const std::string& outputFile);        // ham chup screeshot
	void onSharePhoto(cocos2d::Ref* sender);                    // share screen shot len facebook
	void onDialogLink(cocos2d::Ref* sender);                  // share link len facebook
		
private:
	int countToShowBanner;
	std::string LinkFileScreenShot;
};

#endif // __STATE_ENDGAME__H__

StateEndGame.cpp

State này để thông báo và tính toán điểm vừa chơi có phải là điểm cao nhất không? Nếu cao nhất thì cập nhật.

#include "StateEndGame.h"
#include "StateMainMenu.h"
#include "StateGamePlay.h"
#include "config.h"
#include "NativeAndroidHelper.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "PluginFacebook/PluginFacebook.h"
#include "PluginChartboost/PluginChartboost.h"
using namespace sdkbox;
#endif

USING_NS_CC;

Scene* StateEndGame::createScene()
{
	// 'scene' is an autorelease object
	auto scene = Scene::create();

	// 'layer' is an autorelease object
	auto layer = StateEndGame::create();

	// add layer as a child to scene
	scene->addChild(layer);

	// return the scene
	return scene;
}

// on "init" you need to initialize your instance
bool StateEndGame::init()
{
	//////////////////////////////
	// 1. super init first
	if ( !Layer::init() )
	{
		return false;
	}

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)	  // khoi tao quang cao chartboost chi danh cho android
	sdkbox::PluginChartboost::init();
	sdkbox::PluginChartboost::cache(sdkbox::CB_Location_Default);
	sdkbox::PluginChartboost::cache(sdkbox::CB_Location_LevelComplete);
#endif

	countToShowBanner = 0;

	auto userdefault = UserDefault::sharedUserDefault();

	int highScore = userdefault->getIntegerForKey(HIGH_SCORE);
	int score = userdefault->getIntegerForKey(POINT_CURRENT);
	if (score > highScore)                                          // cap nhat gia tri diem cao nhat neu co diem lon hon diem cao nhat
	{
		highScore = score;
		userdefault->setIntegerForKey(HIGH_SCORE, score);
		userdefault->flush();
	}


	auto spriteBG = Sprite::createWithSpriteFrameName(NameBG_GP);
	spriteBG->setPosition(posMidleScreen);
	this->addChild(spriteBG, zBG);

	auto textEnd = Label::createWithTTF(Pumpkins_font90, "Game Over!");
	textEnd->setPosition(posTitleEG);
	textEnd->setTextColor(yellowColor4B);
	this->addChild(textEnd, zUi);

	auto bgHighScore = Sprite::createWithSpriteFrameName(NameBGHighScore);
	bgHighScore->setPosition(posScoreEndGame);
	bgHighScore->setOpacity(200);
	this->addChild(bgHighScore, zUi);

	auto textScore = Label::createWithTTF(Pumpkins_font60, "SCORE");
	textScore->setPosition(bgHighScore->getPosition().x, bgHighScore->getPosition().y + bgHighScore->getContentSize().height / 2 - 50);
	textScore->setTextColor(pinkColor4B);
	this->addChild(textScore, zUi);

	auto str = CCString::createWithFormat("%i", score);                                          // tao text mang gia tri diem de ve ra man hinh
	auto Currentscore = Label::createWithTTF(Pumpkins_font60, str->getCString());
	Currentscore->setPosition(bgHighScore->getPosition().x, textScore->getPosition().y - 60);
	Currentscore->setTextColor(whiteColor4B);
	this->addChild(Currentscore, zUi);

	auto textBScore = Label::createWithTTF(Pumpkins_font60, "BEST SCORE");                 
	textBScore->setPosition(bgHighScore->getPosition().x, Currentscore->getPosition().y - 90);
	textBScore->setTextColor(pinkColor4B);
	this->addChild(textBScore, zUi);

	auto strB = CCString::createWithFormat("%i", highScore);                              // tao text mang gia tri diem cao nhat ve ra man hinh
	auto Bscore = Label::createWithTTF(Pumpkins_font60, strB->getCString());
	Bscore->setPosition(bgHighScore->getPosition().x, textBScore->getPosition().y - 60);
	Bscore->setTextColor(whiteColor4B);
	this->addChild(Bscore, zUi);

	auto home_btn = Sprite::createWithSpriteFrameName(NamebtBG);
	home_btn->setPosition(posbtHomeEG);
	home_btn->setOpacity(150);
	this->addChild(home_btn, zUi);

	auto home = MenuItemImage::create();                                    // tao button home de quay ve mainmenu
	home->setNormalImage(Sprite::createWithSpriteFrameName(NamebtHome));
	home->setSelectedImage(Sprite::createWithSpriteFrameName(NamebtHome));
	home->setPosition(posbtHomeEG);
	home->setCallback(CC_CALLBACK_0(StateEndGame::gotoMainMenu, this));

	auto rate_btn = Sprite::createWithSpriteFrameName(NamebtBG);            
	rate_btn->setPosition(posbtRateEG);
	rate_btn->setOpacity(150);
	this->addChild(rate_btn, zUi);

	auto rate = MenuItemImage::create();                                      // tao button rate de danh gia game
	rate->setNormalImage(Sprite::createWithSpriteFrameName(NamebtRate));
	rate->setSelectedImage(Sprite::createWithSpriteFrameName(NamebtRate));
	rate->setPosition(posbtRateEG);
	rate->setCallback(CC_CALLBACK_0(StateEndGame::rateGame, this));

	auto face_btn = Sprite::createWithSpriteFrameName(NamebtBG);           
	face_btn->setPosition(posbtFaceEG);
	face_btn->setOpacity(150);
	this->addChild(face_btn, zUi);

	auto face = MenuItemImage::create();                                // tao button face de share diem len face
	face->setNormalImage(Sprite::createWithSpriteFrameName(NamebtFace));
	face->setSelectedImage(Sprite::createWithSpriteFrameName(NamebtFace));
	face->setPosition(posbtFaceEG);
	face->setCallback(CC_CALLBACK_0(StateEndGame::shareFaceBook, this));

	auto again_btn = Sprite::createWithSpriteFrameName(NamebtBG);
	again_btn->setPosition(posbtAgainEG);
	again_btn->setOpacity(150);
	this->addChild(again_btn, zUi);

	auto again = MenuItemImage::create();                              // tao button choi lai de choi lai game
	again->setNormalImage(Sprite::createWithSpriteFrameName(NamebtAgain));
	again->setSelectedImage(Sprite::createWithSpriteFrameName(NamebtAgain));
	again->setPosition(posbtAgainEG);
	again->setCallback(CC_CALLBACK_0(StateEndGame::playAgain, this));

	auto menu = Menu::create(home, rate, face, again, NULL);

	menu->setPosition(Point::ZERO);
	this->addChild(menu, zUi);

	this->scheduleUpdate();                                 // goi ham update(dt)

	auto showInters = CCCallFuncN::create(CC_CALLBACK_0(StateEndGame::showInterstitial, this)); // goi quang cao hinh lon

	this->runAction(Sequence::create(DelayTime::create(1.0f), showInters, NULL));

	return true;
}

void StateEndGame::update(float dt)
{
	UpdateAdsBanner();
}

void StateEndGame::UpdateAdsBanner()                          // ham hien thi banner 40s sau do se an di 5s
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)	
	countToShowBanner++;

	if (NativeAndroidHelper::AdShowing() && countToShowBanner == 1600)
	{
		NativeAndroidHelper::hideAd();
		countToShowBanner = 0;
	}
	else if (!NativeAndroidHelper::AdShowing() && countToShowBanner == 200)
	{
		NativeAndroidHelper::showAd();
		countToShowBanner = 0;
	}
#endif
}

void StateEndGame::showInterstitial()                                // hien quang cao 
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	int rand = random(1, 15);
	const std::string temp;
	if (rand == 10)
	{
		sdkbox::PluginChartboost::show(sdkbox::CB_Location_LevelComplete);
	}
	else if(rand > 10)
	{
		sdkbox::PluginChartboost::show(sdkbox::CB_Location_Default);
	}
#endif
}

void StateEndGame::gotoMainMenu()                               // quay ve MainMenu khi nhan button Home
{
	Director::getInstance()->replaceScene(StateMainMenu::createScene());
}

void StateEndGame::rateGame()                                     // danh gia game khi nhan button rate game
{
	std::string link = std::string("https://play.google.com/store/apps/details?id=com.gamenvl.pumpkins");
	Application::getInstance()->openURL(link);
}

void StateEndGame::playAgain()                    // choi lai game khi nha button choi lai
{
	Director::getInstance()->replaceScene(StateGamePlay::createScene());
}

void StateEndGame::afterCaptured(bool succeed, const std::string& outputFile) // ham nay se tu goi trong ham shareFaceBook()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	sdkbox::PluginFacebook::login();
	LinkFileScreenShot = outputFile;

	auto SharePhoto = CCCallFuncN::create(CC_CALLBACK_1(StateEndGame::onSharePhoto, this));      // share screenshot diem game len face
	auto ShareDialogLink = CCCallFuncN::create(CC_CALLBACK_1(StateEndGame::onDialogLink, this));   // share link down game len face
	this->runAction(Sequence::create(ShareDialogLink, DelayTime::create(3.0f), SharePhoto, NULL));
#endif
}

void StateEndGame::shareFaceBook()    // share face khi nhan nut face
{
	utils::captureScreen(CC_CALLBACK_2(StateEndGame::afterCaptured, this), "Pumpkins.png");
}

void StateEndGame::onSharePhoto(cocos2d::Ref* sender)                        // share screenshot diem game len face
{
	/*
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	sdkbox::PluginFacebook::requestReadPermissions({ FB_PERM_READ_PUBLIC_PROFILE, FB_PERM_READ_USER_FRIENDS });
	sdkbox::PluginFacebook::requestPublishPermissions({ FB_PERM_PUBLISH_POST });

	sdkbox::FBShareInfo info;
	info.type = sdkbox::FB_PHOTO;
	info.title = "My best score";
	info.image = LinkFileScreenShot;
	sdkbox::PluginFacebook::share(info);
#endif
	*/
}
void StateEndGame::onDialogLink(cocos2d::Ref* sender)                           // share link down game len face
{
	auto userdefault = UserDefault::sharedUserDefault();
	int highScore = userdefault->getIntegerForKey(HIGH_SCORE);

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	sdkbox::PluginFacebook::requestReadPermissions({ FB_PERM_READ_PUBLIC_PROFILE, FB_PERM_READ_USER_FRIENDS });
	sdkbox::PluginFacebook::requestPublishPermissions({ FB_PERM_PUBLISH_POST });
	FBShareInfo info;
	info.type = FB_LINK;
	info.link = "https://play.google.com/store/apps/details?id=com.gamenvl.pumpkins";
	info.title = "Funny Halloween Pumpkins";
	auto tempText = CCString::createWithFormat("My best score is %i. Let try it to get best score with me!", highScore);
	info.text = tempText->getCString();
	info.image = "http://i.imgur.com/vBwYKHH.png";
	PluginFacebook::dialog(info);
#endif
}

Tích hợp Ads Admob

Muốn gắn quảng cáo Admob vào game thì trước tiên phải có tài khoản Admob và tạo id cho quảng cáo.

Tìm hiểu thêm tại trang chủ của Admod.

Khi tạo xong id quảng cáo, mở file "Pumpkins\proj.android\AndroidManifest.xml" và thêm vào các quyền như sau:

 <!-- Activity required to show admod ad overlays. -->
        <activity
            android:name="com.google.android.gms.ads.AdActivity"
            android:theme="@android:style/Theme.Translucent"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
			
    </application>
<supports-screens android:anyDensity="true"
                      android:smallScreens="true"
                      android:normalScreens="true"
                      android:largeScreens="true"
                      android:xlargeScreens="true"/>

    <uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest> 

Mở file "Pumpkins\proj.android\project.properties" và thêm đường dẫn đến thư viện như sau:

target=android-15

android.library.reference.1=../cocos2d/cocos/platform/android/java
android.library.reference.2=../cocos2d/cocos/platform/android/java/libs/facebook_lib/
android.library.reference.3=libs/google-play-services_lib

Thư viện của google play services đã đính kèm trong bài viết trước, copy vào project.

Tiếp tục vào lớp Activity của game để thêm hàm hiển thị ads, lưu ý file này nên lấy giống phần hướng dẫn, chỉ cần đổi id quảng cáo.

Pumpkins\proj.android\src\org\cocos2dx\cpp\AppActivity.java

package org.cocos2dx.cpp;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.cocos2dx.lib.Cocos2dxActivity;

import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;

import com.google.android.gms.ads.*;

import android.content.Intent;
import android.net.Uri;

public class AppActivity extends Cocos2dxActivity {
	private static AppActivity _appActiviy;
	private AdView adView;
	private InterstitialAd interstitial;

	private static final String AD_UNIT_ID = "ca-app-pub-5088964067816727/5954762096";                 // doi id quang cao banner
	private static final String AD_INTERTITIAL_UNIT_ID = "ca-app-pub-5088964067816727/7431495296";     // doi id quang cao hinh lon
	private Point getDisplaySize(Display d) {
		// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			// return getDisplaySizeGE11(d);
		// }
		return getDisplaySizeLT11(d);
	}
	
	private Point getDisplaySizeLT11(Display d) {
		try {
			Method getWidth = Display.class.getMethod("getWidth",
					new Class[] {});
			Method getHeight = Display.class.getMethod("getHeight",
					new Class[] {});
			return new Point(
					((Integer) getWidth.invoke(d, (Object[]) null)).intValue(),
					((Integer) getHeight.invoke(d, (Object[]) null)).intValue());
		} catch (NoSuchMethodException e2) // None of these exceptions should
											// ever occur.
		{
			return new Point(-1, -1);
		} catch (IllegalArgumentException e2) {
			return new Point(-2, -2);
		} catch (IllegalAccessException e2) {
			return new Point(-3, -3);
		} catch (InvocationTargetException e2) {
			return new Point(-4, -4);
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		int width = getDisplaySize(getWindowManager().getDefaultDisplay()).x;

		LinearLayout.LayoutParams adParams = new LinearLayout.LayoutParams(
			width, LinearLayout.LayoutParams.WRAP_CONTENT);

		adView = new AdView(this);
		adView.setAdSize(AdSize.BANNER);
		adView.setAdUnitId(AD_UNIT_ID);

		AdRequest adRequest = new AdRequest.Builder().build();
                // .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                // .addTestDevice("HASH_DEVICE_ID").build();

		adView.loadAd(adRequest);
		adView.setBackgroundColor(Color.BLACK);
		adView.setBackgroundColor(0);
		addContentView(adView, adParams);

		interstitial = new InterstitialAd(this);
		interstitial.setAdUnitId(AD_INTERTITIAL_UNIT_ID);

		// Begin loading your interstitial.
		interstitial.loadAd(adRequest);        
		_appActiviy = this;
	}
    
	public static void hideAd() {
		_appActiviy.runOnUiThread(new Runnable() {
			@Override
			public void run() {
  				if (_appActiviy.adView.isEnabled())
					_appActiviy.adView.setEnabled(false);
				if (_appActiviy.adView.getVisibility() != 4)
					_appActiviy.adView.setVisibility(View.INVISIBLE);
			}
		});
	}

	public static void showAd() {
		_appActiviy.runOnUiThread(new Runnable() {
			@Override
			public void run() {
				if (!_appActiviy.adView.isEnabled())
					_appActiviy.adView.setEnabled(true);
				if (_appActiviy.adView.getVisibility() == 4)
					_appActiviy.adView.setVisibility(View.VISIBLE);
			}
		});
	}

	public static void showInterstitial() {
		_appActiviy.runOnUiThread(new Runnable() {
			@Override
			public void run() {	
				_appActiviy.interstitial.show();
			}
		});
	}

	public static void loadInterstitalAgain() {
        	_appActiviy.runOnUiThread(new Runnable() {
			@Override
			public void run() {
				AdRequest adRequest = new AdRequest.Builder()
										.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
										.addTestDevice("HASH_DEVICE_ID").build();

				_appActiviy.interstitial.loadAd(adRequest);
			}
		});
	}

	// Open URL
	public static void openURL(String url) {
		Intent i = new Intent(Intent.ACTION_VIEW);
		i.setData(Uri.parse(url));
		_appActiviy.startActivity(i);
	}
    
	@Override
 	protected void onResume() {
		super.onResume();
		if (adView != null) {
			adView.resume();
		}
	}

    @Override
	protected void onPause() {
		if (adView != null) {
			adView.pause();
		}
		//   uiHelper.onPause();
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		adView.destroy();
		super.onDestroy();
	}
}

Nếu muốn hiện quảng cáo, tại file .cpp phải gọi các hàm trong lớp Activity trên. Để làm được điều đó thì nhờ đến lớp NativeAndroidHelper để gọi hàm trong code Java, đã đính kèm trong tài liệu nên có thể sử dụng file này mà không cần phải thêm code. Thêm file NativeAndroidHelper cũng giống như thêm các file StateMainMenu, StateGamePlay, StateEndGame ở phần trước.

Tiến hành gọi banner và interstital:

void StateEndGame::UpdateAdsBanner()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)	
	countToShowBanner++;

	if (NativeAndroidHelper::AdShowing() && countToShowBanner == 1600)
	{
		NativeAndroidHelper::hideAd();                   // hàm an banner
		countToShowBanner = 0;
	}
	else if (!NativeAndroidHelper::AdShowing() && countToShowBanner == 200)
	{
		NativeAndroidHelper::showAd();                   // ham hien thi banner
		countToShowBanner = 0;
	}
#endif
}
void StateEndGame::showInterstitial()
{

	NativeAndroidHelper::hideAd();             // truoc khi goi quang cao lon, nen tat banner
	NativeAndroidHelper::showInterstitial();  // hien thi quang cao lon
}

Đến đây là đã xong phần tích hợp quảng cáo Admob.

2 bài viết đã hướng dẫn toàn bộ các công việc cũng như các bước để làm game "Funny Halloween Pumpkins".

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024