View框架下实现角色的上下左右移动

  玩过游戏的朋友都知道,不管是RPG游戏或者是飞行射击又或者其他类型的游戏,都会有这中功能——控件角色的移动。现在就来实现这个功能。

                                                                              

这是一张用来展示角色行走的图片,大小 188*380,名字是hero.png。

首先新建一个class(RoleAnimation.java),该类主要是绘制hero.png中的单个角色和连贯的动画,方便其他地方调用

public class RoleAnimation {
    /** 上一帧播放时间 **/
    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 framBitmaps
     * @param isloop
     */
    public RoleAnimation(Context context,Bitmap[]frameBitmaps,boolean isloop){
        mFrameCount=frameBitmaps.length;
        mframeBitmap=frameBitmaps;
        mIsLoop=isloop;
    }
    /**
     * 绘出某一帧
     * @param canvas
     * @param mPaint
     * @param x
     * @param y
     * @param frameID
     */
    public  void DrawFram(Canvas canvas,Paint mPaint,int x,int y,int frameID) {
        canvas.drawBitmap(mframeBitmap[frameID], x, y, mPaint);
    }
    /**
     * 绘出该对象的动画
     * @param canvas
     * @param mPaint
     * @param x
     * @param y
     */
    public void DrawAnimtion(Canvas canvas,Paint mPaint,int x,int y) {
        if(!mIsend){
            DrawFram(canvas,mPaint,x,y,mPlayID);
            long time=java.lang.System.currentTimeMillis();
            if(time-mLastPlayTime>=ANIM_TIME){
                mPlayID++;
                mLastPlayTime=time;
                if(mPlayID>=mFrameCount){ //将所有帧播放完毕
                    mIsend=true;
                    if(mIsLoop){
                        mIsend=false;
                        mPlayID=0;
                    }
                }
            }
        }
    }
}

再建一个class(RoleView)继承 View

public class RoleView extends View {
    private int FloatX=0;
    private int FloatY=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;
    RoleAnimation mHeroAnim[] = new RoleAnimation[ANIM_COUNT];
    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;
    
    public RoleView(Context context, int SrceemWidth, int SrceenHeight) {
        super(context);
        mPaint = new Paint();
        // 利用程序来切割hero.png图片
        Bitmap testmap = ReadBitMap(context, R.drawable.hero);
        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++) {
            y = 0;
            bitmap[ANIM_DOWN][i] = BitmapClipBitmap(testmap,
                    x, y, tileWidth, tileHeight);
            y += 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;
        }
        mHeroAnim[ANIM_DOWN] = new RoleAnimation(context, bitmap[ANIM_DOWN],
                true);
        mHeroAnim[ANIM_LEFT] = new RoleAnimation(context, bitmap[ANIM_LEFT],
                true);
        mHeroAnim[ANIM_RIGHT] = new RoleAnimation(context, bitmap[ANIM_RIGHT],
                true);
        mHeroAnim[ANIM_UP] = new RoleAnimation(context, bitmap[ANIM_UP], true);
    }
    
    /**
     * 该方法在实例化view的时候会被调用
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        canvas.save();
        canvas.clipRect(0, 0, 320, 30);
        mPaint.setColor(Color.WHITE);
        canvas.drawRect(0, 0, 480, 30, mPaint);
        mPaint.setColor(Color.RED);
        canvas.restore();
        /** 根据按键更新显示动画 **/
        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);
            }
        } else {
            /** 按键抬起后人物停止动画 **/
            mHeroAnim[mAnimationState].DrawFram(canvas, mPaint, 20+FloatX, 100+FloatY, 0);
            canvas.drawText("按键已经抬起动画停止", 0, 20, mPaint);
        }
        super.onDraw(canvas);
        invalidate();  //重新调用onDraw方法,相当于刷屏重绘
    }
    
    /**
     * 设置按键状态true为按下 false为抬起
     * 
     * @param keyCode
     * @param state
     */
    public void setKeyState(int keyCode, boolean state) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_DOWN:
            mIskeyDown = state;
            FloatY++;
            break;
        case KeyEvent.KEYCODE_DPAD_UP:
            mIskeyUp = state;
            FloatY--;
            break;
        case KeyEvent.KEYCODE_DPAD_LEFT:
            mIskeyLeft = state;
            FloatX--;
            break;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            mIskeyRight = state;
            FloatX++;
            break;
        }
        mAllkeyDown = state;
    }

    
    /**
     * 获取本地的图片资源
     * @param context
     * @param resources
     * @return
     */
    public static Bitmap ReadBitMap(Context context, int resources) {
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Bitmap.Config.RGB_565;
        opt.inInputShareable = true;
        // 获取资源图片
        InputStream is = context.getResources().openRawResource(resources);
        return BitmapFactory.decodeStream(is, null, opt);
    }
    /**
     * 程序切割图片
     * 
     * @param bitmap
     * @param x
     * @param y
     * @param w
     * @param h
     * @return
     */
    public static Bitmap BitmapClipBitmap(Bitmap bitmap, int x, int y, int w, int h) {
        return Bitmap.createBitmap(bitmap, x, y, w, h);
    }
}

最后在Activity里面调用

public class RoleMoveActivity extends Activity {
    RoleView mAnimView;
    @Override
    protected 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();
        mAnimView = new RoleView(this, display.getWidth(), display.getHeight());
        setContentView(mAnimView);
    }

    @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);
    }
}
原文地址:https://www.cnblogs.com/cindyOne/p/2991650.html