实现了个类似blood brothers中的转轴特效
在美区有个游戏叫bloodbrothers,玩了玩,感觉还不错,其中有一个页面,可以选择人物的奴仆,页面布局是中间是主人,四周是奴仆,以一个椭圆形围着主人转圈,仆人的数目可以增减,觉得这个页面挺有意思,我就试着实现了一个。
blood brothers的效果:
玩家滑动屏幕,两个骷髅兵会围着中间的老大按照椭圆轨迹转圈。
我实现的效果:
中间的老大我没做,滑动屏幕,四周的机器人图片会以椭圆轨迹旋转,个人感觉效果尚可,如果美工跟得上
我觉得效果不会比人家的差-_-!
废话不多说了,上代码
cwMainLayer.h
#ifndef _cwMainLayer_h_
#define _cwMainLayer_h_
#include "cocos2d.h"
using namespace cocos2d;
#include <string>
#include <vector>
using namespace std;
class cwShowSprite : public CCSprite
{
public:
cwShowSprite() : m_fAngle(0) {}
~cwShowSprite() {}
public:
staticcwShowSprite* create(const char *pszFileName);
private:
//当前角度
CC_SYNTHESIZE(float, m_fAngle, Angle);
};
class cwMainLayer : public CCLayer
{
public:
cwMainLayer() : m_pArrShow(NULL), m_fAngleStep(0),m_fScaleStart(1.0f), m_fScaleEnd(0.6f) {}
~cwMainLayer();
//增加显示图片
voidaddShow(const char* pcName);
//排列图片
voidarrange();
private:
//计算图片角度
voidarrangeAngle();
//计算图片位置
voidarrangePosition();
//计算图片zorder
voidarrangeZOrder();
//计算图片缩放值
voidarrangeScale();
//根据y坐标排序(由小到大)
vector<cwShowSprite*>orderByY();
//计算那个图片被点击
cwShowSprite* clickSprite(CCPoint& pt);
//将图片移动指定角度
voidmoveShow(float angle);
public:
CREATE_FUNC(cwMainLayer);
boolinit();
virtual voidonEnter();
virtual voidonExit();
virtual boolccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual voidccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual voidccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
private:
//存储图片数组
CCArray*m_pArrShow;
//圆环中点
CC_SYNTHESIZE_PASS_BY_REF(CCPoint, m_nCenter, Center);
//椭圆长短轴
CC_SYNTHESIZE(float, m_fLongA, LongA);
CC_SYNTHESIZE(float, m_fShortB, ShortB);
//缩放范围
CC_SYNTHESIZE(float, m_fScaleStart, ScaleStart);
CC_SYNTHESIZE(float, m_fScaleEnd, ScaleEnd);
//图片的起始zorder
CC_SYNTHESIZE(int, m_iZStart, ZStart);
//图片在圆环上排列的角度步长
floatm_fAngleStep;
//图片Y值区间,也就是椭圆短轴y坐标区域
floatm_fYMin;
floatm_fYMax;
//fortouch
CCPointm_nTouchBegin;
CCPointm_nTouchMoving;
//background
CCSprite*m_pBackGround;
};
#endif
cwMainLayer.cpp
#include "cwMainLayer.h"
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
cwShowSprite* cwShowSprite::create(const char *pszFileName)
{
cwShowSprite* pSprite = new cwShowSprite();
if(pSprite&&pSprite->initWithFile(pszFileName)) {
pSprite->autorelease();
returnpSprite;
}
CC_SAFE_DELETE(pSprite);
returnNULL;
}
cwMainLayer::~cwMainLayer()
{
CC_SAFE_RELEASE_NULL(m_pArrShow);
}
bool cwMainLayer::init()
{
if(!CCLayer::init()) return false;
CCSizewinSize =CCDirector::sharedDirector()->getWinSize();
m_pBackGround = CCSprite::create("bk.png");
m_pBackGround->setPosition(ccp(winSize.width*0.5,winSize.height*0.5));
this->addChild(m_pBackGround, -1);
m_pArrShow =CCArray::create();
m_pArrShow->retain();
this->setAnchorPoint(ccp(0, 0));
setCenter(ccp(winSize.width*0.5, winSize.height*0.7));
setLongA(winSize.width*0.3);
setShortB(getLongA()*0.25);
m_iZStart =1;
m_fYMin =m_nCenter.y - m_fShortB;
m_fYMax =m_nCenter.y + m_fShortB;
returntrue;
}
void cwMainLayer::addShow(const char* pcName)
{
cwShowSprite* pSprite = cwShowSprite::create(pcName);
if(!pSprite)return;
m_pArrShow->addObject(pSprite);
m_fAngleStep= 360.0f / float(m_pArrShow->count());
this->addChild(pSprite);
}
void cwMainLayer::arrange()
{
arrangeAngle();
arrangePosition();
arrangeScale();
arrangeZOrder();
}
void cwMainLayer::arrangeAngle()
{
if(m_pArrShow->count() == 0) return;
float fStart=((cwShowSprite*)(m_pArrShow->objectAtIndex(0)))->getAngle();
int index =0;
CCObject*pObj;
CCARRAY_FOREACH(m_pArrShow, pObj) {
cwShowSprite* pSprite = (cwShowSprite*)pObj;
pSprite->setAngle(fStart -index*m_fAngleStep);
index++;
}
}
void cwMainLayer::arrangePosition()
{
CCObject*pObj;
CCARRAY_FOREACH(m_pArrShow, pObj) {
cwShowSprite* pSprite = (cwShowSprite*)pObj;
float fAngle= fmod(pSprite->getAngle(), 360.0f);
float x =cosf(fAngle/180.0*3.14159)*m_fLongA + m_nCenter.x;
float y =sinf(fAngle/180.0*3.14159)*m_fShortB*0.5f + m_nCenter.y;
pSprite->setPosition(ccp(x, y));
}
}
void cwMainLayer::arrangeZOrder()
{
int iZMax =m_iZStart + m_pArrShow->count();
vector<cwShowSprite*> v =orderByY();
vector<cwShowSprite*>::iterator it =v.begin();
for(;it!=v.end(); ++it) {
(*it)->removeFromParentAndCleanup(false);
this->addChild((*it), iZMax--);
}
}
void cwMainLayer::arrangeScale()
{
CCObject*pObj;
CCARRAY_FOREACH(m_pArrShow, pObj) {
cwShowSprite* pSprite = (cwShowSprite*)pObj;
float fy =pSprite->getPositionY() - m_fYMin;
if(fy< 0) fy = 0;
float fScale= fy / (m_fShortB*2);
pSprite->setScale(1.0 -(m_fScaleStart-m_fScaleEnd)*fScale);
}
}
void cwMainLayer::moveShow(float angle)
{
CCObject*pObj;
CCARRAY_FOREACH(m_pArrShow, pObj) {
cwShowSprite* pSprite = (cwShowSprite*)pObj;
pSprite->setAngle(pSprite->getAngle()+angle);
}
}
void cwMainLayer::onEnter()
{
CCLayer::onEnter();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-200, false);
}
void cwMainLayer::onExit()
{
CCLayer::onExit();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool comp(const cwShowSprite* p1, const cwShowSprite* p2)
{
return((CCNode*)(p1))->getPositionY() <((CCNode*)(p2))->getPositionY();
}
vector<cwShowSprite*>cwMainLayer::orderByY()
{
vector<cwShowSprite*> v;
CCObject*pObj;
CCARRAY_FOREACH(m_pArrShow, pObj) {
cwShowSprite* pSprite = (cwShowSprite*)pObj;
v.push_back(pSprite);
}
sort(v.begin(), v.end(), comp);
returnv;
}
cwShowSprite* cwMainLayer::clickSprite(CCPoint&pt)
{
vector<cwShowSprite*> v =orderByY();
vector<cwShowSprite*>::iterator it =v.begin();
for(;it!=v.end(); ++it) {
if((*it)->boundingBox().containsPoint(pt)) return(*it);
}
returnNULL;
}
bool cwMainLayer::ccTouchBegan(CCTouch *pTouch, CCEvent*pEvent)
{
m_nTouchBegin =this->convertTouchToNodeSpace(pTouch);
m_nTouchMoving = m_nTouchBegin;
returntrue;
}
void cwMainLayer::ccTouchMoved(CCTouch *pTouch, CCEvent*pEvent)
{
CCPoint pt =this->convertTouchToNodeSpace(pTouch);
float fStep= 1.0;
if(pt.x< m_nTouchMoving.x)
fStep =-fStep;
moveShow(fStep);
arrange();
m_nTouchMoving = pt;
}
void cwMainLayer::ccTouchEnded(CCTouch *pTouch, CCEvent*pEvent)
{
CCPoint pt =this->convertTouchToNodeSpace(pTouch);
float fDist= cocos2d::ccpDistance(pt, m_nTouchBegin);
if(fDist> 5.0) return;
cwShowSprite* pSprite = clickSprite(pt);
if(!pSprite)return;
CCLog("click%d", pSprite->m_uID);
}
///
代码量不大,300行左右。
其中cwMainLayer::init()中的“bk.png”是我随手做的背景图片。
原理就是椭圆上每个对象保存与向量(1,0)的夹角,有了这个夹角,就可以根据椭圆公式计算其x,y坐标;
根据y坐标来计算其所在层的zorder,计算zorder的目的是使前面的图片可以盖住后面的图片;还可以根据其y值计算其缩放值,计算缩放值目的是达到近似近大远小的效果。
关键的就是那么几个函数:
void cwMainLayer::arrangeAngle()
这个函数计算每个对象在椭圆上与向量(1,0)。
void cwMainLayer::arrangePosition()
使用椭圆公式,根据对象的夹角计算其位置,关于椭圆方面的数学知识可以参考
http://hi.baidu.com/ejoqsqmrmvakuxr/item/389ed4d5d48b03d9241f402b
的文章。
void cwMainLayer::arrangeZOrder()
计算图片zorder,首先对所有图片根据其y坐标由小到大进行排序,然后重新设置其zorder,y值越小
的zorder值越大,熟悉3D的朋友应该对这算法比较熟悉吧,原理类似于z-buffer,不过细节上比z-buffer
简单。
void cwMainLayer::arrangeScale()
计算对象的缩放值,图片y值越大,scale值越小,这样就得到近大远小的效果。
使用起来也不麻烦
在HelloWorld::init()中添加如下代码:
cwMainLayer* pMLayer = cwMainLayer::create();
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->addShow("show3.png");
pMLayer->addShow("show4.png");
pMLayer->arrange();
pMLayer->setPosition(ccp(0,0));
this->addChild(pMLayer, 10);
“show3.png”与“show4.png”就是那两个机器人图片。
忙活了两个多小时,边听歌边写代码,感觉还不错。
不过现在该去睡觉了,最近偏头痛犯了,得早休息!
实现了个类似blood brothers中的转轴特效相关推荐
- Java实现类似C/C++中的__FILE__、__FUNC__、__
原文地址 import java.text.SimpleDateFormat; import java.util.Date; /** * Java实现类似C/C++中的__FILE__.__FUNC_ ...
- 利用输入输出流及文件类编写一个程序,可以实现在屏幕显示文本文件的功能,类似DOS命令中的type命令
利用输入输出流及文件类编写一个程序,可以实现在屏幕显示文本文件的功能,类似DOS命令中的type命令 package p1;import java.io.BufferedReader; import ...
- 一些WPF中的滤镜特效——Effect Library
原文:一些WPF中的滤镜特效--Effect Library WPF支持类似PhotoShop的滤镜功能,称之为Effect.在.Net 4.0中,WPF就废弃了对BitMapEffect的支持,转向 ...
- 在视频中实现图像特效
by fanxiushu 2020-06-24 转载或引用请注明原始作者. 说起图像特效,可以打开Photoshop软件,里边有个"滤镜"菜单,再到"滤镜"里边 ...
- UE5虚幻引擎5中的实时特效学习 Introduction to real time FX in Unreal Engine 5
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:40节课(3h 36m) |大小解压后:2.65 G ...
- Fedora 8中完全开启compiz-fusion特效
Fedora 8中完全开启compiz-fusion特效 之前发的举措必需手动运转emerald --replace本事互换主题,因而我做了纠正和更新 1.下载ccsm软件包,并安装好 2.封闭桌面结 ...
- Ureal:用ue4做出游戏中的爆炸特效真实感和力量感
//博主是一个热爱游戏的玩家,并不是专业游戏开发者,内容如有不足,还请各位多多包涵 大家好!今天主要想聊一下:如何体现出游戏中的爆炸特效真实感和力量感 包括Ue4中爆炸的蓝图代码实现的思路(如过需要代 ...
- Vue实战项目开发--Vue中的动画特效
项目的源代码在GitHub上:点击查看 目录 vue中的css动画原理 在Vue中使用Animate.css库 在Vue中同时使用过渡属性和动画 Vue中的Js动画与Velocity.js的结合 Vu ...
- Unity中调整光照特效的7个技巧
适当为游戏场景添加光照效果,能够有效增强场景氛围,让玩家体验更佳.今天将为大家分享在Unity中调整光照特效的7个技巧,让整个游戏场景氛围更引人入胜. 1.使用线性颜色空间 在为场景添加光照效果之前, ...
最新文章
- Σ-delta ADC是否可以测量热噪声?
- rtmp的URL里面mp3:和mp4:是啥意思
- 最近读的那些性能测试书
- android点击按钮底部暗影,android – 圆形按钮,像5.0 FAB一样的阴影
- 当我们谈高性能时,我们谈些什么?(送书活动)
- pc模式 华为mate30_华为mate30与电脑连不上怎么回事
- Color the ball(HDU-1556)
- spring面向接口编程
- 什么是Git?——Git的学习与使用(一)
- 工厂利用计算机实现温度调节属于,工厂利用计算机系统实现温度调节、阀门开关,该应用属于()。A.过程控制B.数据处理C.科学计算D.C...
- Android启动页欢迎界面大全 (网址)
- cocos2d-x 之TableView
- php策略模式作用,PHP设计模式之策略模式详解
- 计算机英语念法,电脑的英文读音标准带音标的
- 乌镇现场 | 倪光南:人工智能应该更好的为人类的服务
- 7大不跳槽就会死的理由!
- 不知足者常乐:SAP云在中国的落地
- 可充电电池安规认证标准、GB 9706.1-2020对医用电气设备中电池的要求
- 5款神级软件,装机必备,不看后悔
- 区别:托管代码与非托管代码