[AndEngine学习教程] 第4节 制作人物动画

转自:http://blog.csdn.net/cen616899547/article/details/8131842

 

1.回顾

在上一节我们制作一个可以变幻的图形,这节将基于上一节的内容,制作一个行走的人物动画.在这里就称它为战士吧!呵呵!!!!

2.新使用到的资源

1.RepeatingSpriteBackground 游戏场景中使用到的背景绘制策略,本节中使用到草坪背景,由于背景大小是可以自动调节的,

不可能绘制一张固定大小的图片来作为背景.一方面占用空间大不说,另一方面背景图片经过缩放后效果也不好


2.PathModifier 为战士设定行走路径.需要说明的是:这里的路径是两点间的直线路径.比如只需要设定起点和终点.战士就会

沿着这两点间的直线进行移动

3.源代码陈述

1.关于RepeatingSpriteBackground ,这是一种重复绘制背景图片的策略,此类继承于SpriteBackground ,有两个构造函数:

  1. /**
  2. * @param pCameraWidth
  3. * @param pCameraHeight
  4. * @param pTextureManager
  5. * @param pBitmapTextureAtlasSource needs to be a power of two as otherwise the <code>repeating</code> feature doesn't work.
  6. */
  7. public RepeatingSpriteBackground(finalfloat pCameraWidth, finalfloat pCameraHeight, final TextureManager pTextureManager,final IBitmapTextureAt lasSource pBitmapTextureAtlasSource,final VertexBufferObjectManager pVertexBufferObjectManager)throws IllegalArgumentException {
  8. this(pCameraWidth, pCameraHeight, pTextureManager, pBitmapTextureAtlasSource,1, pVertexBufferObjectManager);
  9. }
  10. public RepeatingSpriteBackground(finalfloat pCameraWidth, finalfloat pCameraHeight, final TextureManager pTextureManager,final IBitmapTextureAt lasSource pBitmapTextureAtlasSource,final float pScale,final VertexBufferObjectManager pVertexBufferObjectManager)throws IllegalArgumentException {
  11. super(null);
  12. this.mScale = pScale;
  13. this.mEntity = this.loadSprite(pCameraWidth, pCameraHeight, pTextureManager, pBitmapTextureAtlasSource, pVertexBufferObjectManager);
  14. }
/**
	 * @param pCameraWidth
	 * @param pCameraHeight
	 * @param pTextureManager
	 * @param pBitmapTextureAtlasSource needs to be a power of two as otherwise the <code>repeating</code> feature doesn't work.
	 */
	public RepeatingSpriteBackground(final float pCameraWidth, final float pCameraHeight, final TextureManager pTextureManager, final IBitmapTextureAt              lasSource pBitmapTextureAtlasSource, final VertexBufferObjectManager pVertexBufferObjectManager) throws IllegalArgumentException {
		this(pCameraWidth, pCameraHeight, pTextureManager, pBitmapTextureAtlasSource, 1, pVertexBufferObjectManager);
	}

	public RepeatingSpriteBackground(final float pCameraWidth, final float pCameraHeight, final TextureManager pTextureManager, final IBitmapTextureAt                 lasSource pBitmapTextureAtlasSource, final float pScale, final VertexBufferObjectManager pVertexBufferObjectManager) throws IllegalArgumentException {
		super(null);

		this.mScale = pScale;
		this.mEntity = this.loadSprite(pCameraWidth, pCameraHeight, pTextureManager, pBitmapTextureAtlasSource, pVertexBufferObjectManager);
	}

本例子中使用到的是第一种构造函数,实现形式如下:

  1. private static finalint CAMERA_WIDTH=800;
  2. private staticfinal int CAMERA_HEIGHT=480;
  3. private Camera mCamera;
  4. private RepeatingSpriteBackground mGrassBackground;
  5. private TiledTextureRegion mPlayerTextureRegion;
  6. private BitmapTextureAtlas mTexture;
  7. @Override
  8. public EngineOptions onCreateEngineOptions() {
  9. // TODO Auto-generated method stub
  10. mCamera = new Camera(0,0, CAMERA_WIDTH, CAMERA_HEIGHT);
  11. EngineOptions engineOptions = new EngineOptions(true,ScreenOrientation.LANDSCAPE_SENSOR,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT), mCamera);
  12. return engineOptions;
  13. }
  14. @Override
  15. public void onCreateResources(
  16. OnCreateResourcesCallback pOnCreateResourcesCallback)
  17. throws Exception {
  18. // TODO Auto-generated method stub
  19. this.mTexture = new BitmapTextureAtlas(getTextureManager(), 128, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
  20. this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"player.png",0,0,3,4);
  21. this.mGrassBackground =new RepeatingSpriteBackground(CAMERA_WIDTH, CAMERA_HEIGHT, getTextureManager(), AssetBitmapTextureAtlasSource.create(getAssets(),"background_grass.png"), getVertexBufferObjectManager());
  22. mTexture.load();
  23. pOnCreateResourcesCallback.onCreateResourcesFinished();
  24. }
        private static final int CAMERA_WIDTH=800;
	private static final int CAMERA_HEIGHT=480;
	private Camera mCamera;
	private RepeatingSpriteBackground mGrassBackground;
	private TiledTextureRegion mPlayerTextureRegion;
	private BitmapTextureAtlas mTexture;
	
	@Override
	public EngineOptions onCreateEngineOptions() {
		// TODO Auto-generated method stub
		mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		EngineOptions engineOptions = new EngineOptions(true,ScreenOrientation.LANDSCAPE_SENSOR, new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT), mCamera);
		return engineOptions;
	}

	@Override
	public void onCreateResources(
			OnCreateResourcesCallback pOnCreateResourcesCallback)
			throws Exception {
		// TODO Auto-generated method stub
		this.mTexture = new BitmapTextureAtlas(getTextureManager(), 128, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this,"player.png", 0,0,3, 4);
		this.mGrassBackground = new RepeatingSpriteBackground(CAMERA_WIDTH, CAMERA_HEIGHT, getTextureManager(), AssetBitmapTextureAtlasSource.create(getAssets(), "background_grass.png"), getVertexBufferObjectManager());
		
		mTexture.load();
		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}


 

然后在onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)函数中实现

  1. Scene mScene = new Scene();
  2. mScene.setBackground(mGrassBackground);
  3. pOnCreateSceneCallback.onCreateSceneFinished(mScene);
        Scene mScene = new Scene();
        mScene.setBackground(mGrassBackground);
        pOnCreateSceneCallback.onCreateSceneFinished(mScene);

这样就把重复是的背景放置完成.

3.重点介绍

本例中用到一个72x128大小,3列4行的精灵战士

因此动画的创建方式为:

  1. final AnimatedSprite player =new AnimatedSprite(10,10, 48,64, mPlayerTextureRegion, getVertexBufferObjectManager());
  2. mScene.attachChild(player);
final AnimatedSprite  player = new AnimatedSprite(10, 10, 48, 64, mPlayerTextureRegion, getVertexBufferObjectManager());
mScene.attachChild(player);		

这样就把战士般到了屏幕上,但是此时,战士还不会动,为了让它动起来可要花费点力气的.呵呵!.有什么办法呢?就是给战士注册监听实体,

由于本例子要求的是战士按照设定路径移动,自然想到AndEngine中的Path类,定义一个可以围绕整个屏幕的path路线:

  1. final Path path = new Path(5).to(10,10).to(10, CAMERA_HEIGHT -74).to(CAMERA_WIDTH-58, CAMERA_HEIGHT -74).to(CAMERA_WIDTH-58,10).to(10,10);
final Path path = new Path(5).to(10, 10).to(10, CAMERA_HEIGHT - 74).to(CAMERA_WIDTH-58, CAMERA_HEIGHT - 74).to(CAMERA_WIDTH-58, 10).to(10, 10);
		

每个to函数为Path添加一个路径,最终形成一个从屏幕左上角->左下角->右下角->右上角->左上角的封闭路径.

有了以上基础,当然是添加基于Path类修改器啦.

  1. PathModifier pathModifier = new PathModifier(30.0f, path,new IPathModifierListener(){
  2. @Override
  3. public void onPathStarted(PathModifier pPathModifier,
  4. IEntity pEntity) {
  5. // TODO Auto-generated method stub
  6. }
  7. @Override
  8. public void onPathWaypointStarted(PathModifier pPathModifier,
  9. IEntity pEntity, int pWaypointIndex) {
  10. // TODO Auto-generated method stub
  11. switch(pWaypointIndex) {
  12. case 0:
  13. player.animate(new long[]{200,200, 200},6, 8,true);
  14. break;
  15. case 1:
  16. player.animate(newlong[]{200,200, 200},3, 5,true);
  17. break;
  18. case 2:
  19. player.animate(new long[]{200,200, 200},0, 2,true);
  20. break;
  21. case 3:
  22. player.animate(newlong[]{200,200, 200},9, 11,true);
  23. break;
  24. }
  25. }
  26. @Override
  27. public void onPathWaypointFinished(PathModifier pPathModifier,
  28. IEntity pEntity, int pWaypointIndex) {
  29. // TODO Auto-generated method stub
  30. }
  31. @Override
  32. public void onPathFinished(PathModifier pPathModifier,
  33. IEntity pEntity) {
  34. // TODO Auto-generated method stub
  35. }
  36. },EaseSineInOut.getInstance());
PathModifier pathModifier = new PathModifier(30.0f, path, new IPathModifierListener(){

			@Override
			public void onPathStarted(PathModifier pPathModifier,
					IEntity pEntity) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onPathWaypointStarted(PathModifier pPathModifier,
					IEntity pEntity, int pWaypointIndex) {
				// TODO Auto-generated method stub
				switch(pWaypointIndex) {
				case 0:
					player.animate(new long[]{200, 200, 200}, 6, 8, true);
					break;
				case 1:
					player.animate(new long[]{200, 200, 200}, 3, 5, true);
					break;
				case 2:
					player.animate(new long[]{200, 200, 200}, 0, 2, true);
					break;
				case 3:
					player.animate(new long[]{200, 200, 200}, 9, 11, true);
					break;
			}
			}

			@Override
			public void onPathWaypointFinished(PathModifier pPathModifier,
					IEntity pEntity, int pWaypointIndex) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onPathFinished(PathModifier pPathModifier,
					IEntity pEntity) {
				// TODO Auto-generated method stub
				
			}

		
			
		},EaseSineInOut.getInstance());

战士行走动作的变化是一个基础动画,所以需要Animate方法.但是战士在每个位置脸朝向不一样的,所以到了每个拐点的开始处都

需要修改动画的脸部朝向,这样就更加逼真点.从图片可以看出他们的对应关系.需要说明的是player.animate()函数:

  1. public void animate(finallong[] pFrameDurations, finalint pFirstTileIndex, finalint pLastTileIndex, finalboolean pLoop) {
  2. this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex, pLoop,null);
  3. }
public void animate(final long[] pFrameDurations, final int pFirstTileIndex, final int pLastTileIndex, final boolean pLoop) {
		this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex, pLoop, null);
	}

各个参数的含义为:(战士图片中可以看出:有4组动作,每组动作为3个画面)

pFrameDurations:连续播放3个画面,三个long数据为每个动画的播放时间间隔,单位为毫秒;

pFirstTileIndex:动画的其起始列,按照"Z"字形排列计数.
pLastTileIndex:动画的结束序列,按照"Z"字形排列计数.
pLoop:是否循环播放

为了让战士行走路径也能循环,在PathModifier的基础上增加LoopEntityModifier

  1. LoopEntityModifier loopModifier = new LoopEntityModifier(pathModifier, -1);
LoopEntityModifier loopModifier = new LoopEntityModifier(pathModifier, -1);


有了loopModifier,当然是把它绑定到player上啦

  1. player.registerEntityModifier(loopModifier);
player.registerEntityModifier(loopModifier);


至此,整个设计任务完成了,下面看看运行的结果图片:








本例子源代码:http://download.csdn.net/detail/cen616899547/4705911

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值