3D开发学习-初识SurfaceView

来源:互联网 发布:原生js实现find方法 编辑:程序博客网 时间:2024/06/04 19:19

在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

0 0
原创粉丝点击