[cocos2d-x]瓦片地图的应用
应用 地图 cocos2d 瓦片
2023-09-27 14:29:23 时间
我们在做经典的格斗类的游戏的时候,场景常常用的是45°斜地图来创建的。下面我就来实现一个简单的Demo来展现一下斜地图的使用。
功能实现: 1.倾斜地图的加载; 2.点击地图居中; 3.主角只能在一定的范围内移动; 4.鼠标点击屏幕,主角移动一格,如果连续点击则主句不断的移动; 5.具备碰撞检测的效果,实现人物在某些地方不能走动。 地图的设计: 用Tiled软件设计自己的瓦片地图。图层要设置z轴属性,方便可以隐藏主角: 在图层的属性中加上 cc_vertexz -400 如果前面的图层那就设置为automatic 代码实现: 在AppDelegate添加代码:
//深度测试,方便实现遮盖效果 CCDirector::sharedDirector()- setDepthTest(true); //Opengl渲染设置,如果地图有背景图层的话就需要加这句 CCDirector::sharedDirector()- setProjection(kCCDirectorProjection2D);Player类:
#ifndef ___5tilemap__Player__ #define ___5tilemap__Player__ #include iostream #include "cocos2d.h" using namespace cocos2d; class Player : public CCSprite public: static Player * create(); virtual bool initPlayer(); //获取地图中某瓷砖快的z轴属性 void updateVertextZ(CCPoint tilePos,CCTMXTiledMap * tileMap); #endif /* defined(___5tilemap__Player__) */
#include "Player.h" static Player *s; Player* Player::create() s = new Player(); if (s s- initPlayer()) { s- autorelease(); return s; else delete s; s = NULL; return NULL; //初始化一个对象 bool Player::initPlayer() if (!CCSprite::initWithFile("ninja.png")) { return false; return true;HelloWorld.h:
void Player::updateVertextZ(cocos2d::CCPoint tilePos, cocos2d::CCTMXTiledMap *tileMap) //获取最小的z轴属性 float lowestZ = -(tileMap- getMapSize().width + tileMap- getMapSize().height); //以瓷砖块的x,y坐标来计算当前瓷砖块的z轴属性 float currentZ = tilePos.x + tilePos.y; //设置z轴属性 this- setVertexZ(lowestZ+currentZ - 1); }
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "Player.h" using namespace cocos2d; //枚举列出移动的方向 typedef enum { MoveDirectionNone = 0, MoveDirectionUpperLeft, MoveDirectionLowerLeft, MoveDirectionUpperRight, MoveDirectionLowerRight, MAX_MoveDirections }EMoveDirection; class HelloWorld : public cocos2d::CCLayer public: // Method init in cocos2d-x returns bool, instead of id in cocos2d-iphone (an object pointer) virtual bool init(); // theres no id in cpp, so we recommend to return the class instance pointer static cocos2d::CCScene* scene(); CREATE_FUNC(HelloWorld); virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); //获取屏幕点击的坐标 CCPoint locationFromTouches(CCSet *touches);HelloWorldScene.cpp
//获取瓷砖块的坐标 CCPoint tilePosFromLocation(CCPoint location,CCTMXTiledMap * tilemap); //图层居中 void centerTileMapOnTileCoord(CCPoint tilePos,CCTMXTiledMap *tileMap); //设置不可移动 virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); CCPoint screenCenter; //记录下当前的地图 CCTMXTiledMap * tileMap; //屏幕以中点为划分点,将屏幕分成四份 CCRect upperLeft,lowerLeft,upperRight,lowerRight; //移动数组记录5个移动状态 CCPoint moveOffsets[MAX_MoveDirections]; //当前移动的状态 EMoveDirection currentMoveDirection; //不断的更新监听是否移动 void update(float delta); //检测移动的地图是否越界 CCPoint ensureTilePosIsWithinBounds(CCPoint tilePos); //添加碰撞检测 bool isTilePosBlocked(CCPoint tilepos,CCTMXTiledMap * tileMap); #endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h" #include "SimpleAudioEngine.h" #include "Player.h" using namespace cocos2d; using namespace CocosDenshion; 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() // 1. super init first if ( !CCLayer::init() ) return false; CCSize size = CCDirector::sharedDirector()- getWinSize(); //添加一个地图 CCTMXTiledMap * tileMap = CCTMXTiledMap::create("huohuo.tmx"); // CCTMXTiledMap * tileMap = CCTMXTiledMap::create("isometric.tmx"); // tileMap- setAnchorPoint(CCPointMake(size.width/2, size.height/2)); // tileMap- setPosition(CCPointMake(size.width/2, size.height/2));
//获取碰撞检测的图层,并设置为不可见 CCTMXLayer * layer = tileMap- layerNamed("Collisions"); layer- setVisible(false); CCSize s = tileMap- getContentSize(); CCLog("width:%f",-s.width/2); tileMap- setPosition(ccp(-s.width/2,0)); this- addChild(tileMap,-1,1); this- setTouchEnabled(true); this- tileMap = tileMap; //添加主角精灵 player = Player::create(); player- setPosition(CCPointMake(size.width / 2, size.height / 2)); player- setAnchorPoint(ccp(0.3f,0.1)); this- addChild(player);
/********设置可以活动的区域***********************************************/ //外围不可活动区域的瓷砖块数 const int borderSize = 10; //最小活动区域 playableAreaMin = CCPointMake(borderSize, borderSize); //最大活动区域的瓷砖块数(总块数-不可活动的区域瓷砖块) playableAreaMax = CCPointMake(tileMap- getMapSize().width - 1 - borderSize, tileMap- getMapSize().height - 1 - borderSize);
/**********设置鼠标点击屏幕四个方位区域(起始坐标左下角)************************/ upperLeft = CCRectMake(0, screenCenter.y, screenCenter.x, screenCenter.y); lowerLeft = CCRectMake(0, 0, screenCenter.x, screenCenter.y); upperRight = CCRectMake(screenCenter.x, screenCenter.y, screenCenter.x, screenCenter.y); lowerRight = CCRectMake(screenCenter.x, 0, screenCenter.x, screenCenter.y); /**********定义四个方向的坐标点********************************************/ moveOffsets[MoveDirectionNone] = CCPointZero; moveOffsets[MoveDirectionUpperLeft] = CCPointMake(-1, 0); moveOffsets[MoveDirectionLowerLeft] = CCPointMake(0, 1); moveOffsets[MoveDirectionUpperRight] = CCPointMake(0, -1); moveOffsets[MoveDirectionLowerRight] = CCPointMake(1, 0); currentMoveDirection = MoveDirectionNone; //通过预约的更新方法来检查角色的移动 this- scheduleUpdate(); return true; //不断的检测是否按下鼠标 void HelloWorld::update(float delta) //如果当前地图没有移动 if (tileMap- numberOfRunningActions() == 0) { //如果有按下鼠标方向 if (currentMoveDirection != MoveDirectionNone) { //获取瓷砖块的坐标 CCPoint tilePos = this- tilePosFromLocation(screenCenter, tileMap); //获取当前要移动一个位置的相对坐标 CCPoint offset = moveOffsets[currentMoveDirection]; //计算获得要移动到那个位置的绝对坐标 tilePos = CCPointMake(tilePos.x + offset.x, tilePos.y + offset.y); //确保主角不会超出屏幕的边界,如果超出则按照边界点来算 tilePos = this- ensureTilePosIsWithinBounds(tilePos); //判断目标位置是否能移动 if (this- isTilePosBlocked(tilePos, tileMap) == false) { //将要移动的那个坐标的瓷砖块移动到当前屏幕的中央 this- centerTileMapOnTileCoord(tilePos, tileMap); //连续不断的修改角色的vertexz的值 CCPoint tilePos = this- tilePosFromLocation(tilePos, tileMap); player- updateVertextZ(tilePos, tileMap); //添加碰撞检测,是否走到不可碰撞的区域 bool HelloWorld::isTilePosBlocked(cocos2d::CCPoint tilepos, cocos2d::CCTMXTiledMap *tileMap) CCTMXLayer * layer = tileMap- layerNamed("Collisions"); bool isBokcked = false; unsigned int tileGID = layer- tileGIDAt(tilepos); if (tileGID 0) { CCDictionary * tileProperties = tileMap- propertiesForGID(tileGID); void * blocks_movement = tileProperties- objectForKey("blocks_movement"); isBokcked = (blocks_movement != NULL); return isBokcked; //获取瓷砖块相对地图的坐标 CCPoint HelloWorld::tilePosFromLocation(cocos2d::CCPoint location, cocos2d::CCTMXTiledMap *tilemap) //减去地图的偏移量 CCPoint pos = ccpSub(location, tilemap- getPosition()); float halfMapWidth = tilemap- getMapSize().width * 0.5f; float mapHeight = tilemap- getMapSize().height; float tileWidth = tilemap- getTileSize().width; float tileHeight = tilemap- getTileSize().height; CCPoint tilePasDiv = ccp(pos.x / tileWidth, pos.y / tileHeight); float inverseTileY = mapHeight - tilePasDiv.y; float posX = (int)(inverseTileY + tilePasDiv.x - halfMapWidth); float posY = (int)(inverseTileY - tilePasDiv.x + halfMapWidth); // posX = MAX(0, posX); // posX = MIN(tilemap- getMapSize().width - 1, posX); // posY = MAX(0, posY); // posY = MIN(tilemap- getMapSize().height - 1, posY); posX = MAX(playableAreaMin.x,posX); posX = MIN(playableAreaMax.x, posX); posY = MAX(playableAreaMin.y, posY); posY = MIN(playableAreaMax.y, posY); pos = CCPointMake(posX, posY); CCLog("X:%f,Y:%f",pos.x,pos.y); return pos; //将地图居中 void HelloWorld::centerTileMapOnTileCoord(cocos2d::CCPoint tilePos, cocos2d::CCTMXTiledMap *tileMap) //获取屏幕大小和屏幕中心点 CCSize size = CCDirector::sharedDirector()- getWinSize(); CCPoint screenCenter = CCPointMake(size.width/2, size.height/2); //获取地板层 CCTMXLayer * layer = tileMap- layerNamed("Ground"); //CCTMXLayer * layer = tileMap- layerNamed("GroundLayer1"); //仅仅在内部使用;瓷砖的Y坐标减去1 tilePos.y -=1; //获取瓷砖块坐标 CCPoint scrollPosition = layer- positionAt(tilePos); //考虑到地图移动的情况,我将像素坐标信息乘以-1,从而得到负值 scrollPosition = ccpMult(scrollPosition, -1); //为屏幕中央坐标添加位移值 scrollPosition = ccpAdd(scrollPosition, screenCenter); CCMoveTo * move = CCMoveTo::create(.2f, scrollPosition); tileMap- stopAllActions(); tileMap- runAction(move); //确保主角不会超出屏幕的边界 CCPoint HelloWorld::ensureTilePosIsWithinBounds(CCPoint tilePos) tilePos.x = MAX(playableAreaMin.x,tilePos.x); tilePos.x = MIN(playableAreaMax.x, tilePos.x); tilePos.y = MAX(playableAreaMin.y,tilePos.y); tilePos.y = MIN(playableAreaMax.y, tilePos.y); return tilePos; //返回点击屏幕的坐标点 CCPoint HelloWorld::locationFromTouches(cocos2d::CCSet *touches) CCTouch *touch = (CCTouch *)touches- anyObject(); return touch- getLocation(); CCLog("点击屏幕的坐标点%f,%f",touch- getLocation().x,touch- getLocation().y); void HelloWorld::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) // CCNode * node = this- getChildByTag(1); // CCTMXTiledMap *tileMap = (CCTMXTiledMap *)node; // CCPoint touchLocation = this- locationFromTouches(pTouches); // CCPoint tilepos = this- tilePosFromLocation(touchLocation, tileMap); // CCLog("%f,%f",tilepos.x,tilepos.y); // this- centerTileMapOnTileCoord(tilepos, tileMap); // player- updateVertextZ(tilepos, tileMap); CCTouch *touch = (CCTouch *)pTouches- anyObject(); CCPoint touchLocation = touch- getLocation(); if (upperLeft.containsPoint(touchLocation)) currentMoveDirection = MoveDirectionUpperLeft; else if (lowerLeft.containsPoint(touchLocation)) currentMoveDirection = MoveDirectionLowerLeft; else if(upperRight.containsPoint(touchLocation)) currentMoveDirection = MoveDirectionUpperRight; else if(lowerRight.containsPoint(touchLocation)) currentMoveDirection = MoveDirectionLowerRight;
实现效果:
源码下载:
==================== 迂者 丁小未 CSDN博客专栏=================
MyBlog:http://blog.csdn.net/dingxiaowei2013 MyQQ:1213250243
Unity QQ群:375151422 cocos2dx QQ群:280818155
====================== 相互学习,共同进步 ===================
转载请注明出处:http://blog.csdn.net/dingxiaowei2013/article/details/11894879
欢迎关注我的微博:http://weibo.com/u/2590571922
《Cocos2D-x权威指南》——1.3 Cocos2D-x与Cocos2D-iPhone的比较 本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第1章,第1.3节,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
《Cocos2D-x权威指南》——1.2 什么是Cocos2D-x 本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第1章,第1.2节,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
《Cocos2D-x权威指南》——1.1 什么是Cocos2D 本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第1章,第1.1节,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
《Cocos2D-x权威指南》——第1章 认识Cocos2D-x 本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第1章,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
《Cocos2D权威指南》——1.1 什么是Cocos2D 本节书摘来自华章计算机《Cocos2D权威指南》一书中的第1章,第1.1节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
蓬莱仙羽 麦子学院讲师,游戏蛮牛专栏作家,CSDN博客专家,热爱游戏开发,热爱Coding!
相关文章
- 深度学习在物理层信号处理中的应用研究
- CleanMyMac4.11.3macOS系统垃圾清理应用
- 数据分析在私有云平台运维中的应用
- 如何在vue单页应用中使用百度地图
- 过滤器应用【编码、敏感词、压缩、转义过滤器】
- 5 个快速的 Node.js 应用性能提示
- 首届大数据分析论坛成功举办 GPU加速大数据分析应用创新
- [算法题] 安排会议室——贪心算法的应用
- 《区块链原理、设计与应用》一2.2 技术的演化与分类
- Android物联网应用程序开发(智慧城市)—— 查询购物信息界面开发
- 苹果浏览器应用实战篇(一)
- Xenu-web开发死链接检測工具应用
- Infragistics Professional应用程序开发
- Android应用之——百度地图最新SDK3.0应用,实现最经常使用的标注覆盖物以及弹出窗覆盖物
- Kotlin Flow 冷流 StateFlow 热流 StateFlow 的应用
- 用OpenLayers开发地图应用
- 微信小程序----高德地图开发应用(获取key)
- iOS7应用开发13:应用类UIApplication、网络活动指示器、地图
- [IOS]地图的简单应用