Android游戏开发入门: 贪吃蛇 源代码分析

作为一个刚入门或者还没入门的新手,着实花了我一些力气来理解这段代码。

对于各种不懂的地方,慢慢查询资料,对于新的方法,通过修改代码尝试效果。到现在终于能算个一知半解。

在代码中,对于自己有所收获的地方,我都做了相应的注释。

回过头来,觉得从这段代码中,能学到不少东西~~

包括Android应用的基本架构,他的面向对象的思想,以及代码的简洁明了。

于是,我想到,何不将这些东西分享出来,如果碰巧对感兴趣的朋友们有搜帮助,那就更好了~

好了,闲话不说~代码和注释如下(处于对源码的敬意,原本的英文注释部分都没有删去~大家可以配合理解):

PS:最近我正在写自己的“贪吃蛇”,说事贪吃蛇,其实完全颠覆了这个经典版本的设计理念和操作方式。具体细节先卖一个关子,作品准备参加这次第二届大学生Android应用开发大赛。

Snake工程中,总共有三个文件: *TileView是基于Android的View类实现的方块图类,用来支撑上层类的调用,绘制方块图的显示界面。通过这些代码,能打之了解如何 扩展View,实现特色的界面效果。 *SnakeView调用了TileView,实现了游戏逻辑 和 具体的显示。 *Snake为主Activity类。

建议大家按照上面的顺序看三个文件,可能逻辑上更舒服一点~~

下面贴上代码和注释。

PS: 调试版本为Android2.2。 其他版本应该也没问题吧,不过得用虚拟机。因为它是上下左右按键操作,现在大多数android机是没有方向键的吧。


  1: package com.example.Android.snake;  

  2: import Android.content.Context;  

  3: import Android.content.res.TypedArray;  

  4: import Android.graphics.Bitmap;  

  5: import Android.graphics.Canvas;  

  6: import Android.graphics.Paint;  

  7: import Android.graphics.drawable.Drawable;  

  8: import Android.util.AttributeSet;  

  9: import Android.view.View;  

 10: /**

 11:  * TileView: a View-variant designed for handling arrays of "icons" or other

 12:  * drawables.

 13:  * 

 14:  */

 15: public class TileView extends View {  

 16: /**

 17:      * Parameters controlling the size of the tiles and their range within view.

 18:      * Width/Height are in pixels, and Drawables will be scaled to fit to these

 19:      * dimensions. X/Y Tile Counts are the number of tiles that will be drawn.

 20:      */

 21: protected static int mTileSize; //每个tile的边长的像素数量 

 22: protected static int mXTileCount; //屏幕内能容纳的 X方向上方块的总数量 

 23: protected static int mYTileCount;//屏幕内能容纳的 Y方向上方块的总数量 

 24: private static int mXOffset; //原点坐标,按pixel计。 

 25: private static int mYOffset;  

 26: /**

 27:      * A hash that maps integer handles specified by the subclasser to the

 28:      * drawable that will be used for that reference

 29:      * 存储着不同种类的bitmap图。通过resetTiles,loadTile,将游戏中的方块加载到这个数组。

 30:      * 可以理解为 砖块字典

 31:      */

 32: private Bitmap[] mTileArray;      

 33: /**

 34:      * A two-dimensional array of integers in which the number represents the

 35:      * index of the tile that should be drawn at that locations

 36:      * 存储整个界面内每个tile位置应该绘制的tile。

 37:      * 可看作是我们直接操作的画布。

 38:      * 通过setTile、clearTile 进行图形显示的修改操作。 

 39:      * 

 40:      */

 41: private int[][] mTileGrid;   

 42: //画笔,canvas的图形绘制,需要画笔Paint实现。 

 43: private final Paint mPaint = new Paint();  

 44: public TileView(Context context, AttributeSet attrs, int defStyle) {  

 45: super(context, attrs, defStyle);  

 46: //使用TypedArray,获取在attrs.xml中为TileView定义的新属性tileSize 。参考: http://weizhulin.blog.51cto.com/1556324/311453 

 47:         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);  

 48:         mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);  

 49:         a.recycle();  

 50:     }  

 51: public TileView(Context context, AttributeSet attrs) {  

 52: super(context, attrs);  

 53:         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);  

 54:         mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);  

 55:         a.recycle();  

 56:     }  

 57: /**

 58:      * Rests the internal array of Bitmaps used for drawing tiles, and

 59:      * sets the maximum index of tiles to be inserted

 60:      * 重置清零mTileArray,在游戏初始的时候使用。

 61:      * 即清空砖块字典

 62:      * @param tilecount

 63:      */

 64: public void resetTiles(int tilecount) {  

 65:         mTileArray = new Bitmap[tilecount];  

 66:     }  

 67: /*

 68:      * 当改变屏幕大小尺寸时,同时修改tile的相关计数指标。

 69:      */

 70: @Override

 71: protected void onSizeChanged(int w, int h, int oldw, int oldh) {  

 72:         mXTileCount = (int) Math.floor(w / mTileSize);  

 73:         mYTileCount = (int) Math.floor(h / mTileSize);  

 74: //mXOffset mYOffset是绘图的起点坐标。 

 75:         mXOffset = ((w - (mTileSize * mXTileCount)) / 2);  

 76:         mYOffset = ((h - (mTileSize * mYTileCount)) / 2);  

 77:         mTileGrid = new int[mXTileCount][mYTileCount];  

 78:         clearTiles();  

 79:     }  

 80: /**

 81:      * Function to set the specified Drawable as the tile for a particular

 82:      * integer key.

 83:      * 加载具体的砖块图片 到 砖块字典。

 84:      * 即将对应的砖块的图片 对应的加载到 mTileArray数组中

 85:      * @param key

 86:      * @param tile

 87:      */

 88: public void loadTile(int key, Drawable tile) {  

 89: //这里做了一个 Drawable 到 bitmap 的转换。由于外部程序使用的时候是直接读取资源文件中的图片, 

 90: //是drawable格式,而我们的数组是bitmap格式,方便最终的绘制。所以,需要进行一次到 bitmap的转换。 

 91:         Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);  

 92:         Canvas canvas = new Canvas(bitmap);  

 93:         tile.setBounds(0, 0, mTileSize, mTileSize);  

 94:         tile.draw(canvas);  

 95:         mTileArray[key] = bitmap;  

 96:     }  

 97: /**

 98:      * Used to indicate that a particular tile (set with loadTile and referenced

 99:      * by an integer) should be drawn at the given x/y coordinates during the

100:      * next invalidate/draw cycle.

101:      * 在相应的坐标位置绘制相应的砖块

102:      * 记得哦,mTileGrid其实就是我们直接操作的画布。

103:      * @param tileindex

104:      * @param x

105:      * @param y

106:      */

107: public void setTile(int tileindex, int x, int y) {  

108:         mTileGrid[x][y] = tileindex;  

109:     }  

110: /**

111:      * Resets all tiles to 0 (empty)

112:      * 清空图形显示。

113:      * 用以更新画面。

114:      * 调用了绘图的setTile()。

115:      */

116: public void clearTiles() {  

117: for (int x = 0; x < mXTileCount; x++) {  

118: for (int y = 0; y < mYTileCount; y++) {  

119:                 setTile(0, x, y);  

120:             }  

121:         }  

122:     }  

123: /*

124:  * 将我们直接操作的画布绘制到手机界面上!

125:  * @see Android.view.View#onDraw(android.graphics.Canvas)

126:  */

127: @Override

128: public void onDraw(Canvas canvas) {  

129: super.onDraw(canvas);  

130: for (int x = 0; x < mXTileCount; x += 1) {  

131: for (int y = 0; y < mYTileCount; y += 1) {  

132: if (mTileGrid[x][y] > 0) {  

133:                     canvas.drawBitmap(mTileArray[mTileGrid[x][y]],   

134:                             mXOffset + x * mTileSize,  

135:                             mYOffset + y * mTileSize,  

136:                             mPaint);  

137:                 }  

138:             }  

139:         }  

140:     }  

141: }

142: 

SnakeView.java


: package com.example.Android.snake;  

  2: import Android.app.Activity;  

  3: import Android.os.Bundle;  

  4: import Android.view.Window;  

  5: import Android.widget.TextView;  

  6: /**

  7:  * Snake: a simple game that everyone can enjoy.

  8:  * This is an implementation of the classic Game "Snake", in which you control a

  9:  * serpent roaming around the garden looking for apples. Be careful, though,

 10:  * because when you catch one, not only will you become longer, but you'll move

 11:  * faster. Running into yourself or the walls will end the game.

 12:  */

 13: public class Snake extends Activity {  

 14: private SnakeView mSnakeView;  

 15: private static String ICICLE_KEY = "snake-view";  

 16: /**

 17:      * Called when Activity is first created. Turns off the title bar, sets up

 18:      * the content views, and fires up the SnakeView.

 19:      * 

 20:      */

 21: @Override

 22: public void onCreate(Bundle savedInstanceState) {  

 23: super.onCreate(savedInstanceState);  

 24:         setContentView(R.layout.snake_layout);  

 25:         mSnakeView = (SnakeView) findViewById(R.id.snake);  

 26:         mSnakeView.setTextView((TextView) findViewById(R.id.text));  

 27: if (savedInstanceState == null) {  

 28: // We were just launched -- set up a new game 

 29:             mSnakeView.setMode(SnakeView.READY);  

 30:         } else {  

 31: // We are being restored 

 32:             Bundle map = savedInstanceState.getBundle(ICICLE_KEY);  

 33: if (map != null) {  

 34:                 mSnakeView.restoreState(map);  

 35:             } else {  

 36:                 mSnakeView.setMode(SnakeView.PAUSE);  

 37:             }  

 38:         }  

 39:     }  

 40: @Override

 41: protected void onPause() {  

 42: super.onPause();  

 43: // Pause the game along with the activity 

 44:         mSnakeView.setMode(SnakeView.PAUSE);  

 45:     }  

 46: @Override

 47: public void onSaveInstanceState(Bundle outState) {  

 48: //Store the game state 

 49:         outState.putBundle(ICICLE_KEY, mSnakeView.saveState());  

 50:     }  

 51: }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值