Wednesday, April 11, 2018

Gameplay footage

I put together a quick clip of the battle gameplay. The recording is not the best quality, but it should at least demonstrate several features of the game.


I made a couple design changes prior to the recording:
  • Each hero (left) will do a basic attack if their assigned gem color is matched on the board. Previously they would simply roll a percent chance to attack, following the enemy's turn. This change speeds up the battles and feels more action oriented.
  • All creatures have green (poison) armor of 500 points for sake of demonstration. This armor is impervious, so will not affect the creature's life points until the armor is destroyed by incoming attacks of its color. Simple and easy to understand. Previously I only had physical and magical armor amounts, which would reduce incoming damage by a percentage; some creatures could be immune to specific elements. It was unclear and very confusing.
I'll have to add a feature later to help color-blind players discern the gem colors and their assigned elements. Color deficiency affects 1 in 12 men, and one in 200 women (source).
  • Orange: physical melee and range based attacks. Swords, bows, maces.
  • Red: fire.
  • Green: poison and heals.
  • Blue: cold.
  • Purple: arcane magic attacks, beneficial enchantments.
Now, I get to clear the main board and work on the main screen that contains all the features like character customization, inventory, stage selection, and upgrades.


So many possibilities. I will buy more art through the Unity asset store to help me with this task. I may want to have a map for stage selection and some large packs of metal or wooden interface objects like buttons and scroll screens.

In addition, I need to contemplate how to extend playability of the game. Zombie Guard is flawed in that the game is way too easy when going back to previous stages to collect all the outstanding loot. It basically dead-ends too, without advancement to harder difficulties once all the stages are beaten.

Saturday, April 7, 2018

Easing curves for game balance

To my casual readers, you may skip to the below section on Final Thoughts if the math here seems a bit intimidating.

For Unity you can download my Easings.cs script that borrows from tween.js on GitHub. A delegate for exact choice of easing function can be passed into your custom scripts.

Lerp and easing functions

I have been using easing functions extensively for many years, usually for animation. Easing functions are just curved functions for values $t$ from 0 to 1.

Linear is boring, but sometimes necessary to interpolation. Meaning, a value changes gradually - neither speeding up, nor slowing down as time $t$ goes from 0 to 1. Linear interpolation $lerp$ is a convenient function to compute this linear value:

$lerp(x_0, x_1, t) = x_0+(x_1-x_0)*t$.

Where $x_0$ is the initial value and $x_1$ is the final value as $t$ goes from 0 to 1. These values can be colors, vector positions, numbers, etc.

If $t=0.25$ then the value would be 25% of $x_0$ and 75% of $x_1$. If these are positions, then it would be 75% of the way from to $x_1$ starting from $x_0$.

Easing functions, from easings.net

To understand these functions, just choose one and slide your finger from the left and gradually to the right. If the point on the line is closer to the bottom horizontal line, then it is closer to the initial value. If it is closer to the top horizontal line then it is closer to the final value. Some functions can even go beyond the bounds of the initial and final values.

If we have a fireball in a game, then perhaps we might want to have its movement towards its target begin slowly, and then pick up speed until it explodes. In the second row of the figure above, are cubic functions. Notice how $easeInCubic$ would be very suitable for the fireball's movement. On the other hand, $easeOutCubic$, may seem a bit strange, where the fireball shoots quickly and then seemingly slows down before it explodes.

Game Balance


I use these easing functions extensively for game balance as well. In my game, weapons can be upgraded from ranks 1 to 10. At rank 1 it is the weakest, and at rank 10 it is the strongest and does the most damage. The easiest solution would be to just write the damage values manually.

Morning Star

For example, the damage of a morning star for each of the 10 ranks could be manually coded like this:
\[[1, 3, 5, 18, 13, 23, 50, 83, 88, 92]\]
But this gets confusing! It is too many numbers to work with. Plus, it is hard to immediately see the difference between each rank. Notice how the damage can go from 50 to 83, which is a 63% increase. That is massive and throws off the balance of the game. Also the damage at rank 4 is greater than rank 5.. oops! These errors can occur easily if we write the damage values manually.

Fail.
A generated graph of the damage of the morning star quickly illustrates the flaws.

We need a better solution...

In my game, weapons have an initial damage of $d_0$ at rank 1. In addition, a multiplier that determines the final value $dmul$, where for example a value of 4 would mean the damage at maximum rank would be $d_1 = d_0*dmul$, four times the initial starting value. Easy! The damage for the morning star now can be specified by just two values!

So, let's give it an initially large damage $d_0$ value of 42, but a tiny $dmul$ of 1.25, so fully upgrading it only provides an extra 25% damage increase.

The linear damage of the morning star for each rank would be $lerp(d_0, d_1, t)$ where $t$ is:

$t = (rank - 1)/(maxrank - 1).$

The linear damage increase is a bit unfair because a weapon casually upgraded to rank 2, would completely outshine a new weapon at rank 1. The game balance would feel off. In addition, upgrading from ranks 9 to 10 would provide the same damage increase as upgrading from ranks 1 to 2.

$easeInCubic$ looks like a good choice. So, the revised damage of the morning star would be:

$lerp(d_0, d_1, easeInCubic(t))$.

Similar to how damage is calculated, the cost of upgrading needs to be considered as well. Suppose we use the same curve, $easeInCubic$. This would not be balanced because it would be too easy to upgrade anything to around rank 7!

I think $easeInOutCubic$ would be an interesting choice for the cost of upgrades:
Better!

The cost for sequential upgrades always increases, but ranks 4 to 6 would have the largest increases in cost. This would be suitable because most weapons could casually be upgraded to around rank 4 until the costs get awfully pricey. Ranks 7 to 10 are where the costs are very high, but would be very rewarding due to the drastic increase in damage; there is an incentive to max it out.

Final thoughts


Balancing a game is a continued struggle. As written above, I have chosen an approach to help adjust the difficulty of my current game in order to feel balanced and rewarding to play. In-game currency is used to upgrade weapons from ranks 1 to 10. Here is the ideal mindset a player should have while upgrading these weapons:
  • Ranks 1 to 4: "Oh, these were easy upgrades. It feels like I am rich. I upgraded everything to rank 4! I like the slight increase in damage and I am not certain which weapons are my favorites. I just found some new weapons that still look powerful even at rank 1, so I will try those out too."
  • Ranks 4 to 7: "Woh, these upgrades are starting to get expensive! I must be more careful in how I invest my money. There does not seem to be a noticeable improvement on damage by upgrading these, but the enemies are starting to get really tough too."
  • Ranks 7 to 9: "All these upgrades are so pricey, but the damage is going way up now! It looks like the damage at rank 10 is twice as good as rank 7 so it is worth it!
  • Rank 9 to 10: "Well, it was a struggle to upgrade it to rank 9, but looks like it is totally worth maxing it out because it is the largest increase in damage of all the upgrades! Now I can choose something else to max out."

Saturday, March 31, 2018

Milestone reached

There I sat today, in one of my favorite cafes in Chiang Mai called Ombra. It is decorated with American and European antiques. Organized, to avoid seeming gaudy or noisy. It feels like visiting someone's home. Alternative rock plays in the background, from a hidden speaker near the unplugged record player. A typewriter sits on a display desk, near books and records of classic rock bands. The hot cafe lattes contrast with the cold air-conditioning. I realize hours have passed, when my laptop alerts me that its battery is running low.

Other days I may visit the London Tea Room, which is like sitting in the lobby of Fawlty Towers.

The spacious cafe called CAMP is open 24/7 on the top floor of the nearby mall. The usual selection of Thai food vendors are just one convenient escalator ride down.

But back on track, I deployed a build of my game to my Android phone and then left Ombra. It looks and sounds great, thanks to my shopping sprees in the Unity asset store and sonniss.com. This game has a lot of potential if I keep at it. Here I am holding it up in my apartment, before going out for dinner around the corner:



Unlike my previous titles, I plan to go for an early release, but continue to nurture it full-time. It will get the attention it deserves through additional characters, items, features, and things requested by the community. The first version probably will only contain 50% of the anticipated total content to allow for flexibility.

Monday, March 19, 2018

A mini debug tool in Unity

There are many ways of creating a tool to debug a game. Console commands on run-time is a common one. In-game rendered menus is another. In Unity I have been using a simple game object that has a script that exposes check-boxes which act as either toggles or buttons (they automatically get unchecked). It's sufficient for my needs. It's like having a handy dandy remote control with a bunch of options to speed up testing.

The inspector of the single debug game object in the Unity scene will look something like this:


And the script is as simple as this:

 using System.Collections;  
 using System.Collections.Generic;  
 using UnityEngine;  
 public class EPDebug : MonoBehaviour {  
      public bool toggle1;  
      public bool toggle2;  
      public bool option1;  
      public bool option2;  
      public bool option3;  
      [HideInInspector] public static EPDebug instance;  
      public void Awake() {  
           instance = this;  
      }  
      public void Start () {  
      }  
      public void Update () {  
           base.Update();  
           if (toggle1) {  
                // do stuff each frame  
                // other game objects can check this variable too  
           }  
           if (toggle2) {  
                // do stuff each frame  
                // other game objects can check this variable too  
           }  
           if (option1) {  
                // do something once  
                option1 = false;  
           }  
           if (option2) {  
                // do something once  
                option2 = false;  
           }  
           if (option3) {  
                // do something once  
                option3 = false;  
           }  
      }  
 }  

I have a toggle that has the game print out verbose information regarding game states and whatever information suits me. I use the button options for creating spontaneous game objects and invoking commands like giving some in-game currency. This debug menu can be extended with number fields to change global variables too.

Sunday, February 4, 2018

Big upcoming milestone

I am working towards an important milestone of this project - a fully playable demo. It will showcase an entire prearranged battle to demonstrate the general gameplay. It will be fairly polished, with special effects and audio that I plan to purchase in large commercial packs. From there, it will just be a matter of going into full production on the rest of the content and features, like the hero classes, enemies, and areas.


I have been contemplating some of the design features...

Damage Types and Defense Stats


The damage types are: physical, fire, cold, poison, and arcane. All creatures tend to focus on one or more. I considered defense stats for all these, but as a player, it gets unnecessarily complicated quickly: "This creature has half the cold defense as fire, but my fire spell does x more damage, should I use that or poison at wait.. what was the poison defense again? It is a goblin, which is green, so is that more or less resistant to poison? Screw it, I'll just attack with fire and pretend it was the ideal strategy."

...So, instead, defense stats only will be physical and magical that groups all the elements into one. In order to create distinctions between the elements, some creatures in particular areas can be completely immune or resistant to one, such as fire. It ought to force the player to utilize different heroes at different areas, rather than just blindly grinding away on a select few.

Weapons


Each of the player's heroes can wield an interchangeable weapon for basic attacks and passive bonuses. I considered having an inventory system with procedurally generated weapons and a crafting system. Instead I am just going to individually draw and author five named weapons for each class type, depending on the desired play style. The specific names will be easier to translate, rather than procedurally generated ones with names like: "Cruel Swift Dagger of Burning Flames". The grammar would not hold.

Upgrades for Skills and Equipment


I almost always use a five-rank upgrade system in my games. Instead I may extend to ten, requiring rare and limited reagents past rank five. Otherwise there is too much incentive to just dump everything into one specific upgrade that ends up skewing the difficulty curve too much.

Monday, January 15, 2018

A few months later...

It has been a few months since I departed my home in the US to become a digital nomad. Unless there is some emergency, I am going to continue this lifestyle for many more years. I did all this without second-guessing myself. I am thrilled it is all working out for the best.

The small things matter here. There are a lot of must-do things in various cities, but really it is the smaller things that matter. The details. The unexpected occurrences and events uncovered just around the corner.

Monks along the northern moat of the old city, Chiang Mai.


For new year's eve, I simply followed the trail of rice-paper lanterns to the eastern side of the old city of Chiang Mai.

Thapae Gate - Chiang Mai
Those lanterns are banned in other parts of Thailand, especially in Bangkok near the two major airports. Many lanterns hilariously got caught in trees. Others levitated and singed the hairs off tourists. These lanterns also were lit for the recent Yee Peng festival in November, which is a tradition that dates back to the days when this city of Chiang Mai was the the capital of the Lan Na Kingdom contested by the Burmese. The city joined Siam, modern day Thailand, in 1920.



In the city of Siem Reap of Cambodia, I met a couple from central Canada, Carly and Mitch. We reconnected in Chiang Mai and I casually showed them around as I got to know them better. Here is their blog entry that I want to share (link).

Even while touring around, we had an interesting conversation with a traveler from California during our round-trip to Wat Phra That in Doi Suthep - golden temple at the top of the mountain. "Serendipitous" would be an accurate word to describe my lifestyle here in south-east Asia. Sometimes it's fun to plan not to plan. just figure it out when you get there. Hostels are the easiest way to meet random interesting people from all over the world.

Carly, Mitch, and I went to a Muay Thai fight and explored the Saturday night market. They shared with me some tips on Singapore and funny stories experienced on ships along the islands of southern Cambodia. They will visit Ho Chi Minh City ("Saigon"), Vietnam in a couple weeks, so I will gain tips when I visit afterwards in the end of February.

Wat Phra That in Doi Suthep

The camera does not lie.. my gut is no longer bulging out from the sedentary high-sugar low-exercise lifestyle that I used to live back home. Some of the food in Thailand may be high in sodium, but the portion sizes are appropriately smaller and rich in spices and herbs. Ground transportation generally costs about a dollar, but I avoid it. Last month I walked over 150 miles thanks to Google Fit, which automatically keeps track. It is easier to make drastic improvements in lifestyle by relocating to an entirely new place.