推箱子游戏开发(1) surfaceView 实现动画效果
推箱子游戏开发(一) surfaceView 实现动画效果
SurfaceView是View的子类,常用于实现游戏中的动画效果。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实现一个完整的欢迎界面