Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin pour le développement d’un jeu avec libGDX : avantage & inconvénient

David
March 14, 2018

Kotlin pour le développement d’un jeu avec libGDX : avantage & inconvénient

libGDX est un framework de développement de jeux vidéo Java. Mais quand on développe un jeu, on veut se concentrer sur le design du jeu, itérer rapidement : on ne veut pas perdre de temps avec des problèmes de syntaxes ou autre. Mais Kotlin s’intègre t’il facilement avec les APIs Java de libGDX ? Qu’apporte Kotlin dans ce contexte et surtout. Les avantages de Kotlin sont-ils toujours des avantages dans le code d’un jeu vidéo ?

(Kotlin Paris Meetup - https://www.meetup.com/fr-FR/Kotlin-Paris-Meetup/events/247733641/ )

David

March 14, 2018
Tweet

More Decks by David

Other Decks in Programming

Transcript

  1. class HelloWorld : ScreenAdapter() { override fun show() { }

    override fun render(delta: Float) { } } Initialisation de l’écran de jeu Rendu de l’écran de jeu
  2. class HelloWorld : ScreenAdapter() { var batch: SpriteBatch? override fun

    show() { batch = SpriteBatch() } override fun render(delta: Float) { batch!!.begin() // ... batch!!.end() } }
  3. class HelloWorld : ScreenAdapter() { var batch: SpriteBatch? override fun

    show() { batch = SpriteBatch() } override fun render(delta: Float) { batch!!.begin() // ... batch!!.end() } }
  4. class HelloWorld : ScreenAdapter() { lateinit var batch: SpriteBatch override

    fun show() { batch = SpriteBatch() } override fun render(delta: Float) { batch.begin() // ... batch.end() } }
  5. class HelloWorld : ScreenAdapter() { lateinit var batch: SpriteBatch override

    fun show() { batch = SpriteBatch() } override fun render(delta: Float) { batch.begin() // ... batch.end() } }
  6. fun String.toColor(): Color = Color.valueOf(this) val background = « 0089d5".toColor()

    fun ShapeRenderer.rect(pos: Vector2, size: Vector2) { this.rect(pos.x, pos.y, size.x, size.y) } batch.rect(pos1, pos2)
  7. fun String.toColor(): Color = Color.valueOf(this) val background = « 0089d5".toColor()

    fun ShapeRenderer.rect(pos: Vector2, size: Vector2) { this.rect(pos.x, pos.y, size.x, size.y) } batch.rect(pos1, pos2) Méthode d’extension = étendre une API à son besoin
  8. const val TOUCH_DOWN = 1 const val TOUCH_UP = 2

    const val TOUCH_MOVE = 3 Compile-Time Constants Properties the value of which is known at compile time can be marked as compile time constants using the const modifier. Such properties need to fulfil the following requirements: Top-level or member of an object Initialized with a value of type String or a primitive type No custom getter
  9. private void readMeasureHeader(InputStream is, int measureIndex) throws IOException { int

    header = helper.readUnsignedByte(is); boolean repeatStart = ((header & ParserHelper.BITMASK_3) != 0); boolean doubleBar = ((header & ParserHelper.BITMASK_8) != 0); int numerator = 0; if ((header & ParserHelper.BITMASK_1) != 0) { numerator = helper.readByte(is); } int denominator = 0; if ((header & ParserHelper.BITMASK_2) != 0) { denominator = helper.readByte(is); } }
  10. private void readMeasureHeader(InputStream is, int measureIndex) throws IOException { int

    header = helper.readUnsignedByte(is); boolean repeatStart = ((header & ParserHelper.BITMASK_3) != 0); boolean doubleBar = ((header & ParserHelper.BITMASK_8) != 0); int numerator = 0; if ((header & ParserHelper.BITMASK_1) != 0) { numerator = helper.readByte(is); } int denominator = 0; if ((header & ParserHelper.BITMASK_2) != 0) { denominator = helper.readByte(is); } }
  11. Vector2(3f, 5f).set(entity[cameraData].direction) .scl(5f) .add(entity[position].value) .add(halfX, halfY val v1 = Vector2(3f,

    5f) + Vector2(4f, 2f) v2 = v1 * 5f Surcharge d’opérateur (add) Surcharge d’opérateur (scl)
  12. engine.addEntity({ e -> val left = spriteDef.slices("left") val leftRegion =

    left.textureRegion(assets["sheets/pico8/keyboard.png"]) e.add(Controller()) e.add(Position(42 v2 26)) e.add(Size(16 v2 16)) e.add(EntityRender(texture = leftRegion)) e.add(ButtonComponent(ButtonSystem.LEFT)) e.add(StateComponent()) }) Vector2
  13. engine.addEntity({ e -> val left = spriteDef.slices("left") val leftRegion =

    left.textureRegion(assets["sheets/pico8/keyboard.png"]) e.add(Controller()) e.add(Position(42 v2 26)) e.add(Size(16 v2 16)) e.add(EntityRender(texture = leftRegion)) e.add(ButtonComponent(ButtonSystem.LEFT)) e.add(StateComponent()) }) infix fun Int.v2(that: Int): Vector2 = Vector2(this.toFloat(), that.toFloat())
  14. inline fun <reified T : Component> EntitySystem.get(): ComponentMapper<T> = ComponentMapper.getFor(T::class.java)

    private val move: ComponentMapper<TurnMove> = ComponentMapper.getFor(TurnMove::class.java) Extracteur
  15. inline fun <reified T : Component> EntitySystem.get(): ComponentMapper<T> = ComponentMapper.getFor(T::class.java)

    private val move: ComponentMapper<TurnMove> = ComponentMapper.getFor(TurnMove::class.java) Inline + reified
  16. private val move: ComponentMapper<TurnMove> = get() private val position: ComponentMapper<Position>

    = get() private val state: ComponentMapper<StateComponent> = get() private val direction: ComponentMapper<Direction> = get()
  17. altLayers = map.layers .mapIndexed { index, layer -> index to

    layer } .filter { it.second.name.startsWith("alt_") } .map { it.first } .toIntArray() mutableList !
  18. val a = Array<String>(5, { "" }) val b =

    Array<String>() Différence ? Array libGDX
  19. interface EventListener { fun onEvent(event: Event, eventData: EventData) } fun

    register(eventListener: EventListener, vararg events: Event) { events.forEach { val lst = listeners[it] if (lst == null) { listeners.put(it, listOf(eventListener)) } else { listeners.put(it, lst + eventListener) } } }
  20. interface EventListener { fun onEvent(event: Event, eventData: EventData) } fun

    register(eventListener: EventListener, vararg events: Event) { events.forEach { val lst = listeners[it] if (lst == null) { listeners.put(it, listOf(eventListener)) } else { listeners.put(it, lst + eventListener) } } } Interface avec une méthode
  21. eventBus.register(object : EventListener { override fun onEvent(event: Event, eventData: EventData)

    { game.loadingScreen() } }, GameEvents.EVENT_GAME_MAIN_MENU) Class anonyme
  22. fun on(event: Int, block: Transition): OnState { var currentTransitions =

    parent.transitions[state] ?: emptyMap() currentTransitions += event to block parent.transitions += state to currentTransitions return this } Lambda
  23. startWith(WAIT) onState(WAIT).on(GameEvents.EVENT_COMPUTER_ALLOW_MOVE) { entity, event -> if (entity[dragon].currentTurn > 3)

    { entity[dragon].currentTurn = -1 go(FIRE, entity, event) } else { go(MOVE, entity, event) } } onState(FIRE).on(GameEvents.EVENT_DRAGON_FIRE_BALL) { entity, event -> go(MOVE, entity, event) } Lambda
  24. startWith(WAIT) onState(WAIT).on(GameEvents.EVENT_COMPUTER_ALLOW_MOVE) { entity, event -> if (entity[dragon].currentTurn > 3)

    { entity[dragon].currentTurn = -1 go(FIRE, entity, event) } else { go(MOVE, entity, event) } } onState(FIRE).on(GameEvents.EVENT_DRAGON_FIRE_BALL) { entity, event -> go(MOVE, entity, event) } Etat Event Transition