Gods of Sparta: gameplay works fully
I finished conversion to landscape mode and implemented the attack icons and
animations. For most attacks the cards just move and shake a little bit.
Ranged units have special animations, Zeus fires thunderbolts and Catapult
throws rocks at enemies. I added the damage numbers to attack icons and
it's now visible which type of attack deals the most damage.
I also created some nice icons for unit Energy (heart) and also
Attack (sword) and Defense (shield). Those show up when the default
unit values are modified (by artifact or an ally that stands next to
them). This makes the game fluid to play, as you don't have to
keep do the calculations manually all the time.
What's left to do: Turn indicator graphics, Sound effects, Music (I'm going to get help
from a musician), AdMob integration. Initially the game was supposed
to be only a two-player game, but now I'm thinking about single
player mode as well. Writing good AI for this strategy might get
complicated, but it's worth a shot.
There's still enough time before the end of
Feedback & Share
Reducing .apk size of my Android game by 88%
As I switched to landscape mode, I started to create mirror-flipped images
of unit cards using the -flop option in ImageMagic in one of the card-generating
steps. As the script rolled on for some time, it hit me that this would
increase the amount of graphics a lot. I got worried
about the size of the final .apk file. First time since I started the project I
decided to check.
I created a package containing only the lowest (800x480) and
highest (2560x1600) resolution images. It's 106MB!
I need to add 4 intermediate resolutions, so I'm looking at 300+ MB for the
final .apk. I searched the docs and found that the limit is 50MB and rest
has to be provided as a separate package. Or, you can distribute two different
.apk files. I didn't like any of those. I hate when you download an Android
game, and then you have to wait for it to download hundreds of megabytes more.
I needed a new approach.
I searched the Internet. Most advices are about packing your code using
compressor/obfuscator programs. But the gains are really negligible. Then one
thing caught my eye: using JPEG for textures. I'm using TextureAtlas to pack
everything automatically, but I could separate the images with and those
without transparent areas and pack them separately as PNG or JPG.
The problem is that 90% or the graphics need transparency. In this particular
case the main problem are the card images, which have rounded corners. And
then I got this great idea: separate the card image into frame
and contents. There are only four card types in the game (one for each faction
and gold one for the items), and all cards of the same type share the same frame.
The inside of the card is different for each one, but it does not require transparency.
Instead of packing 126 cards into PNG texture, I would pack 126 cards into JPG texture
plus 4 frames into PNG.
As I tried this, I got some weird clipping artifacts in the JPG texture, probably
because I turned off the 2-pixel padding. So, instead of pixel precise cropping,
I increased part of the graphics that gets copied to JPG so that there is some overlap.
When staging the images, make sure the jpg one is drawn first and PNG frame over it.
The part that overlays will covers the bad edge pixels.
BTW, by “staging” I mean placing the Images into libGDX Stage. To
make the code simpler, I created a nice CardImage class (descended from Group)
to handle drawing transparently. This Group contains the center of the card
from JPG texture and then positions the frame from PNG texture over that.
This saved A LOT, but I got so concerned about the size that I wanted to
do something about flipping as well. I researched if I could only flip a
part of the image. It's possible using AtlasRegion.flip() function. But I
also had the problem that I didn't want to flip the whole image. The textual
part should remain the same and only the unit graphics should be mirrored.
To do this, after calling flip(true,false) I used setRegionY and setRegionHeight to
reduce the flipped region size. Using the flipped region I created another Image and added it to the CardImage group.
At runtime, I simply show or hide this image when I need to unit to face left or right.
New .apk file with the same content is now only 12MB. A 88% save. Once I add
all the other resolutions, I estimate
the final .apk to be about 40MB if all goes as planned. Compare this with 300MB+
I expected at the beginning.
Beside all the other advice you might find on the web (compressing the code, etc.), add these three:
Feedback & Share
- use JPG wherever possible
- if you use PNG only for semi-transparent border, cut the image into frame + content. Store the frame in PNG and content in JPG
Of course, if your frame is not reusable on multiple images and has complex colors this my have the opposite effect.
However, there's a solution to that as well: cut the frame into four pieces (left,right,up,down) and assemble it at runtime. No more empty space in the middle of the frame in PNG.
- If you have images that are flipped or rotated, store only the original and flip/rotate at runtime.
Use the Landscape, Luke
Just like the last time, I decided that I have to change the screen
orientation mid-project. This time from portrait into landscape.
Here are the reasons:
- attack graphics looks odd upside down
- I want to provide hints how damage is calculated, awkward since all the enemy cards are upside down.
- Thumbnails used to pick units from your deck are too small on phones.
- YouTube videos are landscape.
- Desktop version of the game (if I ever release any) can use larger resolution.
- I can test larger resolutions on my monitor instead of having to run it on the Android devices.
- Players will sit next to each other, so they won't have to put the device down on a table to play.
You can play it with a friend in a bus or on a train.
- Much more available screen space for unit stack and enough space for additional user interface.
See how everything is crammed currently and a lot of space is wasted sideways:
- I have to redraw some of the graphics
- I now need horizontally flipped unit graphics which will almost double the memory consumption of the game (I cannot simply flip the whole card, as it contains pregenerated text as well)
- The drafting screen cannot use the rotations to indicate current player
To conclude: unless the game is meant to be played like Flappy Bird (using the
same hand that holds the phone and having only one command: “tap anywhere”)
use the LANDSCAPE orientation.
Feedback & Share
If got a lot done in the past two days. The main battle mechanics work.
You can place and move units, and attack. There is still no attack animation.
As you can see on the screenshot, some units are turned upside-down. This
is because it's a two player game. The idea is that you put the phone/tablet
down and sit across each other and play.
Flying units like dragons can reach any field, while others have to
move one step at the time. Each turn, a player can move and attack, or attack
only. Once you attack, it's the other player's turn.
I'm currently drawing some attack icons. When you select your unit in the
field, those circles would rotate over the adjacent enemies and you can pick
which one to attack.
Depending on the attacker, a different circle would be used. Olympus
units would get a blue round one. Humans get the yellow square (at least I
tried to make it resemble a cross). Underworld units have the hexagram.
I drew all these in Inkscape.
Feedback & Share
Picking cards and explaining how they work
I know players hate reading complex rules, so I tried to make a screen
that would explain how the cards work without getting too complicated.
Here are the basic rules:
At the start of each game, the players are presented with a deck of 20
cards and they take turns picking one by one until each has 10 in their hand.
After that the battle starts.
When the first player picks the card, all the other cards rotate 180 degrees
to face the player sitting across. It's a two-player local duel game.
Feedback & Share
Understanding relations between setOrigin, setScale and setPosition in libGdx
For card animations in Gods of Sparta I'm using the largest card graphics
all around. The cards get scaled and rotated as they move. To rotate the image
around it's center, you need to setOrigin to (width/2, height/2). However,
the origin is also used for scaling, so if you scale the image it will no
longer stay at the same (x,y) position you set with setPosition.
To get the scaled image in some particular position, you need to offset
the coordinates. See the image below for the exact math:
We want to position the scaled image to (60,70), but since it has setOrigin,
it shows up in a different spot. To place it properly, we need to move it
half of the difference between full and scaled image.
Now that we know how it works, it all makes sense. I hope this saves
other developers some time.
Feedback & Share
How to draw a ring with Inkscape
On of the artifacts in my game is the mythical Ring of Gyges. I decided to improve my
graphics skills and learn Inkscape better. Rings and other metal surfaces
are rather simple to draw, you just need to combine proper gradients.
I started with basic eclipse, duplicated the shape multiple times and
then created unions and intersections needed to assemble the ring. I used
a brown-gold-white-gold-brown gradient (it's easy to make a custom gradient
like this in Inkscape). To get the proper gradient (straightforward or
reverse) I put a real ring on my desk and watched the colors.
This is the basic ring. But lets make it look really good. First I rotated it
about 180 degrees and then added a gem to it:
As you can see the gem has multiple layers. On the bottom we have a black
circle with white border. Border is not the same everywhere, it has a
gray-white gradient stretching from left to right. Outside it, there's another
border, with black-to-transparent gradient. This is used to create a 3D
effect on the ring's metal surface. Over that, we have
a half-circle with another gradient. This time the gradient is radial,
extending from the bottom-left corner which has a white point. That point
looks like a point where the light enters the gem.
This is the base. Now we will add color. You can pick any color. I choose blue.
First, we create the dark blue overlay (one the the right in the image above).
Note that is also has a slight gradient going from left to right.
The light blue layer on the top
is used to complement the bottom-left white point in the black and white
base. As the light enters in
the bottom-left corner it goes through the gem and exits in it's top-right part.
There is no sharp point there, although you could put one if you want to
achieve a different effect.
Finally, here's the artifact's card in my Gods of Sparta game:
Feedback & Share
Gods of Sparta factions
The game is based on 4 card types. There's 3 unit factions: Olymups (Zeus, Athena and some
creatures), Underworld (Hades, Cerberus, Minotaur...) and Humans (Achilles, Hercules, etc.)
and some items that the units can equip.
Olympus will have bonus when fighting against Humans. In mythology the
gods of Olympus always had control over human fate.
Humans will have bonus against the Underworld units. In myths, greek
heroes often defeated the monsters and some even went into the world of dead to do some quests.
Underworld unit will have bonus against Olympus. This will make the game
fairly balanced. A single unit can be extremely deadly against one opponent
and completely useless against the other.
The units will have a single number for attack, defense and energy. But
there will be different special abilites that can increase or decrease that
during battle. There will also be items (artifacts) that modify attack
and defense. For example, here's a sword I drew in InkScape:
Feedback & Share
How to pick artists on Fiverr
I'm still learning how to draw well, and I'll make all the artifacts images.
But for units, I need some good artists to make nice pictures. I searched
the fiverr.com and found some really good ones. Here are some pictures I
commisioned for Gods of Sparta game.
Most artists on Fiverr are only good with a particular style, so make
sure you look at their portfolio before ordering. For example, an artist
from South Africa with username seatongrey has a great style that
would fit Underworld units in Gods of Sparta. But I wouldn't use him for
Human faction. He made the Dragon above, and here's the Hades:
For Human units, I hired glass84
Here's Achilles from glass84:
The turnaround is usually a couple of days. You can see the average in
the artist's profile. Now, be prepared that some artists might be busy and
won't get back to you quickly (or ever). If that happens, just cancel the
gig and hire another one.
Be prepared that some designs might fail. For Olympus units I had to
combine different artists. flannery
is good with horses, so I got Pegasus and Unicorn:
Medusa was a tough nut. I hired four different artists and in the end
had to use one
who is really expensive. But he's a pro:
I had to edit each of the images a little bit. The dragon was completely
ok, but it had a big belly, so I had to crop the image to focus on the head
and fire. I had to change or add the background to Achilles, Unicorn and
Medusa. I also increased the contrast, added a drop shadow or glow where
needed, etc. The only picture I did not touch at all is Hades. So, don't
expect to get a perfect image served on a silver platter. Remember that
Fiverr is meant to be the cheapest service while still having a decent
I'm pretty satisfied the way all this turned out. Still, I think that
for my next project I will learn how to draw myself.
Feedback & Share