Once at leisure I came up with a card game and, without thinking twice, I created its electronic version. And then he added four more games, including Texas Hold'em poker. And to make it even more interesting, I built in some kind of progress: if you win in one game, a new one opens. I planned to place my game in two social networks and in the Windows Store as an html5-js application. And also, perhaps, create more builds for Android and iOs. You can play through the server with other people, or you can play off-line with AI.
As usual, I didn’t use any third-party engines and libraries for work, I didn’t even need jQuery. Only vanilla javascript features, including canvas. Canvas in the game - the basis for the withdrawal of all game graphics. In WebGL, this time, there was no need, so the zoo of supported browsers has expanded. The programming environment, as usual, was an advanced notepad. The game turned out to be 3.8 MB in volume, of which 3 MB is seven sprite cards in png format. The game starts by html-file. PHP server. In the case of choosing a single-player game (that is, with AI), requests to the server are not sent and all calculations are carried out on the client. Dizdok did not write - he does not need the hipsters.
Next is entertaining geometry and programming, and in the second part there will be a story about the placement of the game in social networks and in the store.
GUI
Writing the code for the graphic part did not take me too long, since for my previous games I had already developed a JavaScript menu engine on the canvas tag with loading sprites from jpg and png formats, or in other words, GUI. It was enough just to take that code and define all active regions, that is, maps and menu buttons, as screen buttons using an associative array. Well, still sketch yourself sprites, that is, to create a design. The main time was spent, in fact, on the description of the game logic of all five games. And a little later - to create a multiplayer version for two social networks and a Windows store.
')
However, I was a little misleading about the fact that my canvas-menu is so completely completely ready. It can not just take it and ... In general, it (govnokod) is far from perfect and very limited in its capabilities. But most importantly, I wanted the cards not to be boring with a straight line, but to be laid out in a cheerful fan, regardless of their number. However, my menu did not support the “buttons” rotation. Therefore, it is time to program this disgrace once and for all. To start.
Welcome to vegas
I decided that the bend will be set by a certain parameter d, which indicates how far the center of the line of cards moves up.
So, given: the number of cards (n), the width of the rectangle (w), bounded by the centers of the extreme, boring, "non-bent" cards, and the shift of the middle of the line of cards up (d), giving them fun. It is required to find the points of the centers and the angles of rotation of each map so as to make a fan, as in the picture. It is difficult to say how good my method is, but this is what I was able to recall from geometry. We will write on JavaScript.
var L=0, h=0, dx=0, hx=0, hy=0;
Vegas is somewhere close.
The code for displaying all the sprites on the canvas on a formed array of points and angles is trivial and uses only standard canvas functions. The scheme is simple: you need to save the canvas state, move to where the center of the sprite will be, rotate the canvas to the desired angle, display the sprite, and then restore the canvas state. By the way, the half width (w2) and height (h2) of the sprite do not have to be calculated every time, they can be predetermined. In general, something like this:
var w2 = Math.floor(spriteW/2), h2 = Math.floor(spriteH/2); var x = spriteX+w2, y = spriteY+h2; ctx.save(); ctx.translate(x, y); ctx.rotate(spriteL - Math.PI/2); ctx.drawImage(spriteMapImage, spriteMapX, spriteMapY, spriteW, spriteH, -w2, -h2, spriteW, spriteH); ctx.restore();
Hooray! Now the cards are put in a fan, well, just like in Vegas - I saw them in a movie. The drawback or, more precisely, the flaw so far is that, although the sprites of the map buttons are now at an angle, the clickable areas still remain not rotated, even if they are correctly biased. That is, they co sprites coincide only centers. However, this is quite enough for this game. The deviation angle of the cards will be quite small, and it is unlikely that you accidentally click on the next map. Here, if there will be similar circles from maps, as in this picture, then they are not clickable, but just for effect. For player cards there will be much less bends.
There is always something to strive for. It is possible to count sines and cosines in the handler of the mouse pointer to check the entry into the click area, in order to more precisely position by the tilted button. Or you can rotate the canvas while moving the mouse. But all this will, as it seemed to me, be very and unreasonable to load the processor. After all, it will be necessary at each mouse movement to sort through the sine-cosines of all the “on-screen buttons” to determine if the pointer enters any area of ​​the click. You can, of course, work out the corners only at the event of a click, but then there will be no such beautiful change in the appearance of the pointer when entering and exiting the clickable area. I will also think about how this problem can be solved. In the meantime, move on.
AI
After reading this subtitle, one might have thought that he, at last, invented artificial intelligence. What happened to all the bright minds of civilization for so long has been accomplished. However, disappoint. In this case, under the pretentious abbreviation AI hides the usual random number generator. Okay, just kidding, not quite normal. The minimum logic of our game AI (Ivan Ivanich) is still there. Ivan Ivanovich is a serious man. The logic will still be supplemented, but even now, Ivan Ivanovich often beats me, for example, in my own game, insolent. In poker, I generally almost always lose. But maybe I can't play it. And you say artificial intelligence does not exist. No, he is obviously plotting something ... I am afraid, as if by chance I did not create Sky-Net.
Animation cards
Let's make a candy out of the game. Without animation of cards everything works somehow abruptly and ugly. Add another graphic layer (read - transparent canvas, canvas) on top of the main one and will arrange “races” on it between the deck and the table, the table and the players, the deck and the players. With rotation, songs and dances. The map you want to animate will simply be placed on an external canvas and there you can easily move there without fear of becoming an elephant in a china shop so as not to accidentally erase your neighbors and background. And at the end of the journey, it will fall back onto the lower canvas and continue to behave decently. Animation can be turned off via the game menu if it is not needed. Handlers of clicks, by the way, we will hang immediately on the outer canvas.
The motion of the map on the canvas will be set with the following input parameters: velocity V and points, initial (X0; Y0) and final (X, Y). When moving, we will draw the sprite in the position in which it should be after the time ti has elapsed since the beginning of the movement. And first, of course, erase the sprite from the old position. We will call the next drawing immediately after the previous one is completed. Thus, we will provide as smooth movement as the device on which the code will be executed allows. A binding to time will make the movement as a whole uniform, regardless of the possible short-term brakes of the browser. The calculation principle is as follows:
At the beginning of the motion call function, we define some parameters for the motion.
And in the cycle of motion, we will each time calculate the coordinates by time.
And finally, we will check these coordinates for belonging to a segment of motion. That is, Xi should lie between X0 and X, and Yi - between Y0 and Y. As long as this condition is met, we draw the sprite in (Xi; Yi) and loop the motion function. Next, the code, I think, is understandable, and there is no point in writing it in detail. I explained the whole principle.
Now regarding the angle of rotation of the sprite (ai). If the initial angle (a0) and end angle (a) given as input parameters are different, then in the motion function, we calculate the current angle ai as follows. The increment of the angle, that is, (ai) refers to the increment of the path, for example, along the horizontal axis (which we have is (Xi - X0)), as the total angle of rotation (a - a0) refers to the common path along the horizontal axis (Sx) , i.e:
ai / (Xi - X0) = (a-a0) / Sx
We draw the sprite with a standard drawImage with a preliminary rotation of the canvas using the standard JS translate and rotate functions, here, I think, everything is clear.
Yes, this algorithm does not take into account some special cases. When, for example, the distance is 0, then a division error by 0 occurs. But we will not set the cards to zero movement, why should we? Therefore, it is unnecessary to check for such extremes in this case.
Games
The games included are as follows. "Three bags" - my author's game. "Fool", "Poker Texas Hold'em". These are the ones that are open initially. Now closed: "Czech fool" and "Three sticks". They open if you win enough coins: to open the first closed game, the player must have 700 coins, the second - 900 coins. Initially, the player is given 650 coins. If you lose, then the game, on the contrary, will be closed right up to the very first. Coins can be won from other players in open games or purchased. In the single-player version of the coin removed completely, but only three of the five games are available.
Separately about poker
I have never played poker before, but I heard that this is a popular game and it even hosts world tournaments. I watched one such, as well as a couple of films about card cheats. Like when I was doing Sea Battle, I watched a series about pirates. It is difficult for a beginner to remember all the poker combinations, and even more so, as the game progresses, immediately present all possible options. Therefore, I added a screen that can be called up during my turn and see all the possible combinations for myself at the moment. And depending on this, make one or another move. Ivan Ivanovich (Artificial Intelligence) also uses this algorithm to evaluate his chances, therefore, in any case, this function would have to be written. This is how it looks in the end. Bright cards are those that are on the table and on the hands. Shaded are those that do not yet exist, but they may still come from the deck. And, if all 5 cards are turned, then this combination is no longer possible under any circumstances. The green dots mark the collected combinations: the closer to number one, the better.

For poker, I simply, for the sake of fun, also provided for such an option, when only AI is involved in the game, without people. It turned out something like a screen saver, where the computer with itself endlessly playing poker.
Design
Design is not my element. In the process of creating a game, he, as usual, was reworked and corrected many times. As a result, at the time of the release of the game, I stopped at the black and red version of the pub with the main menu on the suits that came to my head. I thought for a long time which of the two types to leave, and then I decided that they should both be switching between them.
English
The experience of localization of previous games told me how dreary then to pull out all the Cyrillic strings from the scripts and replace them with links. Therefore, I added them to the language file right on the go, and in the scripts of the main program I immediately inserted links (with comments). At first, I filled out only the Russian-language file, and then made a copy and translated it into English. The language file is connected dynamically, depending on the selected language, and is an array of strings with a specific name. As usual, a simple script:
var el=document.createElement("script"); el.type="text/javascript"; el.src="lng/lng_"+lng+".js"; el.async=true; document.getElementsByTagName("head")[0].appendChild(el);
Here, the lng variable is previously read from the command line parameters. The function of applying the language is started by the readiness of the html document And in all functions where text strings are present, references to elements of the language file array with phrases are already specified. There are no phrases in the layout of the html-page itself, because, in fact, the document is simply two canvas (canvas), superimposed one on another, and an empty block element for displaying the rules of the game. The rules are also located in the "language" file.
Those phrases that were “hardened” in the images - for example, the signatures on the buttons, are rendered into separate images in the png format, respectively, for the Russian and English languages. And the backgrounds - for example, the gaming table itself, podlozh for the menu and other sprites without inscriptions, are located in the general file.
Here is an example of Russian-language localization and a common background for Russian and English (in a reduced form):
"Russian-speaking" map spritesGeneral map of sprites (backgrounds) for all languagesSubstrates for the main menu are too large, so they are located in another, additional file. They are also common to all languages, and “buttons” for them are already included in both “language” maps.
Sounds
The sounds for the game were partially generated using a synthesizer, partially taken from free assets and connected with the audio tag. There’s nothing to talk about here. There was only one unpleasant moment related to the fact that if the current sound did not end up playing, the new sound is skipped and not played at all. Therefore, it was necessary to reduce the sounds so that they would not “overlap” each other in some situations.
Subtotal
In the next article I will talk about the experience of placing a universal Windows application in the Windows Store, about creating a classic (desktop) application for Windows from html-js files, as well as about the multiplayer version for social networks VKontakte and Facebook. At the moment, the game is currently available only in Windows Store as a single-user UWP application x86 and x64 under Windows 8.1 - 10. I also plan to make assemblies for Android and iOs. And also, perhaps, to lay out just a zip-archive to run the single-player version of the game by index.html for all operating systems.
In general, the archive with html-js files seems to me the best option for distributing such applications, since there is no need to build something with the help of “heavy” development tools, there is no need to create an installer, there is no need to include any libraries in the build, html You can open it in any OS with a choice of any browser and use the one in which the application will work best. It is a pity that application stores do not allow distributing applications in this way, and operating systems do not install and do not create shortcuts for html, such as, for example, they do with executable files. Unless, Windows 8.1 - 10 somehow moves in this direction, the assembled package for the Windows Store takes only 4.4 MB. Browser manufacturers could also turn to html-js applications and provide some kind of launch mode without showing the browser interface, as is done, for example, in node-webkit, when using the browser engine. Then it would not be necessary, for example, to include the engine in the assembly of a “classic” application and “drag” this engine with each such application. After all, there is potential for web applications: WebGL 3D graphics are available, bytecode, and soon, perhaps, the browser code will be even closer to native speed. But about all this - in the next part. In the meantime, I'm writing a server.