瓦片地图
在游戏开发过程中,我们会遇到超过屏幕大小的地图,例如即时战略游戏,使得玩家可以在地图中滚动游戏画面。这类游戏通常会有丰富的背景元素,如果直接使用背景图切换的方式,需要为每个不同的场景准备一张背景图,而且每个背景图都不小,这样会造成资源浪费。瓦片地图就是为了解决这问题而产生的。一张大的世界地图或者背景图可以由几种地形来表示,每种地形对应一张小的的图片,我们称这些小的地形图片为瓦片。把这些瓦片拼接在一起,一个完整的地图就组合出来了,这就是瓦片地图的原理。
开发实例-利用瓦片地图工具创建一个简单的地图 使人物在地图上随意移动
1.工具:TileMap 并且将制作好的地图的tmx文件和资源导入到工程中
2.编译器:Xcode
3.新建一个HelloWorld的类 在HelloWorld.hpp里添加以下代码
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "ui/CocosGUI.h"
using namespace cocos2d;
using namespace ui;
enum{
UP,
DOWN,
LEFT,
RIGHT,
}direction;
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
//人物移动
bool ontouchbegan(Touch* touch,Event* event);
void selfMove(int x,int y);
CREATE_FUNC(HelloWorld);
private:
TMXTiledMap* map;
Sprite* hero;
};
#endif // __HELLOWORLD_SCENE_H__
4.在HelloWorld.cpp文件中添加以下代码
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
map=TMXTiledMap::create("Map_1.tmx");
this->addChild(map);
TMXLayer* colorlayer=map->getLayer("颜色层");
colorlayer->setVisible(false);
//获得对象组
TMXObjectGroup* objectGroup=map->getObjectGroup("人物层");
ValueMap object=objectGroup->getObject("新手");
//添加人物到对象层
hero=Sprite::create("player.png");
hero->setPosition(Vec2(object.at("x").asFloat(),object.at("y").asFloat()));
this->addChild(hero);
//人物移动
auto listener=EventListenerTouchOneByOne::create();
listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::ontouchbegan,this);
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
//人物移动回调函数
bool HelloWorld:: ontouchbegan(Touch* touch,Event* event)
{
log("111");
//1.获得人物的位置和触摸屏幕的位置
auto selfPoint=hero->getPosition();
auto touchPoint=touch->getLocation();
//2.在HelloWorld.h文件中定义一个方向的枚举类型
int x=touchPoint.x-selfPoint.x;//两者之间的间距用来判断人物的移动方向(横向)
int y=touchPoint.y-selfPoint.y;//两者之间的间距用来判断人物的移动方向(纵向)
int setX=0;//人物横向的偏移量
int setY=0;//人物纵向的偏移量
if(abs(x) > abs(y))//x、y的绝对值来判断人物横向还是纵向移动
{
if (x>=0) {
setX=32;
direction=RIGHT;
}else{
setX=-32;
direction=LEFT;
}
}else{
if (y>=0) {
setY=32;
direction=UP;
}else{
setY=-32;
direction=DOWN;
}
}
this->selfMove(setX,setY);
return true;
}
void HelloWorld:: selfMove(int x,int y)
{
auto size=Director::getInstance()->getWinSize();
auto selfPoint=hero->getPosition();
auto mapPoint=map->getPosition();
auto mapSize=map->getMapSize();
auto tileSize=map->getTileSize();
int selfMoveNextX=selfPoint.x+x;
int selfMoveNextY=selfPoint.y+y;
int UPMapY=-(mapSize.height*tileSize.height-size.height);
int DOWNMapY=0;
int LEFTMapX=0;
int RIGHTMapX=-(mapSize.width*tileSize.width-size.width);
switch (direction) {
case UP:
if (selfMoveNextY>size.height/2 && mapPoint.y>UPMapY) {
map->setPosition(Vec2(mapPoint.x,mapPoint.y-y));
}
else
{
hero->setPosition(Vec2(selfPoint.x,selfMoveNextY));
}
break;
case DOWN:
if (mapPoint.y >= DOWNMapY ||(selfMoveNextY >= size.height/2 && mapPoint.y>=UPMapY )) {
hero->setPosition(Vec2(selfPoint.x,selfMoveNextY));
}else
{
map->setPosition(Vec2(mapPoint.x,mapPoint.y-y));
}
break;
case LEFT:
if ( mapPoint.x>=LEFTMapX ||(selfMoveNextX >= size.width/2 && mapPoint.x<= RIGHTMapX)) {
hero->setPosition(Vec2(selfMoveNextX,selfPoint.y));
}
else
{
map->setPosition(Vec2(mapPoint.x-x,mapPoint.y));
}
break;
case RIGHT:
if (selfMoveNextX>=size.width/2 && mapPoint.x > RIGHTMapX) {
map->setPosition(Vec2(mapPoint.x-x,mapPoint.y));
}else
{
hero->setPosition(Vec2(selfMoveNextX,selfPoint.y));
}
break;
default:
break;
}
}