GameMain.java
package edu.hhxy.mysnakegame; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import edu.hhxy.view.SnakeView; public class GameMain extends Activity { private SnakeView mSnakeView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game_main); mSnakeView = (SnakeView) findViewById(R.id.snake); mSnakeView.setTextView((TextView) findViewById(R.id.textView)); mSnakeView.setMode(SnakeView.READY); } }
BasicView.java
package edu.hhxy.view; /* * 基类,继承自view,加载图片,画出围墙 */ import android.annotation.SuppressLint; import android.content.Context; 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; @SuppressLint("DrawAllocation") public class BasicView extends View { public int picSize = 0; protected static int rows = 0;//行 protected static int columns = 0;//列 protected static int oxOff = 0;//起始位置橫座標 protected static int oyOff = 0;//起始位置縱座標 private Bitmap bitMap[] = null; private int[][] maps = null; private final Paint mPaint = new Paint();//画笔,onDraw时调用,不用再new Paint()了 public BasicView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); picSize = 15; } public BasicView(Context context, AttributeSet attrs) { super(context, attrs); picSize = 15; } /* * * @see android.view.View#onSizeChanged(int, int, int, int) * 當view的大小发生变化是调用该方法 得到行rows和列columns 和边距(oxOff,oyOff) Math.floor()向下取整 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { columns = (int) Math.floor(w / picSize); rows = (int) Math.floor(h / picSize); oxOff = (w - columns * picSize) / 2; oyOff = (h - rows * picSize) / 2; maps = new int[rows][columns]; clearMaps(); } /* * 设置Bitmp的大小 */ public void resetBitmapArray(int count) { bitMap = new Bitmap[count]; } /* * 加载图片 */ public void loadPicture(int index, Drawable drawable) { Bitmap bt = Bitmap.createBitmap(picSize, picSize, Bitmap.Config.ARGB_8888); Canvas cs = new Canvas(bt); drawable.setBounds(0, 0, picSize, picSize); // 把图片画到画布上 drawable.draw(cs); bitMap[index] = bt; } /* * 把图置为0 */ public void clearMaps() { for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { setMaps(0, i, j); } } } /* * 把图中的某一点置titleindex */ protected void setMaps(int titleindex, int i, int j) { maps[i][j] = titleindex; } /* * 再view上画图,根据maps[i][j]的只不同画出不同的图 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if (maps[i][j] > 0) { canvas.drawBitmap(bitMap[maps[i][j]], oxOff + j * picSize, oyOff + i * picSize, mPaint); } } } } }
SnakeView.java
package edu.hhxy.view; import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.TextView; import edu.hhxy.mysnakegame.R; public class SnakeView extends BasicView { private int mMode = READY; public static final int PAUSE = 0; public static final int READY = 1; public static final int RUNNING = 2; public static final int LOSE = 3; public static final int RED_STAR = 1; public static final int YELLOW_STAR = 2; public static final int GREEN_STAR = 3; public static final int BITMAP_ARRAY_SIZE = 4; private TextView mStatusText; //////////////////// private long period=1000L; private long lastMove=0L; @SuppressLint("HandlerLeak") class Refresh extends Handler{//开启子线程,定时对界面刷新 @Override public void handleMessage(Message msg) { SnakeView.this.update(); SnakeView.this.invalidate(); super.handleMessage(msg); } public void delayed(long times){ this.removeMessages(0);//把栈顶消息清空 sendMessageDelayed(obtainMessage(0),times ); } } private Refresh gameFresh =new Refresh(); //////////////////// public void update() { if (mMode == RUNNING) { long now=System.currentTimeMillis(); if(now-lastMove>period)//如果当前时间离最近一次刷新的时间大于period,就刷新,同时更新lastMove { clearMaps(); updateWalls(); gameFresh.delayed(period); lastMove=now; } } } public SnakeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initGame(); } public SnakeView(Context context, AttributeSet attrs) { super(context, attrs); initGame(); } /* * 初始化SnakeView加载图片 */ private void initGame() { setFocusable(true); /* 调用父类方法设置bitMap大小 */ resetBitmapArray(BITMAP_ARRAY_SIZE); /* 调用父类加載picture資源 */ loadPicture(GREEN_STAR, this.getResources().getDrawable(R.drawable.greenstar)); loadPicture(YELLOW_STAR, this.getResources().getDrawable(R.drawable.yellowstar)); loadPicture(RED_STAR, this.getResources().getDrawable(R.drawable.redstar)); } public void setTextView(TextView findViewById) { mStatusText = findViewById; } public void setMode(int newMode) { int oldMode = mMode; mMode = newMode; if (newMode == RUNNING & oldMode != RUNNING) { mStatusText.setVisibility(View.INVISIBLE); update(); return; } CharSequence str = ""; if (newMode == READY) { str = "Snake Press Up to Play"; } if (newMode == LOSE) { str = "Game Over "; } mStatusText.setText(str); mStatusText.setVisibility(View.VISIBLE); } @Override public boolean onKeyDown(int keyCode, KeyEvent msg) { //判断是否隐藏主界面,显示当前界面 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { if (mMode == READY | mMode == LOSE) { setMode(RUNNING); update(); return (true); } return (true); } return super.onKeyDown(keyCode, msg); } /* * 初始墙 */ private void updateWalls() { for (int x = 0; x < columns; x++) { setMaps(GREEN_STAR, 0, x); setMaps(GREEN_STAR, rows - 1, x); } for (int y = 1; y < rows - 1; y++) { setMaps(GREEN_STAR, y, 0); setMaps(GREEN_STAR, y, columns - 1); } Log.d("freshed", "freshed wall"); } }
game_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <edu.hhxy.view.SnakeView android:id="@+id/snake" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center_horizontal" android:text="@string/snake_layout_text_text" android:textColor="#ff8888ff" android:textSize="24sp" android:visibility="visible" /> </RelativeLayout> </LinearLayout>