简体   繁体   中英

LibGDX: Kotlin vs. Java

I'm currently working through the examples in the book "Java Game Development with LibGDX" by Lee Stemkoski. I wanted to try Kotlin and converted the code in chapter 2 into Kotlin.

I'm asking if the following code is best practice, since it seems the Kotlin code is much more cumbersome (and not as 'good') as the Java counterpart.

package chapter2

import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.math.Rectangle

class StarfishCollectorAlpha : Game() {
    private lateinit var batch: SpriteBatch

    private var turtleTexture: Texture? = null
    private var turtleX: Float? = null
    private var turtleY: Float? = null
    private lateinit var turtleRectangle: Rectangle

    private var starfishTexture: Texture? = null
    private var starfishX: Float? = null
    private var starfishY: Float? = null
    private lateinit var starfishRectangle: Rectangle

    private var oceanTexture: Texture? = null
    private var winMessageTexture: Texture? = null

    private var win: Boolean? = null

    override fun create() {
        batch = SpriteBatch()

        turtleTexture = Texture(Gdx.files.internal("assets/turtle-1.png"))
        turtleX = 20f
        turtleY = 20f
        turtleRectangle = Rectangle(
            turtleX!!,
            turtleY!!,
            turtleTexture!!.width.toFloat(),
            turtleTexture!!.height.toFloat()
        )

        starfishTexture = Texture(Gdx.files.internal("assets/starfish.png"))
        starfishX = 380f
        starfishY = 380f
        starfishRectangle = Rectangle(
            starfishX!!,
            starfishY!!,
            starfishTexture!!.width.toFloat(),
            starfishTexture!!.height.toFloat()
        )

        oceanTexture = Texture(Gdx.files.internal("assets/water.jpg"))
        winMessageTexture = Texture(Gdx.files.internal("assets/you-win.png"))

        win = false
    }

    override fun render() {
        // check user input
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
            turtleX = turtleX!! - 1
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT))
            turtleX = turtleX!! + 1
        if(Gdx.input.isKeyPressed(Input.Keys.UP))
            turtleY = turtleY!! + 1
        if(Gdx.input.isKeyPressed(Input.Keys.DOWN))
            turtleY = turtleY!! - 1

        // update turtle rectangle location
        turtleRectangle.setPosition(turtleX!!, turtleY!!)

        // checks win condition: Turtle must be overlapping starfish
        if (turtleRectangle.overlaps(starfishRectangle))
            win = true

        // clear screen
        Gdx.gl.glClearColor(0f, 0f, 0f, 1f)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

        // draw graphics
        batch.begin()
        batch.draw(oceanTexture, 0f, 0f)
        if (!win!!)
            batch.draw(starfishTexture, starfishX!!, starfishY!!)
        batch.draw(turtleTexture, turtleX!!, turtleY!!)
        if (win!!)
            batch.draw(winMessageTexture, 180f, 180f)
        batch.end()
    }
}

Firstly: The Java version defines nullable variables in only three words:

private Texture turtleTexture;

Secondly: You have to explicitly convert ints to floats with Kotlin, wheras Java manages this for you.

Thirdly: In order to use the nullable defined variables you have to use a double exclamation signs !! at the end, and also whenever you want to change them.

I want to use Kotlin with game development (LibGDX), but it seems to me (with my limited knowledge perhaps) that Java is the better language.

Please tell me my Kotlin code is rubbish and that there is a better way to refactor my mess.

For libgdx the usual case is that either all your variables should be null, or all your variables should be initialized, and nothing in between. Because of that you can use a single nullable variable in your Game class to delegate to a context class that has no nullable properties.

That gets rid of most of the annoying null-checking.

As for needing to explicitly convert between number types - for me that's a feature :D. I can see how it might irritate though. I'd give it a try though and see if it grows on you.

Here's the one I've just whipped up for my own purposes:

class GolGui : ApplicationAdapter() {
  companion object {
      private val SCREEN_HEIGHT = 480
      private val SCREEN_WIDTH = 800
      private val SCREEN_CENTER_X = SCREEN_WIDTH / 2
      private val SCREEN_CENTER_Y = SCREEN_HEIGHT / 2
  }

  private class Context : Disposable {
      val batch = SpriteBatch();
      val img = Texture("badlogic.jpg")
      val gameSession = GameSession(GameBoard(12, 12))
      val camera = OrthographicCamera(SCREEN_WIDTH.toFloat(), SCREEN_HEIGHT.toFloat())
      val shapeRenderer = ShapeRenderer()
      init {
          shapeRenderer.projectionMatrix = camera.combined
      }

      fun render() {
          Gdx.gl.glClearColor(0.2f, 0f, 0f, 1f)
          Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
          shapeRenderer.apply {
              begin(ShapeRenderer.ShapeType.Filled)
              rect(200f, 200f, 200f, 200f)
              end()
          }
      }

      override fun dispose() {
          batch.dispose()
          img.dispose()
          shapeRenderer.dispose()
      }
  }

  private var context: Context? = null

  override fun create() {
      context = Context()
  }

  override fun render() {
      context!!.render()
  }

  override fun dispose() {
      context!!.dispose()
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM