最近比较忙,有一段时间没写东西了,今天算是忙里偷闲,分享点东西。
在美区有个游戏叫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中的转轴特效相关推荐

  1. Java实现类似C/C++中的__FILE__、__FUNC__、__

    原文地址 import java.text.SimpleDateFormat; import java.util.Date; /** * Java实现类似C/C++中的__FILE__.__FUNC_ ...

  2. 利用输入输出流及文件类编写一个程序,可以实现在屏幕显示文本文件的功能,类似DOS命令中的type命令

    利用输入输出流及文件类编写一个程序,可以实现在屏幕显示文本文件的功能,类似DOS命令中的type命令 package p1;import java.io.BufferedReader; import ...

  3. 一些WPF中的滤镜特效——Effect Library

    原文:一些WPF中的滤镜特效--Effect Library WPF支持类似PhotoShop的滤镜功能,称之为Effect.在.Net 4.0中,WPF就废弃了对BitMapEffect的支持,转向 ...

  4. 在视频中实现图像特效

    by fanxiushu 2020-06-24 转载或引用请注明原始作者. 说起图像特效,可以打开Photoshop软件,里边有个"滤镜"菜单,再到"滤镜"里边 ...

  5. 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 ...

  6. Fedora 8中完全开启compiz-fusion特效

    Fedora 8中完全开启compiz-fusion特效 之前发的举措必需手动运转emerald --replace本事互换主题,因而我做了纠正和更新 1.下载ccsm软件包,并安装好 2.封闭桌面结 ...

  7. Ureal:用ue4做出游戏中的爆炸特效真实感和力量感

    //博主是一个热爱游戏的玩家,并不是专业游戏开发者,内容如有不足,还请各位多多包涵 大家好!今天主要想聊一下:如何体现出游戏中的爆炸特效真实感和力量感 包括Ue4中爆炸的蓝图代码实现的思路(如过需要代 ...

  8. Vue实战项目开发--Vue中的动画特效

    项目的源代码在GitHub上:点击查看 目录 vue中的css动画原理 在Vue中使用Animate.css库 在Vue中同时使用过渡属性和动画 Vue中的Js动画与Velocity.js的结合 Vu ...

  9. Unity中调整光照特效的7个技巧

    适当为游戏场景添加光照效果,能够有效增强场景氛围,让玩家体验更佳.今天将为大家分享在Unity中调整光照特效的7个技巧,让整个游戏场景氛围更引人入胜. 1.使用线性颜色空间 在为场景添加光照效果之前, ...

最新文章

  1. Σ-delta ADC是否可以测量热噪声?
  2. rtmp的URL里面mp3:和mp4:是啥意思
  3. 最近读的那些性能测试书
  4. android点击按钮底部暗影,android – 圆形按钮,像5.0 FAB一样的阴影
  5. 当我们谈高性能时,我们谈些什么?(送书活动)
  6. pc模式 华为mate30_华为mate30与电脑连不上怎么回事
  7. Color the ball(HDU-1556)
  8. spring面向接口编程
  9. 什么是Git?——Git的学习与使用(一)
  10. 工厂利用计算机实现温度调节属于,工厂利用计算机系统实现温度调节、阀门开关,该应用属于()。A.过程控制B.数据处理C.科学计算D.C...
  11. Android启动页欢迎界面大全 (网址)
  12. cocos2d-x 之TableView
  13. php策略模式作用,PHP设计模式之策略模式详解
  14. 计算机英语念法,电脑的英文读音标准带音标的
  15. 乌镇现场 | 倪光南:人工智能应该更好的为人类的服务
  16. 7大不跳槽就会死的理由!
  17. 不知足者常乐:SAP云在中国的落地
  18. 可充电电池安规认证标准、GB 9706.1-2020对医用电气设备中电池的要求
  19. 5款神级软件,装机必备,不看后悔
  20. 区别:托管代码与非托管代码

热门文章

  1. 网易Java岗社招面试经历分享
  2. IOS中 如何实现汽车报价大全主界面中选择车型的UI
  3. vue 插件vetur提示错误
  4. Spring Boot(五十六):基于Redis的搜索栏热搜功能
  5. 重返20岁(2020年末,到2021年新年计划)
  6. sounds speech_An organized speech would sounds
  7. 央视赋能,强势出击——方圆出海与《品牌中国》栏目达成战略合作
  8. IB学习者培养目标-知识渊博
  9. win10开机蓝屏代码0xc000001怎么办 错误代码0xc000001的解决教程
  10. 字典树——字典树树模板