Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
198 views
in Technique[技术] by (71.8m points)

java - Android / Kotlin: How to make moving background with SurfaceView and SurfaceHolder

I'm new to Kotlin and Android. I'm trying to make moving background for 2D game and exactly following this video but in Kotlin. (https://www.youtube.com/watch?v=RQoT9BUsl1Q&list=PLsOU6EOcj51e7YesVnTrEtvJDD016p9oS&index=3)

My problem is that after clicking "play" button, all I see is just black screen. But, I see that the thread is still running(update->draw->sleep). So, I guess I might have problem with setting up screen or background related stuffs.

Emulator: Nexux 4 API29, 768x1280, android 10.0

Before click play button

After click play button

If you could give me any kind of advice, I would really appreciate it. Thank you in advance.

  1. [GameView.kt]

import android.content.Context
import android.graphics.*
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView

class GameView(context: Context, screenX: Int, screenY: Int): SurfaceView(context), SurfaceHolder.Callback{

    private lateinit var thread: Thread
    private var isPlaying: Boolean? =null
    private lateinit var background1: Background
    private lateinit var background2: Background
    private var screenX: Int? = null
    private var screenY: Int? = null
    private lateinit var ourHolder: SurfaceHolder
    private val painter = Paint()

    private var screenRatioX: Float? = null
    private var screenRatioY: Float? = null

    init{
        this.screenX = screenX
        this.screenY = screenY

        screenRatioX = 1184f / screenX
        screenRatioY = 768f / screenY

        background1 = Background(screenX, screenY, resources)
        background2 = Background(screenX, screenY, resources)

        background2.x = screenX

        painter.isAntiAlias = true
        painter.colorFilter = PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)

        ourHolder = holder
        ourHolder.addCallback(this)
    }
    override fun surfaceCreated(holder: SurfaceHolder) {
        isPlaying = true
        thread = Thread{
            while(isPlaying!!){
                update()
                drawing()
                sleep()
            }
        }
        thread.start()
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
    }


    fun pause(){
        isPlaying=false
        thread.interrupt()
    }

    fun update(){
        background1.x = background1.x - (10 * (screenRatioX!!.toInt()))
        background2.x = background2.x - (10 * (screenRatioX!!.toInt()))

        if(background1.x + background1.background.width < 0){
            background1.x = screenX!!
        }

        if(background2.x + background2.background.width < 0){
            background2.x = screenX!!
        }
    }

    fun drawing(){
        if(ourHolder.surface.isValid){
            val canvas = ourHolder.lockCanvas()
            canvas.drawBitmap(background1.background, background1.x.toFloat(), background1.y.toFloat(), painter)
            canvas.drawBitmap(background2.background, background2.x.toFloat(), background2.y.toFloat(), painter)
            ourHolder.unlockCanvasAndPost(canvas)
        }
    }

    fun sleep(){
        Thread.sleep(17)
    }


}
  1. Background.kt
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory

class Background(screenX: Int, screenY: Int, res: Resources) {
    var x = 0
    var y = 0
    var background: Bitmap

    init {
        x = screenX
        y = screenY
        this.background = BitmapFactory.decodeResource(res, R.drawable.background)
        this.background = Bitmap.createScaledBitmap(background, screenX, screenY, false)
    }

}
  1. GameActivity.kt
import android.graphics.Point
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import androidx.annotation.RequiresApi

class GameActivity : AppCompatActivity() {

    private lateinit var gameView: GameView
    @RequiresApi(Build.VERSION_CODES.R)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)

        val point = Point()
        windowManager.defaultDisplay.getSize(point)

        gameView = GameView(applicationContext, point.x, point.y)

        setContentView(gameView)
    }

    override fun onPause() {
        super.onPause()
        gameView.pause()
    }

    override fun onResume() {
        super.onResume()
    }
}
  1. MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

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

        play.setOnClickListener {
            val intent = Intent(this, GameActivity::class.java)
            startActivity(intent)
        }
    }
}
question from:https://stackoverflow.com/questions/65836408/android-kotlin-how-to-make-moving-background-with-surfaceview-and-surfacehold

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...