贪吃蛇是一款足够经典的游戏。它的经典,在于用户操作的简单,在于技术实现的简介,在于他的经久不衰。
这里的贪吃蛇的android实现,是SDK Samples中的开源例程。可能各位都有看过~界面如下图啦~
作为一个刚入门或者还没入门的新手,着实花了我一些力气来理解这段代码。
对于各种不懂的地方,慢慢查询资料,对于新的方法,通过修改代码尝试效果。到现在终于能算个一知半解。
在代码中,对于自己有所收获的地方,我都做了相应的注释。
回过头来,觉得从这段代码中,能学到不少东西~~
包括android应用的基本架构,他的面向对象的思想,以及代码的简洁明了。
于是,我想到,何不将这些东西分享出来,如果碰巧对感兴趣的朋友们有搜帮助,那就更好了~
好了,闲话不说~代码和注释如下(处于对源码的敬意,原本的英文注释部分都没有删去~大家可以配合理解):
PS:最近我正在写自己的“贪吃蛇”,说事贪吃蛇,其实完全颠覆了这个经典版本的设计理念和操作方式。具体细节先卖一个关子,作品准备参加这次第二届大学生android应用开发大赛。
应该一个月内能完成,到时候也会开源出代码来~欢迎大家讨论指正·~
************************************************************************************************************************************
Snake工程中,总共有三个文件: *TileView是基于Android的View类实现的方块图类,用来支撑上层类的调用,绘制方块图的显示界面。通过这些代码,能打之了解如何 扩展View,实现特色的界面效果。 *SnakeView调用了TileView,实现了游戏逻辑 和 具体的显示。 *Snake为主Activity类。
建议大家按照上面的顺序看三个文件,可能逻辑上更舒服一点~~
下面贴上代码和注释。
PS: 调试版本为android2.2。 其他版本应该也没问题吧,不过得用虚拟机。因为它是上下左右按键操作,现在大多数android机是没有方向键的吧。
TileView.java
package com.example.android.snake;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
/**
* TileView: a View-variant designed for handling arrays of "icons" or other
* drawables.
*
*/
public class TileView extends View {
/**
* Parameters controlling the size of the tiles and their range within view.
* Width/Height are in pixels, and Drawables will be scaled to fit to these
* dimensions. X/Y Tile Counts are the number of tiles that will be drawn.
*/
protected static int mTileSize; //每个tile的边长的像素数量
protected static int mXTileCount; //屏幕内能容纳的 X方向上方块的总数量
protected static int mYTileCount;//屏幕内能容纳的 Y方向上方块的总数量
private static int mXOffset; //原点坐标,按pixel计。
private static int mYOffset;
/**
* A hash that maps integer handles specified by the subclasser to the
* drawable that will be used for that reference
* 存储着不同种类的bitmap图。通过resetTiles,loadTile,将游戏中的方块加载到这个数组。
* 可以理解为 砖块字典
*/
private Bitmap[] mTileArray;
/**
* A two-dimensional array of integers in which the number represents the
* index of the tile that should be drawn at that locations
* 存储整个界面内每个tile位置应该绘制的tile。
* 可看作是我们直接操作的画布。
* 通过setTile、clearTile 进行图形显示的修改操作。
*
*/
private int[][] mTileGrid;
//画笔,canvas的图形绘制,需要画笔Paint实现。
private final Paint mPaint = new Paint();
public TileView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//使用TypedArray,获取在attrs.xml中为TileView定义的新属性tileSize 。参考: http://weizhulin.blog.51cto.com/1556324/311453
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
a.recycle();
}
public TileView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
a.recycle();
}
/**
* Rests the internal array of Bitmaps used for drawing tiles, and
* sets the maximum index of tiles to be inserted
* 重置清零mTileArray,在游戏初始的时候使用。
* 即清空砖块字典
* @param tilecount
*/
public void resetTiles(int tilecount) {
mTileArray = new Bitmap[tilecount];
}
/*
* 当改变屏幕大小尺寸时,同时修改tile的相关计数指标。
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mXTileCount = (int) Math.floor(w / mTileSize);
mYTileCount = (int) Math.floor(h / mTileSize);
//mXOffset mYOffset是绘图的起点坐标。
mXOffset = ((w - (mTileSize * mXTileCount)) / 2);
mYOffset = ((h - (mTileSize * mYTileCount)) / 2);
mTileGrid = new int[mXTileCount][mYTileCount];
clearTiles();
}
/**
* Function to set the specified Drawable as the tile for a particular
* integer key.
* 加载具体的砖块图片 到 砖块字典。
* 即将对应的砖块的图片 对应的加载到 mTileArray数组中
* @param key
* @param tile
*/
public void loadTile(int key, Drawable tile) {
//这里做了一个 Drawable 到 bitmap 的转换。由于外部程序使用的时候是直接读取资源文件中的图片,
//是drawable格式,而我们的数组是bitmap格式,方便最终的绘制。所以,需要进行一次到 bitmap的转换。
Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
tile.setBounds(0, 0, mTileSize, mTileSize);
tile.draw(canvas);
mTileArray[key] = bitmap;
}
/**
* Used to indicate that a particular tile (set with loadTil