【cocos2d-x 手游研发----地图活起来了】
谈到地图不少人都说要做地图编辑器了,但是我暂时绕过这一步,如果不用寻路地图就不能移动?寻路就是会绕过障碍物的算法。
我做了一个简单的地图的思想,就是地图分层3层:背景层、可行区域层、遮罩层,但是地图就不寻路了,通过设置可行区域层来
实现地图障碍物的方法。下面看一个视图,我把地图详细的分层了:
OK,有了这个思路,大家应该也知道我要怎么做了?代码实现上怎么处理呢?
重点:可行区域层原理是根据点击屏幕上的坐标点来取得这个点是否透明!如果不透明那就不让他进行移动,透明则为不可行区域;
首先感谢一下为我提供取色源码的哥们(firedragonpzy),帮助我实现了这个另类的地图设计;下面我贴一下他的源码,
新建了FDPixelSprite.cpp,FDPixelSprite.h代码如下:
FDPixelSprite.h
- //
- // FDPixelSprite.h
- // PixelDemo
- //
- // Created by firedragonpzy on 13-2-19.
- //
- //
- #ifndef __PixelDemo__FDPixelSprite__
- #define __PixelDemo__FDPixelSprite__
- #include "cocos2d.h"
- USING_NS_CC;
- class FDPixelSprite : public CCSprite, public CCTargetedTouchDelegate {
- public:
- FDPixelSprite();
- virtual ~FDPixelSprite();
- void onEnter();
- void onExit();
- void setimg(CCString Url);
- FDPixelSprite* create(CCString Url);
- CCImage* img ;
- CCRect atlasRect();
- bool isContainTouchLocation(CCTouch *pTouch);
- bool ccTouchBegan(CCString thismapurl,CCTouch *pTouch, CCEvent *pEvent);
- void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
- void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
- CC_SYNTHESIZE(const char*, m_pName,Name);
- };
- #endif /* defined(__PixelDemo__FDPixelSprite__) */
FDPixelSprite.cpp
- //
- // FDPixelSprite.cpp
- // PixelDemo
- //
- // Created by firedragonpzy on 13-2-19.
- //
- //
- #include "FDPixelSprite.h"
- #include "FontChina.h"
- FDPixelSprite::FDPixelSprite()
- {}
- FDPixelSprite::~FDPixelSprite()
- {}
- FDPixelSprite* FDPixelSprite::create(CCString Url)
- {
- FDPixelSprite *sprite = new FDPixelSprite();
- if (sprite && sprite->initWithFile(Url.getCString())) {
- sprite->setName(Url.getCString());
- sprite->autorelease();
- return sprite;
- }
- CC_SAFE_DELETE(sprite);
- sprite = NULL;
- return NULL;
- }
- void FDPixelSprite::setimg(CCString Url){
- img= new CCImage();
- img->initWithImageFileThreadSafe(CCFileUtils::sharedFileUtils()->fullPathForFilename(Url.getCString()).c_str());
- }
- void FDPixelSprite::onEnter()
- {
- CCSprite::onEnter();
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, , true);
- }
- void FDPixelSprite::onExit()
- {
- CCSprite::onExit();
- CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
- }
- bool FDPixelSprite::ccTouchBegan(CCString thismapurl,cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- if (this->isContainTouchLocation(pTouch) ) {
- ccColor4B c = {, , , };
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CCPoint touchPoint = pTouch->getLocationInView();
- CCSize cSize = this->getContentSize();
- CCPoint point =this->getAnchorPointInPoints();
- point = ccp(cSize.width - point.x,cSize.height- point.y);
- CCPoint pos(this->getPositionX() - point.x,winSize.height-this->getPositionY()- point.y);
- CCPoint localPoint = ccp(touchPoint.x - pos.x,
- touchPoint.y -pos.y);
- float scaleFactor = CCDirector::sharedDirector()->getContentScaleFactor();
- unsigned int x = localPoint.x * scaleFactor, y = localPoint.y * scaleFactor;
- float _width = this->getContentSize().width*scaleFactor;
- //This method is currently only supports symmetric image
- //unsigned char *data_ = this->getTexture()->getFDImageData();
- //Efficiency of this method is relatively low
- //CCImage * img = new CCImage();
- //img->initWithImageFileThreadSafe(CCFileUtils::sharedFileUtils()->fullPathForFilename(thismapurl.getCString()).c_str());
- unsigned char *data_ = img->getData();
- unsigned int *pixel = (unsigned int *)data_;
- pixel = pixel + (y * (int)_width)* + x * ;
- c.r = *pixel & 0xff;
- c.g = (*pixel >> ) & 0xff;
- c.b = (*pixel >> ) & 0xff;
- c.a = (*pixel >> ) & 0xff;
- if (c.a == ) {
- CCLog(FontChina::G2U("不可点击!"));
- return false;
- }else
- {
- CCLog(FontChina::G2U("可点击!"));
- return true;
- }
- }
- return false;
- }
- void FDPixelSprite::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- //CCPoint pos = this->getPosition();
- //CCPoint sub = pTouch->getDelta();
- //this->setPosition(ccpAdd(pos, sub));
- }
- void FDPixelSprite::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- //CCLog("firedragonpzy:ccTouchEnded");
- }
- CCRect FDPixelSprite::atlasRect()
- {
- CCSize cSize = this->getContentSize();
- CCPoint point = this->getAnchorPointInPoints();
- return CCRectMake( -point.x, -point.y, cSize.width,cSize.height);
- }
- bool FDPixelSprite::isContainTouchLocation(cocos2d::CCTouch *pTouch)
- {
- return this->atlasRect().containsPoint(convertTouchToNodeSpaceAR(pTouch));
- }
有了他们我们就能判断地图上是否可行了。OK废话不多,继续走向精彩,详细解决一下背景层我们应该做些什么东西,有什么内容?
背景层肯定要装载精灵,把我们之前第二章说的【cocos2d-x 大型ARPG手游研发----精灵的八面玲珑】精灵加载出来,就可以当主角了。
这里有人说,那其他不带主角功能的怎么办?继承你写的精灵类拓展成怪物类(智能AI攻击操作),NPC(任务功能模块),可拓展行是
杠杠滴,继承下来NPC都能移动,和你打起来,我的思路是把地图做成一个大容器,每一块新地图继承一个MapsBase的同时他自己也有
有自己的特殊逻辑和特殊业务;
继续贴代码,地图是这么实现的:
Maps_Diyu.h
- #include "cocos2d.h"
- #include "../Commen/FDPixelSprite.h"
- #include "../Spirits/SpiritsPlayer.h"
- USING_NS_CC;
- class Maps_Diyu :public cocos2d::CCSprite
- {
- public:
- Maps_Diyu(CCLayer* layer,CCString mapsurl,CCString mapsurl_1,int zOrder,CCPoint cp);
- ~Maps_Diyu(void);
- CCSprite* nowmap;
- CCSprite* nowmap_zhezhao;
- //基本数据
- float lastmove_x,lastmove_y;
- bool moveMapto(CCPoint cp,FDPixelSprite* mainmap_Touch);
- CCActionInterval* act_moveto_maps;
- CCActionInterval* act_moveto_maps_touch;
- CCActionInterval* act_moveto_maps_zhezhao;
- private:
- SpiritsPlayer* role_main;
- CCAnimate* playdonghua;
- };
Maps_Diyu.cpp
- #include "Maps_Diyu.h"
- #include "../GameData/GetNPCData.h"
- #include "../Commen/FontChina.h"
- #include "../Spirits/SpiritsMonster.h"
- #include "../Effects/SkillEffects.h"
- Maps_Diyu::Maps_Diyu(CCLayer* layer,CCString mapsurl,CCString mapsurl_1,int zOrder,CCPoint cp)
- {
- act_moveto_maps=NULL;
- act_moveto_maps_zhezhao=NULL;
- lastmove_x=;
- lastmove_y=;
- float map_x , map_y;
- float center_x,center_y;
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- nowmap = Maps_Diyu::create(mapsurl.getCString());
- nowmap_zhezhao = Maps_Diyu::create(mapsurl_1.getCString());
- center_x = size.width/;
- center_y = size.height/;
- map_y = nowmap->getAnchorPointInPoints().y+origin.y;
- map_x = nowmap->getAnchorPointInPoints().x;
- if(cp.getLength()>)
- {
- nowmap->setPosition(cp);
- nowmap_zhezhao->setPosition(cp);
- }
- else
- {
- nowmap->setPosition(ccp(map_x,map_y));
- nowmap_zhezhao->setPosition(ccp(map_x,map_y));
- }
- //计算地图上绝对位置的原点坐标
- float map_fornpc_x,map_fornpc_y;
- map_fornpc_x= nowmap->getContentSize().width/;
- map_fornpc_y=nowmap->getContentSize().height/;
- //主角加载
- GetNPCData* basedatas = new GetNPCData();
- basedatas->GetNPCchapter1();
- basedatas->role_player.nowpoint= CCPointMake(map_fornpc_x+,map_fornpc_y+);
- role_main = new SpiritsPlayer(basedatas->role_player,,false);
- role_main->npc->retain();
- //加载NPC
- basedatas->role_mengpo.nowpoint= CCPointMake(map_fornpc_x+,map_fornpc_y+);
- SpiritsPlayer* role_mengpo= new SpiritsPlayer(basedatas->role_mengpo,,true);
- nowmap->addChild(role_mengpo->npc, );
- //-------------------------------------------------------
- nowmap->addChild(role_main->npc, ,);
- layer->addChild(nowmap_zhezhao, zOrder+);
- layer->addChild(nowmap, zOrder);
- }
OK,地图初始化就加载了这些基础的数据,这些应该大家都能看懂,下面贴最核心的代码,如何把他们都关联起来
并且做移动操作呢??????
- /*************************
- 参数说明:
- CCPoint cp 可行区域的坐标
- mainmap_Touch 可行区域,需要去随时改变他移动
- **************************/
- bool Maps_Diyu::moveMapto(CCPoint cp,FDPixelSprite* mainmap_Touch)
- {
- float center_x,center_y,move_x,move_y, map_x , map_y ,to_c_x,to_c_y;
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- center_x = size.width/;
- center_y = size.height/;
- move_x = center_x-cp.x;
- move_y = center_y-cp.y;
- map_x = nowmap->getPositionX();
- map_y = nowmap->getPositionY();
- to_c_x = nowmap->getContentSize().width/;
- to_c_y = nowmap->getContentSize().height/+origin.y;
- map_x = map_x + move_x;
- map_y = map_y + move_y-origin.y;
- //计算移动时间,这边大家可以帮我优化一下
- //现在就这块移动时间有一些问题
- float a1 , b1 ;
- a1 = fabs(move_x)/size.width;
- b1 = fabs(move_y)/size.height;
- float movetime = ((a1+b1)*);
- if(movetime<=)
- {
- movetime=;
- }
- //这里是精华,主要是处理任意地图放进来之后,
- //防止显示区域超出地图的长宽,移动到边界就不能移动了!
- if(map_x>=to_c_x)
- {
- map_x = to_c_x;
- }
- else if(map_x<=-((nowmap->getContentSize().width/)-size.width))
- {
- map_x =-((nowmap->getContentSize().width/)-size.width);
- }
- if(map_y>=to_c_y)
- {
- map_y = to_c_y;
- }
- else if(map_y <= -((nowmap->getContentSize().height/)-size.height))
- {
- map_y = -((nowmap->getContentSize().height/)-size.height);
- }
- //经典中的经典//
- //主角移动
- CCPoint role_move_pc = nowmap->convertToNodeSpace(ccp(cp.x,cp.y));//此处需要通过地图的视角把人物移动的坐标转化一下。
- role_main->moveTomap_dir(role_move_pc);
- role_main->moveTomap_move(movetime,role_move_pc,false);
- //地图移动
- if(map_x!=lastmove_x&&map_y!=lastmove_y)
- {
- nowmap->stopAction(act_moveto_maps);
- nowmap_zhezhao->stopAction(act_moveto_maps_zhezhao);
- mainmap_Touch->stopAllActions();
- act_moveto_maps = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- act_moveto_maps_touch = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- act_moveto_maps_zhezhao = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- nowmap->runAction(act_moveto_maps);
- nowmap_zhezhao->runAction(act_moveto_maps_zhezhao);
- mainmap_Touch->runAction(act_moveto_maps_touch);
- return true;
- }
- else
- {
- return false;
- }
- }
核心的地方有三处,帮大家分析一下:
第一,就是计算移动时间,我是根据屏幕长宽来计算,这个地方一直是我心结,这个方法效果现在很不好,跑起来
长距离用时长,短距离就很快,所以请大家也帮我优化一下,可以往下贴代码,
第二,就是计算出地图移动的区域,你不可能随便丢一张图进去,地图超过边界会显示黑色,不能让黑色显示出来(除非丢进来的图小过屏幕地图);
第三,就是通过地图移动的标识来进行人物和地图的移动,在人物移动的时候需要转化一下成地图的坐标!
- map_x!=lastmove_x&&map_y!=lastmove_y
- 可移动的标识
- act_moveto_maps = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- act_moveto_maps_touch = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- act_moveto_maps_zhezhao = CCMoveTo::create(movetime,ccp((int)map_x,(int)map_y));
- 大家也看到,我移动的时候,移动的是3个层,这下就保证了可行区域也是不停在变动的
然后就是如何传数据了,几句话就可以搞定Scene加载的地图上所有层;
Scene_Diyu.h
- #include "cocos2d.h"
- #include "ToScene.h"
- #include "../MapSpirits/Maps_Diyu.h"
- USING_NS_CC;
- class Scene_Diyu : public CCLayer
- {
- public:
- Scene_Diyu(void);
- ~Scene_Diyu(void);
- Maps_Diyu* mainmap;
- FDPixelSprite* mainmap_Touch;
- void nextCallback(CCObject* pSender);
- virtual void registerWithTouchDispatcher(void);
- virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
- virtual void ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent);
- virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);
- virtual void ccTouchCancelled(CCTouch *pTouch,CCEvent *pEvent);
- };
Scene_Diyu.cpp
- #include "Scene_Diyu.h"
- #include "../ImagePaths.h"
- #include "../PublicUI/BaseUI.h"
- Scene_Diyu::Scene_Diyu(void)
- {
- float x,y;
- CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- x = size.width;
- y = size.height;
- //地图
- mainmap = new Maps_Diyu(this,"map_diyu_naihe.jpg","map_diyu_naihe1.png",,ccp(x/-,y/-));
- mainmap_Touch = mainmap_Touch->create("map_diyu_naihe0.png");
- mainmap_Touch->setimg("map_diyu_naihe0.png");
- mainmap_Touch->setPosition(ccp(x/-,y/-));
- mainmap_Touch->setVisible(false);//是否显示点击层
- BaseUI* baseui = new BaseUI(this);
- this->addChild(mainmap_Touch, );
- setTouchEnabled(true);
- }
- void Scene_Diyu::registerWithTouchDispatcher()
- {
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,,true);
- }
- bool Scene_Diyu::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- if(mainmap_Touch->ccTouchBegan("map_diyu_naihe0.png",pTouch,pEvent)==true)
- {
- mainmap->moveMapto(pTouch->getLocation(),mainmap_Touch);
- }
- return true;
- }
- void Scene_Diyu::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- }
- void Scene_Diyu::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- }
- void Scene_Diyu::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- }
- Scene_Diyu::~Scene_Diyu(void)
- {
- }
大家也看到了再Scene里面控制的点击事件主要就是处理可行区域的:
- if(mainmap_Touch->ccTouchBegan("map_diyu_naihe0.png",pTouch,pEvent)==true)
- {
- mainmap->moveMapto(pTouch->getLocation(),mainmap_Touch);
- }
好了,大家如果理解,可以自己研究一下自己的方式去实现一下这样一套,人物移动,地图移动的原理,当然,我在这里声明一下
这套实现思路其实是很歪门,另类的,应为他并没有采用寻路,但是你也不能完全说不采用寻路算法的地图系统就不行。
跑起来看一下效果截图:
跑起来后的效果图!!!
人物被遮罩层遮挡的效果图!!
这篇就讲这么多了,下一篇直接讲一下【怪物智能AI的制作】怪物实现追踪主角,怪物随机生成怪圈,怪物随机移动巡逻。
游戏demo及素材下载地址(demo里面包含了所有的素材资料);
http://pan.baidu.com/share/link?shareid=4012433582&uk=4097703620&third=15
我建了一个QQ群:和大家一起分享cocos2dx开发经验【41131516】
【cocos2d-x 手游研发----地图活起来了】的更多相关文章
- 【cocos2d-x 手游研发----目录】
感谢大家一直支持我写这样一系列的博客,从中我自己也获益良多,cocos2d-x这样一款非常棒的引擎,是值得我们去学习和分享的,谈到分享,那我就把这套写了差不多一两个月的框架给大家开源下载,写的很一般, ...
- 手游研发CJ抱大腿指南
文摘要:CJ来了,又是一年一度的游戏圈盛事,随着手游行业的迅速崛起,今年CJ上,手游研发商以及发行商必定成为焦点.由于门槛低.市场热.前景好等因素的影响,国内一下子蹦出一大堆手游研发团队.很幸运(或者 ...
- 【cocos2d-x 手游研发----研发思路及感想】
我半年前进入了目前的这家做教育行业的公司(在此之前一直从事原生态开发手游的迷茫之路),学习是一件很快乐的事情,来到这家公司我有了很多时间去学习,不管是公司业务,还是其他技术相关的.于是开始 ...
- 【cocos2d-x 手游研发----界面UI设计】
简单探讨一下如何在cocos2d-x的游戏引擎里面去制作各做交互UI界面,常见的UI如下: 人物头像,血条值,经验条,技能按钮,以及各种玩家交互的界面按钮:背包,人物属性,门派,等: 类似上面的图示交 ...
- 【cocos2d-x 手游研发----精灵的八面玲珑】
继续上一篇文章继续聊吧,这章内容会比较多,也会附上代码,很多朋友加了群,大家在群里面探讨了很多东西,这让大家都觉得受益匪浅,这便是极好的,废话不多了,精灵是游戏的重要组成部分,那ARPG里面的精灵必然 ...
- 【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】
转载请注明出处:http://www.cnblogs.com/zisou/p/cocos2dxJQ-6.html 聊天系统在手机网游中是最常见的交互工具,大家在一起边玩游戏边聊天岂不乐哉: 废话不多了 ...
- 【cocos2d-x 手游研发----怪物智能AI】
原创文章,转载请注明出处:http://www.cnblogs.com/zisou/p/cocos2d-xARPG4.html 谈到怪物AI,我觉得就比较话多了,首先理解一下(Artificial I ...
- 【cocos2d-x 手游研发小技巧(1)自定义制作怪物伤害数值】
直插主题了,今天写了一下午,早就想要写这类似东西的,首先我不会选用CCLabelAtlas了,我直接用帧图片做. 首先我们要准备素材,我先把素材帖出来给大家: 这个是一张比较全的素材图,它包含了扣血的 ...
- 【cocos2d-x 手游研发小技巧(7)图片资源加密,Lua文件加密】
游戏开发中常遇到资源保护的问题. 目前游戏开发中常加密的文件类型有:图片,Lua文件,音频等文件,而其实加密也是一把双刃剑. 需要安全那就得耗费一定的资源去实现它.目前网上也有用TexturePack ...
随机推荐
- python作业之修改用户配置文件
用户的配置文件如下 backend oldboy school school1 age 21 weight 210 qq 550176565 iphone 139987676backend oldgi ...
- python生成验证码,文字转换为图片-乾颐堂
在58或者赶集等一些网站上经常看到手机号是图片格式,或者一些网站的验证码.这些都是动态生成的,今天我们来看一下如何用python把文字生成图片.其实今天主要借助pygame的图像渲染模块,这样比较简单 ...
- laravel的函数asset()、url()
1.asset():用于引入静态文件,如 css/JavaScript/images,文件必须存放在public文件目录下 src="{{ asset('home') }}/images/t ...
- 获取GUID的GET网址:createguid.com
1.在浏览器的地址栏中输入createguid.com,回车之后即可得到一个GUID 2.在JMeter中可以这样填写HTTP Request 然后通过正则表达式提取器提取GUID <texta ...
- oracle 表分区例子
oracle表分区详解-一步一步教你oracle分区表详解 .创建三个不同的表空间,模拟在不同磁盘上的保存不同范围的数据 create tablespace test01 datafile ...
- 【转】Hibernate的getSQLQuery方法对char类型的解析问题
[转]Hibernate的getSQLQuery方法对char类型的解析问题 建立数据库: create table T_TEST1( id char (32), name varchar (255) ...
- 2018.09.08 NOIP模拟eat(贪心)
签到水题啊... 这题完全跟图论没有关系. 显然如果确定了哪些点会被选之后顺序已经不重要了.于是我们给点按权值排序贪心从大向小选. 我们要求的显然就是∑i(a[i]−(n−i))" role ...
- 马婕 2014年MBA,mpacc备考 报刊宣读1 中国的电子商务(转)
http://blog.sina.com.cn/s/blog_3e66af4601015fxi.html 中国电子商务蓄势待发 Chinese e-commerce中国电子商务Pity the par ...
- select自定义下拉选择图标
闲言少叙: 上CSS: appearance: none; -moz-appearance: none; -webkit-appearance: none; cursor: pointer; back ...
- Python+Android开发
1 下载Scripting Layer for Android (SL4A) Scripting Layer for Android (SL4A) 是一个开源项目,目标是为android系统提供脚本语 ...