LoginSignup
1
0

More than 5 years have passed since last update.

kotlinでandroidの入門 ブロック崩し2

Posted at

ボール以外の壁、ブロック、バーのクラスを作り
それぞれ配置(生成)と衝突判定を実装しています

壁は

kabe.kt
class Kabe(val ball : Ball) {
    private var width  : Float = 0F
    private var height : Float = 0F

    // 配置 (画面サイズをもらう)
    fun arrangement( vw : Float, vh : Float) {
        width = vw
        height = vh
    }
    // 衝突判定 戻り true = ぶつかった&ボール反転させた
    fun chkCollision( ) : Boolean {
        return if (ball.newLeft < 0 ) {
            // 左
            ball.resetNewX(0F )
            true
        } else if ( ball.newRight >= width ) {
            // 右
            ball.resetNewX( width )
            true
        } else if (ball.newTop < 0 ) {
            ball.resetNewY(0F)
            true
        } else if (ball.newBottom >= height ) {
            ball.resetNewY(height)
            true
        } else {
            false
        }
    }
}

ブロックは、

配列を使い複数配置
ぶつかったら消す。

block.kt
class Block (val ball : Ball ) {
    val take : Int = 3
    val yoko : Int = 5

    private val top : Float = 10F
    private val height : Float = 40F
    private var stepy : Float = height+ 20F

    private var left : Float = 0F
    private var stepx : Float = 0F
    private var width : Float = 0F
    private var blockSt = Array<Boolean>( take * yoko, { true } )


    //
    val blockCount : Int
        get() = blockSt.count { it == true }

    private fun getTakeIndex(idx : Int) : Int {
        return  idx / yoko
    }
    private fun getColumnIndex( idx : Int, line : Int) : Int {
        return  idx - ( line * yoko )
    }
    fun chkBlock( idx : Int ) : Boolean {
        return blockSt[idx]
    }
    fun getRect( idx : Int) : RectFloat {
        var r : RectFloat = RectFloat()
        if ( blockSt[idx] == true) {
            val line = getTakeIndex(idx)
            val column = getColumnIndex(idx, line)
            r.left = left + (column * stepx )
            r.right = r.left + width
            r.top = top + (line * stepy)
            r.bottom =r.top + height
        }
        return r
    }
    fun arrangement( viewWidth : Float, viewHight : Float) {
        stepx = viewWidth / (yoko+1)
        left = stepx / 2
        width = stepx * 0.8F
    }
    fun reset() {
        blockSt = Array<Boolean>( take * yoko, { true } )
    }


    // 衝突判定 それっぽく
    fun chkCollision(): Boolean {
        var r: Boolean = false

        for (l in 0..take - 1) {
            val yt = top + (l * stepy)
            val yb = yt + height
            if (ball.newBottom >= yt && ball.newTop <= yb) {
                for (c in 0..yoko - 1) {
                    if ( true == blockSt[ l*yoko+c]) {
                        val xl = left + (c * stepx)
                        val xr = xl + width
                        if (ball.newRight >= xl && ball.newLeft <= xr) {
                            // ぶつかっている 
                            blockSt[l * yoko + c] = false

                            val ts = Math.abs(yt - ball.bottom)
                            val bs = Math.abs(yb - ball.top)
                            val ls = Math.abs(xl - ball.right)
                            val bl = Math.abs(xr - ball.left)
                            if (ts <= bs && ts <= ls && ts <= bl) {
                                // 上からぶつかったことに
                                ball.resetNewY(yt)
                            } else if (bs <= ts && bs <= ls && bs <= bl) {
                                ball.resetNewY(yb)
                            } else if (ls <= ts && ls <= bs && ls <= bl) {
                                ball.resetNewX(xl)
                            } else {
                                ball.resetNewX(xr)
                            }
                            return true
                        }
                    }
                }
            }
        }
        return false
    }
}

// 有るかも or 本当はここまでいらないと思う
class RectFloat(var left : Float = 0F, var top : Float = 0F, var right : Float = 0F, var bottom : Float = 0F)

バー(ラケットにすればわかりやすかったな)は

ボタンで左右に移動するようにして
衝突は上からのみ判断してます

Bar.kt
class Bar(val ball : Ball ) {
    // バーの移動状態
    enum class MoveSw {
        move_stop,
        move_left,
        move_right
    }

    // ここでバーの表示状態指定
    private val OffsetY : Float = 100F
    private val h : Float = 20F

    private var vWidth : Float = 0F
    private var x : Float = 0F
    private var y : Float = 0F
    private var moveFlg : MoveSw = MoveSw.move_stop
    private var targetX : Float = 0F

    private var size : Float = 100F
    private var moveSize : Float = 10F

    // バーの座標情報
    val top : Float
        get() = y
    val bottom : Float
        get() = y+h
    val left : Float
        get() = x-size
    val right : Float
        get() = x+size
    val center : Float
        get() = x

    // 配置 (画面の大きさに合わせる)
    fun arrangement( vw : Float, vh : Float) {
        vWidth = vw
        y = vh - OffsetY
    }
    fun reset(barWidih : Float , kizami : Float ) {
        x = vWidth / 2
        size = barWidih
        moveSize = kizami
    }
    fun chkCollision( ) : Boolean {
        var r: Boolean = false
        if ( ball.bottom < y  && ball.newBottom >= y) {
            if ((  ball.right>left || ball.newRight>left ) &&
                    (ball.left < right || ball.newLeft < right))   {
                // ざっくりとした判定 
                ball.resetNewY( y )
                when(moveFlg) {
                    MoveSw.move_left -> { ball.vectorAcceleX(-0.1F)}
                    MoveSw.move_right -> {ball.vectorAcceleX(0.1F)}
                }
                r = true
            }
        }
        return r
    }
    fun chkLeftRight( px : Int, py :Int) {
        targetX = if ( py > top && py < top+100F ) {
            if ((x + (size / 3)) < px) {
                px.toFloat()
            } else if ((x - (size / 3)) > px ) {
                px.toFloat()
            } else {
                moveFlg = MoveSw.move_stop
                0F
            }
        } else {
            Log.d("out", px.toString()+","+(x.toInt()).toString())
            moveFlg = MoveSw.move_stop
            0F
        }
    }
    fun setMove(LeftRight:MoveSw, goStop : Boolean ) {
        if ( goStop == true) {
            moveFlg = LeftRight
        } else if ( moveFlg == LeftRight ) {
            moveFlg = MoveSw.move_stop
        }
    }
    fun moveTo() {
        moveFlg = if ( 0F != targetX ) {
            if ( (x-(size/3)) >= targetX ) {
                MoveSw.move_left
            } else if ( (x+(size/3)) <= targetX) {
                MoveSw.move_right
            } else {
                targetX = 0F
                MoveSw.move_stop
            }
        } else {
            moveFlg
        }
        x = when(moveFlg) {
            MoveSw.move_left -> {
                if (left < 0F) {
                    size
                } else {
                    x - moveSize
                }
            }
            MoveSw.move_right-> {
                if (right > vWidth) {
                    vWidth - size
                } else {
                    x + moveSize
                }
            }
            else -> { x }
        }
    }
}

blockBreak.png

こんな感じて
コードはgitに置いてます

おまけ

壁は四方にあるので、下からも跳ね返ります
ゲームとして成り立ってません
(負けの判定作るのが面倒だったんですが)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0