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

        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 );    		
    	}
    	
    	@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			// TODO Auto-generated method stub			
		}
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			//启动绘图线程
			welcomeViewDrawThread.setFlag( true );
			welcomeViewDrawThread.start();
		}
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			welcomeViewDrawThread.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;
    	}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while( 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 ); 
    	}
    	
    	@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			// TODO Auto-generated method stub			
		}
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			//启动绘图线程
			welcomeViewDrawThread.setFlag( true );
			welcomeViewDrawThread.start();
		}
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			// TODO Auto-generated method stub
			welcomeViewDrawThread.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;
    	}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while( 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实现一个完整的欢迎界面


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章