android游戏开发的技术实现分析

       在android开发中,你可能会有想要开发一个小游戏的冲动,那么用android来开发游戏如何实现呢?幸运的是,google提供了一些已经开发好的游戏实例.我们从他的两个游戏实例入手来探究探究.

      对于轻量级的小游戏,其游戏的核心显示内容,我们可以写一个自己的view来实现!然后以一定的频率刷新这个view,我们调用view的invalidate()来实现.具体的我们来看看一个大家常见的游戏:Snake(贪吃蛇),下面来分析一些实现这个游戏的关键代码.

      和其他app一样,Snake也由一个Activity开始的,同样的通过setContentView(R.layout.snake_layout);这行代码来确定显示内容的布局,这里有必要看看这个布局文件的内容(如下):

<merge xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res/com.example.android.snake">

  <com.example.android.snake.BackgroundView
    android:id="@+id/background"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:colorSegmentOne="@color/muted_red"
    app:colorSegmentTwo="@color/muted_yellow"
    app:colorSegmentThree="@color/muted_blue"
    app:colorSegmentFour="@color/muted_green"
     />

  <com.example.android.snake.SnakeView
    android:id="@+id/snake"
    android:background="@android:color/transparent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:tileSize="24dp" />

  <TextView android:id="@+id/text"
  android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:gravity="center"
    android:textColor="@color/text_violet"
    android:textSize="24sp"
    android:visibility="visible" />

  <RelativeLayout android:id="@+id/arrowContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="gone">

    <ImageView android:id="@+id/imageUp"
    android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:padding="20dp"
      android:src="@drawable/dpad_up" />

    <ImageView android:id="@+id/imageLeft"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentLeft="true"
      android:layout_centerVertical="true"
      android:padding="20dp"
      android:src="@drawable/dpad_left" />

    <ImageView android:id="@+id/imageRight"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_centerVertical="true"
      android:padding="20dp"
      android:src="@drawable/dpad_right" />

    <ImageView android:id="@+id/imageDown"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentBottom="true"
      android:layout_centerHorizontal="true"
      android:padding="20dp"
      android:src="@drawable/dpad_down" />
  </RelativeLayout>

</merge>
        上面的代码,我们首先需要注意的是这个布局文件采用了merge来限定:因为我们的布局是framelayout,所以这里就采用了merge,因为任何加入activity的view的父groupview都是framelayout.

         这里我们重点关注的时SnakeView,这个view就是实现这个游戏的核心.这里需要注意这一行代码:app:tileSize="24dp".这是SnakeView自己定义的一个属性,用于定义贪吃蛇的大小.能够这样使用,你需要先在attrs.xml里面为SnakeView定义这样的属性,看看这里时如何定义的:

  <declare-styleable name="TileView">
    <attr name="tileSize" format="dimension" />
  </declare-styleable>
          你肯定会奇怪,怎么是TileView呢? 其实SnakeView是TileView的子类,而TileView是view的子类.

        所以我们重点来看看SnakeView的实现.(贪吃蛇的具体实现就不设计,这里只是介绍一个游戏开发的实现核心).其实游戏的动画效果就是反复的调用invalidate来促使view重现绘制,通过重写View的onDraw(Canvas canvas)来实现.这样以来,当调用invalidate(),就会触发view自己回调onDraw(Canvas canvas),而游戏每一次需要显示的内容都由onDraw来绘制.

         下面是定时刷新view的代码:

    class RefreshHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            SnakeView.this.update();
            SnakeView.this.invalidate();
        }

        public void sleep(long delayMillis) {
            this.removeMessages(0);
            sendMessageDelayed(obtainMessage(0), delayMillis);
        }
    };

       上面定义的是一个handle,该handle起到一个定时器的作用,每隔delayMillis这么长的时间,来更新update()需要下次绘制的内容,然后invalidate()来刷新.

        下面是他的onDraw的实现:

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int x = 0; x < mXTileCount; x += 1) {
            for (int y = 0; y < mYTileCount; y += 1) {
                if (mTileGrid[x][y] > 0) {
                    canvas.drawBitmap(mTileArray[mTileGrid[x][y]], mXOffset + x * mTileSize,
                            mYOffset + y * mTileSize, mPaint);
                }
            }
        }

    }
        通过上面代码可以知道,其实就绘制了一些图片,这些图片按照一定的坐标就组成来一条蛇.所以每次只要mTileGrid里面的信息准确其绘制出的图像就是准确的.

         对于像贪吃蛇/象棋等这样的轻量级游戏我们可以这么做,不过对于一些格斗类的游戏就不太实用了,当要绘制大量的图片资源/铃声资源的时候就满足不了需要.这个时候我们需要用到一个特殊的view:SurfaceView

           还好,google给我提供了一个实例:JetBoy.下面我们来看看如何使用SurfaceView.

           (1)首先,你写的SurfaceView需要实现这个接口SurfaceHolder.Callback, 其目的是我们需要获取我们的SurfaceView的状态变化(创建成功/大小变化/销毁).如下代码:

public class JetBoyView extends SurfaceView implements SurfaceHolder.Callback {
          (2)  我们需要得到  SurfaceView的SurfaceHolder,并且使用SurfaceHolder.Callback,你需要在构造方法里面完成,如下代码:

    public JetBoyView(Context context, AttributeSet attrs) {
        super(context, attrs);

        // register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);

            (3)由于,我们需要绘制大量的内容,所以我们一般需要开启一个线程来做这些工作.下面来详细介绍其中缘由: 我们通过上面获得的SurfaceHolder就可以获得这个SurfaceView的Canvas,所以只要我们用这个Canvas来绘制我们需要的东西即可,这些工作我们都是在我们定义的线程里面来完成的,当然这一切都应该在SurfaceView创建完成以后(surfaceCreated(SurfaceHolder arg0) 回调以后)才能完成.下面来看thread里面的run里面核心代码:

        public void run() {
            // while running do stuff in this loop...bzzz!
            while (mRun) {
                Canvas c = null;

                ...
				...
				...

                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    // synchronized (mSurfaceHolder) {
                    doDraw(c);
                    // }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }// end finally block
            }// end while mrun block
        }

           上面代码通过mSurfaceHolder.lockCanvas(null);来获取我们SurfaceView的canvas, 然后绘制内容,绘制完成指向这行代码mSurfaceHolder.unlockCanvasAndPost(c);

          (4)所以我们需要在surfaceCreated的时候开始我们的游戏:

    public void surfaceCreated(SurfaceHolder arg0) {
        // start the thread here so that we don't busy-wait in run()
        // waiting for the surface to be created
        thread.setRunning(true);
        thread.start();
    }
          在surfaceDestroyed的时候结束我们的线程:

    public void surfaceDestroyed(SurfaceHolder arg0) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;

            } catch (InterruptedException e) {
            }
        }
    }

其实都很简单的大家使用一下就明白的.

         

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书共分两篇,第一篇介绍了Android 3D游戏开发的基础知识,主要对OpenGL ES的相关内容进行了介绍。   章 名主 要 内 容   第1章 英雄还看今朝—Android简介本章介绍了市场上主流的手机平台,同时也分析了未来手机平台的发展趋势及Android平台的前景   第2章 数风流人物—当前流行游戏类型简介本章以分类的方式简要地介绍了当前流行的游戏的玩法,游戏的视觉效果,游戏的设计及《仙剑》等著名游戏的历史   第3章 不积跬步,无以至千里—游戏开发基础知识本章初步介绍了游戏开发的基础知识   第4章 千里之行,始于足下—3D开发基础知识本章介绍了3D开发中的基础知识,包括OpenGL ES的介绍及OpenGL ES中绘制模型的原理,并通过点、线和三角形的绘制介绍了OpenGL ES中模型的几种绘制方式。最后介绍了3D场景中常用的两种投影方式,并通过例子比较了这两种投影的区别   第5章 愿君多采撷,此物最相思—光照效果的开发本章介绍了光照的基础知识,包括环境光、散射光及镜面光   第6章 为伊消得人憔悴——纹理映射本章主要介绍了纹理的基础知识,以及纹理的不同拉伸方式和纹理过滤高级技术,从绘制三角形开始到绘制地月系,可能会经历很长时间,但是这对以后的学习是有帮助的   第7章 海阔凭鱼跃,天高任鸟飞—3D基本形状的构建在本章中介绍了圆柱体、圆锥体、圆环、抛物面、双曲面和螺旋面在OpenGL ES中的渲染方法。这些基本形状在3D世界中应用广泛,在构造一些复杂物体时,经常会运用这些基本形状来进行拼装组合   第8章 执子之手,与子偕老—坐标变换本章介绍了坐标变换的应用。绘制3D场景的过程,主要是旋转和平移操作的组合,通过合理的堆栈操作,就比较容易绘制出所需的3D场景   第9章 孤帆远影碧空尽—摄像机与雾特效在本章中,首先对摄像机及其配置做了介绍。摄像机在3D编程中至关重要,没有正确的配置,摄像机可能不能获得想要的场景效果。然后对雾特效做了具体介绍,应用雾特效可以使场景更加逼真,并且可以减少场景渲染量来提高性能   第10章 假作真时真亦假—混合本章主要为读者介绍了混合,从混合的背景知识到如何配置源因子和目标因子。在介绍源因子和目标因子的时候,向读者介绍了一些预定义常量和一些常用的组合方式,以及如何启用混合   第11章 蓦然回首,那人却在灯火阑珊处—3D高级技术本章主要为读者介绍了3D的一部分高级技术。每一项技术通过讲解其原理和案例,使读者对3D高级技术有一定的了解   第12章 心有灵犀一点通—传感器在本章中,向读者介绍了Android中传感器的相关知识。包括传感器的种类、配置,并且着重介绍了姿态传感器的应用   第13章 千锤万凿出深山—游戏中的数学与物理在本章中对3D游戏中可能会用到的数学及物理知识进行了简单的介绍,这在3D游戏开发中是相当重要的。游戏中的核心算法,基本上都要用到数学和物理知识。一款游戏的性能很大程度上取决于游戏设计的算法   第14章 山舞银蛇,原驰蜡象—AI基本理念本章主要介绍了AI、AI引擎的基本组成与设计,以及游戏AI中图的搜索和模糊逻辑,其中游戏AI中图的搜索为本章的重点。在本章中详细介绍了5种算法的原理与实现   第15章 独上高楼,望尽天涯路—开发小秘籍本章介绍了地图设计器、多键技术、虚键盘、查找表技术、状态机、AABB边界框、穿透效应、拾取技术,以及天空盒和天空穹在OpenGL ES中的应用 第二篇以7个比较大的案例来说明Android平台下3D游戏开发流程,通过这7个案例的讲解,读者对3D游戏开发将会有更深层次的理解。   章 名主 要 内 容   第16章 体育类游戏——《疯狂投篮》本章介绍了Android 3D游戏《疯狂投篮》的开发。通过该案例向读者介绍了在Android平台下进行3D游戏开发的相关知识和基本流程,并对游戏开发中的编程技巧进行了介绍,并主要介绍了篮球与地面、墙面及篮框的碰撞检测及运动动画的实现方法   第17章 益智类游戏——《旋转积木》本章介绍了Android 3D游戏《旋转积木》的开发。主要介绍了积木旋转的不同状态的实现方法和地图设计器的应用   第18章 休闲类游戏——《摩天大楼》本章介绍了Android 3D游戏《摩天大楼》的开发。主要介绍了楼层与楼层之间的衔接与碰撞及掉落后翻转动画的实现   第19章 动作类游戏——《3D空战》本章介绍了Android 3D游戏《3D空战》的开发。主要介绍了飞机的构造方法和我方战机与敌方战机的操控及动画实现   第20章 桌面类游戏——《激情台球》本章介绍了Android 3D游戏《激情台球》的开发。主要介绍了台球与台球的碰撞检测实现、台球与球桌的碰撞检测实现和进球的判定实现   第21章 射击类游戏——《抢滩登陆》本章介绍了Android 3D游戏《抢滩登陆》的开发。主要运用了灰度图生成技术并且主要介绍了坦克运动的实现方法及炮弹碰撞检测的实现   第22章 竞技类游戏——《乡村飙车》本章介绍了Android 3D游戏《乡村飙车》的开发。主要介绍了运用分层绘制和拼接绘制的策略进行场景的优化绘制,并且对场景部件进行了分类控制   本书面向的读者   本书的内容详细,且几乎涵盖了Android 3D游戏开发所有相关的技术,并向读者介绍了真实项目的开发流程,主要面向以下读者。   Android的初学者   本书详细介绍了OpenGL ES的基础知识,并对Android 3D游戏程序的开发进行了介绍。作为一名Android的初学者,通过本书的学习可以快速全面地掌握Android 3D游戏开发的相关知识,稳健地步入Android 3D游戏开发人员的行列。   有一定Android基础且希望学习Android 3D游戏开发的读者   有一定Android基础的读者通过阅读本书的前半部分便可快速掌握OpenGL ES的基础知识,然后通过7个真实案例的学习迅速掌握Android平台下应用程序的开发。   在职的开发人员
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值