【Cocos2dx】飘字特效与碰撞检测

【Cocos2dx】飘字特效与碰撞检测,第1张

概述飘字特效主要常见与游戏里面的掉血表示伤害输出等。碰撞检测常见于一些横版过关或者跑酷的手游,判断是否有碰到食物,或者什么障碍物等,都是比较常见的功能,下面就用一个小例子,来说明这两个特效如何完成。 如下图所示,有两个按钮,点击/触摸屏幕,则下方的按钮则会跳起来。碰到处于屏幕中央的按钮,则会d出飘字特效,显示碰撞。 同时,左上角的时刻,这两个按钮是否碰撞,也就是是否交汇,相互接触,相交,interse

飘字特效主要常见与游戏里面的掉血表示伤害输出等。碰撞检测常见于一些横版过关或者跑酷的手游,判断是否有碰到食物,或者什么障碍物等,都是比较常见的功能,下面就用一个小例子,来说明这两个特效如何完成。

如下图所示,有两个按钮,点击/触摸屏幕,则下方的按钮则会跳起来。碰到处于屏幕中央的按钮,则会d出飘字特效,显示碰撞。

同时,左上角的时刻,这两个按钮是否碰撞,也就是是否交汇,相互接触,相交,intersection就是这个意思。


0、首先利用(cocos2d-x-2.2.6安装目录).\tools\project-creator下的create_project.py创建一个FlowWords的Cocos2dx工程,之后打开其中的proj.win32中的HelloCpp.sln利用vs2010进行编辑,先在AppDelegate.h关闭调试信息,设置窗口大小。这些简单的创建Cocos2dx工程步骤,我就不再赘述了。详情可以参考《【Cocos2dx】windows平台下Cocos2dx 2.x的下载、安装、配置,打造自己的Helloworld》(点击打开链接)

1、之后新建一个飘字特效的类,包含FlowWord.h与FlowWord.cpp,工程的目录如下图所示:


飘字特效,本质其实就是一个标签文本cclabelTTF的放大->移动->缩小的动作序列,没什么大不了,关于Cocos2dx的动作序列具体可以参考《【Cocos2dx】基本动作、动作序列与动作合并》(点击打开链接),FlowWord.h代码如下,主要用于一些函数的声明,showWord是暴露给其它类调用的方法,private是完成showWord中的一些必须的类成员变量与类成员函数,这里由于用到了cclabelTTF,注意引入cocos2d.h的头文字,当然using namespace cocos2d;也就可以的,看上去没什么区别,当然建议使用#include "cocos2d.h",因为你不用在FlowWord.cpp再写一次using namespace cocos2d;了:

#ifndef _FlowWord_H_#define _FlowWord_H_#include "cocos2d.h"USING_NS_CC;class FlowWord : public CCNode {public:	voID showWord(const char* text,CCPoint pos);//飘字方法,text为飘字的内容,pos为飘字的位置private:	cclabelTTF* label;//类成员	voID flowEnd();//飘字结束时的回调(处理)函数,主要用于删除自己	};#endif
之后的FlowWord.cpp则按照如下的逻辑完成一个动作序列,完成飘字特效:
#include "FlowWord.h"voID FlowWord::showWord( const char* text,CCPoint position){//text为飘字的内容,pos为飘字的位置	/*初始化*/	label=cclabelTTF::create(text,"Arial",18);//创建一个字体为Arial,字号为18,内容为text的cclabelTTF,也就是标签文本	label->setcolor(ccc3(255,255,0));//设置其颜色为黄色	label->setposition(position);//设置其位置	this->addChild(label);//在场景上添加这个标签文本	/*三个动作,放大->移动->缩小*/		CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//获取屏幕的尺寸、位置信息等     	CCFiniteTimeAction* action1=CCScaleto::create(0.2f,3.0f,3.0f);//0.2s内在x、y上方向皆放大为原尺寸的3倍	CCFiniteTimeAction* action2=CCMoveto::create(0.3f,ccp(visibleSize.wIDth/4,3*visibleSize.height/4));//在0.3s内,移动到坐标为(x=屏幕宽度的25%,y=屏幕高度的75%处)	CCFiniteTimeAction* action3 = CCScaleto::create(0.2f,0.1f,0.1f);//之后在0.2s内在x、y上皆缩小为原尺寸的0.1倍	CCCallFunc* callFunc = CCCallFunc::create(this,callfunc_selector(FlowWord::flowEnd));//声明一个回调(处理)函数,为FlowWord类中的flowEnd()	CCFiniteTimeAction* action = CCSequence::create(action1,action2,action3,callFunc,NulL);//以上的所有动作组成动作序列action	/*对label实行action这个动作*/	label->runAction(action);}voID FlowWord::flowEnd() {//动作结束,从父节点中删除自身	label->setVisible(false);//先隐藏显示	label->removeFromParentAndCleanup(true);//再删除}
2、完成了飘字特效的构建,我们要在HelloWorld这个场景中,完成效果图的所有内容。实质是在《【Cocos2dx】精灵触摸跳跃功能》( 点击打开链接)这个工程进一步衍生,在里面多增多一个精灵,再增加一个类似《【Cocos2dx】连续滚动的场景》( 点击打开链接)中的即时更新事件完成碰撞检测的功能。

首先HelloWorldScene.h修改成如下的样子,删去原有的关闭程序的按钮的回调函数,添加一些我们需要的声明:

#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"using namespace cocos2d;//精灵等属于Cocos2dx东西,因此要在此文件的开始声明使用cocos2dx的命名空间,即使有#include "cocos2d.h"也要引用,不知道为什么class HelloWorld : public cocos2d::cclayer{public:	// Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'ID' in cocos2d-iphone	virtual bool init();  	// there's no 'ID' in cpp,so we recommend returning the class instance pointer	static cocos2d::CCScene* scene();	// implement the "static node()" method manually	CREATE_FUNC(HelloWorld);	voID cctouchesBegan(CCSet *ptouches,CCEvent *pEvent);//触摸事件的函数声明  	voID jumpEnd();//声明跳跃结束的回调函数  	virtual voID update(float delta);//即时更新事件private:	cclabelTTF *label;//文字1	CCSprite* sprite1;//精灵1  	bool isJumPing;//精灵1,是否跳跃的flag 	CCSprite* sprite2;//精灵2 	bool isFlowing;//即时更新事件中,判断此时是否正在飘字的flag};#endif // __HELLOWORLD_SCENE_H__
最后是HelloWorldScene.cpp,也就是整个工程的核心了。

1、将原有的HelloWorldScene.cpp中的初始化函数bool HelloWorld::init(){}中的所有内容删去。我们要在里面声明一个位于左上角标签文本cclabelTTF与2个按钮精灵。

2、在声明左上角标签文本cclabelTTF的时候用到setAnchorPoint,这个设置中心点的函数,里面的参数的效果具体如下图所示,以下的按钮精灵的中心店都处于屏幕的中央,然而由于中心点的不同,导致,按钮精灵的位置最终不同。


3、碰撞检测之所以搞这么复杂,要根据中心点与精灵尺寸创建矩形,也是没有办法,这不是单纯的两只的中心点是否相交的问题,比如如下图,两飞机的中心点并没有相交,然而两飞机是相交、已经碰撞的。Cocos2dx自带矩形创建函数已经算给面子了,在原生的JavaScript中,《【JavaScript】黑点捉红点并躲绿点游戏》(点击打开链接)if里面N个无聊的、同质化的不等式写得我想打人。


4、飘字特效必须有个flag控制它,不然在下方的按钮精灵跳跃经过上方的按钮精灵的时候,会疯狂地飘字,极其占有资源,我们仅仅是让其飘一次!

5、其余在注释写明了,个人感觉基本都说明清楚了。

#include "HelloWorldScene.h"#include "FlowWord.h" //飘字特效USING_NS_CC;CCScene* HelloWorld::scene(){	// 'scene' is an autorelease object	CCScene *scene = CCScene::create();	// 'layer' is an autorelease object	HelloWorld *layer = HelloWorld::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 HelloWorld::init(){	//获取屏幕的尺寸、位置信息等      	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();    	//声明这个场景是存在触摸事件的  	this->settouchEnabled(true);  	//声明这个场景是存在即时更新事件的 	this->scheduleUpdate();	//声明一个表示是否碰撞的文字	label = cclabelTTF::create("Collision:false","arial",36);//声明文字内容	label->setAnchorPoint(ccp(0,1));//设置label的中心点在左上角,默认是label->setAnchorPoint(ccp(0.5,0.5));中心点在精灵的中央,label->setAnchorPoint(ccp(1,0));中心点则去了右下角了	label->setposition(ccp(0,visibleSize.height));//把中心点摆在屏幕的左上交     	this->addChild(label);//添加此文字到场景中	isFlowing=false;	//声明2只精灵	//精灵1	sprite1 = CCSprite::create("CloseSelected.png");    	sprite1->setposition(ccp(visibleSize.wIDth / 2,visibleSize.height / 6));    	this->addChild(sprite1);    	//开始精灵处于未跳跃的状态,由于头文件中“只有静态常量整型数据成员才可以在类中初始化”,因此在这里初始化声明变量  	isJumPing=false; 	//精灵2	sprite2 = CCSprite::create("Closenormal.png");    	sprite2->setposition(ccp(visibleSize.wIDth / 2,visibleSize.height / 2));    	this->addChild(sprite2);	return true;}/*触摸导致精灵1跳跃*///开始触摸    voID HelloWorld::cctouchesBegan(cocos2d::CCSet *ptouches,cocos2d::CCEvent *pEvent){    	//获取屏幕的尺寸、位置信息等        	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();      	//如果主角还在跳跃中,则不重复执行  	if(isJumPing) {  		return;  	}	//标记主角为跳跃状态  	isJumPing = true;  	//在2.0秒内,先跳起 屏幕尺寸的2/3 再落下0px,该动作重复1次  	CCJumpBy* jump = CCJumpBy::create(1.5f,ccp(0,0),2* visibleSize.height / 3,1);  	//创建回调函数,声明跳跃结束后调用jumpEnd函数  	CCCallFunc* callFunc = CCCallFunc::create(this,callfunc_selector(HelloWorld::jumpEnd));  	//将回调函数与跳跃动作结合起来  	CCActionInterval* jumpActions = CCSequence::create(jump,NulL);  	//执行动作  	sprite1->runAction(jumpActions);};voID HelloWorld::jumpEnd() {  	isJumPing = false;  }/*碰撞检测*///判断两只精灵是否相交的函数bool is_collision(CCSprite* sprite1,CCSprite* sprite2){	//建立精灵1的矩形	CCSize sprite_size1=sprite1->getContentSize();//求精灵的尺寸	CCPoint sprite_position1=sprite1->getposition();//求精灵的中心点坐标	CCRect sprite_rect1=CCRectMake(//以精灵的中心点为中心点、以精灵的尺寸为宽与高,建立一个矩形。		sprite_position1.x-sprite_size1.wIDth/2,sprite_position1.y-sprite_size1.height/2,sprite_size1.wIDth,sprite_size1.height);	//建立精灵2的矩形,同理	CCSize sprite_size2=sprite2->getContentSize();	CCPoint sprite_position2=sprite2->getposition();	CCRect sprite_rect2=CCRectMake(		sprite_position2.x-sprite_size2.wIDth / 2,sprite_position2.y-sprite_size2.height / 2,sprite_size2.wIDth,sprite_size2.height);	return sprite_rect1.intersectsRect(sprite_rect2);//如果是判断矩形与一个像素点则用Rect实例.containsPoint(像素点);这里是判断两个矩形是否相交}//即时更新事件,就是在程序一开始就不停地执行这个函数voID HelloWorld::update(float delta){//这里的函数名、参数都不能改,即时你没有用到。	if(is_collision(sprite1,sprite2)){//判断精灵1是否碰到精灵2		if(!isFlowing){//如果现在不是在飘字			label->setString("Collision:true");//左上角的文字内容改变			FlowWord* flowWord=new FlowWord();//初始化FlowWord			this->addChild(flowWord);//将FlowWord飘字特效放上舞台,尽管飘字特效,一不是精灵,二在showWord中同样有将字体放上舞台的代码,然而没有这一句,HelloWorldScene这个场景根本不会与FlowWord联系起来,也就是FlowWord中添加的Label根本无法在HelloWorldScene中显示。			flowWord->showWord("collision!",sprite2->getposition());//执行飘字collision!,位置在不动的sprite2位置开始。			isFlowing=true;//表示现在正在飘字		}	}	else{		label->setString("Collision:false");//精灵1没有碰到精灵2才允许继续飘字		isFlowing=false;	}}  
当然,其实还可以写得更好一些,将精灵1与精灵1本身的触摸跳跃事件打包成一个事件,以致于不用在HelloWorldScene.cpp中写这么长的代码。至此,整个程序最终完成。 总结

以上是内存溢出为你收集整理的【Cocos2dx】飘字特效与碰撞检测全部内容,希望文章能够帮你解决【Cocos2dx】飘字特效与碰撞检测所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1073481.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存