您好,登錄后才能下訂單哦!
這篇文章主要介紹怎么使用kotlin實現一個打方塊的小游戲,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
看下要實現的效果圖:
看著效果圖好像挺難的樣子,但理清思緒后,你會發現特別的簡單,還是那句話,學習方法最重要
思路
1、構造界面 :
這個部分比較簡單,根據控件的比例來畫小球、擋板和擊打的方塊,所有擊打的方塊存儲在一個集合里面,方塊里面存儲的信息有left、top、right、bottom位置信息和是否被擊打過了的標志
2、擋板的滑動 :
下面的擋板需要根據手勢的左右移動來反彈小球,所以,我們可以重寫onTouch來實現
3、小球的運動 :
我們在線程里面開啟一個white循環,不停的改變小球的位置,然后重繪界面,小球的運動是有規則的,碰到四周的界面要回彈,碰到擊打的方塊要回彈,碰到擋板也要回彈,那么,如何回彈呢?我們給小球做一個累加值,讓小球不停的去加這個值,碰到碰撞物我們就給這個累加值取反,舉個例子,現在offsetX是一個正整數,那么ballX+=offsetX,現在小球是往右移動,當碰撞到最右邊的時候,我們給offsetX取反,也就是offsetX=offsetX*-1,這時候offsetX變成了一個負數,那么小球ballX+=offset就會越加越少,也就是往左移動,移動到最左邊的時候我們又給offsetX=offsetX*-1,這時候offsetX又變回了正數,這時候,來回的反彈就實現了,ballY的移動也是如此
4、小球擊打方塊 :
小球擊打到方塊有四個方向:左、上、右、下,我們就說說擊打下方的判斷吧,小球頂部碰撞到方塊的區域為方塊的left和right區域,并且當小球的頂部剛好突破方塊的bottom位置時,算是一次有效的碰撞,然后我們給這次碰撞做一個標記,然后反彈小球,下次做碰撞的時候我們忽略已經碰撞過的地方,并且不繪制碰撞過的區域
5、游戲結束 :
在每次循環結束時都去統計集合里碰撞標志數量是否等于集合的size,是的話就結束循環,游戲結束
思路整理清晰后,我們來一一實現
構造界面
首先來繪制一下小球和擋板
var width: Float = 0f var height: Float = 0f /** * 移動滑塊的寬度 */ var boardWdith: Float = 0f /** * 擋板的高度 */ var boardHeight: Float = 0f /** * 擋板距離頂部的距離 */ var board2Top: Float = 0f /** * 擋板距離左邊的距離 */ var board2Left: Float = 0f /** * 小球的半徑 */ var ballRadius: Float = 0f override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) width = w.toFloat() height = h.toFloat() //擋板的寬度 boardWdith = width / 8 //擋板距離頂部的距離 board2Top = height / 8 * 7 //擋板的left距離左邊的距離,目的使擋板居中 board2Left = width / 2 - boardWdith / 2 //設置小球的半徑為擋板的1/4 ballRadius = boardWdith / 4 //設置小球的x和y坐標 ballX = width / 2 ballY = board2Top - ballRadius - dip(10).toFloat() / 2 ballPaint.style = Paint.Style.FILL ballPaint.isAntiAlias = true ballPaint.color = resources.getColor(R.color.colorAccent) boardPaint.style = Paint.Style.STROKE boardPaint.isAntiAlias = true boardPaint.strokeWidth = dip(10).toFloat() boardPaint.color = resources.getColor(R.color.colorPrimary) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) setBackgroundColor(resources.getColor(R.color.black)) canvas.drawLine(board2Left, board2Top, board2Left + boardWdith, board2Top, boardPaint) canvas.drawCircle(ballX, ballY, ballRadius, ballPaint) }
ok,擋板和小球已經畫好了
然后,我們來畫一下被擊打的方塊,首先定義一個存儲方塊信息的Bean類
/** * @author wangqi * @since 2017/12/10 17:26 */ public class Brick { /** * 存儲方塊的顏色 */ private String color; /** * 存儲方塊的坐標 */ private RectF rectF; /** * 判斷是否碰撞到了,默認為false未碰撞 */ private boolean isImpact; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public RectF getRectF() { return rectF; } public void setRectF(RectF rectF) { this.rectF = rectF; } public boolean isImpact() { return isImpact; } public void setImpact(boolean impact) { isImpact = impact; } }
然后我們來看看怎么繪制
/** * 定義一個存儲方塊的集合 */ var brickList: MutableList<Brick> = mutableListOf() /** * 方塊的寬度 */ var brickWidth = 0f /** * 方塊的高度 */ var brickHeight = 0f override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) ... //方塊的寬度是view的1/5 brickWidth = width / 5 //方塊的高度是寬度的一半 brickHeight = brickWidth / 2 /*初始化方塊 設置一個三行四列的方塊*/ for (row in 0..3) { for (col in 0..4) { createBricks(row, col) } } paintLine.strokeWidth = dip(1.0f).toFloat() paintLine.isAntiAlias = true paintLine.textSize = dip(width / 50).toFloat() paintLine.style = Paint.Style.FILL } /** * 創建方塊 */ fun createBricks(row: Int, col: Int) { var brick = Brick() var rectF = RectF() rectF.left = brickWidth * col rectF.top = brickHeight * row rectF.right = brickWidth * (col + 1) rectF.bottom = brickHeight * (row + 1) brick.rectF = rectF val hex = "#" + Integer.toHexString((-16777216 * Math.random()).toInt()) brick.color = hex brickList.add(brick) }
ok,方塊完美的繪制
擋板的滑動
擋板的滑動部分,我們只需要重寫onTouch方法,然后再每次move的過程中去改變擋板距離View左邊界的距離
override fun onTouchEvent(event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN -> { } MotionEvent.ACTION_MOVE -> { board2Left = event.x - boardWdith / 2 invalidate() } MotionEvent.ACTION_UP -> { } } return true }
小球的運動
小球的運動是這里面最核心的部分了,我們得細細的講講
首先,我們需要定義一個線程,在線程里面定義一個while循環,sleep50毫秒去重回界面,所以,我們要在這50毫秒的時間里,去改變小球的運動軌跡、邊界值情況、是否碰撞到方塊、是否碰撞到擋板和游戲是否結束,我們先把小球給運動起來再說
/** * 結束循環的標志位 */ var isOver: Boolean = false /** * 小球x方向每次移動的偏移量 */ var vx: Float = 8f /** * 小球y方向每次移動的偏移量 * 默認為負數,因為小球是向上運動 */ var vy: Float = -8f override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) ... //開啟線程 thread { while (!isOver) { ballX += vx ballY += vy /* 邊界值判定 如果小球小于左邊界或大于右邊界則x方向取反 */ if (ballX + ballRadius > width || ballX - ballRadius < 0) { vx *= -1 } /* 邊界值判定 如果小球大于底部邊界或小于頂部邊界則Y方向取反 */ if (ballY - ballRadius < 0 || ballY + ballRadius > height) { vy *= -1 } Thread.sleep(50) postInvalidate() } }.start() }
小球開始運動了,咦,小球怎么突然不見了,哈哈,因為被方塊遮擋住了
小球移動解決了,接下來我們來處理下小球彈到擋板反彈
//開啟線程 thread { while (!isOver) { //邊界值判斷 ... /* 判斷小球是否落在滑塊上 小球x軸的中心大于擋板的left并且小球x軸中心小于擋板的右邊并且小球的y軸中心加上半徑加上擋板高度的一半 */ if (ballX >= board2Left && ballX <= board2Left + boardWdith && ballY >= board2Top - ballRadius - dip(10).toFloat() / 2 ) { //改變Y軸的運動方向 vy *= -1 } ... } }
擋板的判斷知道了,那么小球和方塊的碰撞也就自然清晰了
//開啟線程 thread { while (!isOver) { //判斷小球是否落在滑塊上 ... /* * 循環集合的每一個方塊,判斷小球當前的位置是否碰撞到方塊 */ for (i in brickList.indices) { //拿到方塊 val brick = brickList[i] //忽略撞擊過的方塊 if (brick.isImpact) { continue } //獲取方塊的坐標 val rectF = brick.rectF /* 判斷小球是否撞擊到方塊的底部 小球x軸的中心大于方塊的left 小球x軸的中心小于方塊的right 小球y軸中心減去半徑,也就是小球的頂部,是否小于等于方塊的底部,也就是穿過方塊底部的一瞬間 */ if (ballX >= rectF.left && ballX <= rectF.right && ballY - ballRadius <= rectF.bottom) { //設置該方塊已被撞擊 brick.isImpact = true //方向取反 vy *= -1 } } /* * 統計被撞擊方塊的數量是否等于集合,是的話表明游戲結束,設置結束標志位,停止while循環 */ if (brickList.count { it.isImpact } == brickList.size) { isOver = true } ... } } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) ... if (isOver) { val text = "通關成功" //獲取文字的寬度,目的是為了文字居中 val textWidth = paintLine.measureText(text) canvas.drawText(text, width / 2 - textWidth / 2, 100, paintLine) } }
最終效果圖
通關成功
以上是“怎么使用kotlin實現一個打方塊的小游戲”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。