Android apps浅析01-Amazed:一个简单但令人上瘾的加速度为基础的大理石指导游戏。

Android apps浅析01-Amazed:一个简单但令人上瘾的加速度为基础的大理石指导游戏。

 

这个例子中只有4个类,一个绘制大理石类Marble,一个绘制迷宫类Maze,一个Amazed视图类,一个Amazed活动类

 

1. 绘制大理石类Marble通过Canvas和Paint绘制,同时提供移动x轴和y轴坐标的方法,每个大理石都有一个状态值:活的/死的

/*
 * Copyright (C) 2008 Jason Tomlinson.
 *
 * 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.amazed;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

/**
 * Marble drawn in the maze.迷宫中的大理石绘制
 */
public class Marble {

    // View controlling the marble.
    private View mView;

    // marble attributes
    // x,y are private because we need boundary checking on any new values to
    // make sure they are valid.
    private int mX = 0;
    private int mY = 0;
    private int mRadius = 8;
    private int mColor = Color.WHITE;
    private int mLives = 5;

    /**
     * Marble constructor.
     *
     * @param view
     *            View controlling the marble
     */
    public Marble(View view) {
        this.mView = view;
        init();
    }

    /**
     * Setup marble starting co-ords.
     */
    public void init() {
        mX = mRadius * 6;
        mY = mRadius * 6;
    }

    /**
     * Draw the marble.
     *
     * @param canvas
     *            Canvas object to draw too.
     * @param paint
     *            Paint object used to draw with.
     */
    public void draw(Canvas canvas, Paint paint) {
        paint.setColor(mColor);
        canvas.drawCircle(mX, mY, mRadius, paint);
    }

    /**
     * Attempt to update the marble with a new x value, boundary checking
     * enabled to make sure the new co-ordinate is valid.
     *
     * @param newX
     *            Incremental value to add onto current x co-ordinate.
     */
    public void updateX(float newX) {
        mX += newX;

        // boundary checking, don't want the marble rolling off-screen.
        if (mX + mRadius >= mView.getWidth())
            mX = mView.getWidth() - mRadius;
        else if (mX - mRadius < 0)
            mX = mRadius;
    }

    /**
     * Attempt to update the marble with a new y value, boundary checking
     * enabled to make sure the new co-ordinate is valid.
     *
     * @param newY
     *            Incremental value to add onto current y co-ordinate.
     */
    public void updateY(float newY) {
        mY -= newY;

        // boundary checking, don't want the marble rolling off-screen.
        if (mY + mRadius >= mView.getHeight())
            mY = mView.getHeight() - mRadius;
        else if (mY - mRadius < 0)
            mY = mRadius;
    }

    /**
     * Marble has died
     */
    public void death() {
        mLives--;
    }

    /**
     * Set the number of lives for the marble
     *
     * @param Number
     *            of lives
     */
    public void setLives(int val) {
        mLives = val;
    }

    /**
     * @return Number of lives left
     */
    public int getLives() {
        return mLives;
    }

    /**
     * @return Current x co-ordinate.
     */
    public int getX() {
        return mX;
    }

    /**
     * @return Current y co-ordinate.
     */
    public int getY() {
        return mY;
    }
}

 

2. 绘制迷宫类Maze绘制一个20列26行的长方形,提供加载背景和数据以及等级的方法,同样通过Canvas和Paint绘制,另外需要提供(x,y)坐标上的大理石数据是活的还是死的

/*
 * Copyright (C) 2008 Jason Tomlinson.
 *
 * 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.amazed;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;

/**
 * Maze drawn on screen, each new level is loaded once the previous level has
 * been completed.屏幕上迷宫绘制,一旦前一个级别完成后,每个新级别会被加载。
 */
public class Maze {

    // maze tile size and dimension
    private final static int TILE_SIZE = 16;
    private final static int MAZE_COLS = 20;
    private final static int MAZE_ROWS = 26;

    // tile types
    public final static int PATH_TILE = 0;
    public final static int VOID_TILE = 1;
    public final static int EXIT_TILE = 2;

    // tile colors
    private final static int VOID_COLOR = Color.BLACK;

    // maze level data
    private static int[] mMazeData;

    // number of level
    public final static int MAX_LEVELS = 10;

    // current tile attributes
    private Rect mRect = new Rect();
    private int mRow;
    private int mCol;
    private int mX;
    private int mY;

    // tile bitmaps
    private Bitmap mImgPath;
    private Bitmap mImgExit;

    /**
     * Maze constructor.
     *
     * @param context
     *            Application context used to load images.
     */
    Maze(Activity activity) {

        // load bitmaps.
        mImgPath = BitmapFactory.decodeResource(activity.getApplicationContext().getResources(),
                R.drawable.path);
        mImgExit = BitmapFactory.decodeResource(activity.getApplicationContext().getResources(),
                R.drawable.exit);
    }

    /**
     * Load specified maze level.
     *
     * @param activity
     *           Activity controlled the maze, we use this load the level data
     * @param newLevel
     *            Maze level to be loaded.
     */
    void load(Activity activity, int newLevel) {
        // maze data is stored in the assets folder as level1.txt, level2.txt
        // etc....
        String mLevel = "level" + newLevel + ".txt";

        InputStream is = null;

        try {
            // construct our maze data array.
            mMazeData = new int[MAZE_ROWS * MAZE_COLS];
            // attempt to load maze data.
            is = activity.getAssets().open(mLevel);

            // we need to loop through the input stream and load each tile for
            // the current maze.
            for (int i = 0; i < mMazeData.length; i++) {
                // data is stored in unicode so we need to convert it.
                mMazeData[i] = Character.getNumericValue(is.read());

                // skip the "," and white space in our human readable file.
                is.read();
                is.read();
            }
        } catch (Exception e) {
            Log.i("Maze", "load exception: " + e);
        } finally {
            closeStream(is);
        }

    }

    /**
     * Draw the maze.
     *
     * @param canvas
     *            Canvas object to draw too.
     * @param paint
     *            Paint object used to draw with.
     */
    public void draw(Canvas canvas, Paint paint) {
        // loop through our maze and draw each tile individually.
        for (int i = 0; i < mMazeData.length; i++) {
            // calculate the row and column of the current tile.
            mRow = i / MAZE_COLS;
            mCol = i % MAZE_COLS;

            // convert the row and column into actual x,y co-ordinates so we can
            // draw it on screen.
            mX = mCol * TILE_SIZE;
            mY = mRow * TILE_SIZE;

            // draw the actual tile based on type.
            if (mMazeData[i] == PATH_TILE)
                canvas.drawBitmap(mImgPath, mX, mY, paint);
            else if (mMazeData[i] == EXIT_TILE)
                canvas.drawBitmap(mImgExit, mX, mY, paint);
            else if (mMazeData[i] == VOID_TILE) {
                // since our "void" tile is purely black lets draw a rectangle
                // instead of using an image.

                // tile attributes we are going to paint.
                mRect.left = mX;
                mRect.top = mY;
                mRect.right = mX + TILE_SIZE;
                mRect.bottom = mY + TILE_SIZE;

                paint.setColor(VOID_COLOR);
                canvas.drawRect(mRect, paint);
            }
        }

    }

    /**
     * Determine which cell the marble currently occupies.
     *
     * @param x
     *            Current x co-ordinate.
     * @param y
     *            Current y co-ordinate.
     * @return The actual cell occupied by the marble.
     */
    public int getCellType(int x, int y) {
        // convert the x,y co-ordinate into row and col values.
        int mCellCol = x / TILE_SIZE;
        int mCellRow = y / TILE_SIZE;

        // location is the row,col coordinate converted so we know where in the
        // maze array to look.
        int mLocation = 0;

        // if we are beyond the 1st row need to multiple by the number of
        // columns.
        if (mCellRow > 0)
            mLocation = mCellRow * MAZE_COLS;

        // add the column location.
        mLocation += mCellCol;

        return mMazeData[mLocation];
    }

    /**
     * Closes the specified stream.
     *
     * @param stream
     *            The stream to close.
     */
    private static void closeStream(Closeable stream) {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                // Ignore
            }
        }
    }
}

 

 

3. Amazed视图类,自定义view用于绘制迷宫和大理石,响应加速度计的更新在屏幕上滚动的大理石,通过SensorListener和SensorManager传感器相关的类监听用户触摸的单元xyz坐标值,重载View的onDraw方法来调用游戏开始前,游戏开始中,游戏结束和游戏完成相应的绘制函数

/*
 * Copyright (C) 2008 Jason Tomlinson.
 *
 * 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.amazed;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

/**
 * Custom view used to draw the maze and marble. Responds to accelerometer
 * updates to roll the marble around the screen.自定义view用于绘制迷宫和大理石,响应加速度计的更新在屏幕上滚动的大理石。
 */
public class AmazedView extends View {
    // Game objects
    private Marble mMarble;
    private Maze mMaze;
    private Activity mActivity;

    // canvas we paint to.
    private Canvas mCanvas;

    private Paint mPaint;
    private Typeface mFont = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
    private int mTextPadding = 10;
    private int mHudTextY = 440;

    // game states
    private final static int NULL_STATE = -1;
    private final static int GAME_INIT = 0;
    private final static int GAME_RUNNING = 1;
    private final static int GAME_OVER = 2;
    private final static int GAME_COMPLETE = 3;
    private final static int GAME_LANDSCAPE = 4;
    // current state of the game
    private static int mCurState = NULL_STATE;

    // game strings
    private final static int TXT_LIVES = 0;
    private final static int TXT_LEVEL = 1;
    private final static int TXT_TIME = 2;
    private final static int TXT_TAP_SCREEN = 3;
    private final static int TXT_GAME_COMPLETE = 4;
    private final static int TXT_GAME_OVER = 5;
    private final static int TXT_TOTAL_TIME = 6;
    private final static int TXT_GAME_OVER_MSG_A = 7;
    private final static int TXT_GAME_OVER_MSG_B = 8;
    private final static int TXT_RESTART = 9;
    private final static int TXT_LANDSCAPE_MODE = 10;
    private static String mStrings[];

    // this prevents the user from dying instantly when they start a level if
    // the device is tilted.
    private boolean mWarning = false;

    // screen dimensions
    private int mCanvasWidth = 0;
    private int mCanvasHeight = 0;
    private int mCanvasHalfWidth = 0;
    private int mCanvasHalfHeight = 0;

    // are we running in portrait mode.
    private boolean mPortrait;

    // current level
    private int mlevel = 1;

    // timing used for scoring.
    private long mTotalTime = 0;
    private long mStartTime = 0;
    private long mEndTime = 0;

    // sensor manager used to control the accelerometer sensor.
    private SensorManager mSensorManager;
    // accelerometer sensor values.
    private float mAccelX = 0;
    private float mAccelY = 0;
    private float mAccelZ = 0; // this is never used but just in-case future
    // versions make use of it.

    // accelerometer buffer, currently set to 0 so even the slightest movement
    // will roll the marble.
    private float mSensorBuffer = 0;

    // http://code.google.com/android/reference/android/hardware/SensorManager.html#SENSOR_ACCELEROMETER
    // for an explanation on the values reported by SENSOR_ACCELEROMETER.
    private final SensorListener mSensorAccelerometer = new SensorListener() {

        // method called whenever new sensor values are reported.
        public void onSensorChanged(int sensor, float[] values) {
            // grab the values required to respond to user movement.
            mAccelX = values[0];
            mAccelY = values[1];
            mAccelZ = values[2];
        }

        // reports when the accuracy of sensor has change
        // SENSOR_STATUS_ACCURACY_HIGH = 3
        // SENSOR_STATUS_ACCURACY_LOW = 1
        // SENSOR_STATUS_ACCURACY_MEDIUM = 2
        // SENSOR_STATUS_UNRELIABLE = 0 //calibration required.
        public void onAccuracyChanged(int sensor, int accuracy) {
            // currently not used
        }
    };

    /**
     * Custom view constructor.
     *
     * @param context
     *            Application context
     * @param activity
     *            Activity controlling the view
     */
    public AmazedView(Context context, Activity activity) {
        super(context);

        mActivity = activity;

        // init paint and make is look "nice" with anti-aliasing.
        mPaint = new Paint();
        mPaint.setTextSize(14);
        mPaint.setTypeface(mFont);
        mPaint.setAntiAlias(true);

        // setup accelerometer sensor manager.
        mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
        // register our accelerometer so we can receive values.
        // SENSOR_DELAY_GAME is the recommended rate for games
        mSensorManager.registerListener(mSensorAccelerometer, SensorManager.SENSOR_ACCELEROMETER,
                SensorManager.SENSOR_DELAY_GAME);

        // setup our maze and marble.
        mMaze = new Maze(mActivity);
        mMarble = new Marble(this);

        // load array from /res/values/strings.xml
        mStrings = getResources().getStringArray(R.array.gameStrings);

        // set the starting state of the game.
        switchGameState(GAME_INIT);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // get new screen dimensions.
        mCanvasWidth = w;
        mCanvasHeight = h;

        mCanvasHalfWidth = w / 2;
        mCanvasHalfHeight = h / 2;

        // are we in portrait or landscape mode now?
        // you could use bPortrait = !bPortrait however in the future who know's
        // how many different ways a device screen may be rotated.
        if (mCanvasHeight > mCanvasWidth)
            mPortrait = true;
        else {
            mPortrait = false;
            switchGameState(GAME_LANDSCAPE);
        }
    }

    /**
     * Called every cycle, used to process current game state.
     */
    public void gameTick() {
        // very basic state machine, makes a good foundation for a more complex
        // game.
        switch (mCurState) {
        case GAME_INIT:
            // prepare a new game for the user.
            initNewGame();
            switchGameState(GAME_RUNNING);

        case GAME_RUNNING:
            // update our marble.
            if (!mWarning)
                updateMarble();
            break;
        }

        // redraw the screen once our tick function is complete.
        invalidate();
    }

    /**
     * Reset game variables in preparation for a new game.
     */
    public void initNewGame() {
        mMarble.setLives(5);
        mTotalTime = 0;
        mlevel = 0;
        initLevel();
    }

    /**
     * Initialize the next level.
     */
    public void initLevel() {
        if (mlevel < mMaze.MAX_LEVELS) {
            // setup the next level.
            mWarning = true;
            mlevel++;
            mMaze.load(mActivity, mlevel);
            mMarble.init();
        } else {
            // user has finished the game, update state machine.
            switchGameState(GAME_COMPLETE);
        }
    }

    /**
     * Called from gameTick(), update marble x,y based on latest values obtained
     * from the Accelerometer sensor. AccelX and accelY are values received from
     * the accelerometer, higher values represent the device tilted at a more
     * acute angle.
     */
    public void updateMarble() {
        // we CAN give ourselves a buffer to stop the marble from rolling even
        // though we think the device is "flat".
        if (mAccelX > mSensorBuffer || mAccelX < -mSensorBuffer)
            mMarble.updateX(mAccelX);
        if (mAccelY > mSensorBuffer || mAccelY < -mSensorBuffer)
            mMarble.updateY(mAccelY);

        // check which cell the marble is currently occupying.
        if (mMaze.getCellType(mMarble.getX(), mMarble.getY()) == mMaze.VOID_TILE) {
            // user entered the "void".
            if (mMarble.getLives() > 0) {
                // user still has some lives remaining, restart the level.
                mMarble.death();
                mMarble.init();
                mWarning = true;
            } else {
                // user has no more lives left, end of game.
                mEndTime = System.currentTimeMillis();
                mTotalTime += mEndTime - mStartTime;
                switchGameState(GAME_OVER);
            }

        } else if (mMaze.getCellType(mMarble.getX(), mMarble.getY()) == mMaze.EXIT_TILE) {
            // user has reached the exit tiles, prepare the next level.
            mEndTime = System.currentTimeMillis();
            mTotalTime += mEndTime - mStartTime;
            initLevel();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // we only want to handle down events .
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mCurState == GAME_OVER || mCurState == GAME_COMPLETE) {
                // re-start the game.
                mCurState = GAME_INIT;
            } else if (mCurState == GAME_RUNNING) {
                // in-game, remove the pop-up text so user can play.
                mWarning = false;
                mStartTime = System.currentTimeMillis();
            }
        }
        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // quit application if user presses the back key.
        if (keyCode == KeyEvent.KEYCODE_BACK)
            cleanUp();

        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        // update our canvas reference.
        mCanvas = canvas;

        // clear the screen.
        mPaint.setColor(Color.WHITE);
        mCanvas.drawRect(0, 0, mCanvasWidth, mCanvasHeight, mPaint);

        // simple state machine, draw screen depending on the current state.
        switch (mCurState) {
        case GAME_RUNNING:
            // draw our maze first since everything else appears "on top" of it.
            mMaze.draw(mCanvas, mPaint);

            // draw our marble and hud.
            mMarble.draw(mCanvas, mPaint);

            // draw hud
            drawHUD();
            break;

        case GAME_OVER:
            drawGameOver();
            break;

        case GAME_COMPLETE:
            drawGameComplete();
            break;

        case GAME_LANDSCAPE:
            drawLandscapeMode();
            break;
        }

        gameTick();
    }

    /**
     * Called from onDraw(), draws the in-game HUD
     */
    public void drawHUD() {
        mPaint.setColor(Color.BLACK);
        mPaint.setTextAlign(Paint.Align.LEFT);
        mCanvas.drawText(mStrings[TXT_TIME] + ": " + (mTotalTime / 1000), mTextPadding, mHudTextY,
                mPaint);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mCanvas.drawText(mStrings[TXT_LEVEL] + ": " + mlevel, mCanvasHalfWidth, mHudTextY, mPaint);
        mPaint.setTextAlign(Paint.Align.RIGHT);
        mCanvas.drawText(mStrings[TXT_LIVES] + ": " + mMarble.getLives(), mCanvasWidth - mTextPadding,
                mHudTextY, mPaint);

        // do we need to display the warning message to save the user from
        // possibly dying instantly.
        if (mWarning) {
            mPaint.setColor(Color.BLUE);
            mCanvas
                    .drawRect(0, mCanvasHalfHeight - 15, mCanvasWidth, mCanvasHalfHeight + 5,
                            mPaint);
            mPaint.setColor(Color.WHITE);
            mPaint.setTextAlign(Paint.Align.CENTER);
            mCanvas.drawText(mStrings[TXT_TAP_SCREEN], mCanvasHalfWidth, mCanvasHalfHeight, mPaint);
        }
    }

    /**
     * Called from onDraw(), draws the game over screen.
     */
    public void drawGameOver() {
        mPaint.setColor(Color.BLACK);
        mPaint.setTextAlign(Paint.Align.CENTER);

        mCanvas.drawText(mStrings[TXT_GAME_OVER], mCanvasHalfWidth, mCanvasHalfHeight, mPaint);
        mCanvas.drawText(mStrings[TXT_TOTAL_TIME] + ": " + (mTotalTime / 1000) + "s",
                mCanvasHalfWidth, mCanvasHalfHeight + mPaint.getFontSpacing(), mPaint);
        mCanvas.drawText(mStrings[TXT_GAME_OVER_MSG_A] + " " + (mlevel - 1) + " "
                + mStrings[TXT_GAME_OVER_MSG_B], mCanvasHalfWidth, mCanvasHalfHeight
                + (mPaint.getFontSpacing() * 2), mPaint);
        mCanvas.drawText(mStrings[TXT_RESTART], mCanvasHalfWidth, mCanvasHeight
                - (mPaint.getFontSpacing() * 3), mPaint);
    }

    /**
     * Called from onDraw(), draws the game complete screen.
     */
    public void drawGameComplete() {
        mPaint.setColor(Color.BLACK);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mCanvas.drawText(mStrings[GAME_COMPLETE], mCanvasHalfWidth, mCanvasHalfHeight, mPaint);
        mCanvas.drawText(mStrings[TXT_TOTAL_TIME] + ": " + (mTotalTime / 1000) + "s",
                mCanvasHalfWidth, mCanvasHalfHeight + mPaint.getFontSpacing(), mPaint);
        mCanvas.drawText(mStrings[TXT_RESTART], mCanvasHalfWidth, mCanvasHeight
                - (mPaint.getFontSpacing() * 3), mPaint);
    }

    /**
     * Called from onDraw(), displays a message asking the user to return the
     * device back to portrait mode.
     */
    public void drawLandscapeMode() {
        mPaint.setColor(Color.WHITE);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mCanvas.drawRect(0, 0, mCanvasWidth, mCanvasHeight, mPaint);
        mPaint.setColor(Color.BLACK);
        mCanvas.drawText(mStrings[TXT_LANDSCAPE_MODE], mCanvasHalfWidth, mCanvasHalfHeight, mPaint);
    }

    /**
     * Updates the current game state with a new state. At the moment this is
     * very basic however if the game was to get more complicated the code
     * required for changing game states could grow quickly.
     *
     * @param newState
     *            New game state
     */
    public void switchGameState(int newState) {
        mCurState = newState;
    }

    /**
     * Register the accelerometer sensor so we can use it in-game.
     */
    public void registerListener() {
        mSensorManager.registerListener(mSensorAccelerometer, SensorManager.SENSOR_ACCELEROMETER,
                SensorManager.SENSOR_DELAY_GAME);
    }

    /**
     * Unregister the accelerometer sensor otherwise it will continue to operate
     * and report values.
     */
    public void unregisterListener() {
        mSensorManager.unregisterListener(mSensorAccelerometer);
    }

    /**
     * Clean up the custom view and exit the application.
     */
    public void cleanUp() {
        mMarble = null;
        mMaze = null;
        mStrings = null;
        unregisterListener();
        mActivity.finish();
    }
}

 

 

4. Amazed活动类,响应Activity来控制应用程序,定义和调用Amazed视图类,同时重载Activity的onResume方法和onSaveInstanceState方法分别进行Amazed类的注册和反注册

/*
 * Copyright (C) 2008 Jason Tomlinson.
 *
 * 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.amazed;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

/**
 * Activity responsible for controlling the application.响应Activity来控制应用程序
 */
public class AmazedActivity extends Activity {

    // custom view
    private AmazedView mView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // remove title bar.
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // setup our view, give it focus and display.
        mView = new AmazedView(getApplicationContext(), this);
        mView.setFocusable(true);
        setContentView(mView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mView.registerListener();
    }

    @Override
    public void onSaveInstanceState(Bundle icicle) {
        super.onSaveInstanceState(icicle);
        mView.unregisterListener();
    }
}

 

源码来源:https://code.google.com/p/apps-for-android/
源码下载:http://download.csdn.net/user/yangzhenping

•Amazed: A simple but addictive accelerometer-based marble-guidance game.
•AndroidGlobalTime: a full representation of the Earth that you can spin around.
•AnyCut: A utility that lets users create Home screen shortcuts to nearly anything in the system.
•Clickin2DaBeat: A game that mashes up YouTube with custom rhythm-game logic.
•DivideAndConquer: a game in which you must isolate bouncing balls by creating walls around them.
•HeightMapProfiler: A simple 3D performance testing tool that renders a 3D height map.
•LOLcat Builder:
ho hai,i see in has cheese burger? I am in our phone, caption in our photos.
•Panoramio: An app that shows you nearby photos and points of interest.
•Photostream: An app that lets you view photostreams from online photo-hosting services.
•Radar: A radar-style relative location display view, used by Panoramio(Google照片分享服务) and others.
•RingsExtended: A utility that provides enhanced control over ringtones.
•Samples: Miscellaneous examples showing features of the Android platform (among which OpenGL ES).
•SpriteMethodTest: An application that compares the speed of various 2D sprite drawing methods.
•WebViewDemo: How Java and JavaScript can call each other inside a WebView.
•WikiNotes: A wiki note pad that uses intents to navigate to wiki words and other rich content stored in the notes.

•Amazed:一个简单但令人上瘾的加速度为基础的大理石指导游戏。
•AndroidGlobalTime:地球全表示,你可以不停地旋转。
•AnyCut:一种实用工具,可以让用户创建主屏幕快捷方式到系统中几乎任何东西。
•Clickin2DaBeat:一个游戏,捣烂了YouTube的自定义节奏的游戏逻辑。
•DivideAndConquer:一个游戏中,你必须隔离他们围绕创建墙壁弹跳球。
•HeightMapProfiler:一个简单的3D性能测试工具,它呈现一个三维高程图。
•LOLcat生成器:
何海,我看到有芝士汉堡?我在我们的电话,说明在我们的照片。
•Panoramio的:一个应用程序,显示你附近的照片和兴趣点。
•照片流:一个应用程序,让您从在线照片托管服务查看照片媒体。
•雷达:雷达式的相对位置显示视图,用于Panoramio的(谷歌照片分享服务)等。
•RingsExtended:提供增强的控制铃声的实用程序。
•Samples:显示Android平台(其中的OpenGL ES)的功能,其他的例子。
•SpriteMethodTest:用于比较各种2D精灵绘制方法速度的应用程序。
•WebViewDemo:如何Java与JavaScript可以调用对方的WebView里面。
•WikiNotes:使用意图导航到维基单词和存储在票据等丰富内容维基便条。

源码来源:https://code.google.com/p/apps-for-android/
源码下载:http://download.csdn.net/user/yangzhenping

时间: 2024-09-20 03:40:20

Android apps浅析01-Amazed:一个简单但令人上瘾的加速度为基础的大理石指导游戏。的相关文章

Android apps浅析02-Android IM:一个类似手机QQ的即时通讯开源实现

Android apps浅析02-Android IM:一个类似手机QQ的即时通讯开源实现 这是Android上的一个简单的IM应用程序运行时,应用程序发出HTTP请求到服务器,在PHP和MySQL,验证,注册和得到其他朋友的状态和数据来实现,那么它与其他设备的其他应用程序通过通信套接字接口.   1. 数据库只要2个表:朋友表和用户表: CREATE TABLE `friends` ( `Id` int(10) unsigned NOT NULL auto_increment, `provid

重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务

原文:重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 [源码下载] 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 开发一个简单的后台任务 示例1.通过"Windows 运行时组件"新建一个后台任务BackgroundTaskLib/Demo.cs /* * 后台任务 * * 注: * 后

简单却令人上瘾:筹码连锁试玩攻略

筹码连锁试玩攻略 游戏名称:<筹码连锁>价格:免费更新时间:2012年11月2日大小:19.2 MB要说什么游戏最老少皆宜.通吃各大年龄层次,消除游戏必须占一位.不过纵观消除游戏的庞大阵容,又基本上是以三消作为龙头老大,玩久了也不免审美疲劳.当然在消除游戏的海洋中,也涌现出不少异质作品,其中数字型消除游戏就以其简单却 上瘾的玩法令人印象深刻,如很早之前的<Super7>等.近日又有一款优质的数字型消除游戏上架--<ChipChain(筹码连锁)>,不要光看到筹码就觉得有

浅析Linux下一个简单的多线程互斥锁的例子_unix linux

复制代码 代码如下: #include <stdio.h>#include <pthread.h>pthread_mutex_t Device_mutex ;int count=0;void thread_func1(){   while(1)   {       pthread_mutex_lock(&Device_mutex);       printf("thread1: %d\n",count);       pthread_mutex_unlo

Windows 8 Store Apps学习(64) 后台任务: 开发一个简单的后台任务

介绍 重新想象 Windows 8 Store Apps 之 后台任务 开发一个简单的后台任务 示例 1.通过"Windows 运行时组件"新建一个后台任务 BackgroundTaskLib/Demo.cs /* * 后台任务 * * 注: * 后台任务项目的输出类型需要设置为"Windows 运行时组件",其会生成 .winmd 文件,winmd - Windows Metadata */ using System; using System.Threading

Android Studio初探:不只是一个简单的IDE

对于Android 开发者来说,日常开发对于他们来说是干脆直接的.你只需要下载Eclipse并且安装Android Developer工具插件就可以了.Android的Eclipse插件为开发者完成了不少工作,而且或多或少能符合大多数开发者期望那样.但现在,Google最新发布的Android Studio 搅局了,这款Android IDE开发工具对任何Android 开发者而言,都是极大的飞跃. 虽然拥有"Android Studio"的名称,并且软件直接来自Google的,但大多

我的Android进阶之旅------&amp;gt;Android关于Log的一个简单封装

android.util.Log类,可以方便地用于在编码调试过程中打印日志.但是在发布后的产品中,如果有太多的日志打印,则会严重地影响性能.对android.util.Log类做一个简单的封装,当产品要发布的话,将Debug设为false. 代码如下. public class LogUtil { /**正式上线時候设为false*/ private final static boolean debug = true; private final static String TAG = "oyp

windows-一个简单Windows程序无法链接,求大神指导,感谢

问题描述 一个简单Windows程序无法链接,求大神指导,感谢 // HelloWin.C 在客户区显示"你好 Windows 7" (c) Charles Petzold 1998 #include #pragma comment(libwinmm.lib"") LRESULT CALLBACK WinProc(HWND UINT WPARAM LPARAM); int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hP

《Android游戏开发详解》一2.7 构建一个简单的计数程序

2.7 构建一个简单的计数程序 Android游戏开发详解在下一个示例中,我们将利用第1章中介绍过的for循环来打印出数字5到12之间的每一个偶数.这是一个简单的游戏示例,但是,掌握for循环语法的技巧很重要. 创建一个名为CountingProject的新的Java项目,并且创建一个名为EvenFinder的新类,添加程序清单2.7所示的main方法. 程序清单2.7 EvenFinder类 01 public class EvenFinder { 02 03 public static vo