Hi Guys, This is our four article on "How to make a 2D Game in Android Studio Using Koltin", also this is our last article on the 2d game in the android studio. In this article, we will draw obstacles on the surface of the screen, And we will draw the game over and scoreboard on the screen. If you did not read the previous article, then Click Here. Let move to the tutorial.
Create A New Kotlin Class
- Create a new Kotlin class, Name it "ObstacleManager".
- Basically, we will handle the color, height, gap of the obstacles and also we will handle the player gap in the obstacles manager, and we will show the game over when the player hits the obstacles, also we will add score when player pass through the obstacles. We will mention an array list of obstacles to the obstacles manager. We will add the color handler in the obstacles manager. So, copy the below codes and it into your "ObstacleManager".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | class ObstacleManager(private val playerGap: Int, private val obstacleGap: Int, private val obstacleHeight: Int, private val color: Int) { private val obstacles: ArrayList<Obstacle> private var startTime: Long = 0 private var initTime: Long = 0 private var score = 0 init { initTime = System.currentTimeMillis() startTime = initTime obstacles = ArrayList() populateObstacles() } fun playerCollide(player: RectPlayer): Boolean { for (ob in obstacles) { if (ob.playerCollide(player)) return true } return false } private fun populateObstacles() { var currY = -5 * Constants.SCREEN_HEIGHT / 4 while (currY < 0) { val xStart = (Math.random() * (Constants.SCREEN_WIDTH - playerGap)).toInt() obstacles.add(Obstacle(obstacleHeight, color, xStart, currY, playerGap)) currY += obstacleHeight + obstacleGap } } fun update() { if (startTime < Constants.INIT_TIME) startTime = Constants.INIT_TIME val elapsedTime = (System.currentTimeMillis() - startTime).toInt() startTime = System.currentTimeMillis() val speed = Math.sqrt(1 + (startTime - initTime) / 2000.0).toFloat() * Constants.SCREEN_HEIGHT / 10000.0f for (ob in obstacles) { ob.incrementY(speed * elapsedTime) } if (obstacles[obstacles.size - 1].rectangle.top >= Constants.SCREEN_HEIGHT) { val xStart = (Math.random() * (Constants.SCREEN_WIDTH - playerGap)).toInt() obstacles.add(0, Obstacle(obstacleHeight, color, xStart, obstacles[0].rectangle.top - obstacleHeight - obstacleGap, playerGap)) obstacles.removeAt(obstacles.size - 1) score++ } } fun draw(canvas: Canvas) { for (ob in obstacles) ob.draw(canvas) val paint = Paint() paint.textSize = 100f paint.color = Color.BLUE canvas.drawText("" + score, 50f, 50 + paint.descent() - paint.ascent(), paint) } } |
- So, In score color, I have added blue color in the draw function, you can add any color you want. And In the "drawText" I have added nothing, you can add text on it.
Create a function
Now, create a new function in Obstacle.class. In the Obstacle class, we will add a handler which handles the speed of our rectangle and rectangle2 which is our obstacles. In this function, we will mention the float value as a "y" and declare it in rectangle and rectangle2. Just copy the codes and paste it into your obstacle.class.
1 2 3 4 5 6 | fun incrementY(y: Float) { rectangle.top += y.toInt() rectangle.bottom += y.toInt() rectangle2.top += y.toInt() rectangle2.bottom += y.toInt() } |
Add more codes in Game Panel
Add more codes for "ObstacleManager" and game over in the "GamePanel.class". So, we will remove some pre-codes from GamePanel.class and add some new codes in GamePanel.class. In the GamePanel.class, we will add the game over variable and game over time in the GamePanel.class. When our player hits the obstacles, then in the middle of the screen it will game over, then the screen will wait for two seconds, after that when we touch the screen, the game will be reset. I have added a few more codes in "OnTouchEvent" method and In the "surfaceCreate", which you will obtain from below code box. For showing game over in the middle of the screen, I don't have a proper method, So I have it from StackOverflow.com. But the problem with StackOverflow.com is that I got the method in java, So I have changed some codes, which you will get from below. I will suggest you delete all code from your "GamePanel.class" and add codes from below code box, for less confusion.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | class GamePanel(context: Context) : SurfaceView(context), SurfaceHolder.Callback { private val thread: MainThread private val r = Rect() private val player: RectPlayer private var playerPoint: Point? = null private var obstacleManager: ObstacleManager? = null private var movingPlayer = false private var gameOver = false private var gameOverTime: Long = 0 init { holder.addCallback(this) thread = MainThread(holder, this) player = RectPlayer(Rect(100, 100, 200, 200), Color.rgb(255, 0, 0)) playerPoint = Point(Constants.SCREEN_WIDTH / 2, 3 * Constants.SCREEN_HEIGHT / 4) player.update(playerPoint!!) obstacleManager = ObstacleManager(200, 350, 75, Color.BLACK) isFocusable = true } private fun reset() { playerPoint = Point(Constants.SCREEN_WIDTH / 2, 3 * Constants.SCREEN_HEIGHT / 4) player.update(playerPoint!!) obstacleManager = ObstacleManager(200, 350, 75, Color.BLACK) movingPlayer = false } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { } override fun surfaceCreated(holder: SurfaceHolder) { Constants.INIT_TIME = System.currentTimeMillis() thread.setRunning(true) thread.start() } override fun surfaceDestroyed(holder: SurfaceHolder) { var retry = true while (retry) { try { thread.setRunning(false) thread.join() } catch (e: Exception) { e.printStackTrace() } retry = false } } override fun onTouchEvent(event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN -> { if (!gameOver && player.rectangle.contains(event.x.toInt(), event.y.toInt())) movingPlayer = true if (gameOver && System.currentTimeMillis() - gameOverTime >= 2000) { reset() gameOver = false } } MotionEvent.ACTION_MOVE -> if (!gameOver && movingPlayer) playerPoint!!.set(event.x.toInt(), event.y.toInt()) MotionEvent.ACTION_UP -> movingPlayer = false } //return super.onTouchEvent(event); return true } fun update() { if(!gameOver) { player.update(playerPoint!!) obstacleManager!!.update() if (obstacleManager!!.playerCollide(player)) { gameOver = true gameOverTime = System.currentTimeMillis() } } } override fun draw(canvas: Canvas) { super.draw(canvas) canvas.drawColor(Color.WHITE) player.draw(canvas) obstacleManager!!.draw(canvas) if (gameOver) { val paint = Paint() paint.textSize = 100f paint.color = Color.BLUE drawCenterText(canvas, paint, "GameOver") } } private fun drawCenterText(canvas: Canvas, paint: Paint, text: String) { paint.textAlign = Paint.Align.LEFT canvas.getClipBounds(r) val cHeight = r.height() val cWidth = r.width() paint.getTextBounds(text, 0, text.length, r) val x = cWidth / 2f - r.width() / 2f - r.left.toFloat() val y = cHeight / 2f + r.height() / 2f - r.bottom canvas.drawText(text, x, y, paint) } } |
Conclusion
So, try the game in your emulator or you can try it on your smartphone. And comment down below, how it's working. Also, I have share APK file and GitHub code repository below, you can check it. If you like this article, then, please visit again. At last, I will say sorry write "Thank You".
Comments
Post a Comment