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:
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:
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:
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:
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:
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:
( 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:
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:
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:
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
Kommentar veröffentlichen