📜 ⬆️ ⬇️

Kotlin and the cost of developing the game (+ a little offtopic)

Good day. Today I want to talk about the development of the game using the programming language Kotlin. I will also give a small example of working with RxJava at the end of the article.

The first commit for this game happened on June 4 of this year, that is, I reached the open beta in about 3 and a half 4 weeks. I can't say that this is the first game or program for Android that I am developing, but I am not an experienced Android developer either. My previous experience was mainly Enterprise development.

I want to identify several topics in this article and run through them shortly. I will try to expand the Kotlin topic in detail, for the rest additional articles are possible if there is such a request from you (well, plus clarifying questions in the comments will help improve the presentation of the material). So to the list: this is a cost comparison of development on Kotlin vs Java, where to get the graphics for your game. A little about money (for now about costs, because there are no statistics on income yet). I also think it is very important to touch on the motivation part. Let's start with the end.

Motivation
Why do I start this article with such seemingly trifles as motivation? After all, if I want to create an application, then I am already motivated. And everything is fine, and success awaits me. The problem is that when we start working we often do not realize our true motivation: whether we are waiting for money, whether there is a personal need, whether we want to create an example for our portfolio. There may be many options. It would seem, what's the difference if I'm still motivated? But taking a portfolio for example is a seemingly good investment. You will be able to show your potential employers a finished product, and of course they will be impressed and will immediately assign a huge salary. So, as you develop, as you invest your time and energy, the value of the portfolio begins to fade into the background (especially if you cannot achieve visual appeal). I already want to get some money, and if initially there were no plans to monetize the application, then every next day requires more and more willpower. So what's the problem? It would seem that he started working with one motivation, and in the middle of the development process he added monetization, put it on Google Play and earned 100,500 rubles. Unfortunately this does not work. Users do not want to spend time on a buggy, raw or uninteresting application. That is, you can not put the project in the middle of development. If you do, most likely it will simply lead to a drop in the rating and the lack of download. That is, all your work will essentially go to the trash.
')
If you initially consider monetization as one of your interests, even before the start of work, you should understand what you will earn money on. The simplest and most ineffective banner ads. Slightly more complicated or about as simple as displaying ads on the whole screen. Next comes the store. But in order for the store to work, you need to hook the user with something. The sooner you get to view ads, the more it will fuel your motivation to continue to work on.

Graphics
The question of graphics for the programmer is probably the main problem. I mean games of course. When I first started developing, I thought that the most important thing was to write code, and finding graphics was not such a big problem. Maybe even order.

There is a significant amount of resource sinks where graphics are sold, there are resources with free images. And in principle, yes, indeed, the way it is. There is only one problem - these resources are made in different artistic style and the combination of them gives extremely strange results. Therefore, if you are developing your first game, I strongly advise you - do not look for graphics for your ideas. Look for ready-made sets of graphics for the game, and based on the graphics decide what you can implement. There are such sets, there are not so many of them, but at least for the first second time you will have enough.

In my case, it turned out that I spent 2 weeks on development, bought some resources in the markets, but naturally they were not enough to realize my idea. Frankly speaking, the purchased graphics made up less than 30% of the required. But there are no unsolvable issues, you can find artists who draw what you need. And here we are surprised to learn that it is not so simple. Especially if we are interested in quality results. What did I do - I looked through the drains, found interesting specimens in terms of graphics, switched to the description of the author and tried to contact.

Already at this stage you should have a list of items that you want to order, and already at this stage, most likely your pink elephants will add trunks. But for now this is only a hunch. You send a letter asking “can I apply for ordering graphics” and depending on the performer’s professionalism (and the people I approached were professionals with the exception of one), you will receive an immediate answer that “Yes you can, an hourly rate of $ 25 / hour” Your request will be completed within 30-40 hours, not including rework on the comments (free time for ordering will be in a month and a half). Or "I can do for a month and a half, it will cost 50 thousand rubles." Or “No, I have too much work and I don’t take additional orders.” These are all professional answers. And the worst thing that happened to me is the following:

- And how much are you willing to pay? (That is, a person does not assess the resource intensity or complexity of the task, but tries to adapt to the customer’s solvency)
- from 10,000 to 20,000 rubles (This was the first artist with whom I contacted and at that moment I believed that this amount is quite suitable for a small, I thought, a little work)
The man did not show much interest, but he seemed to agree. He himself appointed a term when he would give a description of what he could give me for this amount ... and disappeared. This is not even a bell, it is a bell that further work with such a person for you will end in failure. Nevertheless, 3 days after the date he voiced, he contacted me and said that he would do everything I needed for 15,000 rubles. I am very wary of generalizations, so I asked to list what will be included in this “all” point by point. After that, the person disappears and I believe that this is a happy ending to the story.

Kotlin


Development of a personal project is significantly different from the worker. There are several differences, but I will focus on the most significant (for me). This is related to the cost of development. In most cases, the employer determines the requirements, often the tool. He also has financial responsibility. There is testing or not, which libraries and which technology stack. In a personal project, all rights and all responsibilities are on you personally. Want to use the new framework - for God's sake. But the time that you spend on its development you will “pay” from your pocket. And yes, do not think that you work for free. Throw this idea out of your head, write your bet per hour on a sticker and it is highly desirable that it corresponds at least to the average cost of a specialist of your qualifications in the city. Do not underestimate your price.

Thus, the question of the effectiveness of your work comes to the fore. And did I do something useful for these 8 hours, for which otherwise I would receive (for example) 4000 rubles? That is the question of Kotlin vs Java, I propose to solve exclusively from a financial point of view. Both languages ​​are turing-complete and it means that any program written in Kotlin can be implemented in Java and vice versa. Due to what we can get the difference in the cost of development / cost of ownership of the product?

The cost of development is the amount of money to implement the functionality. Cost of ownership = cost of development + cost of support. In some cases, the cost of support is disproportionately higher than the cost of development. This is especially characteristic of write-only languages ​​(RegExp example. It is much easier to write a new expression than to understand where the error is in the existing one).

Ideally, the language should be cheap in development and in support. Reducing the boilerplate code unequivocally reduces the cost of development. Syntactic sugar reduces the cost of development, but it can (let me emphasize it can, but is not obliged to) lead to an increase in the cost of ownership. Syntactic salt increases development costs but reduces the cost of ownership. Below I give examples of code for Kotlin and Java and describe which option is cheaper and why I’m looking. Some examples will be from my project, some will not.

class Car(val id: String) { var speed: Double = 0.0 } 

 public class Car() { public final String id; public Double speed; public Car(String id) { this.id = id; this.speed = 0.0; } } 

* For DTO classes there is no need for getters / setters.
** Getters / setters only make sense if and only if they change behavior when working with fields

In this comparison, we see that the code on Kotlin is more readable and, most importantly, it is protected from the “billion-plus error” - NPE. Both id and speed in Kotlin cannot be null.

 var car: Car = Car(null) // compile error car.speed = null // compile error 

The second, no less important point in the above example is mutability.

 fun toRoman(value: Int): String { val singles = arrayOf("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX") val tens = arrayOf("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC") val hundreds = arrayOf("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM") val thousands = arrayOf("", "M", "MM", "MMM") val roman = thousands[value / 1000] + hundreds[value % 1000 / 100] + tens[value % 100 / 10] + singles[value % 10] return roman } 

 public String toRoman(int value) { final String[] singles = new String[] { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" }; final String[] tens = new String[] { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" }; final String[] hundreds = new String[] { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" }; final String[] thousands = new String[] { "", "M", "MM", "MMM" }; final String roman = thousands[value / 1000] + hundreds[value % 1000 / 100] + tens[value % 100 / 10] + singles[value % 10]; return roman; } 

Not much difference, is it? Nevertheless, final modifiers look extremely inappropriate and visually clog up the program. This leads to the fact that final is used in Java much less frequently than it should. But immutebl much cheaper in development and in possession.

Here is an example of data transformation:

 val data:List<Int> = ArrayList() val sum = data.filter { it > 0 }.sum() 

 List<Integer> data = new ArrayList<>(); final Integer[] sum = { 0 }; //Variable used in lambda expression should be final or effectively final data.stream().filter(value -> value > 0).forEach(value -> sum[0] += value); 

There are two points. Kotlin runs on jvm 6, Java requires jvm 8 for streams. And for android, this is for a minute 24 API. On June 5, it is only 9.5% of devices. And the second point is final or effectively final variables in lambdas of Java.

   private val buttonGroup = ButtonGroup<Button>().apply { setMinCheckCount(0) } 

 private ButtonGroup<Button> buttonGroup = new ButtonGroup<>(); … public constructor(...) { … buttonGroup.setMinCheckCount(0); … } 

Initialization of an object in Kotlin is possible in one place, which reduces the context for the programmer and reduces the cost of investment

In principle, from what I tried at Kotlin, these are the most serious things that affect the cost of ownership of a product. I don’t want to talk about data classes, operator overloading, string template, lazy properties, etc. All these things are interesting, but they can both reduce and increase the cost of ownership.

In conclusion, a small example of Kotlin + RxJava + Jackson. I want to have a dto class, which allows not only to store data, but also to notify about changes. The example is simplified for a more visual demonstration.

 interface Property<T> { var value: T val rx: Observable<T> } open class BaseProperty<T>(defaultValue: T) : Property<T> { override var value: T = defaultValue set(value) { field = value _rx.onNext(field) } private val _rx = PublishSubject.create<T>() override val rx: Observable<T> = _rx get() { return field.startWith(value) } } 

Here I want to draw attention to the overload val rx. When you subscribe to Observable, the current value immediately comes. This is important because deserialization from json'a happens before screen layout and linking graphic elements to a property. And with startWith, we immediately initialize the graphic element with the current value and change it as the play progresses.

 class Car { private val _speed = BaseProperty(0.0) var speed: Double get() = _speed.value set(value) { _speed.value = value } @JsonIgnore val rxSpeed: Observable<Double> = _speed.rx } class Police { val cars: List<Car> = listOf(Car("1st"), Car("2nd"), Car("3rd")) init { cars.forEach { car -> car.rxSpeed .map { speed -> speed > 60 } //  double   boolean  .distinctUntilChanged() .filter { aboveLimit -> aboveLimit == true } .subscribe { writeTicket(car) } } } private fun writeTicket(car: Car) { // do some stuff } } 

The Car class is perfectly serialized / deserialized by Jackson, it can be used as a classic dto class, but at the same time allows you to handle changes of properties in the reagent style.

Below is an example of a Label garter to an object property:

 Label("", assets.skin, "progress-bar-time-indicator").apply { setAlignment(Align.center) craft.rx(DURATION).subscribe { setText(TimeFormat.format(it)) } }) 

Conclusion:

Unfortunately, I can not provide objective figures how much the cost of ownership of a product on Kotlin'e is cheaper than Java. And this very statement I’m sure will be challenged more than once in the comments. I can only say in my subjective judgment, the figure of 1.5 - 2 times is real for me. Moreover, the reduction in the cost of ownership by one and a half times is typical for the start of the transition from Java to Kotlin, after about a week or two, I think it turned out to be a double efficiency. Mainly due to NPE-proof, immutable, lambda & higher order functions.

Upd:
Article on schedule

Source: https://habr.com/ru/post/331976/


All Articles