Android应用开发揭秘(笔记) 第五章Android游戏开发

View开发框架:
1.游戏的核心就是不断的绘图和刷新界面,Android中提供了invalidate方法来实现刷新,invalidate不能直接在线程中调用,因为它违背了单线程模型:
Android UI操作并不是线程安全的。并且这些操作必须在UI线程中执行,因此Android中最常见的方法是利用Handler来实现UI线程更新。
代码如下:
 Handler myHandler = new Handler()
 {
  //接收到消息后处理
  public void handleMessage(Message msg)
  {
   switch (msg.what)
   {
   case Activity01.REFRESH:
    mGameView.invalidate();
    break;
   }
   super.handleMessage(msg);
  }   
 };

 class GameThread implements Runnable
 {
  public void run()
  {
   while (!Thread.currentThread().isInterrupted())
   {
    Message message = new Message();
    message.what = Activity01.REFRESH;
    //发送消息
    Activity01.this.myHandler.sendMessage(message);
    try
    {
     Thread.sleep(100);
    }
    catch (InterruptedException e)
    {
     Thread.currentThread().interrupt();
    }
   }
  }
 }

2.在Android中还提供了一个更新界面的方法postInvalidate。

SurfaceView开发框架:
1.当开发复杂的游戏,而且对程序的执行效率要求很高时,View类就不能满足需求了,这时必须通过SufaceView类进行开发。
2.SurfaceView可以直接访问画布,SufaceView提供给需要直接画像素而不是使用窗体部件的应用使用。
3.使用SurfaceView时需要对其进行 创建、销毁,情况改变时进行监听,需要实现 SurfaceHolder.CallBack接口。SurfaceHolder对象通过getHolder方法来获得。
同时还需要addCallback方法来添加“回调函数”。
4.surfaceChanged:在Suface的大小发生改变时触发。
  surfaceCreated:在创建Surface时触发。
  surfaceDestroyed:在销毁Suface时触发。
  addCallback:给SurfaceView添加一个回调函数。
  lockCanvas:锁定画布,绘图之前必须锁定画布才能得到当前画布对象。
  unlockCanvasAndPost:开始绘制时锁定了画布,绘制完成后解锁画布。
  removeCallback:从SurfaceView中移除回调函数。
5.SurfaceView和View区别:SurfaceView不需要通过线程来更新视图,但在绘图之前必须使用lockCanvas方法来锁定屏幕,并得到画布,然后再绘制;当绘制完成后,使用
unlockCanvasPost来解锁画布,于是才能显示在屏幕上。
代码如下:
GameSurfaceView extends SufaceView implements SurfaceHolder.Callback
implements SurfaceHolder.Callback 方法必须实现:
public void surfaceChanged( SurfaceHolder holder, int format, int width, int height ){

}
public void surfaceCreated( SurfaceHolder holder ){

}
public void surfaceDestroyed( SurfaceHolder holder ){

}

SurfaceHolder m_holder = this.getHolder();
m_holder.addCallback(this);
public void Draw(){
 Canvas canvas = m_holder.lockCanvas();
 Paint paint = new Paint();
 paint.setAntiAlias(true);
 paint.setColor(Color.BLACK);
 canvas.drawRect( 0, 0, 320, 480 );
 m_holder.unlockCanvasPost();
 
}

☆Graphics类开发:
1.Paint画笔、Color类主要定义一些颜色常量。
GameView extends View implements Runnable
在run方法中调用postInvalidate()方法会自动调用onDraw(Canvas canvas)。
2.Canvas类介绍:
Canvas常用方法:
Canvas();创建一个空的画布,可以使用setBitmap方法来设置绘制的具体画布。
Canvas(Bitmap bitmap);以bitmap对象创建一个画布,则将内容都绘制在bitmap上,因此bitmap不能为NULL。
Canvas(GL gl);在绘制3D效果时使用,与OpenGl相关。
drawColor;设置Canvas的背景颜色。
setBitmap;设置具体画布。
clipRect;设置显示区域,即设置裁剪区。
isOpaque;检测是否支持透明。
rotate;  旋转画布
setViewport;设置画布中显示窗口。
skew;       设置偏移量。
对画布上的某个精灵执行旋转、缩放等操作,可以通过旋转画布实现,但是需要注意只需要旋转其中的一个,这时就需要用到save方法来锁定需要操作的对象,在操作完后
需要通过restore方法来解除锁定。
代码如下:

                /* 线锁定画布 */
  canvas.save();
  /* 旋转画布 */
  canvas.rotate(45.0f);
 
  /* 设置颜色及绘制矩形 */
  mPaint.setColor(Color.RED);
  canvas.drawRect(new Rect(15,15,140,70), mPaint);
 
  /* 解除画布的锁定 */
  canvas.restore();

3.几何图形绘制:
drawRect:绘制矩形
drawRect( int x, int y ,int width, int height ,Paint paint );

drawCircle :绘制圆
drawCircle( int x, int y, int r, Paint paint );

drawOval   :绘制椭圆
RectF rectf = new Rectf();
rectf.left = 80;
rectf.top = 30;
rectf.right = 120;
rectf.bottom = 70;
drawOval( Rectf rectf , Paint paint );

drawPath   :绘制任意多边形
Path path = new Path();
path.moveTo(150+5, 80-50);
path.lineTo(150+45, 80-50);
path.lineTo(150+30, 120-50);
path.lineTo(150+20, 120-50);
drawPath( Path path, Paint paint );

darwLine   :绘制直线
darwLine( int a_x, int a_y, int b_x, int b_y, Paint paint );

drawPoint  :绘制点


4.字符串绘制:drawText绘制字符串。
FontMetrics来规划字体的属性。可以通过getFontMetrics 方法来获得系统字体的相关内容。
setTextSize:设置字符串的尺寸
setARGB:设置颜色
getTextWidths:获取字符串宽度
setFlags(Paint.ANTI_ALIAS_FLAG ):消除锯齿。

5.图像绘制。
((BitmapDrawable)getResources().getDrawable(资源索引)).getBitmap() 从res/drawable中获取Bitmap对象。
通过canvas.drawBitmap( bitmap, int x,int y, Paint paint );在屏幕上显示bitmap
drawImage方法实现对图片的剪切:
 /*------------------------------------
  * 绘制图片
  *
  * @param  x 屏幕上的x坐标
  * @param  y 屏幕上的y坐标
  * @param  w 要绘制的图片的宽度
  * @param  h 要绘制的图片的高度
  * @param  bx图片上的x坐标
  * @param  by图片上的y坐标
  *
  * @return  null
  ------------------------------------*/
 public static void drawImage(Canvas canvas, Bitmap blt, int x, int y, int w, int h, int bx, int by)
 {
  Rect src = new Rect();// 图片
  Rect dst = new Rect();// 屏幕
 
  src.left = bx;
  src.top = by;
  src.right = bx + w;
  src.bottom = by + h;
 
  dst.left = x;
  dst.top = y;
  dst.right = x + w;
  dst.bottom = y + h;
  canvas.drawBitmap(blt, src, dst, null);
 
  src = null;
  dst = null;
 }

6.图像旋转:Android中进行图像旋转需要使用Matrix,通过reset或set方法实现。最后通过setRotate设置旋转角度。用createBitmap创建一个经过
旋转等待处理的Bitmap对象。然后将Bitmap显示在屏幕上。
代码如下:
Matrix mMatrix = new Matrix();

public void onDraw( Canvas canvas ){

 super.onDraw(canvas);
 mMatrix.reset();
        mMatrix.setRotate(角度);
 Bitmap mbitmap = Bitmap.createBitamp(之前bitmap对象,x, y ,width, height, mMatrix, true );
 canvas.drawBitmap(bitmap,x,y,null);
mbitmap = null;

}

7.图像缩放:
图片向缩放和图像旋转一样,需要使用Matrix的postScale方法来设置图像的缩放倍数。
代码部分和图像旋转一样。将setRotate、改成postScale即可。

8,图像像素操作:
Android中通过getPixels方法可以获取Bitmap像素。
通过getPixels方法将图像的像素放入一个数组中,然后给对这个数字进行处理。处理完毕后,通过setPixels设置这个像素到Bitmap中。
Android中,每一个图像像素通过一个4字节整数展现:ARGB

9.Shader类介绍:略

10.双缓冲技术:
双缓冲原理:当一个动画争先显示时,程序又在改变它,前画面还没有显示完,程序又在请求重新绘制,这样屏幕就会出现闪烁。为了避免闪烁,可以使用双缓冲技术,
将要处理的图片在内存中处理好之后,再将其显示到屏幕上。这样就不会出现闪烁现象了。
双缓冲的核心技术就是通过setBitmap方法将要绘制的所有图像绘制到一个Bitmap上,然后在调用drawBitmap方法绘制这个Bitmap。
代码如下:
Bitmap mBit = ((BitmapDrawable)getResources().getDrawable(R.draw.xx)).getBitmap();
Bitmap mBufferBitmap = Bitmap.CreateBitmap(int width, int height, Config.ARGB_8888 );
Canvas mCanvas = new Canvas();
mCanvas.setBitmap( mBufferBitmap );
Paint mPaint = new Paint();
mCanvas.drawBitmap( mBit, 0 ,0 , mPaint );

public void onDraw( Canvas canvas ){
    super.onDraw( canvas );
    canvas.darwBitmap( mBufferBitmap, 0, 0, mPaint );
}

11.全面显示:
通过requestWindowFeature发设置标题栏是否显示。通过setFlags方法可以设置全屏模式。
代码如下:
//设置为无标题栏
requestWindowFeature( Window.FEATURE_NO_TITLE );
//设置为全屏
getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN );

12.获得屏幕属性:
Android中的DisplayMetrics定义了屏幕的一些属性,可以通过getMetrics方法得到当前屏幕的DisplayMetrics属性,从而得到屏幕宽、高。
代码如下:
DisplayMetrics dm = new DisplayMetrics();
getWindowManger().getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
int screenHeigth = dm.heightPixels;

☆动画实现:
Android中提供了两类动画:一类是Tween动画,即通过对场景里的对象不进行图像变换(平移、缩放、旋转)来尝试动画效果。第二类是Frame动画,即顺序播放事先做好的图像。
1.Tween动画:
Tween动画通过对View的内容完成一系列的图形变换(包括 平移,缩放,旋转,改变透明度)来实现动画效果。
Alapha:渐变透明度动画效果
Scale:渐变尺寸伸缩动画效果
Translate:画面转换位置移动动画效果。
Rotate:画面转移旋转动画效果。
Tween动画是通过预先定义的一组指令,这些指令指定了图形变换的类型、触发时间、持续时间。程序沿着时间线执行这些指令就可以产生动画效果。
首先需要定义一个Animation动画对象,然后设置改动画的一些属性,最后通过startAnimation方法来开始动画。
AlphaAnimation(float fromAlpha, float toAlpha );构建一个渐变的透明度动画。
ScaleAnimation(float formX, float toX, float fromY, float toY, int pivotXType, float pivotXVale, int pivotYType, float prvotYVale );
构建一个渐变尺寸伸缩动画。pivotXVale、pivotYType伸缩模式,pivotXVale、prvotYVale分别为伸缩动画相对x、y的坐标开始位置。
TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);构建一个动画转换位置移动动画。fromXDelta、fromYDelta起始坐标,toXDelta,toYDelta结束坐标。
RotateAnimation(float fromDegress, float toDegress, int pivotXType, float pivotXVale, int pivotYType, float pivotYVale );
构建一个旋转画面的动画。
fromDegress开始角度,toDegress结束角度,pivotXType,pivotYType分别为x,y的伸缩模式。pivotXVale,pivotYVale分别为伸缩动画相对于x,y坐标开始位置。
setDuration( long durationMillis );设置动画显示时间,durationMillis 为显示动画长度,以毫秒为单位。
startAnimation(Animation animation);//开始播放动画。animation 为要播放的动画。
以上功能还可以通过xml布局实现该动画功能。
AlphaAnimation xml布局:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="2000"
/>
</set>
读取xml部分代码:
    /* 装载动画布局 */
    Animation mAnimationAlpha = AnimationUtils.loadAnimation(mContext,R.anim.alpha_animation);
    /* 开始播放动画 */
    this.startAnimation(mAnimationAlpha);

2.Frame动画:
用法:创建一个AnimationDrawable对象来表示Frame动画,然后通过addFrame方法把每一帧要显示的内容添加进去,最后通过start方法就可以播放这个动画了,同时还可以通过
setOneShot方法来设置动画是否重复播放。
AnimationDrawable    frameAnimation    = null;

/* 实例化AnimationDrawable对象 */
frameAnimation = new AnimationDrawable();
/* 装载资源 */
        //这里用一个循环了装载所有名字类似的资源
        //如“a1.......15.png”的图片
        //这个方法用处非常大
        for (int i = 1; i <= 15; i++)
        {
            int id = getResources().getIdentifier("a" + i, "drawable", mContext.getPackageName());
            mBitAnimation = getResources().getDrawable(id);
            /* 为动画添加一帧 */
            //参数mBitAnimation是该帧的图片
            //参数500是该帧显示的时间,按毫秒计算
            frameAnimation.addFrame(mBitAnimation, 500);
        }
        
        /* 设置播放模式是否循环false表示循环而true表示不循环 */
        frameAnimation.setOneShot( false );  
        
        /* 设置本类将要显示这个动画 */
        this.setBackgroundDrawable(frameAnimation);

frameAnimation.start();播放动画。

小结:
1.介绍了Android游戏开发框架
2.介绍了图形、图像绘制和处理的方法
3.介绍了Android中两种动画。

你可能感兴趣的:(Android应用开发揭秘(笔记) 第五章Android游戏开发)