第三章 显示文字和图片

wongainia 贡献于2012-10-09

作者 gh  创建于2011-06-13 08:40:00   修改者gh  修改于2011-06-13 08:40:00字数4718

文档摘要:第三章显示文字和图片从本章开始,读者就要编写代码了。按照作者的原则——少一些理论,多一些实践,代码中可能会有跳跃的地方。但是请大家不要着急,随着学习的深入,你很快就会了解其中的奥秘。不过在开始之前,我们还是要先来理顺一下思路,看看完成一个坦克大战游戏需要哪些工作:首先,我们需要一个基本的程序,这个程序能够在Android上运行;这个程序要能够显示图形包括地图,主角和NPC等等;程序能够接受用户的输入,控制主角移动;程序要能够控制NPC和子弹的移动;程序还能对各种事件做出判断,比如击中敌人,获得物品,胜利或者失败。现在我们就从基本程序开始,一步一步实现它。
关键词:

第三章 显示文字和图片 从 本章开始,读者就要编写代码了。按照作者的原则——少一些理论,多一些实践,代码中可能会有跳跃的地方。但是请大家不要着急,随着学习的深入,你很快就会 了解其中的奥秘。不过在开始之前,我们还是要先来理顺一下思路,看看完成一个坦克大战游戏需要哪些工作:首先,我们需要一个基本的程序,这个程序能够在 Android上运行;这个程序要能够显示图形包括地图,主角和NPC等等;程序能够接受用户的输入,控制主角移动;程序要能够控制NPC和子弹的移动; 程序还能对各种事件做出判断,比如击中敌人,获得物品,胜利或者失败。 现在我们就从基本程序开始,一步一步实现它。 首先,让我们看一下刚刚生成的文件目录 在源文件目录下,只有Main.java和R.java两个文件,刚刚被我们命名成Main.java的文件就是程序的入口文件。而R.java是由插件来维护的资源定义文件,我们先不管它。 Main.java内容如下: package org.yexing.android.games.tank; import android.app.Activity; import android.os.Bundle; public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } 很 幸运,Main.java的代码非常之少,而且还有一段注释,以致我们很容易知道函数onCreate的作用,需要解释的只是 setContentView()。先不要管注释中提到的Activity和setContentView的参数R.layout.main,我们使用 setContentView的另一种形式:setContentView(View view)。setContentView的作用是设定当前使用的视图即View(依此理解,可以有很多个View,需要用哪个就可以把他作为 setContentView的参数显示出来)。View是一个非常重要的组件,它可以用来显示文字,图片,也可以接收客户的操作,比如触摸屏,键盘等 等,而我们的游戏中正是需要绘图和交互,看来View很符合我们的需要(但是请注意,使用View并不是我们的最终方案,原因会在后面说明。此处介绍 View是为了讲解基础的图形和用户控制)。 下面我们就要订制一个属于自己的View,可以通过继承自系统提供的View,并重载相关的函数来实现。创建类的方法如下: 右击包名 New -> Class 我们将这个View类命名为GameView,并且由android.view.View继承 点 击Finish,一个View类就创建好了。这里是第一次创建类,以后就不会有图片演示了,请大家记住的这个方法。GameView创建好了,但是代码还 有一些错误,这里介绍一下eclipse的使用技巧,将鼠标悬停在有错误的位置,或者将光标停在有错误的行,然后按Ctrl+1键,就会出现修改建议,大 部分时候,使用修改建议都可以改正我们的错误,如图 可以看出来,刚刚的错误是因为没有创建构造函数,选择修改建议的第二项,增加一个构造函数 public GameView(Context context) { super(context); // TODO Auto-generated constructor stub } 我们的View就创建好了。 回到Main.java,刚刚说了,只要将View作为setContentView的参数,这个View就可以被显示出来: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new GameView(this)); } 现在让我们运行模拟器,看看程序变成什么样子了(启动模拟器的方法见第二章)。 不要意外,屏幕上就是一片空白,因为我们创建了一个View,但是没有让它显示任何内容。下面我们就会在View上显示一段文字和一张图片。 让View显示内容也很简单,只需要重载View的onDraw函数,把相应的语句写入onDraw中即可。打开GameView.java,点击菜单 Source -> Override/Implement Method… 选中onDraw点击OK 下面这段代码就会被加入到程序当中,所有与显示有关的代码都会在这里面完成 @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); } 这 里我们遇到了又一个非常重要的类Canvas,Canvas一般翻译成画布,所有的绘图操作都是通过Canvas中的函数来完成的,比如显示文字的函数 Canvas.drawText(),显示位图的函数Canvas.drawBitmap(),以及各种绘制图形的函数如 Canvas.drawRect(),Canvas.drawArc()等等。下面让我们显示一段文字在屏幕上: protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); canvas.drawText("坦克大战", 50, 50, new Paint()); } 坦克大战四个字已经出现在了屏幕上。让我们来详细看一下这条语句: canvas.drawText("坦克大战", 50, 50, new Paint()); 第 一个参数是要显示的文字,第二、第三个参数是文字在屏幕上的坐标,说到坐标得多讲两句。在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通常翻译做上下文,这个名称似乎有点晦涩,他究竟是什么呢?让我们回头看看写好的程序 public GameView(Context context) { super(context); // TODO Auto-generated constructor stub } 这时候我们有一个context实例,继续朔源而上,在Main.java中 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new GameView(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文件 public final class R { public static final class attr { } public static final class drawable { public static final int battlecity=0x7f020000; public static final int icon=0x7f020001; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; } } 果然,位图文件battlecity.png在这里面也被分配了一个id:R.drawable.battlecity,没错,就是它了,这就是我们要找的id。至此为止,我们终于可以使用drawBitmap了。 对于一次创建,多次使用的资源,我们把他放到构造函数里面。增加了图形显示的GameView如下: public class GameView extends View { Bitmap bmp; public GameView(Context context) { super(context); // TODO Auto-generated constructor stub Resources res = context.getResources(); bmp = BitmapFactory.decodeResource(res, R.drawable.battlecity); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); canvas.drawText("坦克大战", 0, 50, new Paint()); canvas.drawBitmap(bmp, 0, 100, new Paint()); } } 运行效果

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 3 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档