从零开始Android游戏编程(第二版) 第三章 显示文字和图片

第三章 显示文字和图片

难度:容易

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

现在我们就从基本程序开始,一步一步实现它。

首先,让我们看一下刚刚生成的文件目录

clip_image002

在源文件目录下,只有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

clip_image004

我们将这个View类命名为GameView,并且由android.view.View继承

clip_image006

点击Finish,一个View类就创建好了。这里是第一次创建类,以后就不会有图片演示了,请大家记住的这个方法。GameView创建好了,但是代码还有一些错误,这里介绍一下eclipse的使用技巧,将鼠标悬停在有错误的位置,或者将光标停在有错误的行,然后按Ctrl+1键,就会出现修改建议,大部分时候,使用修改建议都可以改正我们的错误,如图

clip_image008

可以看出来,刚刚的错误是因为没有创建构造函数,选择修改建议的第二项,增加一个构造函数

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));

}

现在让我们运行模拟器,看看程序变成什么样子了(启动模拟器的方法见第二章)。

clip_image010

不要意外,屏幕上就是一片空白,因为我们创建了一个View,但是没有让它显示任何内容。下面我们就会在View上显示一段文字和一张图片。

让View显示内容也很简单,只需要重载View的onDraw函数,把相应的语句写入onDraw中即可。打开GameView.java,点击菜单 Source -> Override/Implement Method…

clip_image012

选中onDraw点击OK

clip_image014

下面这段代码就会被加入到程序当中,所有与显示有关的代码都会在这里面完成

@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());

}

clip_image016

坦克大战四个字已经出现在了屏幕上。让我们来详细看一下这条语句:

canvas.drawText("坦克大战", 50, 50, new Paint());

第一个参数是要显示的文字,第二、第三个参数是文字在屏幕上的坐标,说到坐标得多讲两句。在2D编程中,屏幕坐标的原点是屏幕的左上角,横向向右增大,纵向向下增大,如上图所示。最后一个参数是Paint,通常翻译成画笔,它决定了文字或图形的颜色,字体,线条粗细等等,后面用到相应属性的时候会详细介绍。那么这条语句就是在屏幕上(50,50)的位置用缺省的画笔写出“坦克大战”四个字。另外如果eclipse提示代码错误,不要忘了用Ctrl+1。

有了文字,下面就是图像了。显示图像比显示文字略微复杂一些,首先我们要准备一张位图,图片必须是png格式的,文件名只能是小写字母,数字和下划线。

clip_image017

battlecity.png

然后将这张图片copy到工程的res/drawable目录下。可以直接在eclipse的目录树中粘贴。

clip_image019

显示位图的函数是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());

}

}

运行效果

clip_image021

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值