logo资料库

编写推箱子游戏程序(第四步).docx

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
编写推箱子游戏程序(第四步)
——绘制游戏区域
本文目标
实现步骤
第一步:绘制背景色
第二步:绘制游戏区网格线
第三步:绘制搬运工
编写推箱子游戏程序(第四步)1 ——绘制游戏区域 叶常春(iamdouble@163.com) 本文目标 本文描述如何绘制游戏区和搬运工。如图 1,在玩家选择关卡后,将进入游戏界面(图 2)。现阶段,游戏界面只有标示游戏区域的网格线。进一步地,我们将在左上角单元格绘制 一个搬运工(见图 3)。将来,在游戏界面绘制推箱子游戏的局面(见图 4)。 图 1 玩家选关卡后进入游戏界面 图 2 游戏界面第 1 版 通过本文,你将学习到: 1. 用 Java 代码(而不是 xml 格式的布局文件)创建活动的界面。 2. 如何绘制 2D 图形(如直线、矩形)。 3. 如何绘制图片(如 jpg 图片或 png 图片)。 1本文遵循 Apache License 2.0 协议。你可以修改和再发布本文档,但须保留原著者和采用 Apache License 2.0 协议。
图 3 游戏界面第 1 版 (左上角绘制了搬运工) 图 4 将来的游戏界面 实现步骤 分三步: 1. 绘制背景色。 2. 绘制游戏区域的网格线。 3. 绘制搬运工。 以上三步采用 Java 代码,而不是 xml 格式的布局文件,来完成。图 4 所示的游戏界面 也是采用 Java 代码绘制 2D 图形和图像达成的。 为什么采用 Java 代码,而不是 xml 格式的布局文件呢?这是因为,在我看来,采用 xml 格式的布局文件是可以实现同样的功能的,但采用 Java 代码会更便利一些。如果你有兴趣 采用 xml 格式的布局文件来实现同样的功能,我建议你试一试,还建议你考虑使用 GridView 控件。 参阅:  Android 自定义 View 的实现 (http://blog.chinaunix.net/uid-26885609-id-3479671.html) 第一步:绘制背景色 游戏界面是采用 Java 代码绘制 2D 图形达成的。这句话是什么意思呢?看表 1 所示的代 码,第 10 行(标有删除线)是加载一个布局文件 activity_game.xml,用作 GameActivity 这
个活动的界面。我们不使用这种方法。我们用的是,如第 11,12 行所示,先创建一个视图对 象,即 GameView 实例,而后把它用作 GameActivity 活动的界面。GameView 是用 Java 代码 实现的。 表 1 游戏界面是 GameActivity 活动的内容视图 com/yescorp/moveboxgame/GameActivity.java public class GameActivity extends AppCompatActivity { public static final String KEY_SELECTED_LEVEL= "Selected_Level"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int selected_level = getIntent().getIntExtra(KEY_SELECTED_LEVEL, 1); setContentView(R.layout.activity_game); GameView gameView = new GameView(this); setContentView(gameView); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 下面我们要定义 GameView 这个类。它的代码如表 2 所示。 表 2 实现 GameActivity 活动的界面的 GameView 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 com/yescorp/moveboxgame/GameView.java public class GameView extends View{ private float mCellWidth; public static final int CELL_NUM_PER_LINE= 12; public GameView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //背景色 Paint background = new Paint(); background.setColor(getResources().getColor(R.color.background)); canvas.drawRect(0, 0, getWidth(), getHeight(), background); } } 对于表 2 的代码,重点要说 3 个地方。
 第 1 行,定义一个视图类,必须继承自 View 类(或它的子类)。View 类是 Android SDK 预定义的,所有视图类(如 Button, TextView, Layout)的父类。GameView 继承 自 View 类,表 1 中第 12 行才能正确运行,否则发生错误。  第 5~8 行是 GameView 类的构造函数。对照表 1 的第 11 行,可知参数 context 实质 上是指 GameActivity 实例。  第 10~16 行定义了 onDraw 方法,它的作用是绘制画面。这个方法需要着重研究下。  onDraw 方法是 View 类内部定义的一个回调函数。它会在需要刷新活动的界面 的时候,由 Android 系统自动调用。那么,需要刷新活动的界面的时候是指哪 些时候呢?举例来说,一是第一次显示它的时候。二是挡住它的活动退出,它 从隐藏状态回到前台的时候(例如,在图 1 中选择关卡后,将进入游戏界面, 按手机上的回退键,返回选择关卡界面,这时将执行选择关卡界面的 onDraw 方法)。三是部分遮挡它的对话框退出的时候。四是程序中执行 invalidate 操作 要求刷新活动的视图的时候(下面会进一步解释)。  onDraw()方法的唯一参数是 canvas ,代表的是 GameView 实例占据的区域, 也就是你能够用 Java 代码“画画”的区域。在这里,GameView 实例占据了整 个屏幕,意味着画布覆盖整个屏幕。  第 11 行,是调用父类的 onDraw()方法。照抄就行。  第 13 行,是定义一个画刷,background 是画刷的名字。画线、画矩形和画圆 等等都会用到画刷。  第 14 行,为 background 画刷设置颜色。 getResources().getColor( R.color.background)是获取 res/values/colors.xml 文件内 的颜色值常量 background 的颜色值。这是一种浅蓝色,它在 colors.xml 中定义 为: #3500ffff getResources()是获取资源管理器,它的 getColor 方法用来获取 colors.xml 中定 义的颜色值。  第 15 行,是绘制一个覆盖整块画布的矩形。Canvas 类的 drawRect()方法是在 画布上绘制矩形。矩形的大小由前四个参数决定。前两个参数对应矩形左上角 的(x, y)坐标,后两个参数对应矩形右下角的(x, y)坐标。这里,(0, 0)代表的是画 布的左上角。getWidth()是获取 GameView 实例的宽度,也就是画布的宽度。 getHeight()是获取高度,也就是画布的高度。(getWidth(), getHeight())代表的是 画布的右下角。由于画布覆盖整个屏幕,因此整个屏幕都变成浅蓝色。 在Java 代码中获取资源的方法:  获取res/values/colors.xml 内名字为xxx 的颜色值: getResources().getColor(R.color.xxx);  获取res/values/strings.xml 内名字为yyy 的字符串: getResources().getString(R.string.yyy); 注意: 所有的绘图操作,无论是绘制图形(如第 15 行绘制了一个矩形)、还是绘制图像,都 要放在这个方法(或它调用的子方法)内。不能放在这个方法(或它调用的子方法) 外!
参考资料  Android Canvas 绘图详解(图文) http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html 第二步:绘制游戏区网格线 这一步想要给游戏界面的游戏区绘制网格线,效果如图 2 所示。 同学们先复习第一步提及的两个知识点。一是绘制图形和图像都要在 onDraw 方法(或 它调用的子方法)内进行。二是 onDraw 方法什么时候会执行。请同学们务必理解这两点。 这对于绘制 2D 图形(编写推箱子游戏程序用到它)是十分关键的。 如何绘制网格线呢?答案是,在 onDraw 方法内绘制直线。这些直线用作分割线。代码 如表 3 所示 表 3 GameView.java 中的 onDraw 方法绘制了背景色和网格线 com/yescorp/moveboxgame/GameView.java public class GameView extends View{ private float mCellWidth; public static final int CELL_NUM_PER_LINE= 12; private Bitmap ManBitmap = null; public GameView(Context context) { super(context); ManBitmap= BitmapFactory.decodeResource(res, R.drawable.eggman_48x48); } //当GameView实例的尺寸发生变化,就会调用onSizeChanged @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mCellWidth = w / CELL_NUM_PER_LINE; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //背景色 Paint background = new Paint(); background.setColor(getResources().getColor(R.color.background)); canvas.drawRect(0, 0, getWidth(), getHeight(), background); //绘制游戏区域 Paint linePaint = new Paint(); linePaint.setColor(Color.BLACK); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
for (int r = 0; r <= CELL_NUM_PER_LINE; r++) canvas.drawLine(0, r * mCellWidth, getWidth(), r * mCellWidth, linePaint); for (int c = 0; c <= CELL_NUM_PER_LINE; c++) canvas.drawLine(c * mCellWidth, 0, c * mCellWidth, CELL_NUM_PER_LINE* mCellWidth, linePaint); 28 29 30 31 32 33 } } 第 26~31 行的功能是绘制游戏区域网格线。  第 26 行是创建画刷。  第 27 行是设置画刷的颜色为黑色。Color.BLACK 是一个常量,是 Android SDK 预定 义的颜色。还有 Color.BLUE, Color.WHITE 等常量都是 Android SDK 预定义的颜色。  第 28, 29 行是一条 for 语句。CELL_NUM_PER_LINE 是一个第 3 行定义的常量,值为 12,代表的是 12X12 的游戏区域。for 语句的作用解释如下。 r=0 时,调用 canvas.drawLine(0, 0, getWidth(), 0, linePaint); 作用是绘制直线。直线的起点是(0, 0),终点是(getWidth(), 0)。参阅“知识点:手 机屏幕的坐标系”可知,这是手机屏幕顶部的一条直线。 r=1 时,调用 canvas.drawLine(0, mCellWidth, getWidth(), mCellWidth, linePaint); 绘制的是(0, mCellWidth)到(getWidth(), mCellWidth())的直线。mCellWidth 是游戏区 域单元格的宽度(即高度),下面将说明之。 r=2, 3, 4, …,依次类推。  第 30, 31 行类似于第 28,29 行,作用是绘制垂直的直线。  mCellWidth 是一个成员变量,用来存储游戏区域单元格的宽度(即有多少个像素)。 它在 onSizeChanged 方法内被设值。onSizeChanged 方法在 GameView 视图大小 发生变化的时候会执行。如果手机屏幕从竖屏切换为横屏,就可能改变 GameView 视图的大小。 知识点:手机屏幕的坐标系 手机屏幕的左上角是坐标系统原点,如图 2-1 所示。水平向右,x 坐标增大。垂直向下, y 坐标增大。
图 2-1 手机屏幕坐标系统 图 2-2 坐标示例 在图 2-2 中,最外围的矩形代表手机屏幕。对第二大的矩形区域,左上角的坐标是(60, 115)。对最小的矩形区域,左上角相对于第二大矩形区域的坐标是(55, 55),但它的左上角在 手机屏幕上的坐标是(115, 170)。 作业:读懂表 3 中绘制游戏区域网格线的第 26~31 行代码。 第三步:绘制搬运工 这一步绘制搬运工。效果如图 3 所示,左上角网格显示了搬运工。 要绘制图片,需要做一项准备工作:把图片文件放到 res/drawable 文件夹下。绘制搬运 工的准备工作是: 1. 准备一幅搬运工图片。图片的尺寸建议是 48x48,也可以是 72x72,或更大。对图片的 唯一要求是高度和宽度要相等。你可以选择自己喜爱的搬运工图像,比如一个动物图片 或精灵图片。这里假设把搬运工图片命名成 eggman_48x48.png(你可以使用别的文件 名)。 2. 接下来把 eggman_48x48.png 复制到推箱子游戏项目的 res/drawable 文件夹下。打开 drawable 文件夹的做法是,在 Android Studio 项目视图下,用鼠标右键点击 drawable 文 件夹(如图 3-1 所示),在弹出的上下文菜单中选择“Show in Explorer”。这将打开 Windows 系统的资源管理器(如图 3-2 所示),所显示的文件夹位置是推箱子游戏项目的 res 文 件夹。双击 drawable 文件夹即打开该文件夹。
图 3-1 在 Android Studio 中打开项目的文件路径 图 3-2 推箱子游戏程序的资源所在的文件夹 做完准备工作后,我们使用 Java 代码来绘制图片。绘制图片是在 onDraw 方法内调用 drawBitmap 方法,如表 4 中第 35 行代码所示。通过查阅 Canvas 类的 drawBitmap 方法的帮 助文档可知,这一方法有好多种,参数彼此不同。我们这里用的是下面这种: public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint) 第一个参数 bitmap 是内存中的图片对象(下面会讲如何得到它);第二个参数 src 是图片中 要被绘制的区域;第三个参数 dst 是画布中绘制图片的区域;第 4 个参数 paint 是画刷对象 (可以设置为 null)。关于 drawBitmap 的更多内容,参阅本节的“知识点:用 drawBitmap 绘制图片”。第 35 行代码中,各个参数的作用说明如下: a) 第一个参数 manBitmap 是内存中的搬运工图片对象。这一变量在表 4 的第 4 行定
分享到:
收藏