Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

itch.ioitch.io logo & titleitch.io logo

Browse GamesGame JamsUpload GameDeveloper LogsCommunity
Log inRegister
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

libGDX Jam - Powered by RoboVM & Robotality

Hosted bybadlogic
1,684
Ratings
OverviewSubmissionsResults
Community163
ScreenshotsSubmission feed

badlydrawnrod's devlog

IntelliJ, LibGDX, Kotlin and Android

As I stated in the "introduce yourself" thread, I've chosen to write my game usingKotlin rather than Java. I've been looking for an opportunity to learn it for a while, and there are few better ways of learning a language than actually building a project with it.

The first step in any project is setting up the build environment. There is plenty of useful guidance on doing this, includingan article on setting up LibGDX to work with Kotlin, but as I hit a few snags along the way I've shared my steps here in case anyone else is thinking of using Kotlin and is struggling to get it to work with an Android project.


Part 1 - Building and running desktop and Android configurations

Install IntellIJ IDEA Community Edition.

Install the standalone Android SDK.

Run the LibGDX project setup and create sub-projects for both desktop and Android.

Open IntelliJ and loadbuild.gradle.

Fix the project so that the desktop run configuration will work, by adding the Java-Gradle facet to all sub-projects except Android,i.e, to the "core" and "desktop" sub-projects.

Create the desktop configuration.

At this point, it should be possible to build and run the desktop and Android configurations without errors. If the desktop configuration doesn't run, try closing and re-opening the project.

Butthat doesn't get usKotlin. That requires jumping through a few more hoops.

Part 2 follows in the next post.

Part 2 - Configuring Kotlin

These instructions are based on the ones that I foundhere. However,they only worked for a desktop-only project and failed with an error for projects with an Android sub-project. The solution was to follow those instructions then tweakbuild.gradle a little. These steps are reproducible - I went through them twice more when writing this guide.

Go to thecore project and find the singleJava file.

Right-click on it and select New ->Kotlin File/Class.

Enter the name, setting it to the same as the Java file, and setting "Kind" to "Class".

You will be prompted to configureKotlin. Click on the link to do this. It will make changes tobuild.gradle in the "core" sub-project.

Open the Java class and copy its contents to the clipboard.

Switch to theKotlin class that you just created, delete its contents, then paste from the clipboard. Select "Yes" when prompted to convert the code from Java toKotlin.

Delete the old Java file. Donot use safe-delete otherwise it won't work.

Insert "lateinit" in front of the "var" for both of the member variables.

 internal lateinit var batch: SpriteBatch internal lateinit var img: Texture

Editbuild.gradle in the "core" project, replacing "kotlin-android" with "kotlin" and removingthe "android" section.

The resulting file should look like this:

apply plugin: "java" apply plugin: 'kotlin'  sourceCompatibility = 1.6 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'  sourceSets.main.java.srcDirs = [ "src/" ]   eclipse.project {  name = appName + "-core" } buildscript {  ext.kotlin_version = '1.0.0-beta-3595'  repositories {  mavenCentral()  }  dependencies {  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"  } } repositories {  mavenCentral() } dependencies {  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" }

Sync the project, then run the desktop configuration. Everything should work as expected.

N.O.A.H.

We have had relatives over for a while (and they're still here) but I've found a spare hour or two where I can think about this. I've decided to go for a game similar to Defender in concept, but the roles are reversed in that you play the alien. It's called "N.O.A.H." for Near Orbit Alien Harvester. Controls will probably be Lunar Lander style, at least for the vertical component. The player will be given quotas of particular animals to collect from Earth, but of course the humans won't take too kindly to that and will no doubt defend themselves vigorously.

I am usingAshley as Entity Component Systems are reminiscent of how we used to write games in the olden days, when would cajole performance out of1.77MHz Z80 processors on computers with less RAM than is required for one line of pixels on my phone. No wonder the T-1000 used a 6502.

It would appear thatI'm not the only one who has tried to use Kotlin, LibGDX and Ashley. This is good, because I don't have to spend hours trawling for simple fixes to things that I just don't know about yet. Admittedly it's a little out of date, but still…

At first glance Kotlin's data classes seem to be a good candidate for implementing Components.

e.g.,

data class TransformComponent(var x: Float, var y: Float) : Component

But then again, it's also fine without being adata class. Either way, I love how it can be done in one line. It did cause me a little difficulty with Family.all() until I found that I had to use TransformComponent::class.java rather than TransformComponent.class.

Progress in the last couple of hours:

  • Implemented a simple RenderSystem, derived from IteratingSystem, overriding update() to bookend the drawing calls with spritebatch begin() and end().
  • Learned about Kotlin's xxx::class.java.
  • Learned about Kotlin's .forEach() but ultimately didn't use it.
  • Created a RenderableComponent.
  • Created a TransformComponent. Again, I love how this can be done in one line.
  • Added a couple of entities just to prove that everything works.
  • Accidentally typed a semi-colon just once.

Still no game, but I know where I'm going with this and I like the idea - always a good sign.

Using Kotlin, libGDX and Ashley as well. One neat trick I learned about is .apply { blocks, for initializing.

You can do, for example:

val myEntity = Entity().apply {
add(TransformComponent())
// Other things here
}

Thanks. I shall give that a try. Relatives leave tomorrow (not that they haven't been great) so hopefully I will get more programming done.

I'm trying to figure out the best way of getting Box2D to play well with Ashley. Fortunately there are existing examples,such as those found in Overlap2D, so I don't have to do too much thinking – just as well as I'm shattered! My daughter wanted to see in the New Year, not realizing just how exhausted my wife and I are having had to cater to her relatives.

Much of today - at least once I got up - was taken up with spending time with my wife and daughter, playing Yoshi's Woolly World on the Wii-U, and Avian Attorney and Shovel Knight on the PC. For what it's worth, Shovel Knight is my favourite as it has very precise controls and a great retro feel. I think I may be putting in more than a few hours.

Eventually, when everyone else had gone to bed and the house was quiet, I managed to squeeze in a couple of hours programming. I'm impressed with Kotlin'swhen expression andsmart casts. By the way, createFixture() is a nested function. Nice.

when (shapedComponent.shape) {
is CircleShaped -> {
val circle = CircleShape().apply { radius = shapedComponent.shape.radius } createFixture(circle) circle.dispose() }
is BoxShaped -> { val polygon = PolygonShape().apply {
setAsBox(shapedComponent.shape.halfWidth, shapedComponent.shape.halfHeight)
}
createFixture(polygon)
polygon.dispose();
}
}

Today's progress:

  • Added Box2D physics and implemented a PhysicsSystem. It still needs some work, but the rudiments are there.
  • Created a BodyComponent to represent Box2D bodies in Ashley.
  • Created a ShapedComponent, which can currently be either circle shaped or box shaped.
  • Learned about Kotlin'ssmart casts andwhen expression.

Kotlin, Kotlin and Kotlin

Kotlin is excellent. Did I mention that? It has all of the benefits of Java such as the rich libraries, LibGDX, with none of the downsides. It's also incredibly succinct.

Lambdas

If I want to run something after a few seconds, I use aTimer class with a methodafter() that takes() -> Unit as its last parameter.

Here's the signature…

fun after(seconds: Float, run: () -> Unit)

That lets me call it with a lambda as follows…

timer.after(5f) {    resetWave()}

For what it's worth, the implementation ofafter() is incredible short…

fun after(seconds: Float, run: () -> Unit) = q.add(Task(run, now + seconds))

Extension Methods

Another thing that works rather well is Kotlin's implementation of extension methods. C# also has extension methods, but Kotlin's go further. Let's say I want to run all the eligible tasks in the timer's update() method. I could write it all inline in theupdate() method, checking that the LibGDXBinaryHeap backing the timer isn't empty, peeking the head to see if it's eligible, popping it and invoking it if it is, but that would be rather verbose and would hide my intent.

Or I could do this…

var task = q.nextTask()while (task != null) {    task.run()    task = q.nextTask()}

Here,q.nextTask() is an extension method onBinaryHeap<Task> that returns null if there isn't an eligible task or the next eligible task if there is. It's implemented as a private method inside Timer, so it has access to its properties, including the all-importantnow property.

private fun BinaryHeap<Task>.nextTask(): Task? {    if (size > 0) {        val task = peek()        if (task.value <= now) {            q.pop()            return task        }    }    return null}

Extension Properties

Kotlin also has extension properties. I have an interfaceTransformable that has propertiesworldXandworldY. When I use objects that implementTransformable in the renderer, I want to know where they are in relation to its camera. To do that, I add a couple of extension properties onTransformable in the renderer, calledcameraX andcameraY. The implementation ofcameraXis shown below.

val Transformable.cameraX: Float    get() = toCameraX(worldX)

That allows the renderer to do things like this…

batch.draw(image, t.cameraX, t.cameraY)

Delegation

Also, Kotlin's implementation of delegation is something that I haven't seen before. In the following example, classAnimal implementsTransformable, but the implementation ofTransformable is handled byt which by default is of typeTransform. That means any call to a method or property onAnimal that implements theTransformable interface is automatically delegated tot, without the need to delegate it yourself.

class Animal(x: Float, y: Float, t: Transformable = Transform()) : Transformable by t {

For example, in the following code, the propertyworldX is implemented by aTransform, without the need for me to write anything more.

var a = Animal(100f, 200f)var x = a.worldX

Conclusion

I am not going to claim to be an expert at Kotlin. I only started using it when I began this project, and have been working my way through the Kotlin koans (found here) on my lunch breaks. But I am very pleased with what I've found so far and I think that I will use it instead of Java in circumstances where that's practical.

Kotlin seems interesting. Did you find it difficult to transition from Java to Kotlin ?

I'm glad to say that it has been a fairly smooth transition, although some of my code has more than a hint of "let's try this Kotlin feature" as I'm still learning. I regularly use Java, C#, Python and JavaScript for my day job, so many of the ideas in it are familiar.

What I like about it is:

  • it's succinct, which is a refreshing change from Java's verbosity
  • it's expressive - some of it is reminiscent of LINQ
  • it has batteries included, as it can use any Java library
  • it doesn't enforce any particular programming paradigm - if all you want is a function then that's fine
  • it has new ideas that work well, such as itsapproach to delegation

If you want to learn it, start with thetutorials, browse thereference and definitely, definitely do theKotlin koans (I've been doing these on my lunch breaks and they're very good).

Update:this is a very good overview of Kotlin (video + transcript)

Log in to reply Join the discussion. Log in or create a free itch.io account to continue.
itch.io on Twitteritch.io on Facebook
AboutFAQBlogContact us
Copyright © 2025 itch corp ·Directory ·Terms ·Privacy ·Cookies

[8]ページ先頭

©2009-2025 Movatter.jp