In the beginning, there was ... - 1 My first job's probation period ended 3 years ago, but only now did I find time to write an article. I spent a year in different departments at my university: in my first semester, I studied management, and in my second semester, I switched to software engineering. I hoped they would teach me how to program, but I was mistaken. So, I collected materials and decided to learn everything on my own. The only reason I'm grateful to my teacher is that he recommended that I start with Stephen Pratt's ebook "The C Programming Language". It truly is a good book with a lot of practical exercises. I spent about 2 months on the book, after which I came across this online Java course in a friend's groups and so it began. At first, I planned to become an Android developer, but the backend seemed more interesting to me as I progressed in my learning. By the way, it took me 3 months of studying to reach Level 20, after which I decided to try to find a job. The first order of business was to move to another city since mine didn't have any openings for a junior Java developer. I found a company, applied, and received a test task, which I was given a week to complete. I had to write a simple web application using Hibernate, Servlet/JSP and MySQL. Seeing all these terms, I only knew that MySQL was a database. At first, I was very disappointed. I even decided to look for job openings at some KFC, but then I resolved to take a crack at the test task. After all, I could always get a job at KFC. I worked non-stop all week and managed to finish the test. I submitted my solution, but it "wasn't pretty", so I revised it 4 more times. My last solution turned out to be correct, but the positions had already been filled and additional applications wouldn't be accepted for 3 months. What are you gonna do, right? For the next 3 months, I learned HTML, CSS, JS, SQL and PHP. Why PHP? I needed a server language that would respond to requests and such. At the time, servlets and jsp seemed too complicated. In the end, I produced a full-fledged web application with a terrible interface. I published the code on GitHub for my portfolio. By this time, 3 months had passed and the same company contacted me again and invited me to an interview, giving another simple task to test my knowledge of SQL, which I managed to complete in a few hours. The person I was talking to about employment hinted that they would ask about algorithms and data structures — topics that I had not had time to master yet. That said, there were 15 days before the interview. I got this! Robert Lafore’s book "Data Structures & Algorithms in Java" helped me. I didn't have time to read and understand all of it in two weeks, but I still learned a lot. And then the day of the interview came. I arrived at the appointed time. Two men greeted me and the interview began. To say I was worried would be a wild understatement. My voice trembled. They asked about everything except algorithms and data structures. They asked about Spring, DI, IoC, Hibernate, how the JVM works, how the garbage collector works — I wasn't able to answer a single one of these questions. I only successfully answered questions about Java Core (collections, exceptions, OOP, etc.). While still at the interview, I knew that I failed it, but I was still disappointed not to receive any feedback. Instead, I identified gaps in my knowledge and began to work diligently to close them. I found a job one month after my failed interview. By the way, I found the job opening in discussions on JavaRush (JavaRush is the Russian-language version of CodeGym — editor’s note). First, there was a Skype interview with a recruiter (it lasted about 2 hours). They asked about Java Core, garbage collection (now I knew how it works), databases, and data structures. The interviewer asked me to share my screen and write a calculator. I almost wept for joy, since I had written a calculator just a week before. Confident in myself, I started the task. But whether because of my excitement or for some other reason, I forgot part of the algorithm. My screen was shared. I was afraid of consulting Google. Fortunately, I had my mobile phone, which saved my ass. The next day, they called for an in-person interview and a couple of days later I received an offer. It wasn't an official position. My role was an apprentice to a sole proprietor. We wrote a service for event planning, selling tickets, etc. I remember my first day of work. My boss took 15 minutes to explain what needed to be done. "Is everything clear?" he asked. "Hmm, not really. Can you go over it one more time?" I asked with great concern. The boss explained everything again. "It is clear now?" "Yes, now it is." Actually, I didn't understand ANYTHING. But I was afraid to ask for another explanation. I think anyone employed can understand that. The task boiled down to porting from Thymeleaf to AngularJS. Fortunately, I found a chunk of finished code and used it as an example of what to do. I didn't understand how it worked, but I finished the task. I was subsequently assigned tasks directly related to the backend. Only after a practical experience with Spring did I begin to understand what I read in "Spring for Professionals". I worked there for 8 months and then moved to another city, where I quickly found an official job, worked for 2 years and changed my title from "junior" to "mid-level" along the way. Then I faced the fact that my job had become routine and didn't give me a drop of pleasure. So I took a break. To stop my fingers from atrophying during my break, I decided to try my hand in another area: game development. More specifically, mobile game development, picking up Android, since I already knew Java. And that's what I'm going to talk about in detail now. My team. In short order, I had assembeld a small team of 4 people (including me): 2 developers, 1 game designer, and 1 sound engineer. Because no one on the team had any experience in game development, and because my vacation time was limited, we decided to implement a simple project that we would definitely be able to finish. And so we did! Initially, the deadline was November 15, but as you know, finishing a project on schedule is just wrong. So, we finished it two weeks late. Our technology stack consisted of Java 8 and libGDX.

Development

Development began on October 17th. In total, we spent 45 days during which:
  1. We learned how to use libGDX.
  2. We wrote code.
  3. We created graphics.
  4. We created music.
Anyone who has seen the game might ask, "Why did it take so long? The game is so simple." Yes, that's true, and to be precise, the development part (writing the code) took about a week and a half. The rest of the time was divided between:
  1. Mastering how to use the game engine.
  2. Drawing and redrawing artwork.
  3. Writing music.
  4. Searching for sounds on https://freesound.org.
  5. Reading heaps of articles on how to promote games.
We also had moments of "downtime" for various reasons: someone had an exam, someone else had a make-up test, etc. We can certainly attribute a week and a half or more to the downtime. Some time was also spent on "debates": new ideas about what to add to the game appeared almost daily, so we debated: "that's superfluous," "that won't fit," etc. We threw out a lot of ideas, for example, adding running cockroaches that could be crushed to get extra points: in my opinion, one of the most difficult things was to decide in advance what would be in the game and to stick to the plan without trying to add "just one more" feature. That's how these 45 days accumulated. A prototype of the game was ready after a week and a half. During this period, we really didn't have any graphics, so we took some things from the public domain (for example, we borrowed paper background from Doodle Jump) and we cranked out some things ourselves in Paint. In the beginning, there was ... - 2The game is very simple in a technical sense. We didn't even need to use box2d (a physics engine). We can handle collisions and calculate the hypotenuse on our own. The most interesting points I will highlight are:
  1. Initially, all game elements were generated randomly. In other words, we put providers (of black holes, scissors, ninja stars, pencil lead, hearts) into an array, got a random provider, got an element with random coordinates. It became clear pretty quickly that this approach was "really not really good". Friends participating in testing told us the same thing, recommending the use of templates. For those involved in game development, this is probably an obvious solution. But because we were newcomers to the field, it was very practical advice for us.

    So we created several templates: a valley of scissors; pencil leads — it's pretty cool to collect them super fast (whoosh, whoosh, whoosh with your finger); and one more template that I don't know what to call — I'll just tell you what we named the class in our code: StraightForwardPattern.

    In the beginning, there was ... - 3

    These templates improved it, but it became too predictable somehow. That's why we added one more: a random template. In other words, we now have some "static" templates and one random one (insert "perfectly balanced" meme here).

  2. Here's the main problem we encountered. LibGDX calls the render (float delta) method in an infinite loop. This is where all the elements are drawn. The pencil line is drawn as follows: we get finger coordinates and draw texture there. So, if we moved our finger across the screen very quickly, then the line would have "gaps" due to the milliseconds between calls to the render(delta) method.

    The solution was quite simple: we remember the last coordinates where the texture is drawn, get the next coordinates, and if the distance between them is more than X and the finger hasn't been released, then we fill the gap. At first, we thought this option might not work — the lines would be angular. But our fears were unfounded, everything worked just as it should.

About the game

The gameplay doesn't claim to be unique, but it is quite good and can pull users in. You control a pencil, literally drawing on paper and dodging obstacles — scissors, ninja stars, and black holes. Meanwhile, your pencil lead is running out and you need to pick up small pencils. If your pencil is coming to an end before you collect a little pencil, you can pick up a piece of a mirror. For a few seconds, instead of consuming the pencil lead, it will be restored, however, at the same time, the controls are mirrored — if your finger moves to the left, then the pencil draws to the right. You can also pick up a heart that will let you hit an obstacle once and stay alive. The longer you move the pencil without lifting your finger, the higher your combo, which means you will accumulate points faster. In the beginning, there was ... - 4The speed of the game also increases gradually. The only thing missing are angry birds. Initially, we planned to name the game Karan Dash (the transliteration of the Russian word for pencil is karandash — ha! get it?), but later we changed our minds and settled on Pencil Dash. We did this because this graceful pun would only be understood by a Russian-speaking audience. We released the game a couple of days ago and are now promoting it. Here, too, no one on the team has any experience. We gained all our knowledge about game promotion from various articles. We published information about the game on various websites/forums for free. Our paid channels included advertising on 4pd, advertising with one blogger, several posts in public groups on VKontakte, and AdMob advertising. In the beginning, there was ... - 5By the way, this post is also part of our promotion, so with permission from the website's administration, I'm including a link to the game here. You can find the game on Google Play here. I'd be grateful if you would install it (maybe you'll like it!), and if you'll leave a rating, I promise to name a child after you! :) In the beginning, there was ... - 6