Android游戏编程从零开始.docx
- 文档编号:28691126
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:96
- 大小:1.19MB
Android游戏编程从零开始.docx
《Android游戏编程从零开始.docx》由会员分享,可在线阅读,更多相关《Android游戏编程从零开始.docx(96页珍藏版)》请在冰豆网上搜索。
Android游戏编程从零开始
从零开始Android游戏编程(第二版)
作者:
邢野时间:
2009-9-25
MSN:
xingye(at)
目录
前言3
第一版前言5
第一章搭建开发环境6
第二章创建第一个程序HelloTank10
第三章显示文字和图片17
第四章响应用户事件30
第五章小结——扫雷游戏的实现36
第六章SurfaceView动画39
第七章精灵、帧动画与碰撞检测46
第八章地图的设计和实现62
第九章游戏程序的生命周期75
第十章游戏循环的设计85
第十一章演员(Actor)、视口(ViewWindow),演出开始88
第十二章音乐与音效94
前言
没想到重新打开这篇文档已经是一年之后了。
去年三月,我停止了这一系列文章的写作。
六月,离开了工作了五年的公司。
作为公司的创始人和业务主管,我不能容忍它发展的如此缓慢,而合伙人却很享受这种慢节奏的生活。
九月底,去了西藏,一如期待中的蓝天白云,雄伟的布达拉宫,美丽的雅鲁藏布江和轻微的高原反应。
开车的刘师傅是个很懂生活的人,当他用一个急转弯将羊卓雍错推入我们眼帘的时候,每个人都惊呆了。
原来照片上的颜色不是PS出来的!
世界上真的有这么美丽的湖!
从高原下来到成都、长沙、武汉。
回到了久违的母校,见到了阔别多年的队长和同学。
才发现不光是高原的美景能让人震撼,久别的重逢一样能冲击人的心灵。
当那些青春的记忆一瞬间被撩起,不知是不是温暖,不知是不是凄凉。
人,也笑了,酒,也醉了。
“南巡”归来,心中一下少了很多杂念,或许是江山如画让人更觉人生苦短吧。
既然自己对移动开发这么感兴趣,何不干脆寄情于此,忘掉什么web,忘掉什么ERP。
于是iPad,MacBook摆上了书桌,多年不用的C语言重新捡起。
arm、toolchain、xcode、跨平台、交叉编译。
陌生,熟悉,可憎,可爱。
突然发现,原来自己还是喜欢学习,一把年纪了,还能觉得吸收知识是一个快乐的过程。
过程虽然曲折,前途却有光明。
看到同一个程序在windows,mac,ios,android都可以运行的时候,自己都有点“马德里不思议”的感觉。
两个来月的学习、尝试终于有所收获。
恰在这时,又一封关于这一教程的邮件出现在了我的邮箱。
如同前面所有的邮件一样,xiangyang也想知道这个系列教程还有没有续集。
很遗憾,它没有。
自从我下定决心制作一个跨平台的框架之后,就放弃了对javaSDK的探索。
我喜欢java的干净快捷,但是我想更集中精力。
当取得了阶段性成果之后,我很想让自己紧绷的神经放松一下。
于是我对xiangyang说“用一周的时间完成这个教程,以减少读者的遗憾”,这也就是大家在后面将看到的。
一些变化:
从现在开始,不再使用OPhoneSDK。
Google的新工具非常好,可以管理多个SDK版本,使用起来非常方便。
而相比之下,OPhone老湿就太不给力了,还在吃Cupcake吧,别吃了,再吃噎到了。
另外,我重新整理了随书源码。
让大家使用起来更方便。
最后,很多人希望我能有个blog以方便交流,所以本文将通过我的csdn博客重新发布。
其实我以前在javaeye上发过,可没想到javaeye上竟然有那么多脑残,看到OPhone就像看到他母亲的裸照一样不能容忍,纷纷想拿五毛钱买回去珍藏!
?
你瞧不起它并不代表你就比它优秀,真的。
邢野
2011-1-10
第一版前言
什么是OPhone
OPhone是基于Linux、面向移动互联网的终端基础软件及系统解决方案。
OPhoneSDK是专为OPhone平台设计的软件开发套件,它包括OPhoneAPI,OPhone模拟器,开发工具,示例代码和帮助文档(摘自OPhone官方网站:
写作本文的目的
为了普及OPhone编程的基本知识,并通过复刻一个坦克大战游戏让读者了解2D游戏编程的简单思路。
文中的程序结构和实现方法并非最优,希望能起到一个抛砖引玉的作用,让更多的人加入到OPhone开发的行列中来。
谁适合阅读本文
虽然本文叫做“从零开始OPhone编程”,但并不能面对那些对编程一无所知的读者。
实际上,本文要求读者了解java语言的基本知识,最好会使用eclipse。
在文章的每个章节都标有难度,有能力的读者完全可以跳过相对容易的章节直接阅读自己感兴趣的内容。
本文的时效性
本文只适合当前版本的OPhoneSDK(v1.0),本文的代码、图片、链接可能会因时间推移而失效。
第一章
搭建开发环境
难度:
容易
工欲善其技,必先利其器。
我们要做的第一件事就是搭建Android开发环境。
本文只介绍Windows下的安装方法,Linux下的安装方法请参考官方网站的介绍。
与PC编程略有不同的是,Android的程序需要在模拟器中运行。
因此,我们需要一个集成开发环境,一个SDK和一个模拟器。
因为Android编程使用java语言,所以我们还需要JDK,最好使用安装版本(6Update16Windows版即可。
集成开发环境我们选用eclipse,可以使用eclipse3.3到3.5的任意版本(http:
//download.eclipse.org/eclipse/downloads/)最好下载JDT集成版。
然后我们可以从Android官方网站()下载AndroidSDK(当然,如果你不能翻墙,可以到国内的网站下载),SDK全部安装完毕之后,还需要安装eclipse插件。
插件是用来扩展eclipse功能的。
开发Android用的插件叫ADT(AndroidDeveloperTools),它可以帮助我们完成创建项目,向模拟器部署并运行程序,调试程序等工作。
关于ADT的功能,在后面使用中我们会逐渐熟悉。
安装ADT的方法如下(以eclipse3.4为例):
启动eclipse,选择菜单中的Help->SoftwareUpdates
点击AddSite
点击Archive…
找到OPhoneSDK安装目录下tools\ophone\ADT-0.8.0.zip(因为我已经安装好了ADT,所以出现了重复URL的提示),点击OK即可开始安装
ADT安装完毕后还要简单配置一下,打开菜单中的Window->Preferences
找到Android项,通过Browse按钮指定AndroidSDK的安装位置
至此为止,Android的安装环境就全部搭建完毕了。
下一章节,我们会遇见经典的helloworld,下章见!
第二章
创建第一个程序HelloTank
难度:
容易
现在开始,我们要真正写作Android程序了。
虽然前面安装过程那么复杂,但是写起程序来却是非常简单。
而且为了让大家有一个直观的认识,本文不会叙述大段的原理,而是在编码的过程中渗透对原理、概念的讲解。
让我们打开eclipse,选择菜单中的File->New->Project…
选择Android->AndroidProject
下面需要我们输入项目的一些信息,因为我们要复刻经典游戏坦克大战,所以我们的程序就取名Tank
这样,一个Android项目就创建完成了,我们可以在eclipse的PackageExplorer看到我们的项目
托ADT的福,虽然我们只输入了几个名字,但这个项目实际上已经可以运行了。
右击项目名,选择RunAs->AndroidApplication
不出意外的话,你会看到一个手机模拟器被启动,而我们刚刚建立的程序会被运行起来
如果你发现模拟器启动了,而程序并没有被运行,可能需要手工启动程序。
这里我们用到一个重要的工具DDMS(DavlikDebugManager)。
运行DDMS快捷方法是点击eclipse右上角的OpenPerspective,如果在弹出的列表中没有DDMS,那么点击Others
选择DDMS
这样我们就打开了DDMS界面,这个工具我们以后会经常用到。
刚刚说到模拟器启动了而程序并没有被运行,很可能是在模拟器启动过程中DDMS失去了与模拟器的链接。
解决方法很简单:
点击Devices标签下的工具栏,选择Resetadb
然后右击项目名称,RunAs->AndroidApplication。
除了右击运行项目,还可以通过工具栏上的运行按钮启动程序
在运行按钮左边的是Debug按钮,这两个我们以后也会经常用到。
现在我们已经有了第一个可以运行的Android,虽然你可能对ADT生成的一堆文件感到一头雾水,也不知道程序界面上那一句“HelloWorld,Main”是从哪里来的,但是没关系,随着本文的深入你会逐渐熟悉Android项目的目录结构,程序设计的原则和方法,以及调试和部署的方法。
现在读者可以自己熟悉一下模拟器的操作,让我们下章再见。
第三章
显示文字和图片
难度:
容易
从本章开始,读者就要编写代码了。
按照作者的原则——少一些理论,多一些实践,代码中可能会有跳跃的地方。
但是请大家不要着急,随着学习的深入,你很快就会了解其中的奥秘。
不过在开始之前,我们还是要先来理顺一下思路,看看完成一个坦克大战游戏需要哪些工作:
首先,我们需要一个基本的程序,这个程序能够在Android上运行;这个程序要能够显示图形包括地图,主角和NPC等等;程序能够接受用户的输入,控制主角移动;程序要能够控制NPC和子弹的移动;程序还能对各种事件做出判断,比如击中敌人,获得物品,胜利或者失败。
现在我们就从基本程序开始,一步一步实现它。
首先,让我们看一下刚刚生成的文件目录
在源文件目录下,只有Main.java和R.java两个文件,刚刚被我们命名成Main.java的文件就是程序的入口文件。
而R.java是由插件来维护的资源定义文件,我们先不管它。
Main.java内容如下:
packageorg.yexing.android.games.tank;
importandroid.app.Activity;
importandroid.os.Bundle;
publicclassMainextendsActivity{
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
很幸运,Main.java的代码非常之少,而且还有一段注释,以致我们很容易知道函数onCreate的作用,需要解释的只是setContentView()。
先不要管注释中提到的Activity和setContentView的参数R.layout.main,我们使用setContentView的另一种形式:
setContentView(Viewview)。
setContentView的作用是设定当前使用的视图即View(依此理解,可以有很多个View,需要用哪个就可以把他作为setContentView的参数显示出来)。
View是一个非常重要的组件,它可以用来显示文字,图片,也可以接收客户的操作,比如触摸屏,键盘等等,而我们的游戏中正是需要绘图和交互,看来View很符合我们的需要(但是请注意,使用View并不是我们的最终方案,原因会在后面说明。
此处介绍View是为了讲解基础的图形和用户控制)。
下面我们就要订制一个属于自己的View,可以通过继承自系统提供的View,并重载相关的函数来实现。
创建类的方法如下:
右击包名New->Class
我们将这个View类命名为GameView,并且由android.view.View继承
点击Finish,一个View类就创建好了。
这里是第一次创建类,以后就不会有图片演示了,请大家记住的这个方法。
GameView创建好了,但是代码还有一些错误,这里介绍一下eclipse的使用技巧,将鼠标悬停在有错误的位置,或者将光标停在有错误的行,然后按Ctrl+1键,就会出现修改建议,大部分时候,使用修改建议都可以改正我们的错误,如图
可以看出来,刚刚的错误是因为没有创建构造函数,选择修改建议的第二项,增加一个构造函数
publicGameView(Contextcontext){
super(context);
//TODOAuto-generatedconstructorstub
}
我们的View就创建好了。
回到Main.java,刚刚说了,只要将View作为setContentView的参数,这个View就可以被显示出来:
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(newGameView(this));
}
现在让我们运行模拟器,看看程序变成什么样子了(启动模拟器的方法见第二章)。
不要意外,屏幕上就是一片空白,因为我们创建了一个View,但是没有让它显示任何内容。
下面我们就会在View上显示一段文字和一张图片。
让View显示内容也很简单,只需要重载View的onDraw函数,把相应的语句写入onDraw中即可。
打开GameView.java,点击菜单Source->Override/ImplementMethod…
选中onDraw点击OK
下面这段代码就会被加入到程序当中,所有与显示有关的代码都会在这里面完成
@Override
protectedvoidonDraw(Canvascanvas){
//TODOAuto-generatedmethodstub
super.onDraw(canvas);
}
这里我们遇到了又一个非常重要的类Canvas,Canvas一般翻译成画布,所有的绘图操作都是通过Canvas中的函数来完成的,比如显示文字的函数Canvas.drawText(),显示位图的函数Canvas.drawBitmap(),以及各种绘制图形的函数如Canvas.drawRect(),Canvas.drawArc()等等。
下面让我们显示一段文字在屏幕上:
protectedvoidonDraw(Canvascanvas){
//TODOAuto-generatedmethodstub
super.onDraw(canvas);
canvas.drawText("坦克大战",50,50,newPaint());
}
坦克大战四个字已经出现在了屏幕上。
让我们来详细看一下这条语句:
canvas.drawText("坦克大战",50,50,newPaint());
第一个参数是要显示的文字,第二、第三个参数是文字在屏幕上的坐标,说到坐标得多讲两句。
在2D编程中,屏幕坐标的原点是屏幕的左上角,横向向右增大,纵向向下增大,如上图所示。
最后一个参数是Paint,通常翻译成画笔,它决定了文字或图形的颜色,字体,线条粗细等等,后面用到相应属性的时候会详细介绍。
那么这条语句就是在屏幕上(50,50)的位置用缺省的画笔写出“坦克大战”四个字。
另外如果eclipse提示代码错误,不要忘了用Ctrl+1。
有了文字,下面就是图像了。
显示图像比显示文字略微复杂一些,首先我们要准备一张位图,图片必须是png格式的,文件名只能是小写字母,数字和下划线。
battlecity.png
然后将这张图片copy到工程的res/drawable目录下。
可以直接在eclipse的目录树中粘贴。
显示位图的函数是Canvas.drawBitmap(),drawBitmap有很多种形态,我们先看其中最简单的一种
canvas.drawBitmap(bitmap,left,top,paint)
乍一看似乎和drawText差不多,4个参数有三个都相同,但这第一个参数bitmap要比文本复杂得多。
首先,他是一个Bitmap类实例,因为我们现在还不需要这个类的其他功能,所以不过多介绍Bitmap,只考虑它是怎么来的。
得到Bitmap实例的方法也有很多种,这里只介绍其中的一种
BitmapFactory.decodeResource(res,id);
此方法可以返回一个bitmap实例,但是这个函数还需要两个参数res和id。
res是Resources实例,而id是一个整数,下面让我们分别了解这两个参数。
res的地位跟bitmap差不多,只需要作为参数被使用,因此,只要得到实例就可以了,获得Resources实例的方法如下:
res=context.getResources();
天哪,事情越来越复杂了,因为这段代码里面有多了一个陌生面孔context。
context是Context实例,Context通常翻译做上下文,这个名称似乎有点晦涩,他究竟是什么呢?
让我们回头看看写好的程序
publicGameView(Contextcontext){
super(context);
//TODOAuto-generatedconstructorstub
}
这时候我们有一个context实例,继续朔源而上,在Main.java中
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(newGameView(this));
}
原来,context指向Main类。
好了,我们终于找到res的源头了。
还有另外一个分支第二个参数id。
BitmapFactory.decodeResource(res,id);
id是一个整形,它到底是谁的id呢?
我们还是得往前面找,还记得我们第一次见到函数setContentView时什么样子么
setContentView(R.layout.main);
对,他的参数是R.layout.main,后来被我们替换成了GameView实例。
R.layout.main就是一个整数。
它被定义在文件R.java中,我们前面讲过R.java是由插件维护的资源定义文件。
说到这里大家应该猜到了吧。
让我们打开R.java文件
publicfinalclassR{
publicstaticfinalclassattr{
}
publicstaticfinalclassdrawable{
publicstaticfinalintbattlecity=0x7f020000;
publicstaticfinalinticon=0x7f020001;
}
publicstaticfinalclasslayout{
publicstaticfinalintmain=0x7f030000;
}
publicstaticfinalclassstring{
publicstaticfinalintapp_name=0x7f040001;
publicstaticfinalinthello=0x7f040000;
}
}
果然,位图文件battlecity.png在这里面也被分配了一个id:
R.drawable.battlecity,没错,就是它了,这就是我们要找的id。
至此为止,我们终于可以使用drawBitmap了。
对于一次创建,多次使用的资源,我们把他放到构造函数里面。
增加了图形显示的GameView如下:
publicclassGameViewextendsView{
Bitmapbmp;
publicGameView(Contextcontext){
super(context);
//TODOAuto-generatedconstructorstub
Resourcesres=context.getResources();
bmp=BitmapFactory.decodeResource(res,R.drawable.battlecity);
}
@Override
protectedvoidonDraw(Canvascanvas){
//TODOAuto-generatedmethodstub
super.onDraw(canvas);
canvas.drawText("坦克大战",0,50,newPaint());
canvas.drawBitmap(bmp,0,100,newPaint());
}
}
运行效果
第四章
响应用户事件
上一章介绍了如何显示文字和图片,一般来说,下一步就该讲到动画了。
可是我们前面说了,使用View不是最终的选择,要实现动画还需要很多复杂的代码。
相对来说,学习如何响应用户事件要简单些。
本章前半部分讲解按键事件的响应,但是这也不是最终方案,因为实际上的手机可能没有硬键盘,需要使用虚拟键盘,所以后半部分我们会讲解虚拟键盘的设计和实现。
同绘图一样,View也是通过回调函数来响应用户事件的。
键盘事件的回调函数有多个,以对应不同的事件,我们暂时只用到onKeyDown,对应按键被按下的事件,其他函数以后用到再介绍。
让我们重载onKeyDown(重载一个函数的方法前面章节有介绍):
@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent){
//TODOAuto-generatedmethodstub
returnsuper.onKeyDown(keyCode,event);
}
onKeyDown有两个参数:
keyCode和event,通过keyCode能判断是哪个键被按下,event比较复杂,包含了这次按键更多的信息,我们暂时先不考虑它。
现在我们要通过按键控制主角向四个方向移动。
所谓移动,就是将主角的图像在不同的位置显示出来,也就是改变函数drawBitmap中的第二、第三个参数。
比如用户按下右方向键,我们就把横坐标增加,这样下次显示出来的时候,主角就会往右一点。
为了节约时间,我们就把刚刚显示的图片BattleCity作为主角好了。
首先定义两个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 游戏 编程 从零开始
