Android应用程序入门 推箱子游戏开发(一) surfaceView 实现动画效果

来源:互联网 发布:手机淘宝怎么快速秒杀 编辑:程序博客网 时间:2024/06/05 21:52
        SurfaceView是View的子类,常用于实现游戏中的动画效果。SurfaceView最大的特点就是:从主线程中,把具体的绘图线程独立出来。这样做的好处在于:当绘图任务比较繁重时,避免主线程的阻塞,从而提高主线程的反应速度。

        废话少说,言归正传,下面用几个例子说明surfaceview的使用。

 

(一) 基本功能:用SurfaceView显示一副背景图片。 运行后的效果很简单,就是在屏幕上显示一副图片。 

package com.pushBox;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;public class PushBoxActivity extends Activity {//欢迎界面WelcomeView welcomeView = null;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                //显示欢迎界面        welcomeView = new WelcomeView( this );                setContentView( welcomeView );     }        //内部类,欢迎界面    class WelcomeView extends SurfaceView implements SurfaceHolder.Callback    {    private SurfaceHolder holder;        private WelcomeViewDrawThread welcomeViewDrawThread;    //背景图片,大小640 * 480    Bitmap background;        //图片显示的位置    int backgroundX = 0;    int backgroundY = 0;        public WelcomeView( Context context )    {    super( context );        holder = this.getHolder();    holder.addCallback( this );        background = BitmapFactory.decodeResource( getResources(), R.drawable.background );    //创建一个绘图线程    welcomeViewDrawThread = new WelcomeViewDrawThread( this, holder );    }        //自定义的绘图函数,具体的绘图在这里完成    public void onDraw( Canvas c )    {    c.drawBitmap( background, backgroundX, backgroundY, null );        }        @Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {// TODO Auto-generated method stub}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stub//启动绘图线程welcomeViewDrawThread.setFlag( true );welcomeViewDrawThread.start();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stubwelcomeViewDrawThread.setFlag( false );}    }                //内部类,欢迎界面的绘图线程    class WelcomeViewDrawThread extends Thread    {    private WelcomeView welcomeView;    private SurfaceHolder holder;    private boolean isRun;      private int sleepSpan = 200;        public WelcomeViewDrawThread( WelcomeView welcomeView, SurfaceHolder holder )    {    this.welcomeView = welcomeView;    this.holder = holder;    isRun = true;    }    public void setFlag( boolean flag )    {    isRun = flag;    }@Overridepublic void run() {// TODO Auto-generated method stubwhile( isRun ){Canvas c = null;try{c = holder.lockCanvas();synchronized( holder ){//调用绘图函数welcomeView.onDraw( c );}}finally{if( c != null ){holder.unlockCanvasAndPost( c );}}try{//睡眠200毫秒Thread.sleep( sleepSpan );}catch(Exception e){e.printStackTrace();}}}        }}


(二) 初露锋芒:用SurfaceView显示一个动态打开的门。运行后的效果,左右两扇门缓缓打开。     

        如果只用SurfaceView显示一副背景图片,那绝对是“大炮打蚊子”------大材小用。从主线程中拉出一个单独的线程,就是为了处理动态效果。这里具体实现的时候有两个线程:welcomeViewGoThread和welcomeViewDrawThread。welcomeViewGoThread只负责修改图片显示的坐标,welcomeViewDrawThread负责在具体的位置显示图片。这种进一步分离,使得各模块的功能更加独立和明确。

package com.pushBox;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;public class PushBoxActivity extends Activity {//欢迎界面WelcomeView welcomeView = null;//欢迎界面的动画线程WelcomeViewGoThread welcomeViewGoThread = null;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                //显示欢迎界面        welcomeView = new WelcomeView( this );                setContentView( welcomeView );         welcomeViewGoThread = new WelcomeViewGoThread( welcomeView );        //启动动画线程        welcomeViewGoThread.start();    }        //内部类,欢迎界面    class WelcomeView extends SurfaceView implements SurfaceHolder.Callback    {    private SurfaceHolder holder;        private WelcomeViewDrawThread welcomeViewDrawThread;    //背景图片,大小640 * 480    Bitmap background;    //左边的木门,大小180 * 450    Bitmap leftWood;    Bitmap rightWood;        //图片显示的位置    int backgroundX = 0;    int backgroundY = 0;    int leftWoodX = 10;    int leftWoodY = 15;    int rightWoodX = 150;    int rightWoodY = 15;        public WelcomeView( Context context )    {    super( context );        holder = this.getHolder();    holder.addCallback( this );        background = BitmapFactory.decodeResource( getResources(), R.drawable.background );    leftWood = BitmapFactory.decodeResource( getResources(), R.drawable.image33 );    rightWood = BitmapFactory.decodeResource( getResources(), R.drawable.image3 );        //创建一个绘图线程    welcomeViewDrawThread = new WelcomeViewDrawThread( this, holder );    }        //自定义的绘图函数,具体的绘图在这里完成    public void onDraw( Canvas c )    {    c.drawBitmap( background, backgroundX, backgroundY, null );      c.drawBitmap( leftWood, leftWoodX, leftWoodY, null );     c.drawBitmap( rightWood, rightWoodX, rightWoodY, null );     }        @Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {// TODO Auto-generated method stub}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stub//启动绘图线程welcomeViewDrawThread.setFlag( true );welcomeViewDrawThread.start();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stubwelcomeViewDrawThread.setFlag( false );}    }         //内部类,欢迎界面的动画线程,只修改坐标,不负责具体显示    class WelcomeViewGoThread extends Thread    {    private WelcomeView welcomeView;    private int sleepSpan = 200;    private boolean isRun;        public WelcomeViewGoThread( WelcomeView welcomeView )    {    this.welcomeView = welcomeView;    isRun = true;    }    public void setFlag( boolean flag )    {    isRun = flag;    }        @Override    public void run() {    // TODO Auto-generated method stub    while( isRun )    {    // 修改木门坐标    welcomeView.leftWoodX -= 2;    welcomeView.rightWoodX += 2;    if( welcomeView.leftWoodX < -90 )    {    welcomeView.leftWoodX = 10;        welcomeView.rightWoodX = 150;    }        try{    //睡眠200毫秒    Thread.sleep( sleepSpan );    }    catch(Exception e){    e.printStackTrace();    }    }    }        }            //内部类,欢迎界面的绘图线程    class WelcomeViewDrawThread extends Thread    {    private WelcomeView welcomeView;    private SurfaceHolder holder;    private boolean isRun;      private int sleepSpan = 200;        public WelcomeViewDrawThread( WelcomeView welcomeView, SurfaceHolder holder )    {    this.welcomeView = welcomeView;    this.holder = holder;    isRun = true;    }    public void setFlag( boolean flag )    {    isRun = flag;    }@Overridepublic void run() {// TODO Auto-generated method stubwhile( isRun ){Canvas c = null;try{c = holder.lockCanvas();synchronized( holder ){//调用绘图函数welcomeView.onDraw( c );}}finally{if( c != null ){holder.unlockCanvasAndPost( c );}}try{//睡眠200毫秒Thread.sleep( sleepSpan );}catch(Exception e){e.printStackTrace();}}}        }}

(三) 脱胎换骨:修改程序框架。

           上述的程序框架有问题,所有代码都放在一个文件里。下面要做的就是把相关的class都独立出来。代码改起来也很简单,只要把几个内部类单独写到一个文件即可。

(四) 重出江湖:用SurfaceView实现一个完整的欢迎界面


 

原创粉丝点击