The zone that a player interacts with the most in a card game is their hand (not to be confused with the hand in games with 18+ content). A hand is a set of cards that a player can play in the current turn. And since this is one of the most important places, I decided already at the prototype stage to make the hand pleasant and beautiful.
Disclaimer: I’m describing my shit code here. I don’t know how to program at all, so I don’t advise using it as an instruction.
Just while working with the hand (not to be confused with “while working with the hand”), I realized the difference between a high-quality game and a craft at the prototype level for testing gameplay. It’s all about the little things and details. See how the cards in hand behave in Slay the Spire:
Now look at the same cards on the video of the person who writes in the title of the video that he made Slay the Spire in a week (9:11):
Now this name makes me laugh bitterly, because just because of such small chips with animations, it will not be possible to program everything from Slay the Spire in a week, even if you have absolutely all the art, game design and other content ready.
The key difference in these two examples is how the cards react when the mouse is hovered over them. In the original, the card comes to the foreground and scales beautifully, while the rest of the cards fly away from it. In the copy, the map simply rises and does not even come out into the foreground. This is exactly what I stumbled upon when I wanted to make beautiful animations for the hand.
How do I make a hand with cards
I made my first hand according to the tutorial from which I made the first prototype. In it, the Grid component was responsible for the formation of the hand, which arranges objects on the grid. Grid eliminates the need for you to write code that is responsible for the arrangement of cards: you simply set the settings and the cards themselves stand up exactly for any number when they fall into the right parent object.
The problem with the Grid was that it was done ugly: the cards teleported into the grid, and I wanted them to smoothly transition.
After some googling, I found a free Smooth Grid asset in the Asset Store. There were welcome smooth transitions. If I pulled out a card, it then stood at the end – well, okay, I decided.
Problems with Smooth Grid came when I decided to make the hand look like a hand in real life and in other card games – so that the cards run over each other a little – and after that I began to think about how I could make the selection of the card on hover. At first, the cards simply did not want to leave. When I figured out the exit, I realized that the map does not want to come to the fore. An issue that surfaced was that this smooth grid moved maps to the left or right depending on the position of the object with the map in the inspector. This means that if I bring the card to the forefront using the move in the inspector, the card will jump from its position to the most extreme in the hand. This definitely didn’t work for me.
I realized that in 2D in Unity there was no way to drag an object to the back and front other than the Sorting Layer property. But it can only be applied to objects with a Sprite Renderer component. He is responsible, for example, for ensuring that the card displays the desired picture. And all my objects had an Image component – I displayed the card image using it.
So, in order to bring the card to the forefront, I needed to change the Image component to the Sprite component. And this led to its own surprises. It turns out that all objects inside a Canvas with an Image component will overlay any other object. And when I create a Background object, which I thought was a background, it overlaps the sprites of the cards, and nothing is visible on top of the background. And this is quite logical: Unity recognizes any object inside Canvas as part of the interface: and the interface, as it were, should be on top of everything else in the game. But…it took me a long time to understand these rules. And there is still a lot of time to figure out how to set the settings for the sprites, fix the camera that has gone wrong and do a bunch of small actions.
Next discovery: Event Trigger, the component I used to bring cards to the fore on mouseover and play cards, didn’t want to work with sprites. The same script worked for me on an object with an Image and stopped working on an object with a Sprite Renderer. It turned out that there is another way to register mouse hover: using the MouseEnter, MouseExit and MouseOver methods.
Then new problems awaited me. I used the Lerp method to make the cards fly nicely into the hand and slide out nicely when you hover over them. Everything worked fine until I combined card animations with their addition to Smooth Grid. Then the catwalk began.
The fact is that Smooth Grid is also built on Lerp. And Lerp is a function that, like a rubber band, pulls an object to its parent place. And the problem was that Lerp in the grid and my Lerp were arguing with each other, and the cards ended up shaking and throwing in different directions. I tried to solve this by alternately disabling Lerps – it did not work. Everything started to go even more.
As a result, we had to abandon the Grid component altogether: both Smooth and normal. I myself made a simple conclusion to the desired position using the for loop, as crutch as possible.
Here’s what I ended up with
Most likely, a ride for the trailer. But for a real game, you will need to edit so that, for example, the cards are aligned in the center and the distance between them changes when there are more or less cards in the row. Also, hovering the cursor is not always registered, and if desired, the order of issuing and flying cards to the discard pile can be broken.
What do I think about sisharp
Despite a lot of problems, I like working with seasharp. But compared to all kinds of JS and Python, its syntax looks more redundant:
Does this remind you of this moment from JoJo Rabbit (0:18):
Of course, I would like to make it as juicy as in Slay the Spire, but it’s a hell of a lot more tinkering. In general, when developing, I try to cut off everything superfluous as much as possible. For example, when I now realized that I needed to cut a lot of things, I cut off all the logic that was not needed for the task that I set myself here in the cart. I also follow this path when developing part of the game for the trailer: maximum shit code (even by my standards, and I’m still a programmer), maximum fake stuff. For example, my cards stupidly climb out of the edge of the screen, and there they initially lie before the screen starts.
If you share guides and tutorials in the comments on how best to make a hand with cards, I will be very grateful.
This post is part of a series of posts about a game that I’ve been slowly making for a few months now. I share the entire production process: what decisions I make in development, game design, interface, art and other areas. In my telegram channel you can see other posts and find out when to expect the following: @nigylamchan.