Place items in the hands of 2D characters in a 3D world

For my tactical RPG game "Silence is a lie" ( in a custom written engine using: OpenGL and Java )  i needed to find a way to place any item or weapon in the hands of any character in the the 3D world.


The basic idea is, to be able to let any unit on the battleground use any weapon or item sprite i have. I did not liked the idea to be bound to only 1 or few weapons or items for any characters, and that would also mean to draw way more sprites. As this project is privately founded and with help of patreons, and i need to hire artists for every sprite to be drawn, so it´s also a financial decision to find a way to gain max flexibility by minimum number of sprite-sheets.

Here you see what the final result should look like for any HIT-WEAPON i add to the game:

2d sprite in 3d world



As i am using 2d pixel characters in a 3d world i am using the billboard rendering.
If you like to know more about it, check this link:
http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/

So in my engine the character and the weapon he is using are both drawn onto quads that are always placed in a 90 degree angle to the camera.
While the character quad is keeping its position, the weapon quad is moved around and rotated along the way, so the impression of a moving weapon is created.


This screenshot shows the different quads in action:

quad render - 2d sprite in 3d world



My first approach was to instruct the pixel artists to always draw the hands of the characters at the same positions.
Additionally i would place this information in the code to and get the pixel offset of the weapon that way.

Here is the old approach:

sprite sheet pixel positions
code - sprite sheet pixel positions

Of course this way had its limitations.

The artist could not work freely on the movement of the different characters and the code i needed to create and adjust did not really feel right. Additionally any changes in the characters sprites would result in code changes and that is something i´d like to avoid.

So the basic idea was, to find a way that would allow the artists to freely work on the characters and for me to be sure to have no need to ever touch the code again.
In sprite sheets it´s common to hide some information in colored pixels, so i decided to go with such a approach.

First of all i needed to define a color, that won´t appear in the sprites in general so i can give special functionality to it.
I decided to use the RGB  value ( 255 , 0 , 255 ) ... so some kind of "purple".

Next step was to set 1 pixel in this purple color in every frame of a character animation using a weapon. Obviously i placed the pixel in the palm of the hand.

Here is how the special pixel are placed in the sprite sheet:

sprite sheet pixel positions purple

Now with the 'special pixel' in the sprite sheet, i needed to add a function to read the sprite-sheet and detect the pixels.

To keep it simple i decided to go through all pixels and check for the color value. If the defined color is found i need to calculate the row and the column of the sprite-sheet in order to be able to store this information in a 'quick access' structure. This time a 2-dimensional array seemed to be the quickest way to do it. As i am working in opengl i am used to store pixel coords from the lower left to the upper ride side. So i store the pixel coords of the purple point in that format for every row/column in the sprite sheet.

-- this function will definitely get a performance optimization in the future as it is way to much load to be reasonable --
-- but keep in mind: make it work first >> than make it nice !!! --

Here is the code to check for the special pixels:

code to detected special pixels
 

With the information of the 'markedPoints' attached to each sprite-sheet i am now able to replace the old approach of hard-coded  positions for each sprite frame.

Now i can access the markedPoints array for, e.g. the 2nd row 5th column of the sprite-sheet and grab the X and Y coordinates for the 'palm of the hand'.

If there is no marked Point for the current frame of the sprite i remind myself to bring in the purple points into the sprite-sheet and switch back to the old approach for the time being. 

Here is how the code looks like to calculate the 3d offset for the quad holding the weapon based on the marked Points:

code to position 2d quad in 3d space
 ( this code could for sure be reduced to a cleaner mathematical approach ... again i spend more lines to do it step by step )


To my own surprise, this worked very well on the first strike!
So i had the weapons now moving according to the purple dots on the hand of the current character. ( the rotation is still hard-coded >> that's my next to do ) But of course i would not like to see this purple pixel when the game is rendering.

Here you see the intermediate result:

visible purple pixel in sprite
 

So i came up with a 'quick & dirty & easy' solution for this one. I decided to detect special purple pixels in the GLSL shader that is rendering the quads of the sprites and to just move 1 pixel to the upper right.
With the pixel I get by moving this 1 pixel to the up right i overwrite the current purple pixel.
I assume that the similarity of this neighbor pixels will always be good enough to not be recognizable on a moving hand holding a sword inside a complex 3d scene ... and till now it works just fine.

Here is the simple fix in the GLSL shader code: 

glsl shader code
... pretty simple, isn't it ?


With this changes in my code i am now able to take any weapon from my weapons sprite sheet and put it into the hand of any character in my game. A few things to keep in mind here, is that the weapon or item handle must always be at the same position. But i am already working on changing this to use the purple pixel as well.

Additionally i will try to implement the rotation of the weapon in the given frame also in the sprite sheet of the character, so any character will swing the weapons differently as well.
The Idea for this, is to place a 2nd purple pixel in the sprite of each frame and use the 2d vector between the 2 points as the rotation of the current weapon.

But for now i can easily use my weapons if i keep in mind to place them properly in the sprite sheep grid.

Here is the weapon sprite sheet with the grid background visible:

weapon sprite positions
 

Let me know what you think about this approach and if you see problems in it.

I hope i could inspire you to come up with even cooler solutions that give you more freedom and variety in the movement and actions of the 2d characters in your game.


If you like to get more information about this game or you even like to support me, please see the links below.

Instagram: https://www.instagram.com/silence_is_a_lie/
Twitter: https://twitter.com/lie_silence
YouTube: https://www.youtube.com/user/uwi2k2/
Patreon: https://www.patreon.com/silence_is_a_lie


Stay healthy and take care!
cu
kai

Kommentare

Beliebte Posts aus diesem Blog

Variables - A piece of memory that we can name whatever we want.

Variablen - Ein Stückchen Arbeitsspeicher, das wir nennen können, wie wir wollen.