溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

[cocos2d-x]瓦片地圖的應(yīng)用

發(fā)布時間:2020-07-09 07:19:53 來源:網(wǎng)絡(luò) 閱讀:441 作者:蓬萊仙羽 欄目:游戲開發(fā)

前言:

我們在做經(jīng)典的格斗類的游戲的時候,場景常常用的是45°斜地圖來創(chuàng)建的。下面我就來實現(xiàn)一個簡單的Demo來展現(xiàn)一下斜地圖的使用。

功能實現(xiàn):

1.傾斜地圖的加載;

2.點擊地圖居中;

3.主角只能在一定的范圍內(nèi)移動;

4.鼠標點擊屏幕,主角移動一格,如果連續(xù)點擊則主句不斷的移動;

5.具備碰撞檢測的效果,實現(xiàn)人物在某些地方不能走動。

地圖的設(shè)計:

用Tiled軟件設(shè)計自己的瓦片地圖。
[cocos2d-x]瓦片地圖的應(yīng)用
[cocos2d-x]瓦片地圖的應(yīng)用

圖層要設(shè)置z軸屬性,方便可以隱藏主角:
在圖層的屬性中加上 cc_vertexz -400 
如果前面的圖層那就設(shè)置為automatic

代碼實現(xiàn):

在AppDelegate添加代碼:

 //深度測試,方便實現(xiàn)遮蓋效果  CCDirector::sharedDirector()->setDepthTest(true);  //Opengl渲染設(shè)置,如果地圖有背景圖層的話就需要加這句  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;     //設(shè)置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;          //限定獲取區(qū)域     CCPoint playableAreaMin,playableAreaMax;          //獲取瓷磚塊的坐標     CCPoint tilePosFromLocation(CCPoint location,CCTMXTiledMap * tilemap);          //圖層居中     void centerTileMapOnTileCoord(CCPoint tilePos,CCTMXTiledMap *tileMap);          //設(shè)置不可移動     virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);          CCPoint screenCenter;          //記錄下當前的地圖     CCTMXTiledMap * tileMap;          //屏幕以中點為劃分點,將屏幕分成四份     CCRect upperLeft,lowerLeft,upperRight,lowerRight;          //移動數(shù)組記錄5個移動狀態(tài)     CCPoint moveOffsets[MAX_MoveDirections];          //當前移動的狀態(tài)     EMoveDirection currentMoveDirection;          //不斷的更新監(jiān)聽是否移動     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));               //獲取碰撞檢測的圖層,并設(shè)置為不可見     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);           /********設(shè)置可以活動的區(qū)域***********************************************/     //外圍不可活動區(qū)域的瓷磚塊數(shù)     const int borderSize = 10;     //最小活動區(qū)域     playableAreaMin = CCPointMake(borderSize, borderSize);     //最大活動區(qū)域的瓷磚塊數(shù)(總塊數(shù)-不可活動的區(qū)域瓷磚塊)     playableAreaMax = CCPointMake(tileMap->getMapSize().width - 1 - borderSize, tileMap->getMapSize().height - 1 - borderSize);               //獲取屏幕的中點     screenCenter = CCPointMake(size.width/2, size.height/2);      /**********設(shè)置鼠標點擊屏幕四個方位區(qū)域(起始坐標左下角)************************/     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;     //通過預(yù)約的更新方法來檢查角色的移動     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);             }         }     }          //連續(xù)不斷的修改角色的vertexz的值     CCPoint tilePos = this->tilePosFromLocation(tilePos, tileMap);     player->updateVertextZ(tilePos, tileMap); }  //添加碰撞檢測,是否走到不可碰撞的區(qū)域 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");          //僅僅在內(nèi)部使用;瓷磚的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; }




實現(xiàn)效果:

[cocos2d-x]瓦片地圖的應(yīng)用[cocos2d-x]瓦片地圖的應(yīng)用

[cocos2d-x]瓦片地圖的應(yīng)用

×××:

×××



==================== 迂者 丁小未 CSDN博客專欄=================

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

Unity QQ群:858550         cocos2dx QQ群:280818155

====================== 相互學習,共同進步 ===================

轉(zhuǎn)載請注明出處:http://blog.csdn.net/dingxiaowei2013/article/details/11894879

歡迎關(guān)注我的微博:http://weibo.com/u/2590571922


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI