History of participation in the Game Jam. Snowbox

Published on January 26, 2018

History of participation in the Game Jam. Snowbox

    imageAt the end of 2017, I had the opportunity to test my strength and enthusiasm as a participant in one of the many world-wide Game Jams.

    Since this was my first experience in a similar project, I learned a few useful lessons and a couple of pleasant surprises. Well, I also received a toy that you could play with your colleagues on the pre-Fridays.

    Under the cat a description of how the intensive 30 days of development and the slow 20 days of waiting for the results.

    Note: The article is a narrative, with a small amount of technical details.

    Prologue


    I have long wanted to try myself as a game developer, and in the last year this desire became more and more obsessive. By the end of the year, I decided to start doing something - to attend game development meetups, read books, and even make a small prototype of the game.

    So one day Selim, my colleague, offered to take part in one of the many Game Jam and I thought that this was the best opportunity to explore the game kitchen without any long-term commitments. This is not a prototype, but not a long-running Project. In addition, tight deadlines are often one of the best motivators. And the main advantage is that the output in any case is something holistic and complete, which always inspires new achievements.

    So we decided to take part. Two java-developers, absolutely no experience in igrodelaniya. But when the same need to start?

    Training


    The selected Game Jam was thematic, and the organizers had to announce the topic strictly before starting the development. The contestants were given 1 month to create the game.

    We registered a week before the start and, due to the lack of a topic, spent time in anxious waiting and inaction. Perhaps it was better to spend this time choosing a genre and game mechanic. And then wrap it in the appropriate style.

    At hour X, the organizers announced the theme of the competition - Throwback (return back) and the countdown began.

    Selim had the only wish for the game - the presence of a game server and necessarily real time. He was interested to learn the charm and complexity of the development of the server part. Also, the game was supposed to be simple, otherwise we could not have time to complete it.

    Regarding the topic, thoughts were first about either retro or prehistoric times. The retro theme is not interesting to me, so I tried to think of something about dinosaurs or ancient people. However, I was not able to come up with something simple and multiplayer on this topic.

    And then I came up with the idea to make a sandbox game, while literally - a reference to children's entertainment on the beach. We build castles, run and rush to rivals with sand (I hope not everyone had such a difficult childhood), well, disgruntled parents are punished for it. All this in 2D with a top view.

    Selim thought it was too cruel in the eyes and suggested replacing sand with snow, and castles with ice fortresses. On this option, we stopped. As time and effort we could add new functionality and variety.

    Development. Week 1


    Our roles in the project are divided by themselves. As I said, Selim was interested only in server development. And I was interested in trying to develop UI, because, in my opinion, it is the most different from developing business applications. The interface of the game was planned web.

    Brief description of the technologies used
    Клиент-серверное взаимодействие было полностью построено на вебсокетах, поскольку нам требовалось асинхронно и регулярно отправлять сообщения от сервера на клиент. Сообщения от клиента также передавались через вебсокет, но просто по причине «почему бы и нет». Все сообщения были в формате Json.

    Для работы с вебсокетами на сервере был использован микро-фреймворк Spark. А в качестве физического движка использовался box2d, как один из самых популярных. Он отвечал за расчёт физики на сервере.

    Клиент писался на чистом JS, без использования каких-либо фреймворков, поскольку я в них не силён, к тому же в этом мало смысла для небольшого проекта. В качестве игрового движка использовался Phaser 2 — молодой и перспективный JS движок. В отличие от физического движка на сервере, его главным предназначением была графика и простенькие физические расчёты. Также использовался KnockoutJS для data binding.

    В качестве IDE использовались продукты от JetBrains: Intellij IDEA и пробная версия WebStorm (как раз 30-дневная версия, на время Game Jam).

    Development began with a joint meeting at the weekend. In the first 2 hours, I picked up "temporary" sprites and implemented a running boy who could throw snowballs. There could be a “was / became” picture, but it is devoid of all sorts of meaning - visually what it was, then it remained.

    Having a working UI, it remained only to fasten the server interaction. Therefore, the rest of the day was devoted to integration: a discussion of the API, setting up the connection, the implementation of the interaction. By the end of the day, our little man could move 1 pixel to the side, when you press a key. It was a modest, but still a success.

    Further development continued only in his spare time, with 6 days a week separately at home, and one day off together. This was quite enough thanks to a simple API and a hard distribution of roles.

    To repeat the success of the first day (run and throw snowballs), but through the server, it took us a week. Many technical factors equally influenced this, including problems with tools that were poorly designed for our client-server interaction model. I would like to dwell on this model in more detail.

    Client-server interaction model


    Initially, it was decided that the server would be responsible for any movement, and the client would only send commands, such as pressing a key, and draw what came from the server. Later, this philosophy was slightly refined, but the server remained central to the end.

    In the first implementation, the server sent updates to the client every clock cycle. Those. for example, if a key is held down, the player’s position changes every few milliseconds and a new position is sent to the client.

    With the help of such a simple algorithm, we implemented the player movement. But striving for the best prompted us to change the algorithm to an event one: only important events sufficient for synchronization are sent to the server, as well as to the client.

    For example, for a player to move up the map you need 4 events:

    1. Client : up key pressed;
    2. Server : the player began to move from the point [x, y1 ], at an angle α, at a speed ν;
    3. Client : key pressed up;
    4. Server : the player has finished moving at [x, y2 ].

    This approach has both advantages and disadvantages.

    Minuses

    • much more logic on the client: the client must calculate movement, collisions, etc .;
    • logic on the client must very accurately repeat the logic on the server, otherwise jumps in the movement of objects are obtained. Further in the article there will be several examples on this subject;
    • in the case of network problems, receiving events later may lead to incorrect states (going beyond the boundaries, passing through objects, etc.);
    • in general, it is much easier to get out of sync on the server and client.

    pros

    • much less load on I / O;
    • Additional logic can be added to events. For example, at the beginning / end of the movement, you can start / stop the animation;
    • network problems have less effect on smooth movement. While the snow is flying, the delay even in one second will not affect anything, since the server should not send anything;
    • The API and the interaction itself becomes more transparent.

    From these lists it is clear that if you work hard on the implementation of the client, then there are practically some advantages. For our project, we managed to achieve this and client-server interaction worked without any complaints. But we must pay tribute, it took quite a lot of strength and nerves.

    Development. Weeks 2 and 3


    After a week, when we managed at the very least to master the integration and make support for several types of messages between the server and the client, it was time to add something more to the game than just a running boy.

    Therefore, we decided to add a running girl! Along the way, for the girl I had to make a character selection window. And since the window still had to be done, it’s a sin not to add the input of the name. In addition, I had to do the stretching of the images, by analogy with the 9-patch approach .

    image
    This is how the first version of the login window looked.

    Because of all this, such a simple and important task of adding a girl took away a couple of evenings, but it was clearly worth it. And then gray days with similar tasks went on: new simple functions, error correction, minor visual improvements.

    As my progress progressed on the client side, the problem of uneven server and UI development speeds up. And since the server is a central part of any interactions, without the ready and working functionality on the server, the development of the client was stalled.

    Therefore, I implemented a simple mock server right in the client. Many things in it were implemented very clumsily, incl. through the use of the global state of the game world. This was enough to develop a UI completely independent of the server and saved me a lot of time.

    The mock server had another definite plus. There were bots in it that could not shoot, so there was a chance to win at least someone.

    Selim at this time struggled with the server. On the server, he connected the physics engine box2d to simulate physics in the game. This engine has a lot of nuances, and their study took a lot of time. The biggest difficulty in developing was the lack of visualization of the game world. Our client rendered only what was needed. And some elements of the "server world" were hidden from the client side. In addition, there were no full guarantees that the client renders everything correctly.

    One of the important subtasks that Selim had to solve was the checking of collisions of objects. On the client, collisions were checked only for fixed elements. On the server, it was necessary to do everything in an honest way so as not to infringe the rights of moving objects.

    During the development of collisions, I remember one funny bug that could claim to be a special functional: when a player threw a snowball, he was thrown back by “kickback”. This happened because in box2d, by default, anyone can collide with everyone, and a repulsion always happens.

    This problem was solved by the introduction of masks, i.e., an indication of classes of objects that cannot collide with each other. For example, for a player and his snowballs, the mask was made the same.

    Selim decided not to waste time on special handling of collisions of snowballs with each other and marked this collision with a comment:

    // for the unlikely event that we collide with a sibling snowball

    As practice has shown, the frequency of this "unlikely" event tends to the frequency of throwing snowballs, because when you are facing each other, the trajectories of snowballs coincide. Because of this, other people's snowballs constantly beat off with their own. Our opinion about this behavior diverged, so we left as is.

    While Selim was having fun with collisions, I debugged the synchronous movement of objects on the server and client. There were minor bugs in our own implementation, but Phaser presented the biggest surprise. In his physics engine, the real speed of objects is adjusted to the FPS and stop the world. This is done to improve the smoothness of the movements. Unfortunately, such clever behavior did not agree with synchronous work regarding the server and had to do its own implementation of moving objects.

    Description of the specifics of the speed in the Phaser or "race with a shadow"
    С целью проверки и отладки скорости, я добавил на карту ещё один объект игрока, который двигался с условно той же скоростью, но рядом. Этот игрок-тень и нормальный игрок использовали разные алгоритмы перемещения. И таким образом я устраивал соревнования и сравнивал стабильность скорости.

    Сперва я пытался решить проблему неравномерной скорости с помощью настроек движка и физики, которую мы используем. Но, как я понял, это поведение никак не изменить. Можно было переключиться на более сложную реализацию физики, но делать это ради одной лишь скорости не хотелось. К тому же эта реализация тоже не давала абсолютно стабильную скорость.

    Следующим шагом я попытался сам реализовать перемещение объектов, но от движка я взял контроль и дельту времени между каждым циклом мира. В Phaser есть несколько моделей времени и на одной из них как раз основана стандартная реализация скорости. Но, по неизвестной причине, не у одного из этих времён нет стабильности и они не могут обеспечить постоянную скорость. Это известная проблема, которая не планируется к исправлению в версии 2: github.com/photonstorm/phaser/issues/798.

    На «соревнования» игрока и тени я потратил 2 дня и так и не нашёл рабочего варианта. Поэтому в конце концов я сделал полностью свою обработку скорости, основанную на стандартном времени в JS. Очень удивительно, что такая важная функция получила такую странную поддержку в движке и пришлось реализовывать собственный велосипед.

    With such jokes and jokes, we have passed the second and third weeks imperceptibly. In addition, each week began with the phrase "well, by next week we must prepare a playable version" - every time it seemed to us that we were about to be ready. The complete lack of experience and the presence of tremendous optimism is the worst way to estimate timelines.

    A week before the change, at the developer meeting we could not even show the normal version and had to show the mock server.

    Of course, with such a speed of development there was nothing to dream about the originally conceived list of functionality, and even more so about nice to have things. Therefore, we had to forget about the "sandbox" and stop at the simplest 2D shooter.

    Development. Week 4, last


    In the last week of development, we focused on fixing bugs. It is better to have something modest and working than a multifunctional, but falling apart. There were many problems and most of them dealt with ill-fated integration. Here and there, small defects popped up, greatly worsening the impression of the game.

    In addition to fixing bugs, I also brought a final gloss to the UI: adding music and sounds, playing with fonts and improving small details.

    Of all the functionality, this week was only added a system of points, as well as limiting the stock of snowballs and restoring them.

    On the last day of Game Jam, we managed to play a little with our colleagues. Despite the general positive feedback, this gaming session was unsuccessful because of a critical bug - the snowballs were flying on the server and on the client at different speeds. Because of this, hitting other players was more of an accident.

    Description of the cause and correction of the error
    Этот баг мы допустили в последний момент, уменьшив количество FPS на сервере с экспериментальных 1000 до 100.

    Надо отметить, что вплоть до этого момента, нам так и не удалось добиться полностью синхронного движения на клиенте и сервере — периодически случались скачки в движении. Изменением FPS мы пробовали увеличить отзывчивость сервера.

    Когда я стал исследовать этот баг, я обнаружил 2 закономерности:

    • движение игрока работало корректно и стабильно;
    • движение снежка на клиенте всегда было быстрее, чем на сервере.

    Значение скорости объектов приходит на клиент от сервера, т. е. это не могло быть банальным несовпадением значений. Также обратное увеличение FPS до 1000 улучшало ситуацию.

    Я провёл немало времени в попытках исправить эту ошибку. Но ничего не помогало. И в итоге причина нашлась при помощи гугления — box2d косвенно ограничивает максимальную скорость, перемещая объект не более чем на 2 пикселя за один шаг мира. Т.е. при 100 FPS максимальная скорость составляет 200 пикселей/c (п/c), а при 1000 FPS — 2000 п/c. Это значение указано в константе и изменить его динамически нельзя. Это полностью объясняло причину замедления наших снежков, т. к. их скорость должна была быть 700 п/c, что требовало стабильное FPS выше 350.

    Для исправления этой проблемы я увеличил FPS до 500, но не просто так. В box2d в функцию шага мира нужно передавать сколько времени прошло с момента предыдущего шага. До моего изменения мы всегда рассчитывали эту разницу перед вызовом функции. Но теперь, зная желаемую частоту, можно было всегда указывать постоянную дельту в 2мс. При сильном отставании времени мира от реального, шаги нужно было повторять друг за другом, пока время мира не нагонит отставание. Затем немного sleep и всё по-новой.

    Это исправление, как и ожидалось, решило проблему скорости снежков. К тому же у нас наконец исчезла проблема с несинхронным движением на сервере и клиенте. В то время это чудесное исцеление было для нас полной неожиданностью, но сейчас я понял причину: несмотря на максимальные 1000 FPS, никто не отменял медленной работы сервера и тем более сборок мусора. Т.е. в какие-то моменты времени FPS мог свободно падать ниже необходимых 350 FPS, что и приводило к произвольным скачкам скорости.

    So, happy from the closed bug and working toys, 2 hours before the deadline, we were ready to surrender. It remained only to send the game to the project site.

    I expected the game to be laid out smoothly and in vain. It was necessary to create a project page, make a description, distribute screenshots and much more. We kept it, as expected, butt. Although later the organizers still individually accepted late projects.

    image
    Screenshot with the final version of the game

    Voting


    Under the terms of the contest, immediately after the completion of the development, a 20-day vote was opened. During this period, anyone could see the submitted projects, of which there were more than 200. Only participants were allowed to vote for the projects. Each game could be assessed in the following categories: general, graphics, sound, gameplay, innovation and relevance to the topic.

    Stage voting prepared us a bad surprise associated with the multiplayer nature of our game. There were relatively few people watching the games and the chance to meet the enemy was toward zero. Those. people came to an empty map, threw a couple of snowballs, ran a few meters and left in disappointment.

    We tried to organize game sessions through the project forum. Also, Selim and I occasionally entered the game, hoping to entertain the bored lonely wanderer. It all gave almost no results.

    It was interesting to watch some people testing the game. I especially remember the case when a player entered several characters at the same time and built a pentagram of boys. I do not know what the author wanted to say, but I still have a screenshot from the process of its creation.

    image

    Another player "hacked" our game. We have a name length check, but only on the client side. Accordingly, he bypassed this protection and began to correspond with me in this way, each time entering a new character, and writing his phrase in the name of the man.

    Simultaneously with the vote, my colleagues and I played again, taking revenge for an unsuccessful game on the day the project was handed over. This time everything went very smoothly and we got a number of ideas on new features, which, however, it was too late to add.

    In my opinion, the quality of the game, especially in terms of interaction with the server, turned out to be very good. How many times we have not played it, have not noticed any problems, just as we have not heard them from other players. For me personally, this was a surprise, given the quality and number of errors a few days before delivery.

    20 days, the data on the evaluation of games, stretched for a very long time, but in the end they ended and the long-awaited time for results came.

    image

    Thus, we took 36th place out of a little more than 200 participants. That, on the one hand, is not bad for the first project, but on the other hand, it is somewhat unpleasant for vanity. Especially considering that the top 10 got good games, but not all of them deserved some special attention.

    Lessons learned


    For the sake of receiving lessons in semi-greenhouse conditions, this was all started. We tried to invent many things ourselves and limited ourselves to a minimum set of tools in order to experience problems and experience bad approaches in our own skin. But now having knowledge of how to do it is not necessary and why, it will be easier to study the theory.

    The need of the artist . As practice has shown (not only ours), you can make a good game, without good graphics. However, selecting the right pictures, fonts, and user interface elements takes up most of the time. And the worst thing is that in the end they do not coincide with each other. From this, the warm lamp atmosphere is lost and the game does not look complete.

    Game tests are very important. Due to problems with the speed of development, we could not test the playability of our implementation most of the time. When we were able to play normally, there was too little time to fix the problem areas. And we were very lucky that there were not so many such problems.
    In my opinion, for games such tests on real users are much more important than for business applications, since, in addition to user convenience and problem solving, a certain level of emotion and involvement is also required.

    Not all libraries are equally useful.. Almost no one develops games on its own engine and there are engines for all occasions on the market. It was 2017 in the yard, and one would expect their high quality. I chose the Phaser as one of the most recommended and young JS engines. After all the problems that we had with him, I am afraid to imagine how the engines look worse. No, on the whole, the impressions from working with Phaser are rather positive, especially considering good documentation and examples. But working with him, not knowing a large number of nuances, is very difficult. In the spring there is a new version and I hope for significant improvements. And also in my plans there is a mini-project on some other engine to compare.
    And I will remember that problem with the maximum speed in box2d for a long time.

    In the process of Game Jam, you can learn. Starting this project, we knew almost nothing about game development, or about the libraries we used. And most of the time was spent studying these things. Despite this, we still managed to bring the game to a completed state.

    Not mandatory a lot of functionality . I'm a little surprised that many people like our game. Yes, they do not sit in it every evening, but enjoy one or two small sessions. But in our game there is neither an original idea, nor a large amount of functionality, nor any history. The same can be said about most of the games in Game Jam, which received positive ratings.

    (Game) Jam is a great reason to try.. It does not matter what: the idea, the new library, its own strength. When there is a clear goal and your result should be seen by others, it is very motivating not to limp and give all the best. And even if the result turns out to be worse than expected, it will not be a pity to throw it away, draw lessons for yourself and move forward!

    Links to resources:



    Thank you all for your time and good mood!