溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

發(fā)布時間:2021-07-01 11:33:04 來源:億速云 閱讀:130 作者:小新 欄目:移動開發(fā)

這篇文章主要介紹怎么使用kotlin實現(xiàn)一個打方塊的小游戲,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

看下要實現(xiàn)的效果圖:

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

看著效果圖好像挺難的樣子,但理清思緒后,你會發(fā)現(xiàn)特別的簡單,還是那句話,學(xué)習方法最重要

思路

1、構(gòu)造界面 :

這個部分比較簡單,根據(jù)控件的比例來畫小球、擋板和擊打的方塊,所有擊打的方塊存儲在一個集合里面,方塊里面存儲的信息有l(wèi)eft、top、right、bottom位置信息和是否被擊打過了的標志

2、擋板的滑動 :

下面的擋板需要根據(jù)手勢的左右移動來反彈小球,所以,我們可以重寫onTouch來實現(xiàn)

3、小球的運動 :

我們在線程里面開啟一個white循環(huán),不停的改變小球的位置,然后重繪界面,小球的運動是有規(guī)則的,碰到四周的界面要回彈,碰到擊打的方塊要回彈,碰到擋板也要回彈,那么,如何回彈呢?我們給小球做一個累加值,讓小球不停的去加這個值,碰到碰撞物我們就給這個累加值取反,舉個例子,現(xiàn)在offsetX是一個正整數(shù),那么ballX+=offsetX,現(xiàn)在小球是往右移動,當碰撞到最右邊的時候,我們給offsetX取反,也就是offsetX=offsetX*-1,這時候offsetX變成了一個負數(shù),那么小球ballX+=offset就會越加越少,也就是往左移動,移動到最左邊的時候我們又給offsetX=offsetX*-1,這時候offsetX又變回了正數(shù),這時候,來回的反彈就實現(xiàn)了,ballY的移動也是如此

4、小球擊打方塊 :

小球擊打到方塊有四個方向:左、上、右、下,我們就說說擊打下方的判斷吧,小球頂部碰撞到方塊的區(qū)域為方塊的left和right區(qū)域,并且當小球的頂部剛好突破方塊的bottom位置時,算是一次有效的碰撞,然后我們給這次碰撞做一個標記,然后反彈小球,下次做碰撞的時候我們忽略已經(jīng)碰撞過的地方,并且不繪制碰撞過的區(qū)域

5、游戲結(jié)束 :

在每次循環(huán)結(jié)束時都去統(tǒng)計集合里碰撞標志數(shù)量是否等于集合的size,是的話就結(jié)束循環(huán),游戲結(jié)束

思路整理清晰后,我們來一一實現(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坐標
 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)畫好了

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

然后,我們來畫一下被擊打的方塊,首先定義一個存儲方塊信息的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 
 
 /*初始化方塊 設(shè)置一個三行四列的方塊*/
 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,方塊完美的繪制

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

擋板的滑動

擋板的滑動部分,我們只需要重寫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
 }

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

小球的運動

小球的運動是這里面最核心的部分了,我們得細細的講講
首先,我們需要定義一個線程,在線程里面定義一個while循環(huán),sleep50毫秒去重回界面,所以,我們要在這50毫秒的時間里,去改變小球的運動軌跡、邊界值情況、是否碰撞到方塊、是否碰撞到擋板和游戲是否結(jié)束,我們先把小球給運動起來再說

 /**
 * 結(jié)束循環(huán)的標志位
 */
 var isOver: Boolean = false
 /**
 * 小球x方向每次移動的偏移量
 */
 var vx: Float = 8f
 /**
 * 小球y方向每次移動的偏移量
 * 默認為負數(shù),因為小球是向上運動 
 */
 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()
 }

小球開始運動了,咦,小球怎么突然不見了,哈哈,因為被方塊遮擋住了

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

小球移動解決了,接下來我們來處理下小球彈到擋板反彈

  //開啟線程
  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) {
   //判斷小球是否落在滑塊上
   ...
    /*
     * 循環(huán)集合的每一個方塊,判斷小球當前的位置是否碰撞到方塊
     */
    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) {
      //設(shè)置該方塊已被撞擊
      brick.isImpact = true
      //方向取反
      vy *= -1
     }
    }
    /*
     * 統(tǒng)計被撞擊方塊的數(shù)量是否等于集合,是的話表明游戲結(jié)束,設(shè)置結(jié)束標志位,停止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)
  }  
 }

最終效果圖

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

通關(guān)成功

怎么使用kotlin實現(xiàn)一個打方塊的小游戲

以上是“怎么使用kotlin實現(xiàn)一個打方塊的小游戲”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI