温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

[cocos2d-x]瓦片地图的应用

发布时间:2020-07-09 07:19:53 来源:网络 阅读:444 作者:蓬莱仙羽 栏目:游戏开发

前言:

我们在做经典的格斗类的游戏的时候,场景常常用的是45°斜地图来创建的。下面我就来实现一个简单的Demo来展现一下斜地图的使用。

功能实现:

1.倾斜地图的加载;

2.点击地图居中;

3.主角只能在一定的范围内移动;

4.鼠标点击屏幕,主角移动一格,如果连续点击则主句不断的移动;

5.具备碰撞检测的效果,实现人物在某些地方不能走动。

地图的设计:

用Tiled软件设计自己的瓦片地图。
[cocos2d-x]瓦片地图的应用
[cocos2d-x]瓦片地图的应用

图层要设置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; }   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); }

HelloWorld.h:

#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();      // there's 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);               Player * player;          //限定获取区域     CCPoint playableAreaMin,playableAreaMax;          //获取瓷砖块的坐标     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__

HelloWorldScene.cpp

#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);               //获取屏幕的中点     screenCenter = CCPointMake(size.width/2, size.height/2);      /**********设置鼠标点击屏幕四个方位区域(起始坐标左下角)************************/     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;     } }   void HelloWorld::ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent) {     currentMoveDirection = MoveDirectionNone; }




实现效果:

[cocos2d-x]瓦片地图的应用[cocos2d-x]瓦片地图的应用

[cocos2d-x]瓦片地图的应用

×××:

×××



==================== 迂者 丁小未 CSDN博客专栏=================

MyBlog:http://blog.csdn.net/dingxiaowei2013             MyQQ:1213250243

Unity QQ群:858550         cocos2dx QQ群:280818155

====================== 相互学习,共同进步 ===================

转载请注明出处:http://blog.csdn.net/dingxiaowei2013/article/details/11894879

欢迎关注我的微博:http://weibo.com/u/2590571922


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI