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

Beat the high-score: build a game using libGDX and Kotlin

David
September 11, 2019

Beat the high-score: build a game using libGDX and Kotlin

Playing games is fun but making games is even better, especially with Kotlin and libGDX. Let’s build together a breakout game and let’s explore the gaming framework libGDX.

This session will show some libGDX’s concepts: how to draw and animate elements of our game, how collision system works to destroy our bricks, what Kotlin brings to libGDX. Then we will dive into more advanced topics like shaders, in order to handle pixels from our images.

Why are we doing all of this? To break the high score, of course!

(11 September 2019 - Oslo - JavaZone 2019)
Video: https://vimeo.com/362771304

David

September 11, 2019
Tweet

More Decks by David

Other Decks in Programming

Transcript

  1. Build a game using libGDX and Kotlin Build a game

    using libGDX and Kotlin Build a game using libGDX and Kotlin Build a game using libGDX and Kotlin Beat the High score Beat the High score Build a game using libGDX and Kotlin
  2. class HelloScreen : ScreenAdapter() { override fun render(delta: Float) {

    Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } }
  3. class HelloScreen : ScreenAdapter() { private val shape = ShapeRenderer()

    override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } }
  4. class HelloScreen : ScreenAdapter() { private val shape = ShapeRenderer()

    override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) shape.begin(ShapeRenderer.ShapeType.Filled) shape.end() } }
  5. class HelloScreen : ScreenAdapter() { private val shape = ShapeRenderer()

    override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) shape.begin(ShapeRenderer.ShapeType.Filled) shape.color = Color.RED shape.circle(0f, 0f, 20f) shape.end() } }
  6. class HelloScreen : ScreenAdapter() { override fun render(delta: Float) {

    Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } }
  7. class HelloScreen : ScreenAdapter() { private val batch = SpriteBatch()

    override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } }
  8. class HelloScreen : ScreenAdapter() { private val batch = SpriteBatch()

    private val texture = Texture("badlogic.jpg") override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } }
  9. class HelloScreen : ScreenAdapter() { private val batch = SpriteBatch()

    private val texture = Texture("badlogic.jpg") override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() batch.end() } }
  10. class HelloScreen : ScreenAdapter() { private val batch = SpriteBatch()

    private val texture = Texture("badlogic.jpg") override fun render(delta: Float) { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() batch.draw(texture, 0f, 0f) batch.end() } }
  11. class MyScreen : ScreenAdapter() { private val batch = ShapeRenderer()

    private val position: Vector2 = Vector2(0f, 0f) override fun render(delta: Float) { position.add(0f, -0.5f) batch.begin(ShapeRenderer.ShapeType.Filled) batch.color = Color.CHARTREUSE batch.circle(position.x, position.y, radius) batch.end() } }
  12. class MyScreen : ScreenAdapter() { private val batch = ShapeRenderer()

    private val position: Vector2 = Vector2(0f, 0f) override fun render(delta: Float) { position.add(0f, -0.5f) batch.begin(ShapeRenderer.ShapeType.Filled) batch.color = Color.CHARTREUSE batch.circle(position.x, position.y, radius) batch.end() } }
  13. class MyScreen : ScreenAdapter() { private val batch = ShapeRenderer()

    private val position: Vector2 = Vector2(0f, 0f) override fun render(delta: Float) { position.add(0f, -0.5f) batch.begin(ShapeRenderer.ShapeType.Filled) batch.color = Color.CHARTREUSE batch.circle(position.x, position.y, radius) batch.end() } }
  14. class MyScreen : ScreenAdapter() { private val batch = ShapeRenderer()

    private val position: Vector2 = Vector2(0f, 0f) override fun render(delta: Float) { position.add(0f, -0.5f) batch.begin(ShapeRenderer.ShapeType.Filled) batch.color = Color.CHARTREUSE batch.circle(position.x, position.y, radius) batch.end() } }
  15. class MyScreen : ScreenAdapter() { private val batch = ShapeRenderer()

    private val position: Vector2 = Vector2(0f, 0f) override fun render(delta: Float) { position.add(0f, -0.5f) val (x, y) = position batch.begin(ShapeRenderer.ShapeType.Filled) batch.color = Color.CHARTREUSE batch.circle(x, y, radius) batch.end() } }
  16. /** * Operator function that allows to deconstruct this vector.

    * @return X component. */ operator fun Vector2.component1(): Float = this.x /** * Operator function that allows to deconstruct this vector. * @return Y component. */ operator fun Vector2.component2(): Float = this.y val vector = Vector2(45f, 50f) val (x, y) = vector
  17. /** * Operator function that allows to deconstruct this vector.

    * @return X component. */ operator fun Vector2.component1(): Float = this.x /** * Operator function that allows to deconstruct this vector. * @return Y component. */ operator fun Vector2.component2(): Float = this.y val (x, y) = Vector2(45f, 50f)
  18. val alpha = Math.abs(ball.x - raquet.x) val direction: Vector2 =

    Vector2(10f, 20f) direction.scl(1f, -1f) .scl(alpha) .nor() .rotate(306f) .add(10f, 20f)
  19. entity.add(Ball()) .add(Position(-100 v2 -100f)) .add(Size(8 v2 9)) .add(Offset(4 v2 4))

    Create a 
 new Vector2 infix fun Number.v2(other: Number): Vector2 { return Vector2(this.toFloat(), other.toFloat()) }
  20. val ball = Rectangle(68f, 64f, 5f, 5f) val player =

    Rectangle(64f, 64f, 100f, 10f) // the ball hit the player? player.overlaps(ball)
  21. val ball = Rectangle(68f, 64f, 5f, 5f) val player =

    Rectangle(64f, 64f, 100f, 10f) // the ball hit the player? player.overlaps(ball)
  22. val ball = Rectangle(68f, 64f, 5f, 5f) val player =

    Rectangle(64f, 64f, 100f, 10f) // the ball hit the player? player.overlaps(ball) (Simple AABB Engine)
  23. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose()
  24. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose() Gravity
  25. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose() Configuration of the « thing »
  26. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose() Attach data from your world to Box2D world
  27. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose()
  28. var world = World(Vector2(0, -10), true) // ... val bodyDef

    = BodyDef() // Set its world position bodyDef.position.set(position.x, position.y) bodyDef.type = BodyDef.BodyType.DynamicBody bodyDef.angle = 0f val body = world.createBody(bodyDef) val shape = CircleShape() shape.radius = 8f // 2. Create a FixtureDef, as usual. val fd = FixtureDef() fd.density = 1f fd.friction = 2f fd.shape = shape body.createFixture(fd) body.userData = Any // attach sprite data shape.dispose()
  29. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = Array<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time)
  30. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = Array<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time)
  31. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = Array<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time)
  32. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = com.badlogic.gdx.utils.Array<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time) import com.badlogic.gdx.utils.Array as GdxArray
  33. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = GdxArray<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time)
  34. // load texture val texture = Texture(Gdx.files.internal("texture.png")) val split =

    TextureRegion.split(texture, 128, 128) // select frames val frames = GdxArray<TextureRegion>() frames.add(split[0][0]) frames.add(split[0][1]) frames.add(split[0][2]) frames.add(split[0][4]) // create animation val animation = Animation<TextureRegion>(100f, frames) // select frame to draw val keyToRender = animation.getKeyFrame(time) Duration per frame
  35. viewport.camera.position.add(0f, 40f, 0f) // Recalculates the projection and // view

    matrix of this camera // Use this after you've manipulated any of // the attributes of the camera. viewport.camera.update() viewport.camera.rotate(10f, 0f, 0f, 1f) viewport.camera.update()
  36. viewport.camera.position.add(0f, 40f, 0f) // Recalculates the projection and // view

    matrix of this camera // Use this after you've manipulated any of // the attributes of the camera. viewport.camera.update() viewport.camera.rotate(10f, 0f, 0f, 1f) viewport.camera.update() Will move the camera up
  37. viewport.camera.position.add(0f, 40f, 0f) // Recalculates the projection and // view

    matrix of this camera // Use this after you've manipulated any of // the attributes of the camera. viewport.camera.update() viewport.camera.rotate(10f, 0f, 0f, 1f) viewport.camera.update() Rotate the camera on the z Axis
  38. class MyScreen : ScreenAdapter() { private lateinit var viewport: Viewport

    private lateinit var bath: SpriteBatch override fun show() { viewport = FitViewport(200f, 200f) bath = SpriteBath() } override fun render(delta: Float) { Gdx.gl.glClearColor(91f / 256f, 110f / 256f, 225f / 256f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() batch.projectionMatrix = viewport.camera.combined // render batch.end() } override fun resize(width: Int, height: Int) { viewport.update(width, height) } }
  39. class MyScreen : ScreenAdapter() { private lateinit var viewport: Viewport

    private lateinit var bath: SpriteBatch override fun show() { viewport = FitViewport(200f, 200f) bath = SpriteBath() } override fun render(delta: Float) { Gdx.gl.glClearColor(91f / 256f, 110f / 256f, 225f / 256f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() batch.projectionMatrix = viewport.camera.combined // render batch.end() } override fun resize(width: Int, height: Int) { viewport.update(width, height) } } Size of the world you’ll display on the screen
  40. class MyScreen : ScreenAdapter() { private lateinit var viewport: Viewport

    private lateinit var bath: SpriteBatch override fun show() { viewport = FitViewport(200f, 200f) bath = SpriteBath() } override fun render(delta: Float) { Gdx.gl.glClearColor(91f / 256f, 110f / 256f, 225f / 256f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() batch.projectionMatrix = viewport.camera.combined // render batch.end() } override fun resize(width: Int, height: Int) { viewport.update(width, height) } }
  41. dependencies { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"

    compile "io.github.libktx:ktx-ashley:$ktxVersion" compile "io.github.libktx:ktx-graphics:$ktxVersion" compile "io.github.libktx:ktx-scene2d:$ktxVersion" compile "io.github.libktx:ktx-log:$ktxVersion" compile "com.github.dwursteisen.libgdx-addons:aseprite-addons:$libgdx_addons" compile "com.github.dwursteisen.libgdx-addons:ashley-addons:$libgdx_addons" compile "com.strongjoshua:libgdx-inGameConsole:$console" }
  42. dependencies { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"

    compile "io.github.libktx:ktx-ashley:$ktxVersion" compile "io.github.libktx:ktx-graphics:$ktxVersion" compile "io.github.libktx:ktx-scene2d:$ktxVersion" compile "io.github.libktx:ktx-log:$ktxVersion" compile "com.github.dwursteisen.libgdx-addons:aseprite-addons:$libgdx_addons" compile "com.github.dwursteisen.libgdx-addons:ashley-addons:$libgdx_addons" compile "com.strongjoshua:libgdx-inGameConsole:$console" }
  43. dependencies { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"

    compile "io.github.libktx:ktx-ashley:$ktxVersion" compile "io.github.libktx:ktx-graphics:$ktxVersion" compile "io.github.libktx:ktx-scene2d:$ktxVersion" compile "io.github.libktx:ktx-log:$ktxVersion" compile "com.github.dwursteisen.libgdx-addons:aseprite-addons:$libgdx_addons" compile "com.github.dwursteisen.libgdx-addons:ashley-addons:$libgdx_addons" compile "com.strongjoshua:libgdx-inGameConsole:$console" }
  44. dependencies { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"

    compile "io.github.libktx:ktx-ashley:$ktxVersion" compile "io.github.libktx:ktx-graphics:$ktxVersion" compile "io.github.libktx:ktx-scene2d:$ktxVersion" compile "io.github.libktx:ktx-log:$ktxVersion" compile "com.github.dwursteisen.libgdx-addons:aseprite-addons:$libgdx_addons" compile "com.github.dwursteisen.libgdx-addons:ashley-addons:$libgdx_addons" compile "com.strongjoshua:libgdx-inGameConsole:$console" }
  45. dependencies { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"

    compile "io.github.libktx:ktx-ashley:$ktxVersion" compile "io.github.libktx:ktx-graphics:$ktxVersion" compile "io.github.libktx:ktx-scene2d:$ktxVersion" compile "io.github.libktx:ktx-log:$ktxVersion" compile "com.github.dwursteisen.libgdx-addons:aseprite-addons:$libgdx_addons" compile "com.github.dwursteisen.libgdx-addons:ashley-addons:$libgdx_addons" compile "com.strongjoshua:libgdx-inGameConsole:$console" }
  46. ComponentMapper<Player> player = ComponentMapper.getFor(Player.class); ComponentMapper<Position> position = ComponentMapper.getFor(Position.class); ComponentMapper<Animation> animation

    = ComponentMapper.getFor(Animation.class); ComponentMapper<StateComponent> state = ComponentMapper.getFor(StateComponent.class); ... player.get(entity).life; position.get(entity).xy; animation.get(entity).getFrame(time); state.get(entity).time; Extractor Extraction
  47. inline fun <reified T : Component> EntitySystem.get(): ComponentMapper<T> = 


    ComponentMapper.getFor(T::class.java) inline operator fun <reified T : Component> Entity.get(mapper: ComponentMapper<T>): T = 
 mapper.get(this)
  48. val player: ComponentMapper<Player> = get() val position: ComponentMapper<Position> = get()

    val animation: ComponentMapper<Animation> = get() val state: ComponentMapper<StateComponent> = get() // access to components entity[player].life entity[position].xy entity[animation].frame(time) entity[state].time
  49. val player = get<Player>() val position = get<Position>() val animation

    = get<Animation>() val state = get<StateComponent>() // access to components entity[player].life entity[position].xy entity[animation].frame(time) entity[state].time
  50. val player = get<Player>() val position = get<Position>() val animation

    = get<Animation>() val state = get<StateComponent>() // access to components entity[player].life entity[position].xy entity[animation].frame(time) entity[state].time Accessing like a map
  51. inline fun <reified T : Component> EntitySystem.get(): ComponentMapper<T> = 


    ComponentMapper.getFor(T::class.java) inline operator fun <reified T : Component> Entity.get(mapper: ComponentMapper<T>): T = 
 mapper.get(this)
  52. 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
  53. 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
  54. 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) } State Event Transition
  55. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java)
  56. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java)
  57. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java)
  58. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java)
  59. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java) Call it in the render method
  60. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture = assetsManager.get("player.png", Texture::class.java)
  61. val assetsManager = AssetManager() assetsManager.load("player.png", Texture::class.java) assetsManager.load("sfx/beat_intro.ogg", Music::class.java) assetsManager.load("krungthep2.fnt", BitmapFont::class.java)

    assetsManager.load("sheets/intro", Aseprite::class.java) // call it until it's loaded val isLoaded = assetsManager.update() val texture: Texture = assetsManager["player.png"] inline operator fun <reified T> AssetManager.get(filename: String): T { return this.get(filename, T::class.java) }
  62. // can be loaded using AssetManager too val tmxMap =

    TmxMapLoader().load(mapName) tmxMap.layers["bricks"]?.objects?.forEach { brick -> // create game entity } mapRenderer = OrthogonalTiledMapRenderer(tmxMap) // render method mapRenderer.setView(viewport.camera as OrthographicCamera) mapRenderer.render()
  63. // can be loaded using AssetManager too val tmxMap =

    TmxMapLoader().load(mapName) tmxMap.layers["bricks"]?.objects?.forEach { brick -> // create game entity } mapRenderer = OrthogonalTiledMapRenderer(tmxMap) // render method mapRenderer.setView(viewport.camera as OrthographicCamera) mapRenderer.render()
  64. // can be loaded using AssetManager too val tmxMap =

    TmxMapLoader().load(mapName) tmxMap.layers["bricks"]?.objects?.forEach { brick -> // create game entity } mapRenderer = OrthogonalTiledMapRenderer(tmxMap) // render method mapRenderer.setView(viewport.camera as OrthographicCamera) mapRenderer.render()
  65. // can be loaded using AssetManager too val tmxMap =

    TmxMapLoader().load(mapName) tmxMap.layers["bricks"]?.objects?.forEach { brick -> // create game entity } mapRenderer = OrthogonalTiledMapRenderer(tmxMap) // render method mapRenderer.setView(viewport.camera as OrthographicCamera) mapRenderer.render()
  66. class BrickProperties(properties: MapProperties) { val x: Double by properties val

    y: Double by properties val hit: Int by properties val sound: String by properties } tmxMap.layers["bricks"].objects.forEach { brick -> val props = BrickProperties(brick.properties) val hit = props.hit }
  67. class BrickProperties(properties: MapProperties) { val x: Double by properties val

    y: Double by properties val hit: Int by properties val sound: String by properties } tmxMap.layers["bricks"].objects.forEach { brick -> val props = BrickProperties(brick.properties) val hit = props.hit }
  68. class BrickProperties(properties: MapProperties) { val x: Double by properties val

    y: Double by properties val hit: Int by properties val sound: String by properties } tmxMap.layers["bricks"].objects.forEach { brick -> val props = BrickProperties(brick.properties) val hit = props.hit } Delegates
  69. inline operator fun <reified T> MapProperties.getValue(thisRef: Any?, property: KProperty<*>): T

    { val asStr = this[property.name].toString() return when (T::class) { Double::class -> asStr.toDouble() Int::class -> asStr.toInt() Boolean::class -> "true" == asStr String::class -> asStr else -> this[property.name] } as T }
  70. val chicken: Aseprite = assets["sheets/chicken"] val idleAnimation: Animation<TextureRegion> = chicken["idle"]

    Inverser slides. Je veux accéder aux animations -> export des metas -> méthode d'extensions. 
 -> explication j'ai fais un plugin qui fait ça pour moi.
  71. open class AsepriteTask : DefaultTask() { // ... @TaskAction fun

    export() { val exec = getExecActionFactory().newExecAction() val exts = project.extensions.getByType(AsepritePluginExtentions::class.java) val aseprite = exts.exec ?: invalideAsepritePath() // ... } private fun invalideAsepritePath(): Nothing { TODO("""Missing aseprite executable path. Please configure it using aseprite.exec property (ie: in your ~/.gradle/gradle.properties) aseprite.exec=<path to exec> or using aseprite extension in your build.gradle aseprite { exec=<path to exec> } MacOS specific : point to aseprite located into <aseprite directory>/Aseprite.app/Contents/MacOS/aseprite""") } }
  72. open class AsepriteTask : DefaultTask() { // ... @TaskAction fun

    export() { val exec = getExecActionFactory().newExecAction() val exts = project.extensions.getByType(AsepritePluginExtentions::class.java) val aseprite = exts.exec ?: invalideAsepritePath() // ... } private fun invalideAsepritePath(): Nothing { TODO("""Missing aseprite executable path. Please configure it using aseprite.exec property (ie: in your ~/.gradle/gradle.properties) aseprite.exec=<path to exec> or using aseprite extension in your build.gradle aseprite { exec=<path to exec> } MacOS specific : point to aseprite located into <aseprite directory>/Aseprite.app/Contents/MacOS/aseprite""") } } What happen if null? Encountered an error, lol!
  73. open class AsepriteTask : DefaultTask() { // ... @TaskAction fun

    export() { val exec = getExecActionFactory().newExecAction() val exts = project.extensions.getByType(AsepritePluginExtentions::class.java) val aseprite = exts.exec ?: invalideAsepritePath() // ... } private fun invalideAsepritePath(): Nothing { TODO("""Missing aseprite executable path. Please configure it using aseprite.exec property (ie: in your ~/.gradle/gradle.properties) aseprite.exec=<path to exec> or using aseprite extension in your build.gradle aseprite { exec=<path to exec> } MacOS specific : point to aseprite located into <aseprite directory>/Aseprite.app/Contents/MacOS/aseprite""") } }
  74. open class AsepriteTask : DefaultTask() { // ... @TaskAction fun

    export() { val exec = getExecActionFactory().newExecAction() val exts = project.extensions.getByType(AsepritePluginExtentions::class.java) val aseprite = exts.exec ?: invalideAsepritePath() // ... } private fun invalideAsepritePath(): Nothing { TODO("""Missing aseprite executable path. Please configure it using aseprite.exec property (ie: in your ~/.gradle/gradle.properties) aseprite.exec=<path to exec> or using aseprite extension in your build.gradle aseprite { exec=<path to exec> } MacOS specific : point to aseprite located into <aseprite directory>/Aseprite.app/Contents/MacOS/aseprite""") } }
  75. val scene = verticalGroup { setFillParent(true) pad(10f) label("Hello JavaZone!") horizontalGroup

    { textButton("Click On Me") label("<-- here") } label("Another label...") selectBoxOf(GdxArray<String>().apply { add("value 1") add("value 2") add("value 3") }) } stage = Stage(FitViewport(screenWidth, screenHeight)) stage.addActor(scene) Hello JavaZone!
  76. val scene = verticalGroup { setFillParent(true) pad(10f) label("Hello JavaZone!") horizontalGroup

    { textButton("Click On Me") label("<-- here") } label("Another label...") selectBoxOf(GdxArray<String>().apply { add("value 1") add("value 2") add("value 3") }) } stage = Stage(FitViewport(screenWidth, screenHeight)) stage.addActor(scene) Hello JavaZone!
  77. val scene = verticalGroup { setFillParent(true) pad(10f) label("Hello JavaZone!") horizontalGroup

    { textButton("Click On Me") label("<-- here") } label("Another label...") selectBoxOf(GdxArray<String>().apply { add("value 1") add("value 2") add("value 3") }) } stage = Stage(FitViewport(screenWidth, screenHeight)) stage.addActor(scene) Hello JavaZone!
  78. val scene = verticalGroup { setFillParent(true) pad(10f) label("Hello JavaZone!") horizontalGroup

    { textButton("Click On Me") label("<-- here") } label("Another label...") selectBoxOf(GdxArray<String>().apply { add("value 1") add("value 2") add("value 3") }) } stage = Stage(FitViewport(screenWidth, screenHeight)) stage.addActor(scene) Hello JavaZone!
  79. open class MenuScreen(val game: Game) : ScreenAdapter() { override fun

    render(delta: Float) { // clear the screen Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() // ... batch.end() if (goToMenu) { game.setScreen(menuScreen) } } }
  80. open class MenuScreen(val game: Game) : ScreenAdapter() { override fun

    render(delta: Float) { // clear the screen Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) batch.begin() // ... batch.end() if (goToMenu) { game.setScreen(menuScreen) } } } ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ game.setScreen(screen) 
 is not the same that
 game.screen = screen ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠
  81. altLayers = map.layers .mapIndexed { index, layer -> index to

    layer } .filter { it.second.name.startsWith("alt_") } .map { it.first } .toIntArray() List 1 List 2 List 3 List 4 mutableList
  82. val ball = Rectangle(68f, 64f, 5f, 5f) val player =

    Rectangle(64f, 64f, 100f, 10f) // the ball hit the player? player.overlaps(ball)
  83. val pool = object : Pool<Rectangle>() { override fun newObject():

    Rectangle = Rectangle() } // ... val ball = pool.obtain().apply { set(68f, 64f, 5f, 5f) } val player = pool.obtain().apply { set(64f, 64f, 100f, 10f) } // the ball hit the player? player.overlaps(ball) pool.free(ball) pool.free(player)
  84. val pool = object : Pool<Rectangle>() { override fun newObject():

    Rectangle = Rectangle() } // ... val ball = pool.obtain().apply { set(68f, 64f, 5f, 5f) } val player = pool.obtain().apply { set(64f, 64f, 100f, 10f) } // the ball hit the player? player.overlaps(ball) pool.free(ball) pool.free(player)
  85. val pool = object : Pool<Rectangle>() { override fun newObject():

    Rectangle = Rectangle() } // ... val ball = pool.obtain().apply { set(68f, 64f, 5f, 5f) } val player = pool.obtain().apply { set(64f, 64f, 100f, 10f) } // the ball hit the player? player.overlaps(ball) pool.free(ball) pool.free(player)
  86. val pool = object : Pool<Rectangle>() { override fun newObject():

    Rectangle = Rectangle() } // ... val ball = pool.obtain().apply { set(68f, 64f, 5f, 5f) } val player = pool.obtain().apply { set(64f, 64f, 100f, 10f) } // the ball hit the player? player.overlaps(ball) pool.free(ball) pool.free(player)
  87. void main() {
 vec4 sum = vec4(0);
 
 float step

    = iResolution.y;
 // y
 for(float i = -area ; i <= area ; i += 1.) {
 // x
 for(float j = -area ; j <= area ; j += 1.) {
 float x = v_texCoords.x + i / iResolution.x;
 float y = v_texCoords.y + j / iResolution.y;
 sum += texture2D(u_texture, vec2(x, y)) * 0.005;
 }
 }
 gl_FragColor = texture2D(u_texture, v_texCoords) + sum;
 } OpenGL Shading Language (GLSL)
  88. if (color_pixel < cutoff) { // light dark pixel =

    gl_FragColor = vec4(0.3, 0.2, 0.4., 1.0); } else { pixel = color_pixel; } 0 1 Cut off
  89. if (color_pixel < cutoff) { // light dark pixel =

    gl_FragColor = vec4(0.3, 0.2, 0.4., 1.0); } else { pixel = color_pixel; }
  90. Beat The High Score Game https://github.com/dwursteisen/beat-the-high-score libGDX Lib https://libgdx.badlogicgames.com/ KTX

    
 (This is NOT Android KTX) Lib https://github.com/libktx/ktx/ libGDX addons Lib https://github.com/dwursteisen/libgdx-addons/ kTerminal Lib https://github.com/heatherhaks/kterminal Game Services Lib https://github.com/MrStahlfelge/gdx-gamesvcs In Game Console
 (A la quake) Lib https://github.com/StrongJoshua/libgdx-inGameConsole Gif Recorder Lib https://github.com/Anuken/GDXGifRecorder Tiled Editor Editor https://www.mapeditor.org Aseprite Editor https://www.aseprite.org
  91. Beat The High Score Game https://github.com/dwursteisen/beat-the-high-score libGDX Lib https://libgdx.badlogicgames.com/ KTX

    
 (This is NOT Android KTX) Lib https://github.com/libktx/ktx/ libGDX addons Lib https://github.com/dwursteisen/libgdx-addons/ kTerminal Lib https://github.com/heatherhaks/kterminal Game Services Lib https://github.com/MrStahlfelge/gdx-gamesvcs In Game Console
 (A la quake) Lib https://github.com/StrongJoshua/libgdx-inGameConsole Gif Recorder Lib https://github.com/Anuken/GDXGifRecorder Tiled Editor Editor https://www.mapeditor.org Aseprite Editor https://www.aseprite.org