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);
}
}