Abilities in Space Jaguar Action RPG

The first article about the game in the development of Space Jaguar Action RPG. In this article I will describe gempleynuyu feature Jaguar – Specifications.

Many RPG system using static characteristics of the character, such as the characteristics of the DnD (Strength, Physique, Agility, Intelligence, Wisdom, Charm) or Fallout – S.P.E.C.I.A.L (Strength, Perception, Endurance, Cha, Intelligence, Agility, Luck).

The Space Jaguar I plan to implement dynamic characteristics of the system, such as Jag main hero of the game at the start of a total of three characteristics – Possession blade (polusablya), shadow transactions (transactions in the criminal world), picaresque capacity (breaking of locks, theft). During the game, characters will be endowed and deprived of the dynamic characteristics within the gaming unit, all checks will be made on the basis of the level of specific characteristics required for a given game situation. For example Jag not be able to win a game of chess, if no response has a chess game or not has sufficient for screening.

To simplify the logic checks, each characteristic is given by 6 digit code for English letters, name, description. Such as possession of Blade:

var bladeFightingAbility = new Object(); 
bladeFightingAbility.name = "BLADFG"; 
bladeFightingAbility.description = "Blade fighting ability"; 
bladeFightingAbility.points = 3;

Before the start of the gaming unit can view the list of public audits required for passage, also the creator can hide part of checks to create interesting game situations.

Know-hou? It will be interesting? Personally, I find this an interesting system that allows both to ensure the freedom of creativity creators of gaming units, and the ability to transfer characters from a different, but similar in characteristics to the players modules.


Skeletal Animation (Part 2 – Node Hierarchy, Interpolation)

Algorithm goes on to describe skeletal animation, as its implementation in the game engine Flame Steel Engine.

Because the algorithm is the most complex of all that I implemented, in the notes on the process of development can occur errors. In the last article of this algorithm, I made a mistake, bone mass is passed to the shader for each mesh separately, rather than for the entire model.

Node Hierarchy

To work correctly you need to model the algorithm contained a link bones together (graph). Imagine a situation in which both played two animations – jumping and raising his right hand. Animation jump should raise the model on the Y axis, the animation show of hands should take this into account and to rise along with the model in a jump, otherwise the hand will remain on its own on the spot.

Describe the relationship of nodes in this case – the body contains a hand. In developing the algorithm will produce bone graph reading, all animations will be included with the correct connections. The memory model graph is stored separately from all animations, just to reflect the connectivity model bones.

Interpolation on CPU

In the last article, I described the principle of rendering skeletal animation – “transformation matrix are transferred from the CPU to the shader when rendering each frame.”

Rendering each frame is processed on the CPU, for each bone mesh engine receives a final transformation matrix by interpolation position, rotation, zoom. During the final interpolation bone matrix produced by extending the tree nodes for all active nodes animations, final matrix is ​​multiplied to the parent, is then sent to the rendering in the vertex shader.

For interpolation position and increasing use of the vector, quaternions are used to rotate because they are very easy interpolated (SLERP) in contrast to the Euler angles, as they are very easy to imagine a transformation matrix.

How to simplify the implementation of

To simplify debugging work vertex shader, I added the simulation work on the vertex shader CPU using FSGLOGLNEWAGERENDERER_CPU_BASED_VERTEX_MODS_ENABLED macro. At NVIDIA graphics cards manufacturer has a tool for debugging the shader code Nsight, perhaps she, too, can simplify the development of complex algorithms vertex / pixel shaders, however, test the functionality I have not had the opportunity, enough simulation on the CPU.

In the next article I plan to describe the mixing of multiple animations, supplement to fill the remaining gaps.




Space Jaguar 3D Action RPG

For a long time I have not announced new projects) The next project I’m starting to work on is a 3D action RPG called Space Jaguar. A story in a sci-fi setting about a tough guy named Jag and his difficult adventure in search of a missing father. There will be 3D graphics on the Flame Steel Engine (or possibly on any other popular), using the achievements of past projects (Death Mask, Cube Art Project), a comedy story with many references, arcade battles and bosses. I’m not ready to talk about release date of the full version, I plan to release the game in parts.

Project Repository:


Write in C (ZX Spectrum) GameDev

This ne’er-do note is devoted to the development of games for the ZX Spectrum old computer to C. Let’s take a look at the handsome:

He began producing in 1982, and was produced until 1992. Technical data: 8-bit processor Z80, 16-128kb memory and other are extensions such as audio chipAY-3-8910.

The competition Yandex Retro Games Battle 2019 for this machine I wrote a game called Interceptor 2020. Since learning assembler for the Z80 did not have time, I decided to develop it in C language. As tulcheyna I chose the Quick Set – z88dk, which includes C compilers, and many support libraries to accelerate the implementation of applications for the Spectrum. It also supports many other Z80 machines, such as MSX, Texas Instruments calculators.

Next I will describe his flight over the surface computer architecture tulcheynom z88dk, show how it was possible to implement OOP approach is to use design patterns.

Special features

z88dk installation should be performed by a manual from the repository, but for Ubuntu users, I would like to mention feature – if you have already installed compilers for Z80 from the deb package, you should remove them as z88dk will default to access them from the bin folder of the -this version incompatibility tulcheyn compiler, you probably will not be able to collect anything.

Hello World

Write Hello World is very simple:

#include void main()
    printf("Hello World");

Assemble the tap in the file is even easier:

zcc +zx -lndos -create-app -o helloworld helloworld.c

To start using any emulator ZX Spectrum tap supporting files, such as Online:


Draw on the image to full screen

tl; dr Pictures drawn tiles, tiles 8×8 pixels size, the tiles themselves are embedded in the font Spectrum, then the string of index picture is printed.

O library sprites and tiles sp1 displays tiles using UDG. The picture is translated into a set of separate UDG (tiles) is then collected on the screen using the indices. It should be remembered that UDG is used to display the text, and if your image contains very large set of tiles (eg more than 128 tiles), you have to go beyond the set boundaries and to erase the default font Spectrum. To work around this limitation, I used a base of 128 – 255 using the simplified representation, leaving the original font on the spot. On simplification of the pictures below.

To draw a full-screen images you need to arm the three utilities:

There is a way ZX real men, real retro warriors is to open the editing palette using Spectrum, especially knowing the output image, prepare it and manually unload using png2c-z88dk or png2scr.

Way easier – take a 32-bit image, switch to Gimp colors to 3-4, slightly to edit, then import into img2spec not to work by hand with color restrictions, export png and transferred to the C array with png2c-z88dk.

It should be remembered that successful export each tile can not contain more than two colors.

As a result, you get the h file that contains a number of unique tiles, if more than ~ 128, simplify the Gimp in a picture (increase repeatability) and spend on a new procedure for export.

After exporting, you literally download a “Font” from the tiles and typing “text” of the indices of tiles on the screen. Here is an example of the “class” of the rendering:

// loading font into memory
    unsigned char *pt = fullscreenImage->tiles;

    for (i = 0; i < fullscreenImage->tilesLength; i++, pt += 8) {
            sp1_TileEntry(fullscreenImage->tilesBase + i, pt);

    // set cursor into 0,0
    sp1_SetPrintPos(&ps0, 0, 0);

    // print string
    sp1_PrintString(&ps0, fullscreenImage->ptiles);

Drawing sprites on the screen

Next, I will describe a way of drawing sprites of 16×16 pixels on the screen. Before the animation and change colors I came because corny at this stage, I guess I ran out of memory. Therefore, in the game there are only transparent monochrome sprites.

Draw in Gimp monochrome png image 16×16, etc. using png2sp1sprite translate it into assembly asm file in C code declare arrays of the assembly file, add the file at build time.

After the declaration of a resource of the sprite, it is necessary to add the screen to the desired position, then the sample code “class” game object:

    struct sp1_ss *bubble_sprite = sp1_CreateSpr(SP1_DRAW_MASK2LB, SP1_TYPE_2BYTE, 3, 0, 0);
    sp1_AddColSpr(bubble_sprite, SP1_DRAW_MASK2,    SP1_TYPE_2BYTE, col2-col1, 0);
    sp1_AddColSpr(bubble_sprite, SP1_DRAW_MASK2RB,  SP1_TYPE_2BYTE, 0, 0);
    sp1_IterateSprChar(bubble_sprite, initialiseColour);

From the names of some functions can understand the meaning – allotsiruem memory sprite, add two columns 8×8, add color for a sprite.

Each frame is affixed position of the sprite:

sp1_MoveSprPix(gameObject->gameObjectSprite, Renderer_fullScreenRect, gameObject->sprite_col, gameObject->x, gameObject->y);

OOP simulations

In C, there is no syntax for OOP, what do you do if you still really want to? It is necessary to connect the Dumka and illumined thought that such a thing as the PLO equipment does not exist, everything eventually comes to a machine architectures in which there is simply no concept of the object and other related abstractions.

This fact bothered me for a long time to understand why do you need the PLO, why you need to use it if in the end everything comes to machine code.

However, having worked in the product development, I opened the charm of this programming paradigms, primarily of course the development of the flexibility mechanisms of the protective code, with the right approach entropy reduction, simplification of teamwork. All of these advantages derive from the three pillars – polymorphism, encapsulation, inheritance.

Also worth noting is the simplification of addressing issues related to the architecture of the application, because 80% of architectural problems were solved by computer-scientists in the last century and described in the literature devoted to the design pattern. Next, I will describe how to add like OOP syntax in C.

For instance data storage more convenient to take the basis of class C structure. Of course, you can use a byte buffer to create its own structure for the classes, methods, but why reinvent the wheel? After all, we already reinventing syntax.

These classes

An example of the data fields “class” GameObject:

struct GameObjectStruct {
    struct sp1_ss *gameObjectSprite;
    unsigned char *sprite_col;
    unsigned char x;
    unsigned char y;
    unsigned char referenceCount;
    unsigned char beforeHideX;
    unsigned char beforeHideY;
typedef struct GameObjectStruct GameObject;

We maintain our class as “GameObject.h” do #include “GameObject.h” in the right place and use.

Class methods

Take into service experience Objective-C language development, the signature method of the class will be from a function in the global osprey, the first argument will always transmitted data structure, method arguments go further. Next, an example of “the method” “class” GameObject:

void GameObject_hide(GameObject *gameObject) {
    gameObject->beforeHideX = gameObject->x;
    gameObject->beforeHideY = gameObject->y;
    gameObject->y = 200;

Method call is as follows:


Constructors and destructors are implemented in the same manner. It can be implemented as an allocator constructor and field initializers, but I prefer separate methods for that,

Working with memory

Manual memory management type using malloc and free macros wrapped in new and delete operators for compliance with C ++:

#define new(X) (X*)malloc(sizeof(X))
#define delete(X) free(X)

For objects that are used by multiple classes at once, realized semi-manual memory management based on reference counting, in the image of the old mechanism of Objective-C Runtime ARC:

void GameObject_retain(GameObject *gameObject) {

void GameObject_release(GameObject *gameObject) {

    if (gameObject->referenceCount < 1) { sp1_MoveSprAbs(gameObject->gameObjectSprite, &Renderer_fullScreenRect, NULL, 0, 34, 0, 0);

Thus, each class must declare the use of a common object using the retain, release the possession through release. In the modern version of ARC uses an automatic affixing call retain / release.

I sound!

Spectrum has a tweeter capable of reproducing 1-bit music, the composers of the time were able to play on it for up to 4 audio channels simultaneously. Spectrum 128k comprises a separate sound chip AY-3-8910, which can reproduce music tracker. To use the Tweeters in z88dk proposed library sound.h

What is to be learned

I was interested to read the Spectrum, to realize the game z88dk means, learn a lot of interesting things. I much remains to be explored, such as the assembler Z80, as it allows you to use the full power of Spectrum, the work of memory banks, working with the sound chip AY-3-8910. I hope to participate in the competition for next year!



Source Code



Death-Mask Wild Beta

Game Death-Mask goes into the status of a public beta (wild beta)
Reworked the main menu screen of the game, added a view of the blue zone of the techno-labyrinth, with pleasant music in the background.

Next, I plan to rework the gameplay controller, add smooth movement like in old shooters, high-quality 3D models of boxes, weapons, enemies, the ability to move to other levels of the techno-maze not only through portals (elevators, doors, fall through holes in the floor, holes in the walls), add a little variety to the environment of the generated maze. I will also work on the game balance.
Skeletal animation will be added at the polishing stage before release.
You can check public beta here:


The Good, the Bad and the Ugly Singleton

In this article I will describe my experience and the experience of my colleagues when working with the Singleton pattern, when working on different (successful and not so successful) projects. I will describe why I personally consider this pattern to not be used anywhere, I will also describe what psychological factors in the team influence the integration of this anti-pattern. Dedicated to all fallen and crippled developers who tried to understand why it all started with one of the team members who brought a cute little puppy, easy to use, does not require special care and knowledge to care for him, and ended up raising the beast, it requires more and more man-hours and eats the man-nerves of users, your money and heavily slow down new features implementation.

Wolf in sheep’s clothing by SarahRichterArt

The story takes place in an alternate universe, all coincidences is purely coincidental…

Pet a cat at home with Cat@Home

Every person sometimes has an overwhelming desire to pet a cat at some point in life. Analysts all over the world predict that the first startup that created the application for the delivery and rental of cats will be extremely popular, in the near future will be bought by Moogle for trillions of dollars. Soon it happens – the guy from Tyumen creates the Cat@Home application, and soon becomes a trillionaire, the Moogle company gets itself a new source of profit, and millions of people who are stressed out can order a cat on home.

Attack of the Clones

Extremely rich dentist from Murmansk Alexey Goloborodko, impressed with the article about Cat@Home from Фorbes, decides that he also wants to be astronomically rich. To achieve this goal, through his friends, he finds a company from Goldfield – Wakeboard DevPops that provides software development services, he orders the development of a Cat@Home clone from them.

The Dream Team

The project is called Fur&Pure, it is assigned to a talented development team of 20 people; further focus on the mobile development group of 5 people. Each team member gets his part of the work, armed with agile and scrum, the team completes the development on time (six months), without bugs, releases the application in the iStore, where it is rated by 100.000 users for 5 stars, many comments about how great the application and excellent service (alternative universe, after all). The cats are ironed, the application is released, everything seems to be going well. However, Moogle is not in a hurry to buy a startup for trillions of dollars, because not only cats, but also dogs have already appeared in Cat@Home.

The dogs bark, but the caravan moves

The owner of the application decides that it’s time to add dogs to the application, applies for an assessment to the company and receives estimation at least six months to add dogs to the application. In fact, the application will be written from scratch again. During this time, Moogle will add snakes, spiders and guinea pigs to the application, and Fur&Pur will only receive dogs.
Why did this happen? The lack of a flexible application architecture is to blame for everything, one of the most common factors is the design pattern anti-pattern Singleton.

Nah, can’t be

In order to order a cat at home, the customer needs to create an request and send it to the office, where they will process it at the office and send the courier with the cat, the courier will already receive payment for the service.
One of the programmers decides to create a class “RequestCat” with the required fields, and brings this class into the global application space through singleton. Why does he do it? To save time (penny saving for half an hour), it’s easier to make an global object than to think about the application architecture and use dependency injection. Then the rest of the developers pick up this global object and couple their classes to it. For example, all the screens themselves refer to the global object “RequestCat” and show the data on the application. As a result, such a monolithic application is being tested and released.
Everything seems to be fine, but suddenly a customer appears with the requirement to add an requests for dogs to the application. The team frantically begins to check how many components in the system will affect this change. At the end of the analysis, it turns out that 60 to 90% of the code needs to be altered to teach the application to take in the global singleton object not only the RequestCat but also the RequestDog, it is already useless to estimate the addition of other animals, it’s already difficult with two.

How to avoid singleton

First, during the requirements gathering phase, clearly indicate the need to create a flexible, extensible application architecture. Secondly, it is necessary to conduct an independent examination of the product code on the side, with the mandatory study of weak points. If you are a developer and you like singletons, then I suggest you think again before it’s too late, otherwise sleepless nights and scorched nerves are 100% guaranteed. If you work with a project, in which there are many singletons, then try to get rid of them as soon as possible, or from the project.
You need to switch from the antipattern of singleton-global objects / variables to dependency injection – the simplest design pattern in which all the necessary data is set to an instance of the class at the initialization stage without further need to be tied to global space.




Gearing Gears

[Feel the power of Artificial Intelligence]
Ах муза, как сложно тебя поймать порой.
Разработка Death-Mask, и связанных фреймворков (Flame Steel Core, Game Toolkit и др.) приостанавливается на несколько месяцев, для того чтобы определиться с художественной частью игры, музыкальным, звуковым сопровождением, продумыванием геймплея.
В планах – создать редактор для Flame Steel Game Toolkit, написать интерпретатор игровых скриптов (на основе синтаксиса Rise), реализовать игру Death-Mask для максимально большого количества платформ.
Сложнейший этап пройден – на практике доказана возможность написания своего собственного кроссплатформенного игрового движка, своего IDE, набора библиотек.
Перехожу к этапу создания действительно продуманного, интересного проекта, следите за новостями.


Black Shaped Box

[English translation may be some day]

К любому разработчику на OpenGL периодически приходит Малевич. Происходит это неожиданно и дерзко, ты просто запускаешь проект и видишь черный квадрат вместо чудесного рендера:

Сегодня я опишу по какой причине меня посетил черный квадрат, найденные проблемы из-за которых OpenGL ничего не рисует на экране, а иногда и вообще делает окно прозрачным.

Используй инструменты

Для отладки OpenGL мне помогли два инструмента: renderdoc и apitrace. Renderdoc – инструмент для отладки процесса рендеринга OpenGL, просматривать можно все – вертексы, шейдеры, текстуры, отладочные сообщения от драйвера. Apitrace – инструмент для трейсинга вызовов графического API, делает дамп вызовов и показывает аргументы. Также есть великолепная возможность сравнивать два дампа через wdiff (или без него, но не так удобно)

Проверяй с кем работаешь

У меня есть операционная система Ubuntu 16.10 со старыми зависимостями SDL2, GLM, assimp, GLEW. В последней версии Ubuntu 18.04 я получаю сборку игры Death-Mask которая ничего не показывает на экране (только черный квадрат). При использовании chroot и сборке в 16.10 я получаю рабочую сборку игры с графикой.

Похоже что-то сломалось в Ubuntu 18.04

LDD показал линковку к идентичным библиотекам SDL2, GL. Прогоняя нерабочий билд в renderdoc, я увидел мусор на входе в вертексный шейдер, но мне нужно было более солидное подтверждение. Для того чтобы разобраться в разнице между бинариками я прогнал их оба через apitrace. Сравнение дампов показало мне что сборка на свежей убунте ломает передачу матриц перспективы в OpenGL, фактически отправляя туда мусор:

Матрицы собираются в библиотеке GLM. После копирования GLM из 16.04 – я снова получил рабочий билд игры. Проблема оказалась в разнице инициализации единичной матрицы в GLM 9.9.0, в ней необходивно явно указывать аргумент mat4(1.0f) в конструкторе. Поменяв инициализацию и отписав автору библиотеки, я принялся делать тесты для FSGL. в процессе написания которых я обнаружил недоработки в FSGL, их опишу далее.

Определись ты кто по жизни

Для корректной работы с OpenGL нужно в добровольно принудительном порядке запросить контекст определенной версии. Так это выглядит для SDL2 (проставлять версию нужно строго до инициализации контекста):


Например Renderdoc не работает с контекстами ниже 3.2. Хочется отметить что после переключения контекста высока вероятность увидеть тот самый черный экран. Почему?
Потому что контекст OpenGL 3.2 обязательно требует наличие VAO буфера, без которого не работают 99% графических драйверов. Добавить его легко:

    glGenVertexArrays(1, &vao);

Не спи, замерзнешь

Также я встретился с интересной проблемой на Kubuntu, вместо черного квадрата у меня выводился прозрачный, а иногда все рендерилось корректно. Решение этой проблемы я нашел на Stack Overflow:

В коде тестового рендера FSGL тоже присутствовал sleep(2s); Так вот на Xubuntu и Ubuntu я получал корректный рендер и отправлял приложение спать, однако на Kubuntu я получил прозрачный экран в 80% случаев запуска из Dolphin и 30% запусков и терминала. Для решения данной проблемы я добавил рендеринг в каждом кадре, после опроса SDLEvent, как это рекомендуется делать в документации.

Код теста:

Поговори с драйвером

OpenGL поддерживает канал связи между приложением и драйвером, для его активации нужно включить флаги GL_DEBUG_OUTPUT, GL_DEBUG_OUTPUT_SYNCHRONOUS, проставить оповещение glDebugMessageControl и привязать каллбек через glDebugMessageCallback.
Пример инициализации можно взять здесь: