Android 自定义 View 之弹球游戏

主程序代码:

package com.toby.personal.testlistview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    final private static String TAG = "Toby_Test";
    final private static int MSG_WHAT = 170411;

    private boolean isOver = false;

    // 桌面的宽高
    private int tableWidth;
    private int tableHeight;
    // 球拍的垂直位置
    private int racketY;
    // 球拍的宽高
    private final int RACKET_WIDTH = 70;
    private final int RACKET_HEIGHT = 20;
    // 小球的大小
    private final int BALL_SIZE = 12;
    // 小球的纵向速度
    private int ySpeed = 20;
    private Random random = new Random();
    // 返回一个介于 -0.5 ~ 0.5 之间的比率,用于控制小球的运行方向
    private double xyRate = random.nextDouble() - 0.5;
    // 小球的横向速度
    private int xSpeed = (int) (ySpeed * xyRate * 2);
    // 小球的坐标
    private int ballX = random.nextInt(200) + 20;
    private int ballY = random.nextInt(10) + 20;
    // 球拍的水平位置
    private int racketX = random.nextInt(200);

    // 球拍上次的 x 坐标
    private float racketLastX = racketX;

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

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        final GameView gameView = new GameView(this);
        setContentView(gameView);

        WindowManager windowManager = getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        display.getMetrics(metrics);

        tableWidth = metrics.widthPixels;
        tableHeight = metrics.heightPixels - 400;

        racketY = tableHeight - 80;

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == MSG_WHAT) {
                    gameView.invalidate();
                }
                super.handleMessage(msg);
            }
        };

        gameView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                float x = event.getX();

                if (x < racketLastX) {
                    if (racketX > 0) racketX -= 10;
                } else {
                    if (racketX < tableWidth - RACKET_WIDTH) racketX += 10;
                }

                racketLastX = x;
                return true;
            }
        });

        final Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (ballX <= 0 || ballX >= tableWidth - BALL_SIZE) {
                    xSpeed = -xSpeed;
                }

                if (ballY >= racketY - BALL_SIZE
                        && (ballX < racketX || ballX > racketX + RACKET_WIDTH)) {
                    timer.cancel();
                    isOver = true;
                } else if (ballY <= 0 || (ballY >= racketY - BALL_SIZE
                        && ballX > racketX && ballX <= racketX + RACKET_WIDTH)) {
                    ySpeed = -ySpeed;
                }

                ballY += ySpeed;
                ballX += xSpeed;

                handler.sendEmptyMessage(MSG_WHAT);
            }
        }, 0, 100);

    }

    class GameView extends View {
        Paint paint = new Paint();

        public GameView(Context context) {
            super(context);
            setFocusable(true);
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.GRAY);
            if (isOver) {
                paint.setColor(Color.RED);
                paint.setTextSize(40);
                canvas.drawText("Game Over!", 50, 200, paint);
            } else {
                paint.setColor(Color.rgb(240, 240, 80));
                canvas.drawCircle(ballX, ballY, BALL_SIZE, paint);

                paint.setColor(Color.rgb(80, 80, 200));
                canvas.drawRect(racketX, racketY, racketX + RACKET_WIDTH, racketY + RACKET_HEIGHT,
                        paint);
            }
        }
    }

}

运行效果:

Android 自定义 View 之弹球游戏_第1张图片
显示效果

本文参考文献:《疯狂Android讲义 : 第2版 》

你可能感兴趣的:(Android 自定义 View 之弹球游戏)