仿一個小鳥過柱子的遊戲

學習時做個一個小遊戲,界面有些簡陋,部分碰撞計算不是很精準。哭

話不多說直接上代碼了,比較簡單

package com.example.administrator.bluebird;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by Administrator on 2017/6/6.
 */

public class GameBackGround extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private boolean isDrawing;
    private Paint pillarPaint;
    /**
     * surface持有者
     */
    private SurfaceHolder mHolder;
    /**
     * 當前畫布
     */
    private Canvas mCanvas;

    /**
     * x軸的單位
     */
    private int mXUnit = dp2px(100);

    /**
     * 柱子寬度
     */
    private int pillarWidth = dp2px(30);

    /**
     * 柱子空隙高度
     */
    private int spaceHeight = dp2px(60);

    /**
     * 畫布寬度
     */
    private int BG_width;

    /**
     * 畫布高度
     */
    private int BG_height;

    /**
     * 柱子集合
     */
    private List<Integer> mPillars;

    /**
     * 柱子偏移量
     */
    private int mOffset;

    /**
     * 主角偏移量
     */
    private int birdOffset;

    /**
     * 主角每次跳高的高度
     */
    private int jump = dp2px(30);

    /**
     * 遊戲主角
     */
    private Bitmap bird;

    /**
     * 主角尺寸
     */
    private int bird_width;
    private int bird_height;

    private int DEFAULT_WIDTH = 300;
    private int DEFAULT_HEIGHT = 200;

    public GameBackGround(Context context) {
        this(context, null);
    }

    public GameBackGround(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GameBackGround(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        // 設置可以獲取焦點
        setFocusable(true);
        // 進入觸摸輸入模式後,該控件是否還有獲得焦點的能力
        setFocusableInTouchMode(true);
        // 是否保持屏幕常亮
        this.setKeepScreenOn(true);

        //初始化幾根柱子
        mPillars = new ArrayList<>();
        mPillars.add(new Random().nextInt(200) + 100);
        mPillars.add(new Random().nextInt(200) + 100);
        mPillars.add(new Random().nextInt(200) + 100);
        mPillars.add(new Random().nextInt(200) + 100);
        mPillars.add(new Random().nextInt(200) + 100);

        //初始化畫筆
        pillarPaint = new Paint();
        pillarPaint.setAntiAlias(true);
        pillarPaint.setStrokeWidth(pillarWidth);

        //初始化主角圖片
        bird = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_launcher);
        bird_width = bird.getWidth();
        bird_height = bird.getHeight();
    }

    /**
     * 計算畫布大小
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode == MeasureSpec.AT_MOST) {
            BG_width = dp2px(DEFAULT_WIDTH);
        } else {
            BG_width = Math.max(widthSize, dp2px(DEFAULT_WIDTH));
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            BG_height = dp2px(DEFAULT_HEIGHT);
        } else {
            BG_height = Math.max(heightSize, dp2px(DEFAULT_HEIGHT));
        }
        setMeasuredDimension(BG_width, BG_height);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // 開始繪畫
        isDrawing = true;
        // 啓動繪畫線程
        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isDrawing = false;
    }

    @Override
    public void run() {
        while (isDrawing) {
            try {
                draw();
                Thread.sleep(10);
                birdOffset++;
                mOffset++;
                if (mOffset == BG_width + mXUnit) {
                    mOffset = BG_width;
                    mPillars.remove(0);
                    mPillars.add(new Random().nextInt(100) + 100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 繪製方法
     */
    private void draw() {
        // 獲取並鎖定畫布
        mCanvas = mHolder.lockCanvas();

        if (mCanvas != null) {
            // 設置畫布背景爲白色
            mCanvas.drawColor(0xffffffff);

            //繪製移動的柱子
            drawPillar();

            //繪製遊戲主角
            drawBird();

            // 保證每次都將繪製的內容提交到服務器
            mHolder.unlockCanvasAndPost(mCanvas);
        }

    }

    /**
     * 畫柱子
     */
    private void drawPillar() {
        mCanvas.save();
        for (int i = 0; i < mPillars.size(); i++) {
            crashEvent(BG_width + mXUnit * i - mOffset, BG_width + mXUnit * i - mOffset, BG_height - dp2px(mPillars.get(i)));
            mCanvas.drawLine(BG_width + mXUnit * i - mOffset, BG_height - dp2px(mPillars.get(i)), BG_width + mXUnit * i - mOffset, BG_height, pillarPaint);
            mCanvas.drawLine(BG_width + mXUnit * i - mOffset, 0, BG_width + mXUnit * i - mOffset, BG_height - dp2px(mPillars.get(i)) - spaceHeight, pillarPaint);
        }
    }

    /**
     * 繪製鳥
     */
    private void drawBird() {
        mCanvas.save();
        mCanvas.drawBitmap(bird, BG_width / 2, BG_height / 2 + birdOffset, pillarPaint);
    }

    /**
     * 碰撞處理
     */
    private void crashEvent(int x, int y_up, int y_down) {
        //此時碰撞發生
        if (x <= BG_width / 2 + bird_width && x >= BG_width / 2 - pillarWidth) {
            if (BG_height / 2 + birdOffset < y_up || BG_height / 2 + bird_height + birdOffset > y_down) {
                isDrawing = false;
            }
        }
        if (birdOffset == BG_height / 2) {
            isDrawing = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            //點擊事件
            case MotionEvent.ACTION_DOWN:
                if (birdOffset > -BG_height / 2) {
                    birdOffset -= jump;
                }
                break;
        }
        return true;
    }

    /**
     * dp轉化爲px工具
     */
    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getContext().getResources().getDisplayMetrics());
    }
}
MainActivity只設置了一個屏幕禁止橫屏

package com.example.administrator.bluebird;

import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //禁止橫屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_main);
    }
}
佈局文件activity_main.xml直接使用自定義的view

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.administrator.bluebird.GameBackGround
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
好了,其他業務處理可以發揮腦洞了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章