zl程序教程

您现在的位置是:首页 >  工具

当前栏目

[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;


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();

 // 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);


//获取瓷砖块的坐标 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);
/**********设置鼠标点击屏幕四个方位区域(起始坐标左下角)************************/ 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!