在android上开发已经有三年多了,这次跳槽来到的是一个做VR的公司,但是我却对3D几乎等于是0基础,一跳漫长的学习道路必然不能少了.
在实际开发中,一把那是用view直接去做动画的,但是基于3D的学习,我们现在用SurfaceView来做一个简单的2D动画.对于图SurfaceView一般是去继承他,然后还需要实现SurfaceHolder.Callback接口.onDraw方法是SurfaceView的绘制方法,没触发一次绘制一帧.
在SurfaceHolder.Callback中有2D界面的3个生命周期回调方法:
1.surfaceCreated(SurfaceHolder holder);该方法在SurfaceView创建的时候被调用;
2.surfaceChanged(SurfaceHolder holder, int format, int width, int height);该方法在SurfaceView变化时被调用,在创建后至少调用一次;
3.surfaceDestroyed(SurfaceHolder holder);该方法在SurfaceView销毁的时候调用;
此动画首先做X做匀速移动,Y轴上抛运动,然后爆炸,效果如下图:
接着对下列实现代码做介绍:
1.控制类MainActivity.java:主要作为SurfaceView的控制类
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 设置window没有标题而且全屏
*/
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN);
//设置屏幕的方向为横向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mCustomSurfaceView = new CustomSurfaceView(this);
/tContentView(R.layout.activity_main);
setContentView(mCustomSurfaceView);
}
2.CustomSurfaceView显示类:绘制是由onDeaw方法实现,另外对于实现的Callback方法如下:
DrawThread mDrawThread; //用于实现绘制的线程
Bitmap mBgBitmap; //背景图
Bitmap mBulletBitmap; //炮弹位图
Bitmap[] mExplodeBmps;//爆炸效果图
Bullet mBullet;//炮弹实体类
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 首先绘制自己的背景
* 然后绘制炮弹自己
*/
canvas.drawBitmap(mBgBitmap , 0 , 0 , mPaint);
mBullet.drawSelf(canvas , mPaint);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mPaint = new Paint();
//抗锯齿
mPaint.setAntiAlias(true);
//加载炮弹图片
mBulletBitmap = BitmapFactory.decodeResource(getResources() , R.mipmap.bullet);
mBgBitmap = BitmapFactory.decodeResource(getResources() , R.mipmap.bg);
mExplodeBmps = new Bitmap[]{
BitmapFactory.decodeResource(getResources() , R.mipmap.explode0) ,
BitmapFactory.decodeResource(getResources() , R.mipmap.explode1) ,
BitmapFactory.decodeResource(getResources() , R.mipmap.explode2) ,
BitmapFactory.decodeResource(getResources() , R.mipmap.explode3) ,
BitmapFactory.decodeResource(getResources() , R.mipmap.explode4) ,
BitmapFactory.decodeResource(getResources() , R.mipmap.explode5)
};
//创建炮弹对象
mBullet = new Bullet(this , mBulletBitmap , mExplodeBmps , 200 , 290 , 1.3f , -5.9f );
mDrawThread = new DrawThread(this);
mDrawThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mDrawThread.setFlag(false);
}
3.DrawThread绘制线程类run方法如下:
@Override
public void run() {
super.run();
Canvas canvas;
while (mFlag){
canvas = null;
//锁定画布
try {
canvas = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder){
//绘制每一帧
mCustomSurfaceView.onDraw(canvas);
}
} finally {
if (canvas != null){
//释放锁
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
try {
//睡眠一会儿
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4.炮弹实体类Bullet类:
public class Bullet {
CustomSurfaceView mCustomSurfaceView;
//位图
private Bitmap mBulletBitmap;
//爆炸动画图组
private Bitmap[] mExplodeBmps;
//X轴位置
float mX;
float mY;
//X轴速度
float mVx;
float mVy;
//生存时间
private float mLiveTime;
//时间间隔
private float mSpanTime = 0.5f;
//炮弹尺寸
private int mBulletSize;
//是否绘制炮弹标记位
private boolean isExplosion;
//爆炸对象的引用
private Explosion mExplosion;
public Bullet(CustomSurfaceView customSurfaceView,
Bitmap bulletBitmap,
Bitmap[] explodeBmps,
float x,
float y,
float vx,
float vy)
{
mCustomSurfaceView = customSurfaceView;
mBulletBitmap = bulletBitmap;
mExplodeBmps = explodeBmps;
mX = x;
mY = y;
mVx = vx;
mVy = vy;
mBulletSize = bulletBitmap.getHeight();
}
/**
* 绘制自己
* @param canvas 画板
* @param paint 画笔
*/
public void drawSelf(Canvas canvas, Paint paint) {
if (isExplosion && mExplosion != null){
mExplosion.drawSelf(canvas , paint);
}else {
go();
canvas.drawBitmap(mBulletBitmap , mX , mY , paint);
}
}
/**
* 绘制炮弹前进的方法
*/
private void go() {
//在水平方向上做匀速运动
mX += mVx * mLiveTime;
//在竖直方向上做上抛运动
mY += mVy * mLiveTime + 0.5f + Constant.G * mLiveTime * mLiveTime;
//爆炸点
if (mX >= Constant.EXPLOSION_X || mY >= Constant.SCREEN_HEIGHT){
mExplosion = new Explosion(mCustomSurfaceView , mExplodeBmps , mX , mY);
//不在绘制炮弹
isExplosion = true;
return;
}
//更新生存时间
mLiveTime += mSpanTime;
}
}
此项目仅作为学习用,github项目地址:https://github.com/ynztlxdeai/Bullet-anim