📄 snakeview.java
字号:
/* * Copyright (C) 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.snake;import java.util.ArrayList;import java.util.Map;import java.util.Random;import android.content.Context;import android.content.res.Resources;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.os.Bundle;import android.util.Log;import android.view.KeyEvent;import android.view.View;import android.widget.TextView;/** * SnakeView: implementation of a simple game of Snake * * */public class SnakeView extends TileView { private static final String TAG = "SnakeView"; /** * Current mode of application: READY to run, RUNNING, or you have already * lost. static final ints are used instead of an enum for performance * reasons. */ 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; /** * Current direction the snake is headed. */ private int mDirection = NORTH; private int mNextDirection = NORTH; private static final int NORTH = 1; private static final int SOUTH = 2; private static final int EAST = 3; private static final int WEST = 4; /** * Labels for the drawables that will be loaded into the TileView class */ private static final int RED_STAR = 1; private static final int YELLOW_STAR = 2; private static final int GREEN_STAR = 3; /** * mScore: used to track the number of apples captured mMoveDelay: number of * milliseconds between snake movements. This will decrease as apples are * captured. */ private long mScore = 0; private long mMoveDelay = 600; /** * mLastMove: tracks the absolute time when the snake last moved, and is used * to determine if a move should be made based on mMoveDelay. */ private long mLastMove; /** * mStatusText: text shows to the user in some run states */ private TextView mStatusText; /** * mSnakeTrail: a list of Coordinates that make up the snake's body * mAppleList: the secret location of the juicy apples the snake craves. */ private ArrayList<Coordinate> mSnakeTrail = new ArrayList<Coordinate>(); private ArrayList<Coordinate> mAppleList = new ArrayList<Coordinate>(); /** * Everyone needs a little randomness in their life */ private static final Random RNG = new Random(); /** * Create a simple handler that we can use to cause animation to happen. We * set ourselves as a target and we can use the sleep() * function to cause an update/invalidate to occur at a later date. */ private RefreshHandler mRedrawHandler = new RefreshHandler(); class RefreshHandler extends Handler { @Override public void handleMessage(Message msg) { SnakeView.this.update(); SnakeView.this.invalidate(); } public void sleep(long delayMillis) { this.removeMessages(0); sendMessageDelayed(obtainMessage(0), delayMillis); } }; /** * Constructs a SnakeView based on inflation from XML * * @param context * @param attrs */ public SnakeView(Context context, AttributeSet attrs) { super(context, attrs); initSnakeView(); } public SnakeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initSnakeView(); } private void initSnakeView() { setFocusable(true); Resources r = this.getContext().getResources(); resetTiles(4); loadTile(RED_STAR, r.getDrawable(R.drawable.redstar)); loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar)); loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar)); } private void initNewGame() { mSnakeTrail.clear(); mAppleList.clear(); // For now we're just going to load up a short default eastbound snake // that's just turned north mSnakeTrail.add(new Coordinate(7, 7)); mSnakeTrail.add(new Coordinate(6, 7)); mSnakeTrail.add(new Coordinate(5, 7)); mSnakeTrail.add(new Coordinate(4, 7)); mSnakeTrail.add(new Coordinate(3, 7)); mSnakeTrail.add(new Coordinate(2, 7)); mNextDirection = NORTH; // Two apples to start with addRandomApple(); addRandomApple(); mMoveDelay = 600; mScore = 0; } /** * Given a ArrayList of coordinates, we need to flatten them into an array of * ints before we can stuff them into a map for flattening and storage. * * @param cvec : a ArrayList of Coordinate objects * @return : a simple array containing the x/y values of the coordinates * as [x1,y1,x2,y2,x3,y3...] */ private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) { int count = cvec.size(); int[] rawArray = new int[count * 2]; for (int index = 0; index < count; index++) { Coordinate c = cvec.get(index); rawArray[2 * index] = c.x; rawArray[2 * index + 1] = c.y; } return rawArray; } /** * Save game state so that the user does not lose anything * if the game process is killed while we are in the * background. * * @return a Bundle with this view's state */ public Bundle saveState() { Bundle map = new Bundle(); map.putIntArray("mAppleList", coordArrayListToArray(mAppleList)); map.putInt("mDirection", Integer.valueOf(mDirection)); map.putInt("mNextDirection", Integer.valueOf(mNextDirection)); map.putLong("mMoveDelay", Long.valueOf(mMoveDelay)); map.putLong("mScore", Long.valueOf(mScore)); map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail)); return map; } /** * Given a flattened array of ordinate pairs, we reconstitute them into a * ArrayList of Coordinate objects * * @param rawArray : [x1,y1,x2,y2,...] * @return a ArrayList of Coordinates */ private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) { ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>(); int coordCount = rawArray.length; for (int index = 0; index < coordCount; index += 2) { Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]); coordArrayList.add(c); } return coordArrayList; } /** * Restore game state if our process is being relaunched * * @param icicle a Bundle containing the game state */ public void restoreState(Bundle icicle) { setMode(PAUSE); mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList")); mDirection = icicle.getInt("mDirection"); mNextDirection = icicle.getInt("mNextDirection"); mMoveDelay = icicle.getLong("mMoveDelay"); mScore = icicle.getLong("mScore"); mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail")); } /* * handles key events in the game. Update the direction our snake is traveling * based on the DPAD. Ignore events that would cause the snake to immediately * turn back on itself. * * (non-Javadoc) * * @see android.view.View#onKeyDown(int, android.os.KeyEvent) */ @Override public boolean onKeyDown(int keyCode, KeyEvent msg) { if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { if (mMode == READY | mMode == LOSE) { /* * At the beginning of the game, or the end of a previous one, * we should start a new game. */ initNewGame(); setMode(RUNNING); update(); return (true); } if (mMode == PAUSE) { /* * If the game is merely paused, we should just continue where * we left off. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -