日々是好日~every day is a good day~

日常の中の非日常の備忘録

【Android Studio】背景が動く中で飛ぶ鳥

Android Studioの前回 ゲームのひな形として背景が動いているだけのアプリを作りました
せっかくなので今回はそこに飛んでいる鳥を追加したいと思います
1.res/drawableに鳥の画像を準備
今回は『ペーパーミュージアム』さんのフリーイラスト集からお借りしました
paperm.jp
2.MainActivity.ktの編集
前回のプログラムに//*****の部分を追加しました

import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity

var SCREEN_WIDTH = 0
var SCREEN_HEIGHT = 0
var isRunning = false

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val surfaceView: SurfaceView = findViewById(R.id.surfaceview)
        PlayView(this, surfaceView)   //SurfaceViewのインスタンスを生成

        GetScreenSize(this)  //スクリーンサイズの取得
    }

    //スクリーンサイズの取得
    fun GetScreenSize(context: Context) {
        val vm: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = vm.defaultDisplay
        val metric = DisplayMetrics()
        display.getMetrics(metric)
        SCREEN_WIDTH = metric.widthPixels
        SCREEN_HEIGHT = metric.heightPixels
    }
}

// SurfaceViewを継承したクラス
class PlayView: SurfaceView, SurfaceHolder.Callback {
    private var surfaceHolder: SurfaceHolder? = null

    constructor(context: Context, surfaceView: SurfaceView) : super(context) {
        surfaceHolder = surfaceView.holder
        // コールバック
        surfaceHolder!!.addCallback(this)
    }

    override fun surfaceCreated(p0: SurfaceHolder) {
        val playgame = PlayGame(surfaceHolder!!, resources)
            //ゲームスタート
            isRunning = true
            playgame.start()
    }

    override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {

    }

    override fun surfaceDestroyed(p0: SurfaceHolder) {

    }
}

//ゲームのThreadクラス
class PlayGame:Thread{
    private var holder : SurfaceHolder
    private var resources : Resources
    private var backBitmap : Bitmap
    private val bird : Bird     //*****追加
    constructor(holder: SurfaceHolder, resources: Resources) {
        this.holder = holder
        this.resources = resources
        backBitmap = BitmapFactory.decodeResource(resources, R.drawable.sougen)
        bird = Bird(resources)     //*****追加
    }
    private var backPosx = 0
    private var backPosy = 0
    private var birdCurrent = 0   //*****追加
    
    override fun run() {
        while(isRunning){
            if(holder == null) return
            val canvas = holder.lockCanvas()
            if(canvas != null){
                try {
                    synchronized(holder){
                        BackGround(canvas)   //背景を表示
                        FlyingBird(canvas)   //*****追加
                    }
                }
                finally {
                    holder.unlockCanvasAndPost(canvas)
                }
            }
        }
    }
    private fun BackGround(canvas: Canvas){
        val backVelocity = 5   //背景の移動速度

        backPosx= backPosx - backVelocity
        if(backPosx < -backBitmap.width){
            backPosx = 0
        }
        canvas.drawBitmap(backBitmap,backPosx.toFloat(),backPosy.toFloat(),null)

        //背景をloop表示
        if(backPosx < -(backBitmap.width-SCREEN_WIDTH) ||
            backBitmap.width < SCREEN_WIDTH) {
            canvas.drawBitmap(backBitmap,(backPosx + backBitmap.width).toFloat(),
                backPosy.toFloat(),null)
            canvas.drawBitmap(backBitmap,(backPosx + backBitmap.width*2).toFloat(),
                backPosy.toFloat(),null)
        }
    }
//*****最後まで追加
    private fun FlyingBird(canvas: Canvas) {
        canvas.drawBitmap(bird.getBird(birdCurrent),bird.x.toFloat(),bird.y.toFloat(),null)
        birdCurrent++
        if(birdCurrent > bird.maxFrame)  //birdCurrent > 5
            birdCurrent = 0
    }
}
//Birdクラス
class Bird(res:Resources) {
    var x = 0
    var y = 0
    val maxFrame = 5
    var birdList : ArrayList<Bitmap>

    init {
        birdList = arrayListOf()

        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori1))
        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori1))
        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori1))
        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori2))
        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori2))
        birdList.add(BitmapFactory.decodeResource(res, R.drawable.tori2))

        x=SCREEN_WIDTH/2 - birdList[0].width/2
        y=SCREEN_HEIGHT/2 - birdList[0].height
    }

    fun getBird(current : Int) : Bitmap{
        return birdList.get(current)
    }
}

鳥が羽ばたくアニメーションをBirdクラスにリストとして設定し
それを毎フレームごとに呼び出す関数を追加しました
実行すると

また新しい機能なりキャラクターなりを追加したくなりますね