So the 2-Week Coding Project came to a close last night, and I spent a little extra time getting everything done to have the first prototype in working order earlier. I posted the release in the Fusion Bunny Productions Google Drive.
Raiders: A Lost Art - Prototype 1 : Download Here (Opens in a new window)
There are still quite a bit of things I need to accomplish, and I'll be adding a log to show what bugs I am currently aware of, and what has been fixed already; this will also give you a good indication of what has been added to the next release so you know what to expect.
Raiders: A Lost Art - Changelog : Check The Log Here (Opens in a new window)
I also wanted to give players a way to submit bug/error reports this time, so I created a form that players can submit detailing any issues they encounter. I can also always be reached at my email, but that doesn't guarantee that the issue gets submitted right away. You are also free to post the issue on our Facebook page, but like the email, it wont get put into the bug report right away.
Raiders: A Lost Art - Bug/Error Report Form : Submit Report (Opens in a new window)
Fusion Bunny Productions - Email : Submit Email (Opens in a new window)
Fusion Bunny Productions - Facebook Page : Check Out Our Facebook (Opens in a new window)
I will still be posting updates on the progress, but it will not be the daily updates that I've been releasing the past 2-weeks. Be sure to look out for more releases, and updates as they come rolling out in the next few days!
Sunday, March 30, 2014
Saturday, March 29, 2014
2 Week Coding Project - Day 14 : Rebuilding the Raid Scripts
So, after taking a closer look at all the scripts pertaining to actual combat (CharacterScript, PerformsAttack, HasHealth, and Fight_GUI) I realized just how much I needed to change. From a coding standpoint, almost nothing was done in a way that would tie into the Main GUI. Because of this I spent most of the day trying to rewrite all of the scripts as efficiently as possible; and I think I got the brunt of it done. The only thing left to really do is to make sure the character's can be placed on the board, and that all the scripts tie into the Fight GUI's calls. Because I wanted to be efficient, I created uniform scripts for all the characters that check to see what value the character script has been given, and then they generate the proper information from there.
What this means is that now if you click on your character once it's placed on the battlefield, you can bring up a specialized menu for that character; which is minimal at the moment. Pretty much telling you what class and role that character is, and allowing you to perform its special attack. When you press the Special Attack button, it sends the current class and role as integers to the Character Script, which then interprets it and sends it along to the PerformsAttack script. The PerformsAttack script then checks the variables to see which ones coincide with an attack action and then sets that attack into motion.
The HasHealth script was updated so that it checks the integer value of the correct "characterLevel" PlayerPrefs file and then creates the right amount of health based on that value using a level multiplier. I wanted to get the level multiplier working for all the character attack scripts as well, but for now they are all uniform aside from the special attack. The enemy works in a similar fashion, it is given a bonus level and then that is taken into account when calculating its health pool. Because of this, it will be easier to create "hard mode" versions of the dungeons.
I need to create the enemies attack pattern still. I also need the characters to be movable when they are selected one at a time. For now the whole group moves as a unit, which is obviously not the way I want it to be. Both are simple to do in theory, but will take me a while to get done. That being said, with the rest of the fleshing out that some of the scripts need done, I'm going to say that I should have the prototype working as intended (for the first prototype at least) and that I will still try and release it by Sunday night; hopefully by midnight. I'm a little disappointed it's going to take me at least an extra day to finish the prototype; but when I look back at everything I learned, created, and replaced, I realize it was a large undertaking for a 2 Week Project. I'm just happy that it's coming together finally and I'll have something to show for all my work. It really has been a great experience.
What this means is that now if you click on your character once it's placed on the battlefield, you can bring up a specialized menu for that character; which is minimal at the moment. Pretty much telling you what class and role that character is, and allowing you to perform its special attack. When you press the Special Attack button, it sends the current class and role as integers to the Character Script, which then interprets it and sends it along to the PerformsAttack script. The PerformsAttack script then checks the variables to see which ones coincide with an attack action and then sets that attack into motion.
The HasHealth script was updated so that it checks the integer value of the correct "characterLevel" PlayerPrefs file and then creates the right amount of health based on that value using a level multiplier. I wanted to get the level multiplier working for all the character attack scripts as well, but for now they are all uniform aside from the special attack. The enemy works in a similar fashion, it is given a bonus level and then that is taken into account when calculating its health pool. Because of this, it will be easier to create "hard mode" versions of the dungeons.
I need to create the enemies attack pattern still. I also need the characters to be movable when they are selected one at a time. For now the whole group moves as a unit, which is obviously not the way I want it to be. Both are simple to do in theory, but will take me a while to get done. That being said, with the rest of the fleshing out that some of the scripts need done, I'm going to say that I should have the prototype working as intended (for the first prototype at least) and that I will still try and release it by Sunday night; hopefully by midnight. I'm a little disappointed it's going to take me at least an extra day to finish the prototype; but when I look back at everything I learned, created, and replaced, I realize it was a large undertaking for a 2 Week Project. I'm just happy that it's coming together finally and I'll have something to show for all my work. It really has been a great experience.
Friday, March 28, 2014
2 Week Coding Project - Day 13 : Main GUI Cleanup and Bugfixes
Today I decided it was time to clean up some code. Considering the main GUI code has reached over 4,500 lines (3,500 after the cleanup) I figured it was time to consolidate a lot of the repetitive lines into methods instead; allowing a single line to replace 10 or more in some cases; all of which had been duplicated for all 15 characters. It was a mess. That's what happens when you learn as you go, and it all functioned fine anyways; I'd just rather learn to be efficient while I learn to code.
I also took the time to do all of the bug fixing for the main GUI, not that there was a lot since I do so much testing while I work. I found a few things that needed to be altered because they created impossible loops in the game, mainly restricted to the Quest system. I had overshot a little bit with the amount of methods I ran to calculate questing and gaining experience; so I took another look and fixed everything I could find. I'm sure if any of you try the prototype you'll find a billion things I didn't, but that's to be expected.
I made sure that experience was being calculated correctly by the system, and that it was also being converted into levels when it was supposed to be. This was simple, although it became an issue after I striped all of the extra "characterExperience" variables. I simply made a function on experience gain that if the character experience is above 25, then it is converted into a level. I can add to this later to make higher levels take longer based on a level multiplier (it will essentially take the base xp required and multiply it by the level to create a new required amount); but since this is just a prototype with 1 enemy, I saw that as overkill. At 25xp per level it takes a 6 minutes and 15 seconds to level up a character. Meaning you can have max characters in a little over an hour.
Tomorrow is going to be a busy day; I need to tie all the information from the main GUI into the character objects, since I have changed so much in the last week they all have to be fully rewritten. Luckily, they all have values stored in the PlayerPrefs which will make it so I no longer have to pull those values from another script, everything important will be stored where it can be accessed from anywhere. I should be able to get it all done tomorrow. The only thing I'm worried about not getting done is the character attack rotations, but it shouldn't be too rough. They only really need a basic attack that they repeat, and then a special attack that the player can cast. So that's a total of 32 attacks that need to be created, even though they will all just use placeholder assets anyways.
Tomorrow will be my final day of working on it before I release it as a prototype #1. This doesn't mean that I'll necessarily just drop it immediately or anything. I'll probably keep working until the system is fleshed out the way I want it to, and feedback will decide how much effort gets put into it after that. I have a few more 2-week projects I want to work on, and it would be a shame to spend much extra time on something that isn't liked when I could be working on improving my skills and possibly coming up with something people will like more. In the end, this was a test I gave myself to see how much I could accomplish with a game type I really know nothing about creating; and that's how all the 2-week projects will be.
I also took the time to do all of the bug fixing for the main GUI, not that there was a lot since I do so much testing while I work. I found a few things that needed to be altered because they created impossible loops in the game, mainly restricted to the Quest system. I had overshot a little bit with the amount of methods I ran to calculate questing and gaining experience; so I took another look and fixed everything I could find. I'm sure if any of you try the prototype you'll find a billion things I didn't, but that's to be expected.
I made sure that experience was being calculated correctly by the system, and that it was also being converted into levels when it was supposed to be. This was simple, although it became an issue after I striped all of the extra "characterExperience" variables. I simply made a function on experience gain that if the character experience is above 25, then it is converted into a level. I can add to this later to make higher levels take longer based on a level multiplier (it will essentially take the base xp required and multiply it by the level to create a new required amount); but since this is just a prototype with 1 enemy, I saw that as overkill. At 25xp per level it takes a 6 minutes and 15 seconds to level up a character. Meaning you can have max characters in a little over an hour.
Tomorrow is going to be a busy day; I need to tie all the information from the main GUI into the character objects, since I have changed so much in the last week they all have to be fully rewritten. Luckily, they all have values stored in the PlayerPrefs which will make it so I no longer have to pull those values from another script, everything important will be stored where it can be accessed from anywhere. I should be able to get it all done tomorrow. The only thing I'm worried about not getting done is the character attack rotations, but it shouldn't be too rough. They only really need a basic attack that they repeat, and then a special attack that the player can cast. So that's a total of 32 attacks that need to be created, even though they will all just use placeholder assets anyways.
Tomorrow will be my final day of working on it before I release it as a prototype #1. This doesn't mean that I'll necessarily just drop it immediately or anything. I'll probably keep working until the system is fleshed out the way I want it to, and feedback will decide how much effort gets put into it after that. I have a few more 2-week projects I want to work on, and it would be a shame to spend much extra time on something that isn't liked when I could be working on improving my skills and possibly coming up with something people will like more. In the end, this was a test I gave myself to see how much I could accomplish with a game type I really know nothing about creating; and that's how all the 2-week projects will be.
2 Week Coding Project - Day 12 : Creating a Quest System
So, today I started tackling the quest system; and boy did I learn a lot. So much that I went back and redesigned the Gathering Professions. Now the two work roughly the same, only with the quest system running a method for each character. How they work is like this:
There is an array that stores the integer values of every character's "PlayerPrefs.GetInt("characterQuesting") values. I then created a method that checks for specific values to be present in the array. Each character's value is unique (character 1 is 1, character 2 is 2, so on and so forth). I then made a single script that checks every 15 seconds to see if the character is questing by running a method designed to count the amount of a single value inside the array. This works hand in hand with the actual questing method to check the value of each character's local questing variable and if it returns 1, it adds an experience point to the character each time the method is run.
void Start()
{
InvokeRepeating("CountQuesting", 14, 15);
InvokeRepeating("PerformQuesting", 15, 15);
}
void CountQuesting()
{
CountOccurrences(1);
CountOccurrences(2);
CountOccurrences(3);
CountOccurrences(4);
//etc...
}
int CountOccurrences(int valueToCheck)
{
int counter = 0;
foreach(int currentValue in gathering)
{
if(currentValue == valueToCheck)
{
counter++; //increase counter
if(valueToCheck == 1)
{
character1Questing = counter;
}
if(valueToCheck == 2)
{
character2Questing = counter;
}
if(valueToCheck == 3)
{
character3Questing = counter;
}
if(valueToCheck == 4)
{
character4Questing = counter;
}
//etc...
}
}
return counter;
}
void PerformQuesting()
{
if(character1Questing == 1)
{
character1Experience ++;
}
if(character2Questing == 1)
{
character2Experience ++;
}
if(character3Questing == 1)
{
character3Experience ++;
}
if(character4Questing == 1)
{
character4Experience ++;
}
//etc...
}
There is an array that stores the integer values of every character's "PlayerPrefs.GetInt("characterQuesting") values. I then created a method that checks for specific values to be present in the array. Each character's value is unique (character 1 is 1, character 2 is 2, so on and so forth). I then made a single script that checks every 15 seconds to see if the character is questing by running a method designed to count the amount of a single value inside the array. This works hand in hand with the actual questing method to check the value of each character's local questing variable and if it returns 1, it adds an experience point to the character each time the method is run.
void Start()
{
InvokeRepeating("CountQuesting", 14, 15);
InvokeRepeating("PerformQuesting", 15, 15);
}
void CountQuesting()
{
CountOccurrences(1);
CountOccurrences(2);
CountOccurrences(3);
CountOccurrences(4);
//etc...
}
int CountOccurrences(int valueToCheck)
{
int counter = 0;
foreach(int currentValue in gathering)
{
if(currentValue == valueToCheck)
{
counter++; //increase counter
if(valueToCheck == 1)
{
character1Questing = counter;
}
if(valueToCheck == 2)
{
character2Questing = counter;
}
if(valueToCheck == 3)
{
character3Questing = counter;
}
if(valueToCheck == 4)
{
character4Questing = counter;
}
//etc...
}
}
return counter;
}
void PerformQuesting()
{
if(character1Questing == 1)
{
character1Experience ++;
}
if(character2Questing == 1)
{
character2Experience ++;
}
if(character3Questing == 1)
{
character3Experience ++;
}
if(character4Questing == 1)
{
character4Experience ++;
}
//etc...
}
Wednesday, March 26, 2014
2 Week Coding Project - Day 11 : Finalizing Professions
Tonight I finalized the gathering professions. I ended up going with a script that adds the character to a pool of gatherers for each specific type of item (Basic and Advanced Herbs, Basic and Advanced Ore). In doing so I also roughed out the system for character quests, which will take me another day to focus on. The script I went with can be found at the bottom of yesterday's post; but that's just the basic script for how the material is gathered.
In order to allow each character to have a different gathering type, and prevent the player from doubling up gathering professions on each character, I went with an integer system like the character class and role systems to set a "currentGathering" and a "newGathering" integer; which when a specific button is pressed, adds the new value into the PlayerPrefs, and then the current value is updated by that information.
Then it was all about duplicating the code to check what each characters PlayerPrefs variable for gathering was set to, and add them to the pool. Because it works off the PlayerPrefs system, it persists through a restart. This means that turning the game off and back on will not change your characters current gathering tasks, eliminating any type of micromanaging you would need to do each time you wish to play. If you find a system that continues to work for you, it wont be changed until you tell it to.
That's about it for my work from today, it doesn't seem like a lot; but it was a task that I spent a few hours with trial and error simply trying to make it work. Then the code had to be reconstructed for each character. It's all working now though, and from that the quest system should go a lot smoother.
In order to allow each character to have a different gathering type, and prevent the player from doubling up gathering professions on each character, I went with an integer system like the character class and role systems to set a "currentGathering" and a "newGathering" integer; which when a specific button is pressed, adds the new value into the PlayerPrefs, and then the current value is updated by that information.
Then it was all about duplicating the code to check what each characters PlayerPrefs variable for gathering was set to, and add them to the pool. Because it works off the PlayerPrefs system, it persists through a restart. This means that turning the game off and back on will not change your characters current gathering tasks, eliminating any type of micromanaging you would need to do each time you wish to play. If you find a system that continues to work for you, it wont be changed until you tell it to.
That's about it for my work from today, it doesn't seem like a lot; but it was a task that I spent a few hours with trial and error simply trying to make it work. Then the code had to be reconstructed for each character. It's all working now though, and from that the quest system should go a lot smoother.
Tuesday, March 25, 2014
2 Week Coding Project - Day 10 : Beginning Professions
Day 10 was spent creating the base foundations for the Profession systems; and all of the crafting systems were finished without a problem. The next step, and one that I have put some serious hours into today is developing a system that allows characters to perform gathering tasks (which will also be the foundation for the quest system). I currently have the system working in-theory, but it is far from the completed system I wanted in place; so I'm going to devote another day to working on it. If it proves to be too much for the next few days, I'll simply revert it to the system I'm using now and move along to other problems; this is simply a 2-Week Prototype project after all.
The crafting systems that currently work are Alchemy, Armorsmith, and Weaponsmith; all of which have a Basic and an Advanced version of their crafting item. I can add as many as I want, but it all goes back to that 2-week project thing: how much does a game with 1 boss fight need? I opted to display the ability of collected inventory to crafted inventory based on character data values, and used that to the best of my abilities. In creating crafting, I also had to create an inventory; which runs in its own script; one that can be accessed from inside and outside of battle.
I first check to see which "characterProfession" integer the "characterSelected" has, and then based on it's return value, I display a specific menu; much like I did for changing Classes, Roles, and Professions. This time, it also checks the character level to see what objects can be crafted. In the future, all of the professions will have their own levels to them, or switching professions will cause you to start over from a base professional level of 1. This would prevent players from using a single character to do all professions; I might implement this tomorrow if time is available.
If the character level meets or exceeds a requirement for a specific crafted object, then the button appears. It also displays statistics about the item such as the crafting materials required, how many of said material you currently have, and how many of the crafted item you already have in your inventory. Basic information, I felt was fairly necessary to a crafting window. If you have the necessary items, it will allow you to craft the object, and all of the basic information updates to reflect the changes.
As for the gathering professions, those are posing a problem. I know how it could be done easily, but it would require thousands of lines of code based on duplicated methods for each of the 15 characters. This will probably be the route that I will have to take. The currently implemented alternative is to simply toggle a bool as true when any character is currently using a gathering method (gather herbs, gather ore); and allow that method to "InvokeRepeating" until it is cancelled. Gathering is time-based with a "roll for success" algorithm to see if the gathering was successful. It simply runs the script every 5 seconds to see if you gathered a plant, and then starts over; if it's successful your inventory count goes up.
The next easiest way to extend this would be to simply add a modifier to the roll, allowing the system to gain a bonus to their roll (or decrease the gathering time, with a higher initial time up from 5 seconds) based on the amount of characters you have gathering that specific object at any one time. This would mean, for example, that each character could add themselves to the Gather Herbs pool, allowing more herbs to be gathered overall in the same amount of time. So, instead of my current script of:
void GatherHerbs()
{
var herbgatherRoll = Random.Range(0,11);
if(herbgatherRoll >= 7)
{
itemBasicHerb ++;
}
}
It would look something like this:
int charactersgatheringHerbs = amt; //where 'amt' is the number of characters you have gathering
void GatherHerbs()
{
var herbgatherRoll = Random.Range(0,11);
var totalherbgatherRoll = herbgatherRoll + charactersgatheringHerbs;
if(totalherbgatherRoll >= 8)
{
itemBasicHerb ++;
}
}
This would allow you to add 8 characters to the gathering pool and always get an herb. I'm going to lean towards this way, simply because it's relatively efficient and still allows the player to benefit from having multiple characters gathering from the same resource. It will also allow me to convert the gathering bonus over to a gathering time reduction later when there are more than 2 types of herbs to gather. Remembering that changing your character profession will immediately remove that character from the pool, and the bonus.
The crafting systems that currently work are Alchemy, Armorsmith, and Weaponsmith; all of which have a Basic and an Advanced version of their crafting item. I can add as many as I want, but it all goes back to that 2-week project thing: how much does a game with 1 boss fight need? I opted to display the ability of collected inventory to crafted inventory based on character data values, and used that to the best of my abilities. In creating crafting, I also had to create an inventory; which runs in its own script; one that can be accessed from inside and outside of battle.
I first check to see which "characterProfession" integer the "characterSelected" has, and then based on it's return value, I display a specific menu; much like I did for changing Classes, Roles, and Professions. This time, it also checks the character level to see what objects can be crafted. In the future, all of the professions will have their own levels to them, or switching professions will cause you to start over from a base professional level of 1. This would prevent players from using a single character to do all professions; I might implement this tomorrow if time is available.
If the character level meets or exceeds a requirement for a specific crafted object, then the button appears. It also displays statistics about the item such as the crafting materials required, how many of said material you currently have, and how many of the crafted item you already have in your inventory. Basic information, I felt was fairly necessary to a crafting window. If you have the necessary items, it will allow you to craft the object, and all of the basic information updates to reflect the changes.
As for the gathering professions, those are posing a problem. I know how it could be done easily, but it would require thousands of lines of code based on duplicated methods for each of the 15 characters. This will probably be the route that I will have to take. The currently implemented alternative is to simply toggle a bool as true when any character is currently using a gathering method (gather herbs, gather ore); and allow that method to "InvokeRepeating" until it is cancelled. Gathering is time-based with a "roll for success" algorithm to see if the gathering was successful. It simply runs the script every 5 seconds to see if you gathered a plant, and then starts over; if it's successful your inventory count goes up.
The next easiest way to extend this would be to simply add a modifier to the roll, allowing the system to gain a bonus to their roll (or decrease the gathering time, with a higher initial time up from 5 seconds) based on the amount of characters you have gathering that specific object at any one time. This would mean, for example, that each character could add themselves to the Gather Herbs pool, allowing more herbs to be gathered overall in the same amount of time. So, instead of my current script of:
void GatherHerbs()
{
var herbgatherRoll = Random.Range(0,11);
if(herbgatherRoll >= 7)
{
itemBasicHerb ++;
}
}
It would look something like this:
int charactersgatheringHerbs = amt; //where 'amt' is the number of characters you have gathering
void GatherHerbs()
{
var herbgatherRoll = Random.Range(0,11);
var totalherbgatherRoll = herbgatherRoll + charactersgatheringHerbs;
if(totalherbgatherRoll >= 8)
{
itemBasicHerb ++;
}
}
This would allow you to add 8 characters to the gathering pool and always get an herb. I'm going to lean towards this way, simply because it's relatively efficient and still allows the player to benefit from having multiple characters gathering from the same resource. It will also allow me to convert the gathering bonus over to a gathering time reduction later when there are more than 2 types of herbs to gather. Remembering that changing your character profession will immediately remove that character from the pool, and the bonus.
Monday, March 24, 2014
2 Week Coding Project - Day 9 : Class Roles and Roster Script Update
Each character class has multiple roles that they can fill. Falling into one of three categories: damage, support, and tank, each role is diverse and different class/role combinations will need to be experimented with to find the most effective for each battle. The menu functionality was fairly simple to integrate into the basic menu.
Because I already had an extra menu system created using integer's to decide what information to display and change, it was simply a matter of taking into account what the current set "characterClass" was, checking to see if the characterClass had even been set, then allowing that integer to change the two-variables available in the menu. Some classes allow for Damage and Support, others for Support and Tank, and lastly for Damage and Tank.
I also wanted to make sure the player was unable to set a character role for a specific class, and then change to a class which does not offer that role; this was simple to counteract by adding a line of code which tells the script to remove the current "characterRole" integer from the PlayerPrefs if the "characterClass" integer is altered in some way. I felt like this was an efficient way to keep the problem from popping up. Now anytime you set a new character class, the character role must be reset as well.
From there I realized there was an issue with the way I had written the script for adding a character to the roster. If the game was reset, the character roster would also be reset; which seemed fine at first thought, but the more I thought about it - it seemed like something that would get really annoying if you had to constantly reset your roster every time you started the game back up. I also didn't want the player to be able to add a character to the roster and then change the characters class, resulting in the character role being revoked but the character left in the roster without any form of role to play out.
The best thing I could think of to combat this was to create another PlayerPrefs integer for "inRoster", and like the characterRole integer, this too would be reset if the playerClass was changed. This allowed the roster to be saved between sessions, and through any scene changes automatically; only being changed if the player decides to remove them from the roster (through direct removal or indirect removal by class or role change). Because the integer for characterRoster is simply a 0,1 system it was easy to allow a single button to do the direct changes right on the Character Menu; without the need of any sub-menu's.
I would love to give a code-snippet or two, but in all honesty the amount of code required to even display the amount of information encompassed is a couple-hundred lines per-character; and is specifically tailored to only fit this system. With that said, if anyone really wants an example for their own project, or learning, ask in the comments and I'll try and accommodate you with some new examples.
Because I already had an extra menu system created using integer's to decide what information to display and change, it was simply a matter of taking into account what the current set "characterClass" was, checking to see if the characterClass had even been set, then allowing that integer to change the two-variables available in the menu. Some classes allow for Damage and Support, others for Support and Tank, and lastly for Damage and Tank.
I also wanted to make sure the player was unable to set a character role for a specific class, and then change to a class which does not offer that role; this was simple to counteract by adding a line of code which tells the script to remove the current "characterRole" integer from the PlayerPrefs if the "characterClass" integer is altered in some way. I felt like this was an efficient way to keep the problem from popping up. Now anytime you set a new character class, the character role must be reset as well.
From there I realized there was an issue with the way I had written the script for adding a character to the roster. If the game was reset, the character roster would also be reset; which seemed fine at first thought, but the more I thought about it - it seemed like something that would get really annoying if you had to constantly reset your roster every time you started the game back up. I also didn't want the player to be able to add a character to the roster and then change the characters class, resulting in the character role being revoked but the character left in the roster without any form of role to play out.
The best thing I could think of to combat this was to create another PlayerPrefs integer for "inRoster", and like the characterRole integer, this too would be reset if the playerClass was changed. This allowed the roster to be saved between sessions, and through any scene changes automatically; only being changed if the player decides to remove them from the roster (through direct removal or indirect removal by class or role change). Because the integer for characterRoster is simply a 0,1 system it was easy to allow a single button to do the direct changes right on the Character Menu; without the need of any sub-menu's.
I would love to give a code-snippet or two, but in all honesty the amount of code required to even display the amount of information encompassed is a couple-hundred lines per-character; and is specifically tailored to only fit this system. With that said, if anyone really wants an example for their own project, or learning, ask in the comments and I'll try and accommodate you with some new examples.
Sunday, March 23, 2014
2 Week Coding Project - Day 8 : Finishing Basic GUI Functions
Today I set out to finish the basic GUI functionality for outside of battle. What this included, and why it took 3 days, was to make sure that all of the character's levels were tracked by a save system, along with their class type, and class role. From these 3 stats, the game will be able to read the integers given by the PlayerPrefs (save information) and translate that information over to the basic attacks and rotation that the characters will perform inside of battle. Once the information is kept by the system, it can easily be accessed with new menu options using if statements to hide key abilities that each character can use.
The other functionality for the basic menu was to allow you to change your character's class as you need. Before, you were going to be limited to 2 of each of the 8 classes, allowing you to utilize unique roles for similar characters if you desired. This was, in truth, a limitation I was placing on the characters because of a lack f programming knowledge on my-part. Well, after a few hours of trial and error I was able to create a menu system that could read the current class, and allow the player to change that class using a simple menu system. I felt like the average player is not going to want a 10-person team of the same class, but if they do they should have the ability to do so.
This was accomplished by creating a sequenced loop for menu's. When the player presses the desired characters button in the roster menu, it reads the character's current class as an integer, and translates that integer into a string to display in the menu. Next to that string I created a button, which offers the player to change the character's class. If the player presses the button, a sub-menu appears at the bottom of the screen which sets a new integer to be written in the form of "newClass". This new class integer is also translated by the script into a string which is displayed in the form of a new button in-place of the "change class" button asking the player to "confirm new class: "class_name"" which when presses, changes the player-prefs for that character to whatever the integer value of "newClass" is. The effect is immediately seen on the menu, where the new class is now displayed as the current class of the character.
In order to prevent any bugs where the player may keep the sub-menu open, I created a method for the sub-menu to run from using an integer system. If the integer value for the method returns "null" then the menu is no longer displayed, and the "newClass" integer is set back to "null" as well. This prevents the player from opening the sub-menu and then switching characters; thereby accidentally changing the class of the wrong character. This integer system will also make it easier in the future to prevent similar issues with all sub-menu systems, as this is the same place that professions and such will also take place.
If you are interested in how this menu system was accomplished, here's an example:
The sub-menu's method (This tells the method to allow an integer to be allocated for use as edM):
void ExtraDisplayMenu (int edM)
{
extradisplayMenu = edM;
//end extra display menu
}
The call-to script (This tells the method to use integer 1 in-place of edM):
if (GUI.Button(new Rect(210,75,200,20), "Set New Class"))
{
ExtraDisplayMenu (1);
}
This is the sub-menu script (Tells the script what to display when a specific integer is called):
if (extradisplayMenu == 1)
{
GUI.Label (new Rect(0, 0, 200, 20), "Set Player Class");
}
The other functionality for the basic menu was to allow you to change your character's class as you need. Before, you were going to be limited to 2 of each of the 8 classes, allowing you to utilize unique roles for similar characters if you desired. This was, in truth, a limitation I was placing on the characters because of a lack f programming knowledge on my-part. Well, after a few hours of trial and error I was able to create a menu system that could read the current class, and allow the player to change that class using a simple menu system. I felt like the average player is not going to want a 10-person team of the same class, but if they do they should have the ability to do so.
This was accomplished by creating a sequenced loop for menu's. When the player presses the desired characters button in the roster menu, it reads the character's current class as an integer, and translates that integer into a string to display in the menu. Next to that string I created a button, which offers the player to change the character's class. If the player presses the button, a sub-menu appears at the bottom of the screen which sets a new integer to be written in the form of "newClass". This new class integer is also translated by the script into a string which is displayed in the form of a new button in-place of the "change class" button asking the player to "confirm new class: "class_name"" which when presses, changes the player-prefs for that character to whatever the integer value of "newClass" is. The effect is immediately seen on the menu, where the new class is now displayed as the current class of the character.
In order to prevent any bugs where the player may keep the sub-menu open, I created a method for the sub-menu to run from using an integer system. If the integer value for the method returns "null" then the menu is no longer displayed, and the "newClass" integer is set back to "null" as well. This prevents the player from opening the sub-menu and then switching characters; thereby accidentally changing the class of the wrong character. This integer system will also make it easier in the future to prevent similar issues with all sub-menu systems, as this is the same place that professions and such will also take place.
If you are interested in how this menu system was accomplished, here's an example:
The sub-menu's method (This tells the method to allow an integer to be allocated for use as edM):
void ExtraDisplayMenu (int edM)
{
extradisplayMenu = edM;
//end extra display menu
}
The call-to script (This tells the method to use integer 1 in-place of edM):
if (GUI.Button(new Rect(210,75,200,20), "Set New Class"))
{
ExtraDisplayMenu (1);
}
This is the sub-menu script (Tells the script what to display when a specific integer is called):
if (extradisplayMenu == 1)
{
GUI.Label (new Rect(0, 0, 200, 20), "Set Player Class");
}
Saturday, March 22, 2014
2 Week Coding Project - Day 7 : More Basic GUI Functionality
Not much to talk about today, it was pretty much just spent expanding on Day 6 to cover more characters. I'm not going to get into details about it since, there is nothing new to say. I worked on getting characters 6-11 integrated, and tomorrow will be from 12-16 and then all of the characters will be added to the GUI. After all the character menus have been added to the GUI I will start adding some more features, as well as adding the quest systems and such. Expect tomorrow to be roughly the same, there's just nothing new to explain.
Friday, March 21, 2014
2 Week Coding Project - Day 6 : Beginning the Main GUI
Since the rest of the scripts require that I call a specific character from the battlefield, I needed to start working on the out of battle GUI; the menu systems which will allow you to check your player stats and set the player class and role. This is going to take a few days to complete, and is 100% code, pretty much from a single script. This doesn't leave a lot to explain, but I'll take a crack at explaining the work I did today.
I created a list (of 5 for now) of characters that you control in the game. I wanted the player to be able to select a specific character, and then be greeted with a set of menu options, which would allow the player to change the characters class, role, do quests, learn professions, and create objects.
I needed to create a method that would check an integer variable when a specific button is pressed. It was easiest done by making a method called "DisplayCharacterMenu (int cM)" and then made the character buttons simply run the line "DisplayCharacterMenu (#)" where "#" represented the character button they pressed. It was simple from there to create if statements which displayed a new menu based on the integer variable set in DisplayCharacterMenu.
From those variables, I knew the basic integer for the character I wanted the information displayed about. All I had to do was write PlayerPrefs based on those integers and then create Label files which displayed text strings including those preferences.
GUI.Label (left, top, width, height), "Level :" + PlayerPrefs.GetInt("character1Level");
The above script is a general look at how I pulled the information to be displayed. But there was also information that needed to display and set; and I didn't want to do so by duplicating menu's for each character. I created a new integer variable for an extra menu system that would allow me to run a method to set parameters for each character based on which character was selected. This menu then feeds back into the GUI, allowing all of the characters to use the same basic menu's without requiring them to be rewritten for each character.
I created a list (of 5 for now) of characters that you control in the game. I wanted the player to be able to select a specific character, and then be greeted with a set of menu options, which would allow the player to change the characters class, role, do quests, learn professions, and create objects.
I needed to create a method that would check an integer variable when a specific button is pressed. It was easiest done by making a method called "DisplayCharacterMenu (int cM)" and then made the character buttons simply run the line "DisplayCharacterMenu (#)" where "#" represented the character button they pressed. It was simple from there to create if statements which displayed a new menu based on the integer variable set in DisplayCharacterMenu.
From those variables, I knew the basic integer for the character I wanted the information displayed about. All I had to do was write PlayerPrefs based on those integers and then create Label files which displayed text strings including those preferences.
GUI.Label (left, top, width, height), "Level :" + PlayerPrefs.GetInt("character1Level");
The above script is a general look at how I pulled the information to be displayed. But there was also information that needed to display and set; and I didn't want to do so by duplicating menu's for each character. I created a new integer variable for an extra menu system that would allow me to run a method to set parameters for each character based on which character was selected. This menu then feeds back into the GUI, allowing all of the characters to use the same basic menu's without requiring them to be rewritten for each character.
Thursday, March 20, 2014
2 Week Coding Project - Day 5 : Character Roster Selection
I wanted to focus on character selection, so I needed to figure out a good way to reference the characters in the game, without actually having to call each object all the time. This was easiest done by creating a series of bools and integers that worked between the "persistentScript" and the "menuScript" to tell the menu which characters have been selected and what menu options to display from that information.
The persistentScript holds the integer variables for "character#Available" (numbers 1-16); as well as an integer variable for "characterParty". The GUI then checks to see if the persistentScript variable is "0" and if so, displays a menu option allowing you to "Add to Party". If the button is pressed, then the persistentScript variable is then set to 1 and the menu is no longer displayed. It also removes 1 from the variable for characterParty; which when it reaches 0, the option for adding more party members is removed.
Because the persistentScript is not reloaded after scene change, this allows the next scene with the Build script to reference which characters were selected by the player. The next step will be to change the build script to check the integer value of character 1, and if it returns 1, then it will allow that character to be placed on the play-field; and then set the variable integer to 0 for that character. If it returns 0, then the build script will check the integer value of character 2 and the process will start all over.
This process will look something like this:
-------------------
The persistentScript holds the integer variables for "character#Available" (numbers 1-16); as well as an integer variable for "characterParty". The GUI then checks to see if the persistentScript variable is "0" and if so, displays a menu option allowing you to "Add to Party". If the button is pressed, then the persistentScript variable is then set to 1 and the menu is no longer displayed. It also removes 1 from the variable for characterParty; which when it reaches 0, the option for adding more party members is removed.
Because the persistentScript is not reloaded after scene change, this allows the next scene with the Build script to reference which characters were selected by the player. The next step will be to change the build script to check the integer value of character 1, and if it returns 1, then it will allow that character to be placed on the play-field; and then set the variable integer to 0 for that character. If it returns 0, then the build script will check the integer value of character 2 and the process will start all over.
This process will look something like this:
-------------------
if(pS.character1Available == 1)
{
GameObject block = (GameObject)Instantiate(Resources.Load ("Block1"), RetAdd.transform.position, Quaternion.identity);
block.name = "Block1";
pS.character1Available -= 1;
}
if(pS.character1Available == 0)
{
if(pS.character2Available == 1)
{
GameObject block = (GameObject)Instantiate(Resources.Load ("Block2"), RetAdd.transform.position, Quaternion.identity);
block.name = "Block2";
pS.character2Available -=;
}
if(pS.character2Available == 0)
{
if(pS.character3Available == 1)
{
//extend script here
}
}
}
-------------------
The script will continue like this until all 16 character integers have been checked. After character 16 has been checked, the build script will then turn placement mode off and the fight will start.
Wednesday, March 19, 2014
2 Week Coding Project - Day 4 : Creating On-Button Special Attacks
Normally this wouldn't have been an issue for me since I can easily reference an object and its scripts and then create a GUI button to manipulate those; however, for this project I need the GUI to interact with multiple objects dynamically based on which characters are in-use. This is something I have no experience in doing, so I decided to go through some old scripts and Frankenstein something together.
In the end, the solution was far simpler than I thought; over-complication can be a huge downfall. The basic principle of what I did was the same as I used in the Attack/Damage scripts. I told the GUI that if a specific bool was active, then to search for a character object, and to then reference the PerformsAttack script within that object. I then told the GUI that if that bool was active to display a button, and if the button was pressed to run a method.
To have the GUI find specific object, I simply told it to "Find.GameObject("Object"), and to reference it as variable "c" (for current). If the Find.GameObject returns false, then to do nothing, but if it returns to true to then search that object for a script. This was easily accomplished using the line "c.GetComponent <PerformsAttack> ();", and again telling it that if PerformsAttack returned false, then to do nothing. Inside of the PerformsAttack script I created a method using the "public void SpecialAttack ()" base so that it could be referenced from an outside source. Then it was simply a matter of telling the GUI that if both the previous statements returned "!= null" then to display a button called "Special Attack", and if that button were to be pressed to tell the PerformsAttack script to run "PerformsAttack.SpecialAttack ();".
I also needed to know that it was going to work from within game-mode in Unity, so I went ahead and added a Debug.Log line inside the PerformsAttack.SpecialAttack () method simply stating "Special Attack Successful". This was the easiest way I could think of to make sure the logic behind this idea was working properly. Sure enough when the game ran, I clicked the Warrior button, and a button stating "Special Attack" showed up. Upon pressing the button I was greeted with the Debug message "Special Attack Successful" in the console. Perfect!
In the end, the solution was far simpler than I thought; over-complication can be a huge downfall. The basic principle of what I did was the same as I used in the Attack/Damage scripts. I told the GUI that if a specific bool was active, then to search for a character object, and to then reference the PerformsAttack script within that object. I then told the GUI that if that bool was active to display a button, and if the button was pressed to run a method.
To have the GUI find specific object, I simply told it to "Find.GameObject("Object"), and to reference it as variable "c" (for current). If the Find.GameObject returns false, then to do nothing, but if it returns to true to then search that object for a script. This was easily accomplished using the line "c.GetComponent <PerformsAttack> ();", and again telling it that if PerformsAttack returned false, then to do nothing. Inside of the PerformsAttack script I created a method using the "public void SpecialAttack ()" base so that it could be referenced from an outside source. Then it was simply a matter of telling the GUI that if both the previous statements returned "!= null" then to display a button called "Special Attack", and if that button were to be pressed to tell the PerformsAttack script to run "PerformsAttack.SpecialAttack ();".
I also needed to know that it was going to work from within game-mode in Unity, so I went ahead and added a Debug.Log line inside the PerformsAttack.SpecialAttack () method simply stating "Special Attack Successful". This was the easiest way I could think of to make sure the logic behind this idea was working properly. Sure enough when the game ran, I clicked the Warrior button, and a button stating "Special Attack" showed up. Upon pressing the button I was greeted with the Debug message "Special Attack Successful" in the console. Perfect!
Tuesday, March 18, 2014
2 Week Coding Project - Day 3 : Character Auto-Attacks and Health
Today I worked on creating auto-attack script for characters. This is the script that will allow the characters to do a rotation of attacks based on what class they are set to. For now, the script simply runs a single attack automatically, using a series of floats, integers and a bool to tell the character when they should be attacking. This will allow players to not have to micromanage every aspect of attacking that every character does. Healers will use this script to perform a heal attack on the targeted allies, and damage dealers will use this script to perform attacks aimed towards the boss. This will free the player up to managing character movement on the play field.
The script works by creating a cooldown timer for the attacks, referenced as a public integer. Because it is public, it can be increased or decreased based on the class, role, and level that the character is; which is stored in the PlayerPrefs, and is referenced by a persistent script throughout gameplay. This integer, is then used by the script to tell a float, which is set to -=Time.deltaTime so that it counts down 1 unit-per second in real-time. Once the timer reaches 0 or below, the script runs the attack method and resets the timer based on the referenced integer and the process starts all over again.
When the attack method is run, it lets out a projectile from a designated position on the character, which for now is directly in-front of them. Because the targeting script tells the characters to look at their target automatically, the projectile is launched in the direction of the characters target using an updated script from Extinction Plan; originally called "RocketEngine". This is a script which tells the object the rate at which to move, and in the forward direction. Because the forward of the character is always facing its target, this automatically allowed the projectile to move towards its target location without any jostling. And because the targeting script auto-adjusts as you move the characters around, the projectile will always go in the proper direction.
I chose to use a projectile over a raycast in this case as I wanted to give a chance for the attacks to miss if the enemy is moving and you aren't positioned properly. With a raycast, it would have simply hit automatically. This also allows me to change the size of the attack much easier, as well as the rate at which the attack moves across the play-field. Some of the other abilities may utilize a raycast, but for now the basic principle of gameplay is in-place.
After I had the attack script setup, I had to make sure that damage could be calculated. This meant that the attack had to reach the enemy, collide, and register a set amount of damage on that enemy from the impact. Because I wanted all of the attacks to do different amounts of damage, I decided that creating collider methods from tags was probably out of the question. This process would have involved creating a health script on the enemy which had a reference tag for each of the attacks in the game, telling it if an attack with that specific collider hit what to do. This posed a number of problems. If the attack damage is registered on the enemies collider system, then I would have to create not only a collider reference for each attack, but each attacks level if I wanted damage to scale by character level. I would also have to create tags for each attack and attack level for the abilities to use. I would also have to script the ability for the attack tag to be swapped by the character every time the character levels up. None of this seemed like an efficient way to calculate damage output.
I decided to write a simple "HasHealth" to hold the enemies Health amount in. This script uses the basic principle of creating a void to calculate received damage against the total health left. Written as "public void RecieveDamage(float amt)" this allows another script to reference this method, and to take whatever float amt the referencing script says into account as the amount of damage to be taken. Using a simple Mathf.Clamp I was able to specify (hitpoints - amt, 0 , hitpoints) telling the script that the "current hitpoints - the damage amount, no less than 0, and no more than the amount of hitpoints available" was the range of damage to calculate from an attack. It was then as simple as telling the enemy to run a "Die" method if hitpoints ever went to 0 or below.
From the attack side, I created a script to act when a collision happens, telling it to destroy the attack object, and to look for any scripts within an OverlapSphere that have the script "HasHealth". If a script is found within that overlap, then to use the amount of damage specified in the attack and to run the ReceiveDamage script with the attack damage replacing (float amt). This allows for a multitude of attacks to simply tell the enemy how much damage to take on an individual basis.
So now the characters can perform an attack automatically, and if the attack hits the enemy, tell the enemy how much damage to take. I even made sure to add some status ailments such as burn, and poison to the scripts, so if the "isPoison" flag returns true on the attack, the Receive Damage script will run a "ContractPoison" method which utilizes an invoke repeating to calculate damage over time.
The script works by creating a cooldown timer for the attacks, referenced as a public integer. Because it is public, it can be increased or decreased based on the class, role, and level that the character is; which is stored in the PlayerPrefs, and is referenced by a persistent script throughout gameplay. This integer, is then used by the script to tell a float, which is set to -=Time.deltaTime so that it counts down 1 unit-per second in real-time. Once the timer reaches 0 or below, the script runs the attack method and resets the timer based on the referenced integer and the process starts all over again.
When the attack method is run, it lets out a projectile from a designated position on the character, which for now is directly in-front of them. Because the targeting script tells the characters to look at their target automatically, the projectile is launched in the direction of the characters target using an updated script from Extinction Plan; originally called "RocketEngine". This is a script which tells the object the rate at which to move, and in the forward direction. Because the forward of the character is always facing its target, this automatically allowed the projectile to move towards its target location without any jostling. And because the targeting script auto-adjusts as you move the characters around, the projectile will always go in the proper direction.
I chose to use a projectile over a raycast in this case as I wanted to give a chance for the attacks to miss if the enemy is moving and you aren't positioned properly. With a raycast, it would have simply hit automatically. This also allows me to change the size of the attack much easier, as well as the rate at which the attack moves across the play-field. Some of the other abilities may utilize a raycast, but for now the basic principle of gameplay is in-place.
After I had the attack script setup, I had to make sure that damage could be calculated. This meant that the attack had to reach the enemy, collide, and register a set amount of damage on that enemy from the impact. Because I wanted all of the attacks to do different amounts of damage, I decided that creating collider methods from tags was probably out of the question. This process would have involved creating a health script on the enemy which had a reference tag for each of the attacks in the game, telling it if an attack with that specific collider hit what to do. This posed a number of problems. If the attack damage is registered on the enemies collider system, then I would have to create not only a collider reference for each attack, but each attacks level if I wanted damage to scale by character level. I would also have to create tags for each attack and attack level for the abilities to use. I would also have to script the ability for the attack tag to be swapped by the character every time the character levels up. None of this seemed like an efficient way to calculate damage output.
I decided to write a simple "HasHealth" to hold the enemies Health amount in. This script uses the basic principle of creating a void to calculate received damage against the total health left. Written as "public void RecieveDamage(float amt)" this allows another script to reference this method, and to take whatever float amt the referencing script says into account as the amount of damage to be taken. Using a simple Mathf.Clamp I was able to specify (hitpoints - amt, 0 , hitpoints) telling the script that the "current hitpoints - the damage amount, no less than 0, and no more than the amount of hitpoints available" was the range of damage to calculate from an attack. It was then as simple as telling the enemy to run a "Die" method if hitpoints ever went to 0 or below.
From the attack side, I created a script to act when a collision happens, telling it to destroy the attack object, and to look for any scripts within an OverlapSphere that have the script "HasHealth". If a script is found within that overlap, then to use the amount of damage specified in the attack and to run the ReceiveDamage script with the attack damage replacing (float amt). This allows for a multitude of attacks to simply tell the enemy how much damage to take on an individual basis.
So now the characters can perform an attack automatically, and if the attack hits the enemy, tell the enemy how much damage to take. I even made sure to add some status ailments such as burn, and poison to the scripts, so if the "isPoison" flag returns true on the attack, the Receive Damage script will run a "ContractPoison" method which utilizes an invoke repeating to calculate damage over time.
Monday, March 17, 2014
2 Week Coding Project - Day 2 : Character Movement with Auto Targeting Rotation
I took an old AI script I wrote for Extinction Plan from a tutorial in JavaScript, and I translated it over to C#, changing some of the unneeded and convoluted lines along the way. This included replacing an entire Vector3.Slerp formula for calculating object rotation based on target rotation with the much simpler transform.LookAt. This transition was done because of a 3D rotation issue I was experiencing when the object was moved around the grid spaces. For some reason when set to move, the character object would rotate 90 degrees onto its back and then move; but would never right itself before coming to a stop.
So I replaced all of the headache-inducing calculation lines with the much simpler idea of simply having the character use the LookAt method to achieve its rotation, and now even during movement the character doesn't rotate on the 3D plane, only the 2D one. This was most easily accomplished by having the character create a currentTarget, which is found by looking for GameObjects with a specific tag, and then rotating to face them. This should make it easy for characters to turn to specified locations when casting spells on other characters, simply by creating an empty game object that they will use as a reference location while a casting bool is active. Then having them simply look back to the boss when they are no longer fixated on casting automatically using a simple if/else statement.
Movement has gone through a couple iterations. At first, I was going to allow the characters to move to a relative location based on the player creating a waypoint for them, and then having a movement bool become active which told the character to move to that location. Once the character moved to the location, they would hit a collider that told the movement bool to flag as inactive and the character would stop moving; and the waypoint would be destroyed. This worked okay, but the characters always seemed to move in a strange arc towards the waypoint, although it was a small arc and they would always reach the correct position one way or another. However, this method created a larger issue: The characters were no longer on a grid-space. That meant that it would be more difficult to keep characters from overlapping, and being able to target specific characters with direct spells. It also gave way to a future issue of allowing all the characters to sit in locations that would be difficult for the boss enemies to target them (like in the center of 4 grid spaces).
To combat the movement problems, I figured it would be better to simply write a new script, that allowed the character to move around on a grid, using the predefined size of the grid spaces as a reference point. Since grids are inherently the same size throughout, it was easy to simply make the movement controls 1 unit at a time in the horizontal and vertical directions. This meant instead of telling my characters to go to a relative position based on a waypoint, I was simply telling them to move 1 unit left or right, up or down. This worked out perfect, and now the characters effectively stay on grid spaces.
So I replaced all of the headache-inducing calculation lines with the much simpler idea of simply having the character use the LookAt method to achieve its rotation, and now even during movement the character doesn't rotate on the 3D plane, only the 2D one. This was most easily accomplished by having the character create a currentTarget, which is found by looking for GameObjects with a specific tag, and then rotating to face them. This should make it easy for characters to turn to specified locations when casting spells on other characters, simply by creating an empty game object that they will use as a reference location while a casting bool is active. Then having them simply look back to the boss when they are no longer fixated on casting automatically using a simple if/else statement.
Movement has gone through a couple iterations. At first, I was going to allow the characters to move to a relative location based on the player creating a waypoint for them, and then having a movement bool become active which told the character to move to that location. Once the character moved to the location, they would hit a collider that told the movement bool to flag as inactive and the character would stop moving; and the waypoint would be destroyed. This worked okay, but the characters always seemed to move in a strange arc towards the waypoint, although it was a small arc and they would always reach the correct position one way or another. However, this method created a larger issue: The characters were no longer on a grid-space. That meant that it would be more difficult to keep characters from overlapping, and being able to target specific characters with direct spells. It also gave way to a future issue of allowing all the characters to sit in locations that would be difficult for the boss enemies to target them (like in the center of 4 grid spaces).
To combat the movement problems, I figured it would be better to simply write a new script, that allowed the character to move around on a grid, using the predefined size of the grid spaces as a reference point. Since grids are inherently the same size throughout, it was easy to simply make the movement controls 1 unit at a time in the horizontal and vertical directions. This meant instead of telling my characters to go to a relative position based on a waypoint, I was simply telling them to move 1 unit left or right, up or down. This worked out perfect, and now the characters effectively stay on grid spaces.
Sunday, March 16, 2014
2 Week Coding Project - Day 1 : Character Placement Script
I utilized the build script that I wrote for the last project and created a series of grid spaces out of blocks. I then altered the build script to fit a 2D environment rather than a 3D by adjusting the y-value offset of the normal collider to fit the z-value instead, this allows the blocks to be built on-top of the 2D plane. Because I built the grid out of blocks, the new system for character placement snaps directly to the grid without any overlapping worries. The next issue to address was the fact that the blocks placed were not going to be blocks, but rather characters and so they could not have other objects placed on-top of them. To combat this I created a new Tag for placed objects, and made sure that the script was updated to include them in the account of "block objetcs" that the script interacts with, but only allowing the script to delete these blocks.
Next, since there is no camera movement I ran into a new issue. The raycast to decide the placement location was coming from Camera.main and going to the exact center of the screen (Screen.width /2, Screen.height /2); I needed to change it to be from the center of the camera to the mouse's pointer location (this way it will be easy to correlate the mouse location for touch location on mobile devices). The string for the target location was changed from the location of half screen size to the location of Input.mousePosition. This creates a new Vector location representative of the distance between the center of the main camera and the current location of the mouse pointer.
To effectively create the illusion of grid-placement, even though the vector itself never follows exact guidelines, I created an object at the end of the raycast that snaps grid space that the mouse is hovering over and does not change until the mouse itself breaks the threshold of the grid space. At which time it simply moves to be centered on the next grid space; this object's vector location is also the location that the object is placed when the button is clicked. Because of this the mouse's pointer is only used to decide what grid space is below the current position and then factors where to place objects based on that locations center; as found by the faux objects current snap position.
Once the interface was working properly I added a resource folder and created a new object to be placed on grid-location for testing. This is easily called by Resources.Load, and then specifying the name of the object I wish to place. This will later be updated to correlate to the currently selected character using a simple array system. I then used the transform position of the faux object to tell the object where to be placed on the grid. Because the object placed is defined as being a block, but not a grid space, it can still be removed from the grid but not overlapped.
So now you can move the mouse cursor around and place objects from the resources folder on the grid space, and remove them if needed. Creating the character objects will be the next process for the character placement script, and then adding them to the array of placeable objects, and updating the GUI to allow them to be accessed by button selection. First though, I am going to take a look at the old Javascript AI system I wrote from a tutorial for my first project Extinction Plan and I am going to rewrite it in C#. This script will be used to allow the players characters to perform an attack rotation, as well as locate the enemy and rotate to face them. Because I am dealing with grid-movement, I am probably going to limit the ability for the script to move the character to rotation only, and continue working on the build script to allow the player to use it to move characters to new grid spaces as they see fit. The scripts movement will still be updated to be used on the enemy AI though, so the changes will still be made.
Next, since there is no camera movement I ran into a new issue. The raycast to decide the placement location was coming from Camera.main and going to the exact center of the screen (Screen.width /2, Screen.height /2); I needed to change it to be from the center of the camera to the mouse's pointer location (this way it will be easy to correlate the mouse location for touch location on mobile devices). The string for the target location was changed from the location of half screen size to the location of Input.mousePosition. This creates a new Vector location representative of the distance between the center of the main camera and the current location of the mouse pointer.
To effectively create the illusion of grid-placement, even though the vector itself never follows exact guidelines, I created an object at the end of the raycast that snaps grid space that the mouse is hovering over and does not change until the mouse itself breaks the threshold of the grid space. At which time it simply moves to be centered on the next grid space; this object's vector location is also the location that the object is placed when the button is clicked. Because of this the mouse's pointer is only used to decide what grid space is below the current position and then factors where to place objects based on that locations center; as found by the faux objects current snap position.
Once the interface was working properly I added a resource folder and created a new object to be placed on grid-location for testing. This is easily called by Resources.Load, and then specifying the name of the object I wish to place. This will later be updated to correlate to the currently selected character using a simple array system. I then used the transform position of the faux object to tell the object where to be placed on the grid. Because the object placed is defined as being a block, but not a grid space, it can still be removed from the grid but not overlapped.
So now you can move the mouse cursor around and place objects from the resources folder on the grid space, and remove them if needed. Creating the character objects will be the next process for the character placement script, and then adding them to the array of placeable objects, and updating the GUI to allow them to be accessed by button selection. First though, I am going to take a look at the old Javascript AI system I wrote from a tutorial for my first project Extinction Plan and I am going to rewrite it in C#. This script will be used to allow the players characters to perform an attack rotation, as well as locate the enemy and rotate to face them. Because I am dealing with grid-movement, I am probably going to limit the ability for the script to move the character to rotation only, and continue working on the build script to allow the player to use it to move characters to new grid spaces as they see fit. The scripts movement will still be updated to be used on the enemy AI though, so the changes will still be made.
2 Week Coding Project: A New Type of Tower Defense
For the next two weeks I will be working on a new type of Tower Defense game as a side-project. After I am done with this project I will take a look back at the 3 projects I have started in the last couple months and start work back up on one of them. I'm not abandoning the joint project with Spencer, but he recently stated he was getting burned out on it, so I figured I'd start something else in the mean time.
I started roughing out some the of GUI stuff for fun the other night while drafting designs for how I wanted the game to work. Now this is just a rough idea for a prototype, but it's the base I'm going to use to make a functioning project over the next week, and then spend the week after polishing it with sprites and interface assets (sound, animations, textures). I'm going to try and document as much of the process as possible. I will be taking some of my old scripts and utilizing them to accomplish the goal.
The idea for the game is a Tower Defense/Management game aimed at running a functioning Raid Guild in an MMO. It's a little difficult to describe how the gameplay will work but I'll try. You will start out with 40 members of your "guild". 5 of each characters in each of the 8 classes in the game. These classes are representative of typical MMO and RPG classes. Wizard (Mage), Priest, Occultist (Warlock), Witch Doctor (Shaman), Trapper (Hunter), Druid, Protector (Warrior), and Trickster (Rogue). You will decide what role each of the characters is going to have; tank, dps, or support. From there you will designate what the character is going to do in their free time: level professions, do quests, repair items, craft items, or perform research.
Leveling professions allows you to create objects to use in battle: equipment, potions, flasks, and food. Doing quests allows the character to level up and gain basic equipment, money, and/or resources for professions. Higher levels means more base damage, health, mana, farther attack range, or faster attack speed. You are required for the cost of repairs for your guild also, so if you find yourself constantly wiping on a boss you will have to quest more to fund your attempts. This will help balance gameplay for someone stuck on a boss as it will essentially force you to level your character to get the money to continue trying, inherently making the boss fight slowly easier. Crafting items comes from professions, but it takes time; so you'll want to balance having designated characters that specifically craft objects for your core raid group.
Once you have a team of able-bodied raiders, you will begin conquering dungeons one boss at a time. To do this you will decide on one of the unlocked dungeons, and select your party of 10 to take. Once you do that, you will designate a starting position on the grid for each of your 10 characters and start the fight. The characters will take over doing whatever they are scripted to do based on typical class/role abilities (healers will heal, ranged will attack the boss, etc...). You will then manage the positions of the group based on the bosses attack patterns, moving them out of harms way when needed. Tanks will gain debuff's that will need to be managed, either by support members or by switching tanks using a taunt and allowing the debuff's to time-out. It will be different on a fight by fight basis, so you'll have to pay attention to everyone's stats and make decisions as you see fit. The idea is for the player to have to create a strategy to defeat each boss, rather than simply powering through a fight with sheer numbers or overpowered characters. Each fight will be difficult to complete, but you will receive good gear, randomly dropped from a list specific to that particular fight. This will increase the reasons to play the fight again later if you need a specific piece of loot to help a character out. Defeating a boss allows you to progress to the next fight, and so forth.
The base of the game is going to use the building script created during the You May Be Eaten... game development cycle that was scrapped from the project. This will give me a decent base to add objects to the game world with little problem; converting it to 2D is easy enough. This will work perfect as it was scripted to snap to a "grid" as long as the grid is created out of blocks (as I wrote the script from Minecraft Clone examples in the first place). The biggest thing I will need to create are the PlayerPrefs, and for that I will have to create a flow-chart for each "character" in the game and correlate a PlayerPrefs Int series to describe what level/role/class each character has, and possibly a name if I go that deep.
This will easily be accomplished by creating an integer that represents any of the 8 classes in the game. I'm going to use 10, 20, 30, 40, 50, 60, 70, and 80 to allow me to create subcategories within each of the classes and have them be diversified by the ten's base they are represented by. This means that Warrior may be represented by a 10, but changing that Warrior's role to a tank will change that to an 11; this allows me to use the GUI to call a line like "PlayerPrefs.GetInt ("warrior1class")" and then tell the GUI; "if (PlayerPrefs.GetInt ("warrior1class") = 11) { WarriorTank == true; }" or at least some form of that. And then defining what WarriorTank is to the GUI and the rotation of attack the character will use automatically based on its level. "PlayerPrefs.GetInt ("warrior1level")" Keeping that script inside of a game object named Warrior1. Then if the player selects the character represented by Warrior1, the character data will be able to tell what class the Warrior is, and what level the Warrior is; then referencing a persistent script that has all of the level statistics for each class and role in it. That way the PlayerPrefs are not attempting to reference and calculate more than they need, as the game will house the basic information that each preference represents.
The rest of the game will be built on the GUI entirely since you wont have any real control over your characters physically doing anything related to questing, or learning. That's all "off-screen" information that only works off timers and integer increases. A 5-minute quest may grant you 100 XP, but a 10 minute quest may grant you 300 XP; remembering that you can't use the guild member in battle while they are busy doing something else. This will hopefully give players something to balance their time past simply trying to smash through dungeons.
I started roughing out some the of GUI stuff for fun the other night while drafting designs for how I wanted the game to work. Now this is just a rough idea for a prototype, but it's the base I'm going to use to make a functioning project over the next week, and then spend the week after polishing it with sprites and interface assets (sound, animations, textures). I'm going to try and document as much of the process as possible. I will be taking some of my old scripts and utilizing them to accomplish the goal.
The idea for the game is a Tower Defense/Management game aimed at running a functioning Raid Guild in an MMO. It's a little difficult to describe how the gameplay will work but I'll try. You will start out with 40 members of your "guild". 5 of each characters in each of the 8 classes in the game. These classes are representative of typical MMO and RPG classes. Wizard (Mage), Priest, Occultist (Warlock), Witch Doctor (Shaman), Trapper (Hunter), Druid, Protector (Warrior), and Trickster (Rogue). You will decide what role each of the characters is going to have; tank, dps, or support. From there you will designate what the character is going to do in their free time: level professions, do quests, repair items, craft items, or perform research.
Leveling professions allows you to create objects to use in battle: equipment, potions, flasks, and food. Doing quests allows the character to level up and gain basic equipment, money, and/or resources for professions. Higher levels means more base damage, health, mana, farther attack range, or faster attack speed. You are required for the cost of repairs for your guild also, so if you find yourself constantly wiping on a boss you will have to quest more to fund your attempts. This will help balance gameplay for someone stuck on a boss as it will essentially force you to level your character to get the money to continue trying, inherently making the boss fight slowly easier. Crafting items comes from professions, but it takes time; so you'll want to balance having designated characters that specifically craft objects for your core raid group.
Once you have a team of able-bodied raiders, you will begin conquering dungeons one boss at a time. To do this you will decide on one of the unlocked dungeons, and select your party of 10 to take. Once you do that, you will designate a starting position on the grid for each of your 10 characters and start the fight. The characters will take over doing whatever they are scripted to do based on typical class/role abilities (healers will heal, ranged will attack the boss, etc...). You will then manage the positions of the group based on the bosses attack patterns, moving them out of harms way when needed. Tanks will gain debuff's that will need to be managed, either by support members or by switching tanks using a taunt and allowing the debuff's to time-out. It will be different on a fight by fight basis, so you'll have to pay attention to everyone's stats and make decisions as you see fit. The idea is for the player to have to create a strategy to defeat each boss, rather than simply powering through a fight with sheer numbers or overpowered characters. Each fight will be difficult to complete, but you will receive good gear, randomly dropped from a list specific to that particular fight. This will increase the reasons to play the fight again later if you need a specific piece of loot to help a character out. Defeating a boss allows you to progress to the next fight, and so forth.
The base of the game is going to use the building script created during the You May Be Eaten... game development cycle that was scrapped from the project. This will give me a decent base to add objects to the game world with little problem; converting it to 2D is easy enough. This will work perfect as it was scripted to snap to a "grid" as long as the grid is created out of blocks (as I wrote the script from Minecraft Clone examples in the first place). The biggest thing I will need to create are the PlayerPrefs, and for that I will have to create a flow-chart for each "character" in the game and correlate a PlayerPrefs Int series to describe what level/role/class each character has, and possibly a name if I go that deep.
This will easily be accomplished by creating an integer that represents any of the 8 classes in the game. I'm going to use 10, 20, 30, 40, 50, 60, 70, and 80 to allow me to create subcategories within each of the classes and have them be diversified by the ten's base they are represented by. This means that Warrior may be represented by a 10, but changing that Warrior's role to a tank will change that to an 11; this allows me to use the GUI to call a line like "PlayerPrefs.GetInt ("warrior1class")" and then tell the GUI; "if (PlayerPrefs.GetInt ("warrior1class") = 11) { WarriorTank == true; }" or at least some form of that. And then defining what WarriorTank is to the GUI and the rotation of attack the character will use automatically based on its level. "PlayerPrefs.GetInt ("warrior1level")" Keeping that script inside of a game object named Warrior1. Then if the player selects the character represented by Warrior1, the character data will be able to tell what class the Warrior is, and what level the Warrior is; then referencing a persistent script that has all of the level statistics for each class and role in it. That way the PlayerPrefs are not attempting to reference and calculate more than they need, as the game will house the basic information that each preference represents.
The rest of the game will be built on the GUI entirely since you wont have any real control over your characters physically doing anything related to questing, or learning. That's all "off-screen" information that only works off timers and integer increases. A 5-minute quest may grant you 100 XP, but a 10 minute quest may grant you 300 XP; remembering that you can't use the guild member in battle while they are busy doing something else. This will hopefully give players something to balance their time past simply trying to smash through dungeons.
Subscribe to:
Comments (Atom)