📜 ⬆️ ⬇️

6 interesting bugs that I encountered while making the game for VKontakte

image

I like making games, this is my hobby. A total of about a year in my free time I made a javascript game for VKontakte. Currently, the game is completed, launched, moderated VKontakte and is available in the games catalog. This is not an article of the form “how I made the game”, but a story about the problems I encountered while creating it. I hope that this information will help someone to avoid difficult situations in their projects. If I knew about some bugs in advance, it would be much easier, and maybe I would make other decisions regarding the code. Welcome under the cat for details.

Introduction


To make the essence of bugs more understandable, I’ll tell you briefly about the game. The game is based on the Chinese puzzle " Tangram ", its meaning is that you need to collect more complex of several simple shapes. In the classical tangram, seven standard figures are used, but in my game I decided to generalize this principle to any number and type of figures.

image
')
Initially, I used pixi.js as a graphics engine; later, for several reasons, I decided to give it up and just draw everything on the canvas. This is a controversial decision, and part of the described bugs came from precisely this. On the other hand, with pixi, I would get other surprises.

A few more points before going to the actual bugs.

First, although I used the word “bug” in the title, some of the situations described below are not bugs at all. These are features, or even correct, but illogical or non-standard behavior of the game / browser. Or just the difficulties that I encountered.

Secondly, although the project is not very large in size, but, of course, there were much more mistakes in creation. It just doesn't make sense to describe everything. I memorized situations that are rare, complex or interesting. Also, all these bugs are united by the fact that there is quite a bit of information on them during fluent googling, and, possibly, with thoughtful. Thus, I think it would be useful to describe them here.

Thirdly, I still haven't fixed some of the bugs. Because I do not know how, and whether it is possible at all. I think it is still necessary to write about them, so that other developers, when confronted with a similar one, know that they are not alone and have received at least some material for reflection. If someone knows how to fix incorrigible, I will be glad to hear the answer in the comments.

At this prolonged entry ends, go to the point.

â„–1. Dancing around fullscreen mode (fullscreen api).


And now, more than one year has passed, as support for full-screen mode has been introduced, but it's still there. There are many articles both on the Internet and on Habré, for example, here . But, as before, every browser does everything in its own way.

It looks like there are so many browsers (well, or how many engines), so many variants of the names of the full-screen api methods.

Not only do the prefixes themselves confuse (moz, webkit). IE11 uses two prefixes: ms and MS. Some browsers use the spelling Fullscreen, part FullScreen (hello firefox). A fullscreen change event is written without capital letters: fullscreenchange (with prefixes, of course). But in IE11 it is written as MSFullscreenChange, in Edge - fullscreenChange.

Also, some browsers center the full-screen element on the screen, some leave it in the same position it was in.

It would seem a trivial thing to turn on and off fullscreen mode. As a result, all this turns into the search for the name of the desired method in the right browser and long testing.

For those interested, here are the results on CodePen . Checked in chrome, yandex, opera, firefox, IE11. Unfortunately, I do not have the opportunity to check in safari and edge, if someone can do this, write in the comments.

â„–2. Fading shadow (context.shadowBlur).


When you hover over a shape, it is highlighted by adding a shadow. That is, to the usual picture, I add the following shadow:

context.shadowBlur = 5 context.shadowColor = “#000” 

For all shapes, this works fine, except for the usual rectangle. His shadow does not appear.

For a long time I put off disassembling with this bug until later, considering it not difficult. When the time came to take him seriously, it turned out that things were not so simple.

Long hours of searching, sampling of various options, and as a result I found out only this:


All the figures are displayed on the screen with the same code, so it’s not about the code. On the other hand, it’s impossible to reproduce this bug outside the game’s code, which means it’s about the code.

Frankly, I am very tired of butting with this bug, and the result is the following: I do not know what caused it; I do not know how to fix it.

But I know how to make a crutch and fix it. What I've done. He opened the picture of the rectangle in the graphic editor, chose one pixel (in the corner, well, it doesn’t matter what I think), and made him transparency not 255, but 254. As a result, the picture is outwardly indistinguishable from the original, and the shadow, that is Blur, way is displayed. And don't ask me how I came up with it.

Number 3. Deco decode bug (decodeAudioData)


To play sounds in the game, I use AudioContext. Sounds are loaded via XMLHttpRequest, then decoded using the decodeAudioData function. All nominally.

After some time, I undertook to test the game on an old laptop, which still has XP and, accordingly, the old version of Chrome. This is where I got the following error: Uncaught (in promise) DOMException: Unable to decode audio data. The same error occurs in the yandex browser.

image

The most interesting thing about this bug is that I did not manage to predict it in advance. You can test the support of an audio context simply by checking its existence: window.hasOwnProperty("AudioContext") . But how to check whether it is possible to decode the sound, except by trying to decode it?

The try-catch construct also does not help. Since the error does not occur in the js script, but in the browser code, it simply throws an exception and stops the script from running.

It turned out that the error occurs when trying to decode a wav file with one channel. If you convert the file to dual channel or burn to mp3, the bug disappears.

In the latest versions of chrome, this bug is missing.

â„–4. Beforeunload and save data.


When exiting the game, in the beforeunload event handler, I send a request to the server to keep the last open level.

In about 50% of cases, and maybe more often, data was not saved. Having spent some time thinking about how much time the browser gives to handle the beforeunload event, and how long the server processes the request, I realized that this was not the case. The answer was simple, if you already know it. It is necessary to use a synchronous request to the server, and not asynchronous.

All the same, an amazing thing - the herd instinct, or the power of habits and beliefs. In any manual and guide it is written: do not use synchronous requests! Use asynchronous requests! And in most cases the way it is.

Well, here is the very place where you can (and should!) Use a synchronous request! At the same time, the execution of the script is suspended, beforeunload expects and does not return a result, thus the data have time to be saved.

PS In the end, I still did save after each level, so safer.

â„–5. Canvas + Text + Firefox


Again, a rather old bug of the gecko engine, which I did not know in advance, but in vain. When displaying text on canvas in firefox, the text is displayed a few pixels higher than in other browsers (engines). This is especially noticeable if you use the context.textBaseline = "top" property. Visually, it looks like this:

image

The offset depends on the font size, i.e. it is not the same. When using other context.textBaseline values, the offset is smaller, but still noticeable by eye: a pair of pixels with a font size of ~ 20.

Discussion of this bug can be read here .

What I have tried:


As a result, I solved this problem “in the forehead”: I defined the browser engine and, if necessary, shifted the text down the required distance manually for each individual inscription. How not strange, it turned out the easiest.

â„–6. Sudden mouseout


I thought to write about this bug or not, because it's quite difficult to catch him, I even doubted if it seemed to me. But in the vivaldi browser, which I use quite actively, the bug is caught steadily. I also managed to catch it in chrome (but this is not accurate!). In firefox and opera, it was not possible to achieve the appearance of a bug, but it may have tried hard.

So, it all started with the fact that I noticed that with several successive clicks on the button in the game, if you do not move the mouse, the cursor is set to default, i.e. as if coming out of a button. After testing different variants, it turned out that the bug arises because a mouseout event suddenly occurs.

To test whether you have this bug, you can here .

I repeat, the bug is more or less confidently caught in vivaldi (after 5 - 30 clicks), uncertainly in chrome. In other browsers, I failed to catch the bug.

The essence of testing: open the pen, open the console (F12), now hover the mouse over the paragraph with the inscription and start clicking the mouse successively, trying not to move it. Watch for console messages. After a certain number of clicks out flashes, i.e. A mouseout event has occurred. It is even possible to achieve the effect that a mouseout event occurred, the mouse cursor changed to defult, after that the slightest movement of the mouse was enough for the mouseover event to occur again and the cursor changed to pointer.

Tried to use mouseenter / mouseleave events; test the file locally; disable selection by click. The results, plus or minus the same.

I do not know what it is and why it is. I can only assume the bug of a specific browser. In the game, I did not do anything about it, because in general there are no such buttons that you can (or should) press many times in a row. Yes, and that with this bug can be done, I honestly did not invent.

Several Yet


Though I indicated the number 6 in the title, I remembered a couple more funny mistakes. About them briefly, a lot of writing seems to be nothing.

It is known that the context.drawImage method can be called with a different number of arguments. Including, it is possible to specify the size of the area that we want to copy from the source and draw on the context. So, in chrome, you can draw a region with the size of 0x0, and firefox will generate an error - it will be scolded for the wrong size.

Strange bug with view code

 bounds = { left: 0 right: GAME_WIDTH top: 0 bottom: GAME_HEIGHT } 

It seems all is well, but for some reason bounds.top further in the code is not equal to 0, but something like 1e-14, which is of course very close to zero, but still not 0. And if below in the code there is a comparison with zero, then the result will be different.
There are two oddities here. Firstly, this bug occurs only after building the code into one file using require.js; while the code is in different modules - files, I did not notice this behavior. Secondly, for some reason, this oddity arises only with the value top, while bounds.left is still strictly zero.

Thank!


That's all, nothing more remembered. If someone wants to see the result of work, evaluate and test, go here .

Thank you for your attention, I hope someone this information will be useful!

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


All Articles