package com.scwang.smart.refresh.header; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.support.annotation.NonNull; import android.support.v4.graphics.ColorUtils; import android.util.AttributeSet; import android.view.View; import com.scwang.smart.refresh.header.fungame.FunGameView; import com.scwang.smart.refresh.layout.api.RefreshKernel; import com.scwang.smartrefresh.header.R; import com.scwang.smartrefresh.layout.util.SmartUtil; import java.util.ArrayList; import java.util.List; /** * Created by scwang on 2018/2/29. * from https://github.com/Hitomis/FunGameRefresh */ public class FunGameHitBlockHeader extends FunGameView { // /** * 默认矩形块竖向排列的数目 */ protected static final int BLOCK_VERTICAL_NUM = 5; /** * 默认矩形块横向排列的数目 */ protected static final int BLOCK_HORIZONTAL_NUM = 3; /** * 矩形块的宽度占屏幕宽度比率 */ protected static final float BLOCK_WIDTH_RATIO = .01806f; /** * 挡板所在位置占屏幕宽度的比率 */ protected static final float RACKET_POSITION_RATIO = .8f; /** * 矩形块所在位置占屏幕宽度的比率 */ protected static final float BLOCK_POSITION_RATIO = .08f; /** * 小球默认其实弹射角度 */ protected static final int DEFAULT_ANGLE = 30; /** * 分割线默认宽度大小 */ static final float DIVIDING_LINE_SIZE = 1.f; /** * 小球移动速度 */ protected static final int SPEED = 3; /** * 矩形砖块的高度、宽度 */ protected float blockHeight, blockWidth; /** * 小球半径 */ protected float BALL_RADIUS; protected Paint blockPaint; protected float blockLeft, racketLeft; protected float cx, cy; protected List pointList; protected boolean isLeft; protected int angle; protected int blockHorizontalNum; protected int speed; // // public FunGameHitBlockHeader(Context context) { this(context, null); } public FunGameHitBlockHeader(Context context, AttributeSet attrs) { super(context, attrs, 0); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FunGameHitBlockHeader); speed = ta.getInt(R.styleable.FunGameHitBlockHeader_srlBallSpeed, SmartUtil.dp2px(SPEED)); blockHorizontalNum = ta.getInt(R.styleable.FunGameHitBlockHeader_srlBlockHorizontalNum, BLOCK_HORIZONTAL_NUM); if (ta.hasValue(R.styleable.FunGameHitBlockHeader_fghBallSpeed)) { speed = ta.getInt(R.styleable.FunGameHitBlockHeader_fghBallSpeed, SmartUtil.dp2px(SPEED)); } if (ta.hasValue(R.styleable.FunGameHitBlockHeader_fghBlockHorizontalNum)) { blockHorizontalNum = ta.getInt(R.styleable.FunGameHitBlockHeader_fghBlockHorizontalNum, BLOCK_HORIZONTAL_NUM); } ta.recycle(); blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); blockPaint.setStyle(Paint.Style.FILL); BALL_RADIUS = SmartUtil.dp2px(4); } @Override public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) { final View thisView = this; final int measuredWidth = thisView.getMeasuredWidth(); blockHeight = 1f * height / BLOCK_VERTICAL_NUM - DIVIDING_LINE_SIZE; blockWidth = measuredWidth * BLOCK_WIDTH_RATIO; blockLeft = measuredWidth * BLOCK_POSITION_RATIO; racketLeft = measuredWidth * RACKET_POSITION_RATIO; controllerSize = (int) (blockHeight * 1.6f); super.onInitialized(kernel, height, maxDragHeight); } // // protected void resetConfigParams() { cx = racketLeft - 3 * BALL_RADIUS; cy = (int) (mHeaderHeight * .5f); controllerPosition = DIVIDING_LINE_SIZE; angle = DEFAULT_ANGLE; isLeft = true; if (pointList == null) { pointList = new ArrayList<>(); } else { pointList.clear(); } } /** * 检查小球是否撞击到挡板 * * @param y 小球当前坐标Y值 * @return 小球位于挡板Y值区域范围内:true,反之:false */ protected boolean checkTouchRacket(float y) { boolean flag = false; float diffVal = y - controllerPosition; if (diffVal >= 0 && diffVal <= controllerSize) { // 小球位于挡板Y值区域范围内 flag = true; } return flag; } /** * 检查小球是否撞击到矩形块 * * @param x 小球坐标X值 * @param y 小球坐标Y值 * @return 撞击到:true,反之:false */ protected boolean checkTouchBlock(float x, float y) { int columnX = (int) ((x - blockLeft - BALL_RADIUS - speed) / blockWidth); columnX = columnX == blockHorizontalNum ? columnX - 1 : columnX; int rowY = (int) (y / blockHeight); rowY = rowY == BLOCK_VERTICAL_NUM ? rowY - 1 : rowY; Point p = new Point(); p.set(columnX, rowY); boolean flag = false; for (Point point : pointList) { if (point.equals(p.x, p.y)) { flag = true; break; } } if (!flag) { pointList.add(p); } return !flag; } // // @Override protected void drawGame(Canvas canvas, int width, int height) { final View thisView = this; drawColorBlock(canvas); drawRacket(canvas); if (status == STATUS_GAME_PLAY || status == STATUS_GAME_FINISHED || status == STATUS_GAME_FAIL || thisView.isInEditMode()) { drawBallPath(canvas, width); } } /** * 绘制挡板 * * @param canvas 默认画布 */ protected void drawRacket(Canvas canvas) { mPaint.setColor(rModelColor); canvas.drawRect(racketLeft, controllerPosition, racketLeft + blockWidth, controllerPosition + controllerSize, mPaint); } /** * 绘制并处理小球运动的轨迹 * * @param canvas 默认画布 * @param width 视图宽度 */ protected void drawBallPath(Canvas canvas, int width) { mPaint.setColor(mModelColor); if (cx <= blockLeft + blockHorizontalNum * blockWidth + (blockHorizontalNum - 1) * DIVIDING_LINE_SIZE + BALL_RADIUS) { // 小球进入到色块区域 if (checkTouchBlock(cx, cy)) { // 反弹回来 isLeft = false; } } if (cx <= blockLeft + BALL_RADIUS) { // 小球穿过色块区域 isLeft = false; } if (cx + BALL_RADIUS >= racketLeft && cx - BALL_RADIUS < racketLeft + blockWidth) { //小球当前坐标X值在挡板X值区域范围内 if (checkTouchRacket(cy)) { // 小球与挡板接触 if (pointList.size() == blockHorizontalNum * BLOCK_VERTICAL_NUM) { // 矩形块全部被消灭,游戏结束 status = STATUS_GAME_OVER; return; } isLeft = true; } } else if (cx > width) { // 小球超出挡板区域 status = STATUS_GAME_OVER; } if (cy <= BALL_RADIUS + DIVIDING_LINE_SIZE) { // 小球撞到上边界 angle = 180 - DEFAULT_ANGLE; } else if (cy >= mHeaderHeight - BALL_RADIUS - DIVIDING_LINE_SIZE) { // 小球撞到下边界 angle = 180 + DEFAULT_ANGLE; } if (isLeft) { cx -= speed; } else { cx += speed; } cy -= (float) Math.tan(Math.toRadians(angle)) * speed; canvas.drawCircle(cx, cy, BALL_RADIUS, mPaint); final View thisView = this; thisView.invalidate(); } /** * 绘制矩形色块 * * @param canvas 默认画布 */ protected void drawColorBlock(Canvas canvas) { float left, top; int column, row; for (int i = 0; i < blockHorizontalNum * BLOCK_VERTICAL_NUM; i++) { row = i / blockHorizontalNum; column = i % blockHorizontalNum; boolean flag = false; for (Point point : pointList) { if (point.equals(column, row)) { flag = true; break; } } if (flag) { continue; } blockPaint.setColor(ColorUtils.setAlphaComponent(lModelColor, 255 / (column + 1))); left = blockLeft + column * (blockWidth + DIVIDING_LINE_SIZE); top = DIVIDING_LINE_SIZE + row * (blockHeight + DIVIDING_LINE_SIZE); canvas.drawRect(left, top, left + blockWidth, top + blockHeight, blockPaint); } } // }