学习时做个一个小游戏,界面有些简陋,部分碰撞计算不是很精准。
话不多说直接上代码了,比较简单
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>好了,其他业务处理可以发挥脑洞了。