地图系统之精灵移动与碰撞

由于学习的过程中,大部分学习过了,过段时间会忘记,所以下面我学习了杨丰盛老师的地图系统中的一些重点,和难点,都统一给分析下来,好以后回头看,一目了然,希望看到我文章的人,也有一些的帮助,在描述的过程中,如果有错误,请提出,我会在最快的时间内给予改正,谢谢!

废话就不多说了,先贴整体代码出来,看给予大家浏览,不懂后面有分析

#include "HelloMap.h"

USING_NS_CC;
#define MAPTILDSIZE 33   //经常使用的参数

typedef enum _CONTROLTAG  //枚举菜单按钮
{
	TAG_UP=100,TAG_DOWN,TAG_LEFT,TAG_RIGHT,TAG_FIRE
}CONTROLTAG;
CCScene* HelloMap::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloMap *layer = HelloMap::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 HelloMap::init()
{
    //
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }
	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
	_mapTild = CCTMXTiledMap::create("map.tmx");
	_mapTild->setPosition(CCPointZero);
	this->addChild(_mapTild);

	_SpriteNPC = CCSprite::create("SpinningPeas.png");
	_SpriteNPC->setPosition(ccp(MAPTILDSIZE/2,MAPTILDSIZE/2));
	_mapTild->addChild(_SpriteNPC);
	
	CCMenuItemFont* upMenuItem = CCMenuItemFont::create("UP",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* downMenuItem = CCMenuItemFont::create("DOWN",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* leftMenuItem = CCMenuItemFont::create("LEFT",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* rightMenuItem = CCMenuItemFont::create("RIGHT",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* fireMenuItem = CCMenuItemFont::create("FIRE",this,menu_selector(HelloMap::menuCallback));

	CCMenu* Menu = CCMenu::create(upMenuItem,downMenuItem,leftMenuItem,rightMenuItem,fireMenuItem,NULL);
	Menu->setPosition(CCPointZero);
	this->addChild(Menu);

	upMenuItem->setPosition(ccp(screenSize.width/2,screenSize.height-30));
	downMenuItem->setPosition(ccp(screenSize.width/2,30));
	leftMenuItem->setPosition(ccp(50,screenSize.height/2));
	rightMenuItem->setPosition(ccp(screenSize.width-50,screenSize.height/2));
	fireMenuItem->setPosition(ccp(50,screenSize.height-30));

	upMenuItem->setTag(TAG_UP);
	downMenuItem->setTag(TAG_DOWN);
	leftMenuItem->setTag(TAG_LEFT);
	rightMenuItem->setTag(TAG_RIGHT);
	fireMenuItem->setTag(TAG_FIRE);	
    return true;
}


void HelloMap::menuCallback(CCObject* pSender)
{
	CCMenuItem *item = (CCMenuItem*) pSender;
	int tag = item->getTag();
	CCPoint spriteCurPos =ccp((int)(_SpriteNPC->getPositionX()/MAPTILDSIZE),_mapTild->getMapSize().height-1-(int)(_SpriteNPC->getPositionY()/MAPTILDSIZE)) ;  //获取精灵所在格子的位置
	CCPoint spriteNextPos =spriteCurPos;//精灵移动下一个位置
	CCTMXLayer *ly = _mapTild->layerNamed("layer2");  //读取地图的层
	int gID = 0; //用于存放GID
	switch (tag)
	{
	case TAG_UP:
		spriteNextPos.y -=1;//精灵下一个精灵的位置
		if(spriteNextPos.y<=0)return;
		 gID = ly->tileGIDAt(spriteNextPos);//获取地图的GID
		if(gID)return;
		if (_mapTild->getContentSize().height+_mapTild->getPositionY()>320+MAPTILDSIZE)//地图的总高度+地图的Y轴是否大于屏幕的大小,
		{
			if(_SpriteNPC->getPositionY()+_mapTild->getPositionY()>160){ //判断精灵是否去到屏幕Y轴的中心点 ,如果是,地图跟着移动,如果不是,精灵移动
				_mapTild->setPosition(ccp(_mapTild->getPositionX(),_mapTild->getPositionY()-MAPTILDSIZE));
			}
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()+MAPTILDSIZE));
		}else if(_SpriteNPC->getPositionY()<_mapTild->getContentSize().height-MAPTILDSIZE){//
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()+MAPTILDSIZE));
		}
		break;
	case TAG_DOWN:
		spriteNextPos.y+= 1;
		if(spriteNextPos.y>_mapTild->getMapSize().height-1)return;
		 gID = ly->tileGIDAt(spriteNextPos);
		 if(gID)return;
		if(_mapTild->getPositionY()<0) //如果地图的Y轴小于0就执行,精灵跟地图一起移动,否则精灵移动
		{
			if(_SpriteNPC->getPositionY()+_mapTild->getPositionY()<160){
			_mapTild->setPosition(ccp(_mapTild->getPositionX(),_mapTild->getPositionY()+MAPTILDSIZE));
			}
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()-MAPTILDSIZE));
		}else if(_SpriteNPC->getPositionY()>MAPTILDSIZE){//如果精灵的Y轴大于一个位置的大小,则执行精灵移动
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()-MAPTILDSIZE));
		}
		break;
	case TAG_LEFT:
		spriteNextPos.x-=1;
		if(spriteNextPos.x<=0)return;
		 gID = ly->tileGIDAt(spriteNextPos);
		 if(gID)return;
		if(_mapTild->getPositionX()<0){
			if(_SpriteNPC->getPositionX()+_mapTild->getPositionX()<240){
				_mapTild->setPosition(ccp(_mapTild->getPositionX()+MAPTILDSIZE,_mapTild->getPositionY()));
			}
			_SpriteNPC->setPosition(ccp(_SpriteNPC->getPositionX()-MAPTILDSIZE,_SpriteNPC->getPositionY()));
		}else if(_SpriteNPC->getPositionX()>MAPTILDSIZE){
			_SpriteNPC->setPosition(ccp(_SpriteNPC->getPositionX()-MAPTILDSIZE,_SpriteNPC->getPositionY()));
		}
		break;
	case TAG_RIGHT:
		spriteNextPos.x+=1;
		if(spriteNextPos.x>_mapTild->getMapSize().width-1)return;
		gID = ly->tileGIDAt(spriteNextPos);
		 if(gID)return;
		if(_mapTild->getContentSize().width+_mapTild->getPositionX()>480+MAPTILDSIZE/2){
			if(_SpriteNPC->getPositionX()+_mapTild->getPositionX()>240){
				_mapTild->setPosition(ccp(_mapTild->getPositionX()-MAPTILDSIZE,_mapTild->getPositionY()));
			}
		_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX()+MAPTILDSIZE,_SpriteNPC->getPositionY()));
		}else if(_SpriteNPC->getPositionX()<_mapTild->getContentSize().width-MAPTILDSIZE){
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX()+MAPTILDSIZE,_SpriteNPC->getPositionY()));
		}
		break;
	case TAG_FIRE:
		ly->setTileGID(46,spriteCurPos);
	default:
		break;
	}
}
创建精灵,这个我想不用多说吧, 

_SpriteNPC = CCSprite::create("SpinningPeas.png");
	_SpriteNPC->setPosition(ccp(MAPTILDSIZE/2,MAPTILDSIZE/2));
	_mapTild->addChild(_SpriteNPC);

载入地图 

_mapTild = CCTMXTiledMap::create("map.tmx");
	_mapTild->setPosition(CCPointZero);
	this->addChild(_mapTild);

创建菜单按钮 设置菜单按钮的位置,设置菜单按钮标签

CCMenuItemFont* upMenuItem = CCMenuItemFont::create("UP",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* downMenuItem = CCMenuItemFont::create("DOWN",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* leftMenuItem = CCMenuItemFont::create("LEFT",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* rightMenuItem = CCMenuItemFont::create("RIGHT",this,menu_selector(HelloMap::menuCallback));
	CCMenuItemFont* fireMenuItem = CCMenuItemFont::create("FIRE",this,menu_selector(HelloMap::menuCallback));

	CCMenu* Menu = CCMenu::create(upMenuItem,downMenuItem,leftMenuItem,rightMenuItem,fireMenuItem,NULL);
	Menu->setPosition(CCPointZero);
	this->addChild(Menu);

	upMenuItem->setPosition(ccp(screenSize.width/2,screenSize.height-30));
	downMenuItem->setPosition(ccp(screenSize.width/2,30));
	leftMenuItem->setPosition(ccp(50,screenSize.height/2));
	rightMenuItem->setPosition(ccp(screenSize.width-50,screenSize.height/2));
	fireMenuItem->setPosition(ccp(50,screenSize.height-30));

	upMenuItem->setTag(TAG_UP);
	downMenuItem->setTag(TAG_DOWN);
	leftMenuItem->setTag(TAG_LEFT);
	rightMenuItem->setTag(TAG_RIGHT);
	fireMenuItem->setTag(TAG_FIRE);	
其中菜单按钮中的响应事件,需要设置,这里我给大家剖析按钮所发生的事件是什么原理,这里我只列举一个 向上的按钮,

首先,我们要让精灵在屏幕上移动,我们可以移动几个像素,这个可以设置, 这里我采用移动32像素,

_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()+MAPTILDSIZE));

                    

   

如果有一张地图大于屏幕的尺寸,这里我们如何让精灵在地图上移动呢,这时候我们应该要想到精灵向前移动,地图向后移动这样就可以达到一个错位的效果,相当于精灵向前移动

_mapTild->setPosition(ccp(_mapTild->getPositionX(),_mapTild->getPositionY()-MAPTILDSIZE));
         
   

看懂没? 不懂,就慢慢思考吧, 当然地图层不可以一直向下移动,也有一个临界点,就是地图层 与屏幕层重合的时候,就停止移动

这时候就有一个条件了

_mapTild->getContentSize().height+_mapTild->getPositionY()>320 中文意思

地图总高度+地图Y轴的坐标(向下移动,坐标为负的) 大于320  还不懂?请思考

_mapTild->getContentSize().height+_mapTild->getPositionY()-320>0 ,这懂了吧?


地图向下移动了,但是精灵这时候向上移动的时候,不可能无止境的向上移动,这时候精灵移动也是有限制的,同样是重合线为终止线  

if(_SpriteNPC->getPositionY()<_mapTild->getContentSize().height-MAPTILDSIZE)
精灵Y轴的坐标小于地图层的高度(320)减去一个单元图片像素


完成了? 没有完成,因为我们的主角不是在屏幕的中间,这游戏怎么玩?

if(_SpriteNPC->getPositionY()+_mapTild->getPositionY()>160){ //判断精灵是否去到屏幕Y轴的中心点 ,如果是,地图跟着移动,如果不是,精灵移动
				_mapTild->setPosition(ccp(_mapTild->getPositionX(),_mapTild->getPositionY()-MAPTILDSIZE));
			}
			_SpriteNPC ->setPosition(ccp(_SpriteNPC->getPositionX(),_SpriteNPC->getPositionY()+MAPTILDSIZE));

精灵的Y轴+地图的Y轴大于160  地图移动,否则精灵移动  ,

给精灵设置障碍物

CCTMXLayer *ly = _mapTild->layerNamed("layer2"); //读取地图障碍物的层

这时候我们要判断精灵的下一步是否有障碍物

CCPoint spriteCurPos =ccp((int)(_SpriteNPC->getPositionX()/MAPTILDSIZE),_mapTild->getMapSize().height-1-(int)(_SpriteNPC->getPositionY()/MAPTILDSIZE)) ;  //获取精灵所在格子的位置
	CCPoint spriteNextPos =spriteCurPos;//精灵移动下一个位置

在精灵的按钮事件上添加

spriteNextPos.y -=1;//精灵下一个精灵的位置
		if(spriteNextPos.y<=0)return;
		 gID = ly->tileGIDAt(spriteNextPos);//获取地图的GID
		if(gID)return;

好了,就总结到这里.下期再见!









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值