您好,登錄后才能下訂單哦!
我們在做經典的格斗類的游戲的時候,場景常常用的是45°斜地圖來創建的。下面我就來實現一個簡單的Demo來展現一下斜地圖的使用。
//深度測試,方便實現遮蓋效果 CCDirector::sharedDirector()->setDepthTest(true); //Opengl渲染設置,如果地圖有背景圖層的話就需要加這句 CCDirector::sharedDirector()->setProjection(kCCDirectorProjection2D);
#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); }
#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__
#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; }
×××
==================== 迂者 丁小未 CSDN博客專欄=================
MyBlog:http://blog.csdn.net/dingxiaowei2013 MyQQ:1213250243
Unity QQ群:858550 cocos2dx QQ群:280818155
====================== 相互學習,共同進步 ===================
轉載請注明出處:http://blog.csdn.net/dingxiaowei2013/article/details/11894879
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。