利用kotlin實(shí)現(xiàn)一個(gè)打方塊的小游戲?qū)嵗坛?/h1>
更新時(shí)間:2017年12月26日 09:54:26 作者:codelang
最近在學(xué)習(xí)kotlin,利用其實(shí)現(xiàn)了一個(gè)小游戲,覺著有必要和大家分享下,所以下面這篇文章主要給大家介紹了關(guān)于利用kotlin實(shí)現(xiàn)一個(gè)打方塊的小游戲的相關(guān)資料,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
前言
今天來做個(gè)打方塊的小游戲,繼續(xù)熟悉kotlin的語法,更多關(guān)于kotlin的語法大家可以參考這篇文章:http://www.dbjr.com.cn/article/114069.htm
看下要實(shí)現(xiàn)的效果圖:

看著效果圖好像挺難的樣子,但理清思緒后,你會發(fā)現(xiàn)特別的簡單,還是那句話,學(xué)習(xí)方法最重要
思路
1、構(gòu)造界面 :
這個(gè)部分比較簡單,根據(jù)控件的比例來畫小球、擋板和擊打的方塊,所有擊打的方塊存儲在一個(gè)集合里面,方塊里面存儲的信息有l(wèi)eft、top、right、bottom位置信息和是否被擊打過了的標(biāo)志
2、擋板的滑動 :
下面的擋板需要根據(jù)手勢的左右移動來反彈小球,所以,我們可以重寫onTouch來實(shí)現(xiàn)
3、小球的運(yùn)動 :
我們在線程里面開啟一個(gè)white循環(huán),不停的改變小球的位置,然后重繪界面,小球的運(yùn)動是有規(guī)則的,碰到四周的界面要回彈,碰到擊打的方塊要回彈,碰到擋板也要回彈,那么,如何回彈呢?我們給小球做一個(gè)累加值,讓小球不停的去加這個(gè)值,碰到碰撞物我們就給這個(gè)累加值取反,舉個(gè)例子,現(xiàn)在offsetX是一個(gè)正整數(shù),那么ballX+=offsetX,現(xiàn)在小球是往右移動,當(dāng)碰撞到最右邊的時(shí)候,我們給offsetX取反,也就是offsetX=offsetX*-1,這時(shí)候offsetX變成了一個(gè)負(fù)數(shù),那么小球ballX+=offset就會越加越少,也就是往左移動,移動到最左邊的時(shí)候我們又給offsetX=offsetX*-1,這時(shí)候offsetX又變回了正數(shù),這時(shí)候,來回的反彈就實(shí)現(xiàn)了,ballY的移動也是如此
4、小球擊打方塊 :
小球擊打到方塊有四個(gè)方向:左、上、右、下,我們就說說擊打下方的判斷吧,小球頂部碰撞到方塊的區(qū)域?yàn)榉綁K的left和right區(qū)域,并且當(dāng)小球的頂部剛好突破方塊的bottom位置時(shí),算是一次有效的碰撞,然后我們給這次碰撞做一個(gè)標(biāo)記,然后反彈小球,下次做碰撞的時(shí)候我們忽略已經(jīng)碰撞過的地方,并且不繪制碰撞過的區(qū)域
5、游戲結(jié)束 :
在每次循環(huán)結(jié)束時(shí)都去統(tǒng)計(jì)集合里碰撞標(biāo)志數(shù)量是否等于集合的size,是的話就結(jié)束循環(huán),游戲結(jié)束
思路整理清晰后,我們來一一實(shí)現(xiàn)
構(gòu)造界面
首先來繪制一下小球和擋板
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
//設(shè)置小球的半徑為擋板的1/4
ballRadius = boardWdith / 4
//設(shè)置小球的x和y坐標(biāo)
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,擋板和小球已經(jīng)畫好了

然后,我們來畫一下被擊打的方塊,首先定義一個(gè)存儲方塊信息的Bean類
/**
* @author wangqi
* @since 2017/12/10 17:26
*/
public class Brick {
/**
* 存儲方塊的顏色
*/
private String color;
/**
* 存儲方塊的坐標(biāo)
*/
private RectF rectF;
/**
* 判斷是否碰撞到了,默認(rèn)為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;
}
}
然后我們來看看怎么繪制
/**
* 定義一個(gè)存儲方塊的集合
*/
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
/*初始化方塊 設(shè)置一個(gè)三行四列的方塊*/
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
}
/**
* 創(chuàng)建方塊
*/
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
}

小球的運(yùn)動
小球的運(yùn)動是這里面最核心的部分了,我們得細(xì)細(xì)的講講
首先,我們需要定義一個(gè)線程,在線程里面定義一個(gè)while循環(huán),sleep50毫秒去重回界面,所以,我們要在這50毫秒的時(shí)間里,去改變小球的運(yùn)動軌跡、邊界值情況、是否碰撞到方塊、是否碰撞到擋板和游戲是否結(jié)束,我們先把小球給運(yùn)動起來再說
/**
* 結(jié)束循環(huán)的標(biāo)志位
*/
var isOver: Boolean = false
/**
* 小球x方向每次移動的偏移量
*/
var vx: Float = 8f
/**
* 小球y方向每次移動的偏移量
* 默認(rèn)為負(fù)數(shù),因?yàn)樾∏蚴窍蛏线\(yùn)動
*/
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()
}
小球開始運(yùn)動了,咦,小球怎么突然不見了,哈哈,因?yàn)楸环綁K遮擋住了

小球移動解決了,接下來我們來處理下小球彈到擋板反彈
//開啟線程
thread {
while (!isOver) {
//邊界值判斷
...
/*
判斷小球是否落在滑塊上
小球x軸的中心大于擋板的left并且小球x軸中心小于擋板的右邊并且小球的y軸中心加上半徑加上擋板高度的一半
*/
if (ballX >= board2Left && ballX <= board2Left + boardWdith
&& ballY >= board2Top - ballRadius - dip(10).toFloat() / 2
) {
//改變Y軸的運(yùn)動方向
vy *= -1
}
...
}
}
擋板的判斷知道了,那么小球和方塊的碰撞也就自然清晰了
//開啟線程
thread {
while (!isOver) {
//判斷小球是否落在滑塊上
...
/*
* 循環(huán)集合的每一個(gè)方塊,判斷小球當(dāng)前的位置是否碰撞到方塊
*/
for (i in brickList.indices) {
//拿到方塊
val brick = brickList[i]
//忽略撞擊過的方塊
if (brick.isImpact) {
continue
}
//獲取方塊的坐標(biāo)
val rectF = brick.rectF
/*
判斷小球是否撞擊到方塊的底部
小球x軸的中心大于方塊的left
小球x軸的中心小于方塊的right
小球y軸中心減去半徑,也就是小球的頂部,是否小于等于方塊的底部,也就是穿過方塊底部的一瞬間
*/
if (ballX >= rectF.left && ballX <= rectF.right && ballY - ballRadius <= rectF.bottom) {
//設(shè)置該方塊已被撞擊
brick.isImpact = true
//方向取反
vy *= -1
}
}
/*
* 統(tǒng)計(jì)被撞擊方塊的數(shù)量是否等于集合,是的話表明游戲結(jié)束,設(shè)置結(jié)束標(biāo)志位,停止while循環(huán)
*/
if (brickList.count { it.isImpact } == brickList.size) {
isOver = true
}
...
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
...
if (isOver) {
val text = "通關(guān)成功"
//獲取文字的寬度,目的是為了文字居中
val textWidth = paintLine.measureText(text)
canvas.drawText(text, width / 2 - textWidth / 2, 100, paintLine)
}
}
最終效果圖

通關(guān)成功

總結(jié)
小球碰撞到底部邊界的判斷我沒有去做,原因是為了能擊打到方塊,增加趣味性,還有碰撞方塊的四個(gè)方向,我只做了碰撞到底部的方向,有興趣的同學(xué)可以自己試著補(bǔ)上,查看完整源碼
理論和實(shí)踐相輔相成,理論是規(guī)劃實(shí)踐的實(shí)施性,實(shí)踐是為了證明理論
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
-
Android NDK開發(fā)(C語言基本數(shù)據(jù)類型)
這篇文章主要介紹了Android NDK開發(fā)中,C語言基本數(shù)據(jù)類型,主要以C語言包含的數(shù)據(jù)類型及基本類型展開相關(guān)資料,需要的朋友可以參考一下 2021-12-12
-
Android使用WebView.loadUri()打開網(wǎng)頁的方法
這篇文章主要介紹了Android使用WebView.loadUri()打開網(wǎng)頁的方法,結(jié)合實(shí)例形式分析了Android中WebView控件的loadUri()打開網(wǎng)頁的使用技巧,需要的朋友可以參考下 2016-01-01
-
Android實(shí)現(xiàn)搜索功能并本地保存搜索歷史記錄
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)搜索功能,并實(shí)現(xiàn)本地保存搜索歷史記錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下 2016-03-03
-
Android原生項(xiàng)目集成React Native的方法
本篇文章主要介紹了Android原生項(xiàng)目集成React Native的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
2017-11-11
-
android TextView中識別多個(gè)url并分別點(diǎn)擊跳轉(zhuǎn)方法詳解
在本篇文章里小編給大家整理的是關(guān)于android TextView中識別多個(gè)url并分別點(diǎn)擊跳轉(zhuǎn)方法詳解,需要的朋友們可以學(xué)習(xí)參考下。 2019-08-08
-
Android制作微信app頂部menu菜單(ActionBar)
這篇文章主要為大家詳細(xì)介紹了Android利用ActionBar制作微信app頂部menu菜單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下 2017-02-02
-
Android 后臺運(yùn)行白名單實(shí)現(xiàn)?;?/a>
這篇文章主要介紹了Android 后臺運(yùn)行白名單實(shí)現(xiàn)保活,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧 2019-12-12
-
解析Android開發(fā)優(yōu)化之:對界面UI的優(yōu)化詳解(三)
本篇文章主要討論一下復(fù)雜界面中常用的一種技術(shù)——界面延遲加載技術(shù) 2013-05-05
最新評論
前言
今天來做個(gè)打方塊的小游戲,繼續(xù)熟悉kotlin的語法,更多關(guān)于kotlin的語法大家可以參考這篇文章:http://www.dbjr.com.cn/article/114069.htm
看下要實(shí)現(xiàn)的效果圖:

看著效果圖好像挺難的樣子,但理清思緒后,你會發(fā)現(xiàn)特別的簡單,還是那句話,學(xué)習(xí)方法最重要
思路
1、構(gòu)造界面 :
這個(gè)部分比較簡單,根據(jù)控件的比例來畫小球、擋板和擊打的方塊,所有擊打的方塊存儲在一個(gè)集合里面,方塊里面存儲的信息有l(wèi)eft、top、right、bottom位置信息和是否被擊打過了的標(biāo)志
2、擋板的滑動 :
下面的擋板需要根據(jù)手勢的左右移動來反彈小球,所以,我們可以重寫onTouch來實(shí)現(xiàn)
3、小球的運(yùn)動 :
我們在線程里面開啟一個(gè)white循環(huán),不停的改變小球的位置,然后重繪界面,小球的運(yùn)動是有規(guī)則的,碰到四周的界面要回彈,碰到擊打的方塊要回彈,碰到擋板也要回彈,那么,如何回彈呢?我們給小球做一個(gè)累加值,讓小球不停的去加這個(gè)值,碰到碰撞物我們就給這個(gè)累加值取反,舉個(gè)例子,現(xiàn)在offsetX是一個(gè)正整數(shù),那么ballX+=offsetX,現(xiàn)在小球是往右移動,當(dāng)碰撞到最右邊的時(shí)候,我們給offsetX取反,也就是offsetX=offsetX*-1,這時(shí)候offsetX變成了一個(gè)負(fù)數(shù),那么小球ballX+=offset就會越加越少,也就是往左移動,移動到最左邊的時(shí)候我們又給offsetX=offsetX*-1,這時(shí)候offsetX又變回了正數(shù),這時(shí)候,來回的反彈就實(shí)現(xiàn)了,ballY的移動也是如此
4、小球擊打方塊 :
小球擊打到方塊有四個(gè)方向:左、上、右、下,我們就說說擊打下方的判斷吧,小球頂部碰撞到方塊的區(qū)域?yàn)榉綁K的left和right區(qū)域,并且當(dāng)小球的頂部剛好突破方塊的bottom位置時(shí),算是一次有效的碰撞,然后我們給這次碰撞做一個(gè)標(biāo)記,然后反彈小球,下次做碰撞的時(shí)候我們忽略已經(jīng)碰撞過的地方,并且不繪制碰撞過的區(qū)域
5、游戲結(jié)束 :
在每次循環(huán)結(jié)束時(shí)都去統(tǒng)計(jì)集合里碰撞標(biāo)志數(shù)量是否等于集合的size,是的話就結(jié)束循環(huán),游戲結(jié)束
思路整理清晰后,我們來一一實(shí)現(xiàn)
構(gòu)造界面
首先來繪制一下小球和擋板
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
//設(shè)置小球的半徑為擋板的1/4
ballRadius = boardWdith / 4
//設(shè)置小球的x和y坐標(biāo)
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,擋板和小球已經(jīng)畫好了

然后,我們來畫一下被擊打的方塊,首先定義一個(gè)存儲方塊信息的Bean類
/**
* @author wangqi
* @since 2017/12/10 17:26
*/
public class Brick {
/**
* 存儲方塊的顏色
*/
private String color;
/**
* 存儲方塊的坐標(biāo)
*/
private RectF rectF;
/**
* 判斷是否碰撞到了,默認(rèn)為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;
}
}
然后我們來看看怎么繪制
/**
* 定義一個(gè)存儲方塊的集合
*/
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
/*初始化方塊 設(shè)置一個(gè)三行四列的方塊*/
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
}
/**
* 創(chuàng)建方塊
*/
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
}

小球的運(yùn)動
小球的運(yùn)動是這里面最核心的部分了,我們得細(xì)細(xì)的講講
首先,我們需要定義一個(gè)線程,在線程里面定義一個(gè)while循環(huán),sleep50毫秒去重回界面,所以,我們要在這50毫秒的時(shí)間里,去改變小球的運(yùn)動軌跡、邊界值情況、是否碰撞到方塊、是否碰撞到擋板和游戲是否結(jié)束,我們先把小球給運(yùn)動起來再說
/**
* 結(jié)束循環(huán)的標(biāo)志位
*/
var isOver: Boolean = false
/**
* 小球x方向每次移動的偏移量
*/
var vx: Float = 8f
/**
* 小球y方向每次移動的偏移量
* 默認(rèn)為負(fù)數(shù),因?yàn)樾∏蚴窍蛏线\(yùn)動
*/
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()
}
小球開始運(yùn)動了,咦,小球怎么突然不見了,哈哈,因?yàn)楸环綁K遮擋住了

小球移動解決了,接下來我們來處理下小球彈到擋板反彈
//開啟線程
thread {
while (!isOver) {
//邊界值判斷
...
/*
判斷小球是否落在滑塊上
小球x軸的中心大于擋板的left并且小球x軸中心小于擋板的右邊并且小球的y軸中心加上半徑加上擋板高度的一半
*/
if (ballX >= board2Left && ballX <= board2Left + boardWdith
&& ballY >= board2Top - ballRadius - dip(10).toFloat() / 2
) {
//改變Y軸的運(yùn)動方向
vy *= -1
}
...
}
}
擋板的判斷知道了,那么小球和方塊的碰撞也就自然清晰了
//開啟線程
thread {
while (!isOver) {
//判斷小球是否落在滑塊上
...
/*
* 循環(huán)集合的每一個(gè)方塊,判斷小球當(dāng)前的位置是否碰撞到方塊
*/
for (i in brickList.indices) {
//拿到方塊
val brick = brickList[i]
//忽略撞擊過的方塊
if (brick.isImpact) {
continue
}
//獲取方塊的坐標(biāo)
val rectF = brick.rectF
/*
判斷小球是否撞擊到方塊的底部
小球x軸的中心大于方塊的left
小球x軸的中心小于方塊的right
小球y軸中心減去半徑,也就是小球的頂部,是否小于等于方塊的底部,也就是穿過方塊底部的一瞬間
*/
if (ballX >= rectF.left && ballX <= rectF.right && ballY - ballRadius <= rectF.bottom) {
//設(shè)置該方塊已被撞擊
brick.isImpact = true
//方向取反
vy *= -1
}
}
/*
* 統(tǒng)計(jì)被撞擊方塊的數(shù)量是否等于集合,是的話表明游戲結(jié)束,設(shè)置結(jié)束標(biāo)志位,停止while循環(huán)
*/
if (brickList.count { it.isImpact } == brickList.size) {
isOver = true
}
...
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
...
if (isOver) {
val text = "通關(guān)成功"
//獲取文字的寬度,目的是為了文字居中
val textWidth = paintLine.measureText(text)
canvas.drawText(text, width / 2 - textWidth / 2, 100, paintLine)
}
}
最終效果圖

通關(guān)成功

總結(jié)
小球碰撞到底部邊界的判斷我沒有去做,原因是為了能擊打到方塊,增加趣味性,還有碰撞方塊的四個(gè)方向,我只做了碰撞到底部的方向,有興趣的同學(xué)可以自己試著補(bǔ)上,查看完整源碼
理論和實(shí)踐相輔相成,理論是規(guī)劃實(shí)踐的實(shí)施性,實(shí)踐是為了證明理論
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Android NDK開發(fā)(C語言基本數(shù)據(jù)類型)
這篇文章主要介紹了Android NDK開發(fā)中,C語言基本數(shù)據(jù)類型,主要以C語言包含的數(shù)據(jù)類型及基本類型展開相關(guān)資料,需要的朋友可以參考一下2021-12-12
Android使用WebView.loadUri()打開網(wǎng)頁的方法
這篇文章主要介紹了Android使用WebView.loadUri()打開網(wǎng)頁的方法,結(jié)合實(shí)例形式分析了Android中WebView控件的loadUri()打開網(wǎng)頁的使用技巧,需要的朋友可以參考下2016-01-01
Android實(shí)現(xiàn)搜索功能并本地保存搜索歷史記錄
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)搜索功能,并實(shí)現(xiàn)本地保存搜索歷史記錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03
Android原生項(xiàng)目集成React Native的方法
本篇文章主要介紹了Android原生項(xiàng)目集成React Native的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
android TextView中識別多個(gè)url并分別點(diǎn)擊跳轉(zhuǎn)方法詳解
在本篇文章里小編給大家整理的是關(guān)于android TextView中識別多個(gè)url并分別點(diǎn)擊跳轉(zhuǎn)方法詳解,需要的朋友們可以學(xué)習(xí)參考下。2019-08-08
Android制作微信app頂部menu菜單(ActionBar)
這篇文章主要為大家詳細(xì)介紹了Android利用ActionBar制作微信app頂部menu菜單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Android 后臺運(yùn)行白名單實(shí)現(xiàn)?;?/a>
這篇文章主要介紹了Android 后臺運(yùn)行白名單實(shí)現(xiàn)保活,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
解析Android開發(fā)優(yōu)化之:對界面UI的優(yōu)化詳解(三)
本篇文章主要討論一下復(fù)雜界面中常用的一種技術(shù)——界面延遲加載技術(shù)2013-05-05

