首先,在之前的一篇实现动画里已经提过一些内容,所这里就会有一些省略
创建一个人类精灵的类:human,继承于CCNode,然后在构造函数里预处理一下人物精灵的动画
public Human() { mode = CCTextureCache.sharedTextureCache().addImage("Images/Sprite/20011"); frames = new List<CCSpriteFrame>(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { CCSpriteFrame frame = CCSpriteFrame.frameWithTexture(mode, new CCRect(j * 318 / 4, i * 451 / 4, 318 / 4, 451 / 4)); frames.Add(frame); } } human = CCSprite.spriteWithSpriteFrame(frames[8]); human.anchorPoint = new CCPoint(0.5f, 0.5f); human.position = ConvertViewPoint(new CCPoint(1, 3)); addChild(human); }
在这里,因为cocs2d -x for xna也是沿袭OpenGL坐标体系,以左下角为原点。而这里代码的位置是tmx地图上的位置,所以对它进行转化--ConvertViewPoint
/// <summary> /// 将坐标转化为GL坐标 /// </summary> /// <param name="p"></param> /// <returns></returns> public CCPoint ConvertViewPoint(CCPoint p) { return CCDirector.sharedDirector().convertToGL(new CCPoint(p.x * 60 + 30, p.y * 60 + 30)); }
运行,人物会出现在地图上,如图:
接下来,添加根据方向实现人物移动
首先,人物每次前进,都是前进一个地图单位即是前进60像素,这个像素大小跟你地图制作时定义的大小相关。
所以先进行数据转化:
/// <summary> /// 根据方向获取角色移动目的地 /// </summary> /// <param name="Direction"></param> public void RunWithDirection(int Direction) { CCPoint moveByPositon = new CCPoint(0, 0); switch (Direction) { case 1: moveByPositon = new CCPoint(0, 60); break; case 2: moveByPositon = new CCPoint(0, -60); break; case 3: moveByPositon = new CCPoint(-60, 0); break; case 4: moveByPositon = new CCPoint(60, 0); break; } //获取移动目的地的point targetPoistion = new CCPoint(human.position.x + moveByPositon.x, human.position.y + moveByPositon.y); Move(moveByPositon, Direction); //查看该移动目的地是否是墙壁 }
/// <summary> /// 根据方向进行移动 /// </summary> /// <param name="p"></param> /// <param name="moveTag"></param> void Move(CCPoint p, object moveTag) { if (isEnemyWalking) return; object tag = moveTag; isEnemyWalking = true; List<CCSpriteFrame> temp = new List<CCSpriteFrame>(); switch ((int)moveTag) { case 1: for (int i = 12; i < 16; i++) { temp.Add(frames[i]); } break; case 2: for (int i = 0; i < 4; i++) { temp.Add(frames[i]); } break; case 3: for (int i = 4; i < 8; i++) { temp.Add(frames[i]); } break; case 4: for (int i = 8; i < 12; i++) { temp.Add(frames[i]); } break; } CCAnimation ani = new CCAnimation(); ani.initWithFrames(temp, 0.1f); CCAction action = CCSequence.actions( CCSpawn.actions(CCAnimate.actionWithAnimation(ani, false), CCMoveBy.actionWithDuration(0.28f, p), CCCallFuncND.actionWithTarget(this, onWalkDone, tag)) ); human.runAction(action); }
在这里,我们需要执行的动作包括:人物完成行走动画、移动到目的位置、行走结束后人物面向行走方向3个不同的动作。所以,我们需要用到CCSequence(序列)和CCSpawn(同步)
在CCSequence里是一个Action集合,而在CCSpawn里面也是一个Action集合。
CCCallFuncND.actionWithTarget(this, onWalkDone, tag),这句代码是一个回调,实现人物面向。
/// <summary> /// 移动完成后角色面向 /// </summary> /// <param name="pTarget"></param> /// <param name="date"></param> void onWalkDone(CCNode pTarget, object date) { int tag = (int)date; isEnemyWalking = false; human.setTextureRect(new CCRect(0, 451 / 4 * tag, 318 / 4, 451 / 4)); }
人物类的方法在这里算是高一个段落了。
接下来,在游戏界面添加4个行进按钮:
tmxMap = new Classes.Map(); human = new Classes.Human(); addChild(tmxMap); addChild(human); CCMenuItem up = CCMenuItemFont.itemFromString("Up", this, CallBack); CCMenuItem down = CCMenuItemFont.itemFromString("Down", this, CallBack); CCMenuItem left = CCMenuItemFont.itemFromString("Left", this, CallBack); CCMenuItem right = CCMenuItemFont.itemFromString("Right", this, CallBack); up.tag = 1; down.tag = 2; left.tag = 3; right.tag = 4; CCMenu menus = CCMenu.menuWithItems(up, down, left, right); menus.alignItemsHorizontallyWithPadding(20); menus.position = new CCPoint(300, 400); addChild(menus);
最后在回调函数里调用human类的行走方法就行了:
void CallBack(CCObject sender) { CCNode node = (CCNode)sender; int tag = node.tag; human.RunWithDirection(tag); }
这样运行之后就可以实现人物走动了。