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.
- [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)
}
}
- 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)
}
}
- 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()
}
}
- 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