1. 程式人生 > >Cocos2D遊戲之旅(四):卡牌翻轉效果的實現(下)

Cocos2D遊戲之旅(四):卡牌翻轉效果的實現(下)

曉石頭的部落格

郵箱:[email protected]

上篇講解了用ScaleTo縮放卡牌,達到翻轉的效果。

條條大道通羅馬,RotateBy 旋轉卡牌同樣能夠實現,而且效果更棒,就看你喜歡哪種了!


效果對比圖

一、先談思路:

ScaleTo縮放卡牌實現翻轉的思路移步:

理解了ScaleTo 的思路,再看RotateBy 就一目瞭然了。

一共兩張圖片

1、正面


1、背面


產生卡牌蓋住的效果:

第一步:將正面旋轉90度;產生卡牌翻轉到中間的效果

第二步:將一開始就旋轉90度的背面再旋轉90度,產生卡牌蓋住的效果

產生卡牌翻開的效果:

第三步:將背面旋轉90度,背面隱藏起來。

第四步:正面有270度旋轉至360,恢復至卡牌開啟的原狀。

二、再說實現

bool HelloWorld::init()
{
    if (!Layer::init())
    {
        return false;
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();

	/* 新增背景 */
	CCSprite* bk = CCSprite::create("bk.png");
	bk->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
	this->addChild(bk);

	/* 卡牌狀態標誌位 */
	cardFlag = 0;
	touchable = 1;

	/* 建立第一個精靈 */
	sprite1 = Sprite::create("card.png");
	sprite1->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
	this->addChild(sprite1);

	/* 建立第二個精靈 */
	sprite2 = Sprite::create("bkCard.png");
	sprite2->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
	this->addChild(sprite2);

	/* 第二個精靈預設x旋轉至90度,於是第二個精靈在一開始是看不見的*/
	sprite2->setRotationY(90);
	

	/* 觸控事件 */
	EventListenerTouchOneByOne* event = EventListenerTouchOneByOne::create();
	/* true表示觸控事件不向下傳遞,如果有兩種重疊的卡牌,就只有第一張能接受到觸控事件。false則兩張卡牌都能接受到觸控事件 */
	event->setSwallowTouches(true);

	event->onTouchBegan = [=](Touch* touch, Event* event){
		/* 取出繫結的精靈 */
		auto target = static_cast<Sprite*>(event->getCurrentTarget());
		/* 將觸控點的螢幕座標轉換成openGL裡的座標 */
		Point point = Director::getInstance()->convertToGL(touch->getLocationInView());

		/* 判斷觸控點是否在精靈範圍內 */
		/* 在範圍為則返回true,執行onTouchEnded,否則false,不執行onTouchEnded */
		/* touchable控制觸控是否有效,避免動作執行完成前又觸控,產生動作混亂的效果 */
		if (target->getBoundingBox().containsPoint(point) && 1 == touchable)
		{
			touchable = 0;
			return true;
		}
		else
		{
			return false;
		}
	};

	event->onTouchEnded = [=](Touch* touch, Event* event){
		switch (cardFlag % 4)
		{
			/* 旋轉方式蓋住卡牌 */
		case 0:
			sprite2->setRotationY(90);
			sprite2->setScaleX(1.0f);
			closeCard();
			break;

			/* 旋轉方式開啟卡牌 */
		case 1:
			openCard();
			break;

			/* 縮放方式蓋住紙牌 */
		case 2:
			sprite2->setRotationY(0);
			sprite2->setScaleX(0.0f);
			closeCard2();
			break;

			/* 縮放方式開啟紙牌 */
		case 3:
			openCard2();

		default:
			break;
		}
		cardFlag++;

		auto funcSettouchable = [&](){
			touchable = 1;
		};

		CallFunc* callFuncTouch = CallFunc::create(funcSettouchable);

		/* 用順序動作保證動作完成後再讓觸控有效 */
		/* touchable用於控制觸控是否有效 */
		Sequence* sequence = Sequence::create(CCDelayTime::create(1.2f), callFuncTouch, NULL);
		this->runAction(sequence);
	};

	/* 註冊監聽事件,繫結精靈1 */
	_eventDispatcher->addEventListenerWithSceneGraphPriority(event, sprite1);
	/* 註冊監聽事件,繫結精靈2,事件監聽物件event複製了一份 */
	_eventDispatcher->addEventListenerWithSceneGraphPriority(event->clone(), sprite2);

    return true;
}

void HelloWorld::closeCard()
{
	/* x方向旋轉90度的動作 */
	RotateBy* rotateToHide = RotateBy::create(0.6f, 0, 90);

	/* 建立卡牌旋轉90度的回撥函式 */
	auto funcScaleToShow = [&](){
		RotateBy* rotateToShow = RotateBy::create(0.6f, 0, 90);
		sprite2->runAction(rotateToShow);
	};

	/* 將回調函式封裝為動作 */
	CallFunc* callFuncSpr2 = CallFunc::create(funcScaleToShow);

	/* 依次執行動作 */
	Sequence* sequence = Sequence::create(rotateToHide, callFuncSpr2, NULL);

	sprite1->runAction(sequence);
}

void HelloWorld::openCard()
{
	/* x方向旋轉90度的動作 */
	RotateBy* rotateToHide = RotateBy::create(0.6f, 0, 90);

	/* 建立卡牌旋轉90度的回撥函式 */
	auto funcScaleToShow = [=](){
		/* 這裡如果不這只是270度,卡牌翻轉後和原來的畫面是左右顛倒的 */
		sprite1->setRotationY(270);
		RotateBy* rotateToShow = RotateBy::create(0.6f, 0, 90);
		sprite1->runAction(rotateToShow);
	};

	/* 將回調函式封裝為動作 */
	CallFunc* callFuncSpr2 = CallFunc::create(funcScaleToShow);

	/* 依次執行動作 */
	Sequence* sequence = Sequence::create(rotateToHide, callFuncSpr2, NULL);

	sprite2->runAction(sequence);
}


void HelloWorld::closeCard2()
{
	/* x方向拉伸至0的動作 */
	ScaleTo* scaleToHide = ScaleTo::create(0.6f, 0.0f, 1.0f);

	/* 建立卡牌放大的回撥函式 */
	auto funcScaleToShow = [=](){
		ScaleTo* scaleToShow = ScaleTo::create(0.6f, 1.0f, 1.0f);
		sprite2->runAction(scaleToShow);
	};

	/* 將回調函式封裝為動作 */
	CallFunc* callFuncSpr2 = CallFunc::create(funcScaleToShow);

	/* 依次執行動作 */
	Sequence* sequence = Sequence::create(scaleToHide, callFuncSpr2, NULL);

	sprite1->runAction(sequence);
}

void HelloWorld::openCard2()
{
	/* x方向拉伸至0的動作 */
	ScaleTo* scaleToHide = ScaleTo::create(0.6f, 0.0f, 1.0f);

	auto funcScaleToShow = [=](){
		ScaleTo* scaleToShow = ScaleTo::create(0.6f, 1.0f, 1.0f);
		sprite1->runAction(scaleToShow);
	};

	CallFunc* callFuncSpr1 = CallFunc::create(funcScaleToShow);

	Sequence* sequence = Sequence::create(scaleToHide, callFuncSpr1, NULL);

	sprite2->runAction(sequence);
}


相關推薦

Cocos2D遊戲翻轉效果實現

曉石頭的部落格 郵箱:[email protected] 上篇講解了用ScaleTo縮放卡牌,達到翻轉的效果。 條條大道通羅馬,RotateBy 旋轉卡牌同樣能夠實現,而且效果更棒,就看你喜歡哪種了! 效果對比圖 一、先談思路: 用ScaleTo縮放卡

Cocos2D遊戲翻轉效果實現

曉石頭的部落格 郵箱:[email protected] 滑鼠點選一次,卡牌蓋住 再次點選,卡牌翻開 效果演示圖 之前一直認為卡牌翻轉是通過幀動畫實現的,當看到@笨木頭用ScaleTo做出來時候,再一次深刻體會到什麼叫大道至簡。 一、先談思路 一共兩張圖片

Cocos2D遊戲主角血條的實現

血槽血量的變化是有兩個元素構成的: 1.血槽圖 2.紅色的進度條 當進度條的進度值不斷減少的時候,就產生血量減少的效果。 UI的佈局我採用了CocoStudio的UI編輯器,感覺不錯,挺容易上手的,如果需要相關資料的給我留言。繼續上圖~ 二、再說實現 bool HelloWorld::init()

Python.第章.模塊與包.總結未完待遇

standard 後綴 att 擔心 lse 綁定 做的 業務 搜索 一、模塊 模塊: 一系列功能的集合體,在python中一個py文件就是一個模塊,模塊名就是py文件的文件名; 模塊的好處: 1.減少重復的代碼 2.拿來主義 定義模塊: 就是創建一個py文件;

python的遊戲-- 數字 字串 列表 元組 字典 即為遊戲職業

        ---恢復內容開始--- 一,個人心得 我覺得學習python就想玩一款遊戲,python的基本資料型別(字串 數字 列表 元組 字典)可以看做一個遊戲職業,每個職業都有相應的技能。 玩好這些職業,讓我們的python之旅更加容易。 &n

Python 遊戲Pygame

Pygame是跨平臺Python模組,專為電子遊戲設計,包含影象、聲音。建立在SDL基礎上,允許實時電子遊戲研發而無需被低階語言(如機器語言和組合語言)束縛。基於這樣一個設想,所有需要的遊戲功能和理念都(主要是影象方面)都完全簡化為遊戲邏輯本身,所有的資源結構都可以由高階語言提供。   Pyga

敏捷開發系列透明的Crystal水晶方法

上一站,我們簡單的談了談FDD,瞭解了什麼是特徵驅動開發,以及它核心的整體模型,在我看來,它是一種有效但有一些複雜的敏捷開發方法,對於小團隊來說,實施起來有些困難。然而,今天我們要認識的是一種新的開發過程——Crystal,透明水晶方法。 概述 水晶方法,Crystal

全面認識Android手機MIUI ROM適配天——移植MIUI Framework

1. 為什麼使用程式碼插樁 首先我們來回顧第一章中的Android軟體架構圖,這個圖中框架層的程式碼完全是由Java語言編寫的,對於這兩層的程式碼,在沒有原始碼的情況下我們可以採取程式碼插樁的方式來注入我們的程式碼。但是對於下面幾層的程式碼幾乎都是以機器碼的形式存在,機器碼

RPG遊戲《黑暗光》流程介紹與程式碼分析角色控制系統的實現

第三章:角色控制本篇部落格主要對人物移動及其相關操作進行分析,主要包括主角以及鏡頭的移動。在遊戲介面中,我們使用Camera作為視角。為了方便之後判斷當前tag,我們新建一個Tag指令碼,存入一些tag資訊,之後呼叫就不容易出錯using UnityEngine; using

[寒江孤葉丶的Cocos2d-x_22]Cocos2d-x如何不進入待機螢幕保持喚醒 不鎖屏 不變黑……

原創文章,歡迎轉載,轉載請註明:文章來自[寒江孤葉丶的Cocos2d-x之旅系列] 部落格地址:http://blog.csdn.net/qq446569365 方法很簡單,一行程式碼就可以輕鬆搞定…… 首先是IOS的實現: 在AppController.mm檔案

《OneForAll框架搭建》前端篇微前端架構設計Vue

心之所向,勇往直前!記錄開發過程中的那些小事,給自己加點經驗值。 前言 作為一個.Net後端開發,在競爭愈加激烈的當下,掌握點前端配菜好像已經是家常便飯了。 剛好在工作的第5個年頭,辭去小主管職務的我要再次踏上面試之路,為了要避免被面試官吊打,除了複習《吊打面試

一起talk C栗子吧第一百二十C語言實例--內置宏

parent tracking 通過 end variable view ddc 工作效率 語法 各位看官們,大家好,上一回中咱們說的是顯示變量和函數地址的樣例,這一回咱們說的樣例是:內置宏。閑話休提,言歸正轉。讓我們一起talk C栗子吧! 看官

在STM32上實現NTFS4GPT分區表的C語言實現1主GPT表頭的實現

center mbr分區 sum 對齊 字節數 決定 容器 alt 水平 題外話:在荒廢了很久沒有更新之後……某日突然收到讀者的站內信!內容大體是詢問GPT分區表信息的讀取方式,筆者激動萬分之下,決定繼續解剖NTFS……其實GPT嚴格上不算是NTFS的內容, GPT和M

Android項目實戰十五Usb轉串口通訊CH34xUARTDriver

spa config 關於 截取 文章 www protect sed bytes 需求為:手機usb接口插入一個硬件,從硬件上獲取數據 例如:手機usb插入硬件A,A通過藍牙通訊獲取設備a、b的數據,作為中轉站(可以做些數據處理)將數據(設備a、b產生的)傳給手機程序。

深入解讀Spring Framework IoC容器p名稱空間和c名稱空間

原文 p名稱空間 使用p名稱空間可以用bean 元素的屬性代替<property/>元素。 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="ht

Java進階學習第二十Spring框架事務管理、Spring與Hibernate整合

一、事務控制 1、引入 使用者訪問 > Action > Service > Dao 如何保證: 在service中呼叫2次dao,其中一個dao執行失敗,整個操作要回滾 2、事務控制概述 ① 程式設計式事務控制:自己手動控制事務 Jdbc程式

Qt 學習路 219):事件的接受與忽略當重寫事件回撥函式時,時刻注意是否需要通過呼叫父類的同名函式來確保原有實現仍能進行!有好幾個例子。為什麼要這麼做?而不是自己去手動呼叫這兩個函式呢?因為我們無法確認父類中的這個處理函式有沒有額外的操作

版本: 2012-09-29 2013-04-23 更新有關accept()和ignore()函式的相關內容。 2013-12-02 增加有關accept()和ignore()函式的示例。 上一章我們介紹了有關事件的相關內容。我們曾經提到,事件可以依情況接受和忽略。現在,我們就

翻譯libevent參考手冊第與事件一起工作 (六)

libevent的基本操作單元是事件。每個事件代表一組條件的集合,這些條件包括:v 檔案描述符已經就緒,可以讀取或者寫入v 檔案描述符變為就緒狀態,可以讀取或者寫入(僅對於邊沿觸發IO)v 超時事件v 發生某訊號v 使用者觸發事件所有事件具有相似的生命週期。呼叫libevent函式設定事件並且關聯到event

PTA 資料結構題目1最大子列和問題分而治、線上處理演算法

題目來源: 問題描述: 問題分析: 對於一般的問題,原始解 都能通過一種 蠻力演算法,即窮舉法的思想得到。這題也不例外。 如果我們,把輸入的陣列,所有的子列都歷遍,並從中找出最大,即可得出我們的演算法。也就是版本一。 學習要點: 1、如何

【玩轉cocos2d-x三十】繪圖CCDrawingPrimitives和CCDrawNode

最近忙出翔了,這年過的也揪心。好久沒來更新部落格了,今天就來寫一寫cocos2d-x中圖形的繪製。 1.概述 其實cocos2d-x封裝了大量的opengl的繪圖函式,我們可以很輕鬆的在遊戲