游戏帧动画处理---注释很详细!@hxx

package cn.hxx.demo;

import java.io.InputStream;

import android.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class AnimationActivity extends Activity {

	AnimView mAnimView=null;
	
	 @Override
	 public void onCreate(Bundle savedInstanceState) {
		 super.onCreate(savedInstanceState);
		
		// 全屏显示窗口
			requestWindowFeature(Window.FEATURE_NO_TITLE);
			getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
			// 获取屏幕宽高
			Display display = getWindowManager().getDefaultDisplay();
			
			//显示自定义的游戏view
			mAnimView = new AnimView(this,display.getWidth(), display.getHeight());
			setContentView(mAnimView);//在屏幕上显示当前的view
	 }
	 public class AnimView extends View {
		 /**向下移动动画,对应Animation[]的0号元素**/
	        public final static int ANIM_DOWN = 0;
	        /**向左移动动画**/
	        public final static int ANIM_LEFT = 1;
	        /**向右移动动画**/
	        public final static int ANIM_RIGHT = 2;
	        /**向上移动动画**/
	        public final static int ANIM_UP = 3;
	        /**动画的总数量**/
	        public final static int ANIM_COUNT = 4;
	        //这个搞了两个人的动态效果针
	        Animation[] mHeroAnim=new Animation[ANIM_COUNT];
	        Animation[] mTestAnim=new Animation[ANIM_COUNT];//放enemy的
	        
	        Paint mPaint = null;//画笔来啦
	        /**任意键被按下**/
	    	private boolean mAllkeyDown = false;
	    	/**按键下**/
	    	private boolean mIskeyDown = false;
	    	/**按键左**/
	    	private boolean mIskeyLeft = false;
	    	/**按键右**/
	    	private boolean mIskeyRight = false;
	    	/**按键上**/
	    	private boolean mIskeyUp = false;
	    	//当前绘制动画状态ID
	    	int mAnimationState = 0;
	    	
	    	这里没有绘制图片了,直接用了一副完整的场景map.png
	    	Bitmap mMapImage = null; 
	    	/**
	    	 * 构造方法
	    	 * 
	    	 * @param context
	    	 */
	    	public AnimView(Context context,int screenWidth, int screenHeight) {
	    	    super(context);
	    	    mPaint = new Paint();
	    	    //这里和enemy.png所有动作一张图上不一样,这里每一张图示一个动作
	    	    //这里可以用循环来处理,总之我们需要把动画的ID传进去
	    	    mHeroAnim[ANIM_DOWN] = new Animation(context,new int []{R.drawable.hero_down_a,R.drawable.hero_down_b,R.drawable.hero_down_c,R.drawable.hero_down_d},true);
	    	    mHeroAnim[ANIM_UP]=new Animation(context,new int[]{R.drawable.hero_up_a,R.drawable.hero_up_b,R.drawable.hero_up_c,R.drawable.hero_up_d},true);
	    	    mHeroAnim[ANIM_LEFT] = new Animation(context,new int []{R.drawable.hero_left_a,R.drawable.hero_left_b,R.drawable.hero_left_c,R.drawable.hero_left_d},true);
	    	    mHeroAnim[ANIM_RIGHT]= new Animation(context,new int []{R.drawable.hero_right_a,R.drawable.hero_right_b,R.drawable.hero_right_c,R.drawable.hero_right_d},true);
	    	   
	    	    //利用程序来切割图片,仅仅切割enemy。png即可,因为hero图片不需要切割
	    	    /**enemy.png。一排四个图,从左到右画吧==》 x=0开始
	    	     * 第一排:向下走。2右走,3左走,4上走
	    	     */
	    	    Bitmap testmap=readBitMap(context,R.drawable.enemy);
	    	    Bitmap[][] bitmap=new Bitmap[ANIM_COUNT][ANIM_COUNT];
	    	    int tileWidth=testmap.getWidth()/ANIM_COUNT;
	    	    int tileHeight = testmap.getHeight() / ANIM_COUNT;
	    	    int i=0,x=0,y=0;
	    	    for(i=0;i<ANIM_COUNT;i++){ //x=0开始,表示从左向右
	    	    	
	    	    	y=0; //一行一行的画
	    	    	//0,0 第一排
	    	    	bitmap[ANIM_DOWN][i]=BitmapClipBitmap(testmap,x,y,tileWidth,tileHeight);
	    	    	y+=tileHeight;
//	    	    	0,tileHeight 第二排
	    	    	bitmap[ANIM_LEFT][i] = BitmapClipBitmap(testmap,x,y,tileWidth,tileHeight);
	    			y+=tileHeight;
	    			bitmap[ANIM_RIGHT][i] = BitmapClipBitmap(testmap,x,y,tileWidth,tileHeight);
	    			y+=tileHeight;
	    			bitmap[ANIM_UP][i] = BitmapClipBitmap(testmap,x,y,tileWidth,tileHeight);
	    			x+= tileWidth;
	    	    }
	    	    mTestAnim[ANIM_DOWN] = new Animation(context,bitmap[ANIM_DOWN],true);
	    	    mTestAnim[ANIM_LEFT] = new Animation(context,bitmap[ANIM_LEFT],true);
	    	    mTestAnim[ANIM_RIGHT]= new Animation(context,bitmap[ANIM_RIGHT],true);
	    	    mTestAnim[ANIM_UP]   = new Animation(context,bitmap[ANIM_UP],true);

	    	    mMapImage = ReadBitMap(context,R.drawable.map);//直接把地图给读出来		
	    	    		
	    	}
	    	@Override
	    	protected void onDraw(Canvas canvas) {
	    		//1:先画地图
	    		canvas.drawBitmap(mMapImage, 0, 0, mPaint);
	    		 if (mAllkeyDown) {
	    			 if (mIskeyDown) {
	    				    mAnimationState = ANIM_DOWN;
//	    				    canvas.drawText("按下下键,开始播放向下动画开始", 0, 20, mPaint);
	    				} else if (mIskeyLeft) {
	    				    mAnimationState = ANIM_LEFT;
//	    				    canvas.drawText("按下左键,开始播放向左动画开始", 0, 20, mPaint);
	    				} else if (mIskeyRight) {
	    				    mAnimationState = ANIM_RIGHT;
//	    				    canvas.drawText("按下右键,开始播放向右动画开始", 0, 20, mPaint);
	    				} else if (mIskeyUp) {
	    				    mAnimationState = ANIM_UP;
//	    				    canvas.drawText("按下上键,开始播放向上动画开始", 0, 20, mPaint);
	    				}
	    			 //2: 绘制主角和enemy动画
	    			 //根据mAnimationState得到animation数组中对于的姿势,然后画出来
	    			 mHeroAnim[mAnimationState].DrawAnimation(canvas, mPaint, 20, 100);
	    			 mTestAnim[mAnimationState].DrawAnimation(canvas, mPaint, 100, 100);
	    		 }else{
//	    			 按键抬起后人物停止动画
	    			 mHeroAnim[mAnimationState].DrawFrame(canvas, mPaint, 20, 100, 0);
	    			 mTestAnim[mAnimationState].DrawFrame(canvas, mPaint, 100, 100, 0);
	    		 }
	    		 super.onDraw(canvas);
	    		    invalidate();
	    		 
	    	}
	    	/**
	    	 * 设置按键状态true为按下 false为抬起
	    	 * @param keyCode
	    	 * @param state
	    	 */
	            public void setKeyState(int keyCode, boolean state) {
	                switch(keyCode) {
	                case KeyEvent.KEYCODE_DPAD_DOWN:
	            	mIskeyDown = state;
	            	break;
	                case KeyEvent.KEYCODE_DPAD_UP:
	            	mIskeyUp = state;
	            	break;
	                case KeyEvent.KEYCODE_DPAD_LEFT:
	            	mIskeyLeft = state;
	            	break;
	                case KeyEvent.KEYCODE_DPAD_RIGHT:
	            	mIskeyRight = state;
	            	break;
	                }
	                mAllkeyDown = state;
	            }

	            @Override
	            public boolean onKeyDown(int keyCode, KeyEvent event) {
	        	mAnimView.setKeyState(keyCode,true);
	                return super.onKeyDown(keyCode, event);
	            }
	            @Override
	            public boolean onKeyUp(int keyCode, KeyEvent event) {
	        	mAnimView.setKeyState(keyCode,false);
	                return super.onKeyUp(keyCode, event);
	            }
	            
	            /**
	             * 程序切割图片
	             * @param bitmap
	             * @param x
	             * @param y
	             * @param w
	             * @param h
	             * @return
	             */
	            public Bitmap BitmapClipBitmap(Bitmap bitmap,int x, int y, int w, int h) {
	                return  Bitmap.createBitmap(bitmap, x, y, w, h);
	            }
	            
	            
	    	/**
	    	 * 读取本地资源的图片
	    	 * 
	    	 * @param context
	    	 * @param resId
	    	 * @return
	    	 */
	    	public Bitmap ReadBitMap(Context context, int resId) {
	    	    BitmapFactory.Options opt = new BitmapFactory.Options();
	    	    opt.inPreferredConfig = Bitmap.Config.RGB_565;
	    	    opt.inPurgeable = true;
	    	    opt.inInputShareable = true;
	    	    // 获取资源图片
	    	    InputStream is = context.getResources().openRawResource(resId);
	    	    return BitmapFactory.decodeStream(is, null, opt);
	    	}
	    	
	        }
	        
	 }
	
}
package cn.hxx.demo;

import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;

public class Animation {

	  /** 上一帧播放时间 **/
    private long mLastPlayTime = 0;
    /** 播放当前帧的ID **/
    private int mPlayID = 0;
    /** 动画frame数量 **/
    private int mFrameCount = 0;
    /** 用于储存动画资源图片 **/
    private Bitmap[] mframeBitmap = null;
    /** 是否循环播放 **/
    private boolean mIsLoop = false;
    /** 播放结束 **/
    private boolean mIsend = false;
    /** 动画播放间隙时间 **/
    private static final int ANIM_TIME = 100;
    
    /**
     * 构造函数
     * @param context
     * @param frameBitmapID 动画帧id数组(标示一种资源int,而不是资源bitmap,一次要播放的一组“动画id”,比如说向右走的四个姿势图片id数组
     * @param mIsLoop 是否循环播放动画
     */
    public Animation(Context context,int[] frameBitmapID, boolean mIsLoop){
    	mFrameCount = frameBitmapID.length;
    	//这个和frameBitmapID区别?mframeBitmap是资源的流形式,而frameBitmapID是资源标识,用于找到资源
    	mframeBitmap = new Bitmap[mFrameCount];
    	for(int i =0; i < mFrameCount; i++) {
    	    mframeBitmap[i] = ReadBitMap(context,frameBitmapID[i]);
    	    
    	}
    	mIsLoop=mIsLoop;
    }
    
    /**
     * 构造函数
     * @param context
     * @param frameBitmap  动画帧数组,一次要连续完成一套动作资源
     * @param isloop  是否循环播放动画
     */
    public Animation(Context context, Bitmap [] frameBitmap, boolean isloop) {
		mFrameCount = frameBitmap.length;
		mframeBitmap = frameBitmap;
		mIsLoop = isloop;
    }
    /**
     * 绘制动画,只画一帧啊,即一套动作中的一个姿势
     * 这个函数的用处在于,最后停止的时候我就只这个动画组中的第一帧(不然停止的时候一个脚抬起)
     * @param canvas
     * @param paint
     * @param x
     * @param y
     * @param frameID
     */
    public void DrawFrame(Canvas canvas, Paint paint, int x,int y,int frameID){
    	canvas.drawBitmap(mframeBitmap[frameID], x, y, paint);
    }
    /**画动画,按照一组的动画从左到右画,注意不一定一组连贯动作全画完,看按键时间
     * 
     * @param canvas
     * @param paint
     * @param x
     * @param y
     */
    public void DrawAnimation(Canvas canvas, Paint paint , int x, int y){
    	if(!mIsend){//没有结束
    		canvas.drawBitmap(mframeBitmap[mPlayID], x, y, paint);
    		 long time = System.currentTimeMillis();
    		 //控制播放帧的速度
    		 if(time-mLastPlayTime>ANIM_TIME){ //如果两帧之间时间超过间隔时间
    			 mPlayID++;//就播放下一帧
    			 mLastPlayTime = time;
    			 if(mPlayID >= mFrameCount){
    				 //标志动画播放结束
    				    mIsend = true;
    				    if (mIsLoop) {
    					//设置循环播放
    					mIsend = false;
    					mPlayID = 0;
    				    }
    			 }
    		 }
    	}
    }
    /**
     * 读取图片资源
     * @param context
     * @param resId
     * @return
     */
    public Bitmap ReadBitMap(Context context, int resId) {
	BitmapFactory.Options opt = new BitmapFactory.Options();
	opt.inPreferredConfig = Bitmap.Config.RGB_565;
	opt.inPurgeable = true;
	opt.inInputShareable = true;
	// 获取资源图片
	InputStream is = context.getResources().openRawResource(resId);
	return BitmapFactory.decodeStream(is, null, opt);
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huangleijay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值