學習時做個一個小遊戲,界面有些簡陋,部分碰撞計算不是很精準。
話不多說直接上代碼了,比較簡單
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>好了,其他業務處理可以發揮腦洞了。