📜 ⬆️ ⬇️

My own game. Part 2

Disclaimer


Here is an article about how my friends and I wrote the game. We finished it and sell it, but it does not bring us money. However, it was very interesting and fun for us to do it, and I decided to share my memories. The article will have a minimum of technical details, I will not lay out the code, since it makes no sense to learn from it. This is the code of amateurs, not professionals, there is an error on a mistake None of us has IT education and no one has ever been professionally engaged in programming. I will sometimes lay out the technical details, as without it, nowhere. I ask readers also not to post comments about what we are fuckers, as it is a shame to read. Though true.

Other parts of the article
Part 1
Part 3

Chapter 3. Jurassic Period


Before solving the memory problem, I thought of it quickly. True. The number of unique models at the level just limited to 5yu for enemies and 6 for our freaks. There could be a lot of “clones”, but they took a penny of memory, since the heaviest — the model and the texture — were stored in a single copy for all the “clones”. Of course, it was impossible to clone the freaks, since the player could decide to send completely different models on the mission, so I just limited the squad to 6 soldiers. In principle, a squad of 6 well-armed freaks should defeat any enemy, I thought, and there will be many enemies of one kind, many more - a second, a little third, a little - a fourth, and a boss of the fifth. I also reduced most of the textures to 128x128 or 256x256 (well, Dimon and Fyodor Mikhalych reduced, I was in charge here), and began to store many vertex components as short or char, instead of float. That was enough for the “game” to run on the device. It was fun to drive freaks on the screen with your finger, and besides, they could walk through walls. They could not avoid obstacles. Worse, I had no idea how to do this. Little by little, models of the game environment began to appear, and Fyodor Mikhalych hinted more and more strongly to me that it was time to write down the level editor.

Somewhere in 2 weeks I did a TEXT level editor. He worked from the command line. At start I asked the dimension of the field. Then I deduced the choice of the type:
')
1.    2.   3.   4.      ?2    (1-15):3   :5   Z:5  .   ? 1.    2.   3.   4.      ? 

And further in this style.

“Terribly convenient,” I thought: “Full control over the development, only the console, only hardcore.”

Fedor Mikhalych did not think so. That's when I needed my old code from our MMORPG under Windows. On its basis, I created a new editor. Yes, our new level editor used to render OpenGL. But creating a graphic editor took quite a lot of time.


This is the latest version of the editor, where there is everything. So he was not immediately.

The originally conceived 6 months are long gone, and we only had a level editor, floor textures, 1 freak model and a few models of the situation in the game. There were no enemies. The weapon was soldered to the freaks (yes, it later goes around comes around!), And, since we only had one model, there was only one weapon too. Worse, it was impossible to move the map on the screen, since the coordinates where the user tapped were transferred from the screen to the world according to the “correspondence table”. The table was a picture of the playing field in the same game perspective, only the red channel in it contained the world X coordinate of the cell that it displayed, and the blue one - the world Z coordinate. Thus, when tap happened, a pixel with tap coordinates in this map was checked, and the blue and red components of this pixel returned the world coordinate.

I considered this system of recognition of tapas the height of perfection. Fedor Mikhalych did not think so. He said that the whole map would not fit on the screen - everything would be too small. The map must be moved.

“Not a problem,” I said, and allowed the user to move the map around the screen in “jumps.” So that after moving the map jumped onto the grid with color coordinates with an offset corresponding to moving the map across the screen, but aligned with the grid squares. Thus, it was possible to move the map by a whole number of game cells along any of the 2 world axes (there was no height in the game).

Fedor Mikhalych, reluctantly agreed to leave it this way for now, but grumbled that the map could not be rotated. And I told him that if he wants to rotate, it is necessary to rewrite the engine, and then we return to the beginning, and already 6 months have passed, and the game is still, though not very, very far away. Fedor Mikhalych was unsatisfied and was silent and made levels. It seems to me, in the end, the levels are the best that is in this game. True.

But the levels were getting harder, there were more and more objects on them, and it all began to be terribly slow. Moreover, the profiler showed that there was no single bottleneck in the code, everything slowed down. From the pros, I screwed A *, and now the freaks could walk normally, only it was unclear how the engine could understand whether it was possible to pass through an object (a doorway, for example) or not (a wall, for example). And Fyodor Mikhalych ignored my enthusiasm for A *, but complained more and more about the speed of the engine.

- The speed fell below 10 frames per second on the newest iPhone 5, - he said, although his iPhone 5 has long ceased to be the newest. - And on the second ipad just a slide show.

Then I decided to introduce visibility maps. It worked as follows. The matrix was created in dimension with the playing field. Every time one of the monsters moved, the matrix was recalculated so that all the cells within a radius of 15 cells from each of the monsters were filled with units, the rest was filled with zeros. Then, only those cells of the map and objects that had coordinates marked with units in the matrix were entered into the rendering list. The rest was not drawn. Fog of war! It helped, but not drastically. That is, cardinally, the speed increased to 20 frames, but if there were many objects outside the fog, all the same, everything was sad.

Separately, I want to write about how the fog map was generated. The entire map was marked as being in the fog, then 360 rays were traced from each of the monsters, forming a complete circle around the monster, with a radius of "monster" in length. Naturally, before the first crossing with an obstacle. Each cell along which the beam passed was labeled as visible. That is, in fact, a primitive model of raytracing from Wolf.

But the 360 ​​rays were clearly not enough.

“You got some kind of crap,” Fyodor Mikhalych told me, showing that the walls along the player’s gaze, but a little to the side, were partially invisible, partially visible, and partly “looking” through them.
“Light is a wave,” I replied. - Do you know diffraction?

But the number of rays to 720, I then increased.


Dark gray squares with a gray worm are the fog of war. Not to be confused with the same, but lighter, this is concrete!

It was then that Fyodor Mikhalych caught the eye of the dEngine engine project , which I decided to study in order to increase my knowledge.

It was code from another planet.

The first thing that threw me into shock: under iOS, you can write in C. How glad I was. I already almost fell in love with the idiotic syntax of Objective C, but the realization that there are people who write humanly did not allow me to eat calmly. And because of this, I drank a lot. And here it is.

I told Fyodor Mikhalych that I needed a month and did not disturb me. I will create. And sat down to rewrite the C code. From scratch.

This helped a lot, because bicycles and crutches in the old code for more than six months have accumulated order. I did not drag them to the new one. Among others, I got rid of the crutch in the form of maps of transforming tapa coordinates through texture, and went deep into studying the issue in detail. Wrote the function of the inverse coordinate transformation. The map could now be rotated, scaled, moved as it pleases, and still the clicks were recognized correctly.
I was happy. Fedor Mikhalych was pleased.

To facilitate the rendering of the level, I decided to make the floor level consisting of a single rectangle, and not from square cells, as before. Since earlier each cell had its own model with its own texture, this innovation greatly increased the performance of the game (yes, there were several hundred texture switchings per frame only for floor rendering, and several hundred draw functions for it), but now for everyone The level needed its own floor texture, completely finished and containing all the cells together. I added functionality to create such a texture in the editor. The fog of war had to be left, but now I did it, passing the "visibility map" of the monsters in the form of a texture to the shader. Plus came the filtering. Now the fog of war did not advance abruptly, but had a gradient. It was nice. We still didn’t draw anything in the fog of war.


New fog of war. And the texture of the floor is new.

We reviewed and the structure of the files that store information about the levels. Now each level contained maps of travel and visibility. Cells through which it was impossible to pass were marked in the mileage map. In the visibility map - through which it was impossible to see, they served to calculate the fog of war. We agreed that if one cannot see through a cell, one cannot even shoot through it. And if you can see, but you can't get through, then you can shoot through it, but the accuracy of the hits decreases. Yes, we counted hits by a probabilistic model. Each weapon had an accuracy that determined the likelihood of a shot hitting the target, and the number of shots in the line. In addition, the probability increased with the growth of the title of a freak, or with the help of a sniper skill training.

At the same time, I added a system of clones for objects of the situation level, in order not to load duplicates, just as I had previously done for enemies. This did not bring significant memory savings, but the rendering speed increased due to the smaller number of texture switches, since all objects of the same type were always drawn in a row.

But it took a little more time than I planned. About a year from the start of writing the game, we returned to the place where we were six months ago, but now the code worked quickly, steadily resisting 60 FPS, iPhone limit, and gave a much better picture. And I had a child outlined. And everyone with whom I talked about the game, they said that it was necessary to have time to complete it before the child appeared, otherwise everything.

Chapter 4. Stone Age


I did not fear much for the project’s progress in connection with the appearance of the child. Yes, I understood that there would be much less time, but by that time Fyodor Mikhalych already had a small child, and, nevertheless, he coped. I thought I could handle it. In general, something like this happened, although progress still went slower. Fyodor Mikhalych did the levels and ordered models for them to Dimon, Dimon worked with freelancers and tried to calculate the balance of forces in the game mathematically. Fedor did everything empirically. I did almost nothing.

It seemed to me then that I was very tired of the game. Approximately 2 years have passed since the start of development. I had a newborn baby in my arms and a fully functional half-game. Yes, we were already close to the final "bohivki". We called it "akshnheim." This is where a player fights terrorists with a squad of freaks. But there was also the second part of the game, which we called “tactics game”, this time at the base, between missions. They need to manage intelligence in order to find the bases of terrorists, manage the detachment, treat wounded soldiers, train healthy ones, build, buy and sell weapons. That all was not. There was no system of points, there was no system of experience, there was no progress of freaks.

- Stupidly stamping levels becomes too stupid. We must take on tacticheim, Fyodor Mikhalych told me.

I rested. I'm tired. Then Fyodor Mikhalych told me that he would be engaged in polishing the akshnheim and ideas for tactics, Dimon would do art for tactics, and I can take some time off. So decided.

Meanwhile, a remake of the X-com for the company has long been released, and we even played enough of it, and the release for ayos loomed on the horizon. Fyodor Mikhalych said that no one will ever pay attention to our game after the release of X-coma for ayos. And I sat down for tactics game.

I sketched the structure of tactics quickly. In my vision, which the others agreed, the player’s alter ego should have stood in the middle of a small room. There were doors leading to other rooms in front of him, behind him, and to his right. The view was supposed to be “out of sight”, as in 3D shooters. With a swipe, the player had to “spin”, “switching attention” from one room to another, and tap to go into the room he was looking at. In these 4 rooms he could, respectively, control reconnaissance, detachment, armament and send the detachment to the missions.

They gave the freelancers the task to create a model of the base, and so far I have painted the backdrops in the paint and used them instead of real models.


One of the "rooms" on the base, made entirely by me.

Progress was relatively fun, and freelancers coped with the base relatively quickly, and soon the functionality was ready. Everything looked rather clumsy, especially, models of freak-soldiers and freak-workers of the base. The models of freak-soldiers, however, were in themselves nothing at all for akshnheim, where they were painted small. But when they were drawn on the whole screen, and even on the iPad, there was a complete failure.

In addition, they ate a lot of memory.

We had 3 basic freak models, each with 3 different head textures. There were also 3 different variants of camouflage textures (2 camouflage and 1 armor variant). Also, there were 4 weapon options. I said earlier that, in order to simplify the animation, we decided to “fry” the weapon into the freak model. That is, for the same freak existed 4 different models, one for each weapon. So, to display the unit on the base, 12 models and 36 textures should be stored in the memory.

In the memory of the 4th (and 4S) iPhones, this did not fit in any way. Especially with the base model. There was a great desire to drop support for the Quartet. But it was difficult to do this, because, despite the imminent release of 6s (yes, there was also a problem with a real resolution of 6 plus! OpenGL operated in real with a real screen resolution, 1920x1080, and the touchscreen gave out virtual coordinates from the 2208x1242 grid. One thing It was possible to convert to another in order to correctly recognize the coordinates of the wheelbarrow, having previously determined that we are working in this configuration), 4S could work quite well with the latest iOS, and I could not imagine how in the appstore to forbid users of fours to buy our game.

Fyodor Mikhalych suggested using their pre-rendered pictures instead of models based on the base. It almost helped. Finally, it also helped to downsize all the base textures. Now everything fit in memory 4ki. And even looked relatively good on the small screen of the 4th iPhone. But on the iPad, or even on the iPhone 6 Plus, it was a disaster.

The final decision was to determine the amount of device memory when loading and executing the corresponding code branch with loading textures of appropriate quality.

Understand when I call our soldiers' models freaks, I’m not joking, because the md2 format operates with 8 bits per coordinate, which gives a resolution of 256x256x256 pixels, and the resolution of the texture bindings is important not so much the spatial resolution of the model itself. The model was drawn on the screen with a height of 1.5 thousand pixels, and even if it occupied half the height of the screen, it was 500 pixels in height. Misses in the texture here were even very visible.

I will not say that the pictures of the monsters were much worse than the models of the monsters themselves, but the models of the monsters themselves were animated, which partially smoothed out the negative experience.

However, the game worked. Yes, she looked unassuming, yes, there were elusive bugs, and the balance was very wry. And yes, there were few levels and at that time they were all very different, some were heavy and heavy, such that the fight could easily last an hour, while others were instantaneous. But the game worked.

By the way, a few words about the levels. In the game, as in the X-coma clone that respects itself, there were two types of missions. Those that influenced the progress we called the plot. These missions to the player fell out when his intelligence found the base of terrorists. After passing the last such mission, the game was supposed to end. The second type of missions fell to the player from time to time, by chance. Such missions we called "random". These were the attacks to which the player had to react: rescue hostages or neutralize bombs in order to earn money and experience.

So, with the story missions everything was more or less clear, after all we had a scenario in which the player gradually went through the terrorists to Greenward (no, not Greenpeace, but Greenward) and to penguins, and in the end - to the mutant penguin , super boss game. But with random was not clear. They needed a lot, because I didn’t really want to force the player to replay the same random levels again and again. In addition, in the room from which the player started the mission, as in any self-respecting X-com clone, the missions were visible on the map (yes, not on the globe, but on the map, this was our know-how, a very striking difference from of the original!), and it was necessary to make some sort of linking of the contents of the level with the map, so that when you click on the mission at the north pole, the level with the desert does not load. It was a simple matter, but a dreary blessing, Fyodor Mikhalych was mainly engaged in everything, sometimes demanding from Dimon new models for levels, and from me to add them to the editor and the game itself (I still answered for the “master build”). And I was free, because, according to the general opinion, the levels made by me were distinguished by special slop. Although 1 or 2 ended up in the game. Perhaps that is why she did not bring money.

Having nothing to do, I started tuning the code. Lighting in our game was not. More precisely, it was flat. I decided to fix it. In the models, of course, there were no normals. It does not matter, I read Lamothe. I screwed the directional lighting, but static, it was calculated when the modelka was loaded. Got better. The “smoothing” of the model came as a bonus, since the normals for each vertex were considered as the average value of the normals of all triangles to which this vertex belonged, and the shader already made a smooth change in the illumination of the triangle from one vertex to another ( Guro toning ).

Then I decided to screw the shadows. It did not work for a very long time on the device. The fact is that in the simulator everything worked great, but in the device the shadows appeared, then disappeared, they were striped. As a result, I spat on the shadows on the walls, and only drew them on the floor, making a shader for it with a shadow, and for all other objects I just ignored the shadow map. Shadows turned out a bit neutered, but they were. True, I did not succeed in adapting the size of the zone in which the shadows were calculated to the size of the visible area, so the shadow map was always calculated for the entire playing field. As a result, despite the huge size of the map at 2048x2048 pixels (16 MB in memory!), At the maximum approximation, the shadows looked very pixelated (but looked!), And in the version for the 4th iPhone, the shadows had to be turned off altogether, since not enough memory.


It looked like a game on new devices

And so, on iPhone 4, 4S and iPad 2 and mini:


At about the same time, after seeing that the difference between the picture drawn by the game on devices with 512 MB of memory (and besides iPhone 4, 4S it is also iPad 2 and iPad mini) and more modern devices was quite noticeable, we decided to display fours for users and Old iPads alert that the device they have, to put it mildly, sucks, and we are not guilty of anything.

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


All Articles