Sunday, 21 December 2014

So long...

Hey guys, it has been a LONG while since I last posted something.

Since last we spoke, I've:

Learned HAXE
Begun looking into Client/Server communication in C#
Made a chat program!

That's right, I actually made something slightly useful!
ChatSharp is an opensource C# chat program.
It's in very early alpha (v0.1.1) and currently features:
Name changing
User List
Chatting

Yep, that's it.
I plan on adding things like PMs, Channels, Moderator Commands, Unique Names (so 2 people can't have the same name) that sorta thing.

If you want to try it out, you will of course need .NET installed, therefore it is Windows only.

Linky: https://www.mediafire.com/?dag3e091hm4e3gp
Please try it out, I need to stress test it, get feedback and find bugs.
All you need to do is download it and run, it's hardcoded to connect to the server I'm running on my VPS (I also coded the server myself :3)

Use !user to change your username.
I'll see you on there!

Wednesday, 26 November 2014

Update

Hey guys, it's been quite a while since my last post.

I've been very busy working on a couple of personal projects, namely:

Learning Java
Learning HAXE (A free, open source alternative to ActionScript3)
Working on a C# Roguelike

Some time soon(tm) I'll be showing you how I'm handling world gen in the roguelike, because I'm very proud of the system.

For now, this is just a quick post to let you know I'm still alive and kicking.

Also, I've had a couple of people asking about me posting C# tutorials, for those people, here are some links to older posts:

Beginner's C# Course, Part 1
Beginner's C# Course, Part 2
Beginner's C# Course, Part 3
Beginner's C# Course, Part 4

These describe some of the core mechanics and principles of OOPs such as C#

Once you understand those, you should look to some of the many C# Source Code posts in this blog, where you can learn the ropes of how to perform various functions.

Remember that this blog DOES have a comment section and I DO read any comments left, so if you're having trouble understanding something in one of my posts, please don't hesitate to comment.

Thursday, 30 October 2014

External launchers in C#

Hey guys, back from vacation, time to discuss external launchers in C#.

As mentioned previously, an external launcher is what you would typically think of when somebody refers to a "launcher". It is a separate EXE, usually used to check the game's version and login if necessary. Common examples of this are EVE Online and Minecraft (previously World of Warcraft, RIFT and many other MMOs before the introduction of multi-game launchers like Glyph and Battle.net)

I'm not going to be delving into the code regarding checking versions or logging in, but in terms of making it function as a launcher. There is only 1 line of code needed:

System.Diagnostics.Process.Start(pathToFile);

This line of code will run any file given to it using whatever the default method is for that particular filetype.

It can be used for EXE files, which is all we really need right now.
This is the line of code you need to make the launcher actually LAUNCH your game.

Now in terms of checking versions, I'm not going to talk about the code behind it, but there are a few common ways of doing it:

verNo Check - A simple check that connects to the server and downloads a version number from it, then compares it to the one shown on the game. If they match, no updates are needed, if the server shows higher, time to patch, if the game shows higher, you either fuqed up your code, or the user fuqed up your game.

File Check - This one is considerably more complex, but also much more reliable. This checks the actual content of the game's files, to ensure that they match completely. With a check like this, you can avoid your users editing game files in order to cheat.

As for logging in, that's as simple as checking the user and password with ones stored on a remote server, although as with any secure login system, I strongly suggest you encrypt or better yet Hash (irreversible encryption) the password BEFORE SENDING.

Simply store a hashed version of the password on the server, instead of a plaintext one.

Friday, 24 October 2014

Vacation time!

Hey guys, sorry for the lack of a post yesterday, I am currently on vacation, and will not be back until next Wednesday, make sure to check back next Thursday for that launcher code I promised!

Saturday, 18 October 2014

C# Source Code Post #5

It's here!

The grand finale to player.cs!
Also, unfortunately, the end of the AwesomeRPG Source Code Posts. I feel like the majority of AwesomeRPG's code is currently too simple, poorly implemented and quite frankly repetitive for it to be that educational.
If you guys disagree and want to see more AwesomeRPG, let me know in the comments, and I might fit it in on Tuesdays, but for now, this is the last AwesomeRPG source post.

Following Saturdays will be how to implement random things that I want to cover.

Anyway, the rest of the code for Player.cs:



So, EquipItem(int itemID).
This is a "simple" method for equipping an item.
However, it doesn't know what kind of item it is, so it has to figure that out, then equip it in the correct spot.

I won't go into detail on the weapon type checks, as they were covered in the previous post.
Basically, first it checks if it's a weapon and has Damage higher than 0.

If it is, it's a Right Hand weapon. (There is no dual wielding yet)
If it isn't, it checks if it has Defense higher than 0.

If it does, it's a Left Hand Shield.

After that, if it's not a weapon, it checks if it's Armor.
If it is, it checks it's Body armor, if it is, it equips it in the body slot.
If not, it checks if it's Boots.
Then Gloves.
Then finally Helm.

Damage(int amt)

Literally removes amt from HP, and makes sure HP doesn't go below 0.

AddXP(int amt)

Adds XP, simple enough.
Also checks if the player can level up, and levels them up if they can.

And there you have it, the super anti-climactic end to the epic file that is player.cs
And the rather anti-climactic end to the AwesomeRPG posts (unless you guys protest in the forums, in which case I'll know you still want these)

Next Saturday I will be covering something new: C# web interaction.

Specifically how to login to a

Thursday, 16 October 2014

10,000 pageviews!

Today, just now, like.. 5 minutes ago, the blog hit 10,000 pageviews!
It's been a wild ride, and sadly I missed a large part of that ride, as there was a 2-3 month gap of innactivity where the blog was getting 50-100 pageviews daily! As a result I came back to see the total had gone from a mere 3000 to just under 9000!

At least I was here to see the "It's over 9000!" moment though eh? :D

Anyway, thank you all for your support and for repeatedly checking in on the blog for new posts.

On an unrelated note, I may have difficulty doing these blog posts soon as I am experiencing some horrible Graphics Card issues, specifically parts of my VRAM are corrupt.

Currently only a very small section is corrupt, and this has only caused issues in certain games and occasionally when loading images in Chrome, however if not fixed it will get worse.

Sadly the only way to "fix" the issue is to replace the card altogether. This is not something I can afford.

I intend to get a GeForce GTX 660 to replace my current AMD HDi Radeon 7770, the price for the GTX 660 is fairly meagre at only ~£140, however this is almost 2 months wages for me (After taking out bills and rent).

Whilst I do, of course, intend to save for this and buy it as soon as possible (hopefully before the current card dies altogether), I would personally appreciate it a lot if you were to help me in this by supporting me on Patreon.

My Patreon link can be found in the sidebar of the blog (That's the extra stuff over to the right).
It should be at the top of the sidebar.

Of course, reward tiers noted in Patreon still apply if you are pledging in order to help with my Graphics Card issue.

Last announcements:
I'm currently thinking of changing the blog's theme, as with the current theme links are difficult to see.

I'm also considering switching to my own hosted site in the future, instead of simply using blogger with my own Domain. If I were to do this, I would be using Wordpress.

Pandaz! Part 2

Hey guys, sorry for the absence this past week, as I said in the previous post, I've not been feeling too well.

However I'm all better now, so posting can resume as scheduled, that means the next AwesomeRPG post WILL be this Saturday (promise!)

For now, it's time for the second Pandaz! post.

Sadly due to me being ill over the past week, there isn't really any coding to speak of today, so it'll just be discussion, namely the combat system.

The combat system in Pandaz! is very simple, there are 5 types of Pandas, Spearmen, Cavalry, Archers, Monks and Ninjas.
Your Panda army can consist of any number and ratio of these types.
For example you could have a pure Spearmen army, or you could split evenly between all 5, its completely up to you.

There is no max army size, although there will be a system in place to avoid impossible battles (eg a pro with an army size of 3000 Pandas vs a newbie with 17).

Originally this system was going to be based on win:loss ratio, however I realized somebody could simply build up a vast army without ever actually fighting, and effectively have a rank of 0 (the same rank as a newbie with his 17 Pandas looking to fight for the first time)

So matches will probably be determined based on a ranking system using win:loss ratio, and based on army size.

Pandas can be upgraded at the cost of Bamboo. You upgrade the different types of Panda individually (so upgrading Spearmen to lvl 2 has no effect on your other Panda types), and level directly determines strength.

To keep it simple, the strength of a Panda is simply their level * 10 (A lvl 1 Panda of any type has 10 strength, a level 378 Panda of any type has 3780 strength).

As stated in the previous posts, each Panda type has a prey and a predator so to speak, one type which they excel against, and one type which excels against them.
This forms a wheel of sorts (graphic can be found in the previous post)
To recap: Spearman > Cavalry > Archer > Monk > Ninja > Spearman

For each "prey" type your opponent has to your "predator", one of your predators gains double strength. (For example, for every Archer your opponent has, one of your Cavalry gains a +100% buff to strength)
However, for every predator your opponent has to your prey, one of your prey loses half strength.
(For example, for every Spearman your opponent has, one of your Cavalry gains a -50% debuff to strength)

Buffs are ALWAYS applied before debuffs, therefore if you have 1  level 1 Cavalry, and your opponent has 1 Archer, your Cavalry has 20 strength instead of the usual 10, however if your opponent also has 1 Spearman, your Cavalry's strength returns to 10.

So for example: (all Pandas in the below examples are level 1 and have base strength of 10)
5 Spearmen vs 5 Cavalry:
50 Strength      50 Strength
     +100%              -50%
        vs                     vs
     Cavalry         Spearmen
100 Strength vs 25 Strength

However:
6 Spearmen vs 3 Cavalry, 3 Ninjas
60 Strength      30 Str        30 Str
     +100%           -50%       +100%
        vs                  vs              vs
     Cavalry      Spearmen  Spearmen
90 Strength      15 Str         60 Str
      -50%
        vs
     Ninjas
60 Strength

60 Strength vs 75 Strength

This second example displays how diversity in an army can vastly improve chances of success, despite half of Player 2's army consisting of Pandas that are weak vs the Spearmen in Player 1's army.
The example also displays how debuffs are always applied AFTER buffs.

You may be wondering how 60 +100% somehow equals 90 in the second example.
This is because the +100% buff to the Spearmen is coming from the Cavalry, however there are only 3 Cavalry, and each can only give the buff to 1 Spearman, meaning that only 3 Spearmen go up to 20 Strength, the other 3 remaining at 10 Strength.

Of course, when it comes to 5 type vs 5 type battles (where each army consists of varying numbers of all 5 types of Pandas), it get's rather difficult to show using the above format.

Thankfully however, due to the magical wonders of programming and foreach loops, it's much simpler to implement in code.

I intend to simply loop through and (for example with Spearmen) double the strength of 1 Spearman for each Cavalry in the enemy army, then half the strength of 1 Spearmen (halving buffed Spearmen first) for each Ninja in the enemy army, then move on to Cavalry and apply buffs then debuffs, and so on.

I'm gunna talk to a few gamer and programmer friends about ideas in the hopes of spicing up this combat system and adding more variety and strategy, but for the time being this is pretty much it.

I hope this wasn't too complex/poorly explained for you guys to understand, and if it was, please let me know in the comments which parts confuse you, and I'll do my best to explain them to you.

Again apologies for not posting over the last week, I'll be doing some extensive coding on Pandaz! leading up to next Saturday, including removing the current internal launcher, and instead making an external launcher (see previous Pandaz! post for distinction), and something which I'm sure a LOT of you wanna see: Server-Client communication.

Or in laymens terms: Making a server program and having a client program connect to it and both send and receive data.

Sunday, 12 October 2014

No post!?

Hey guys, sorry about the lack of an AwesomeRPG source post this weekend, I've been pretty under the weather. This week's post has instead been postponed to Tuesday, so make sure to check back then!

Thursday, 9 October 2014

Pandaz! Part 1

Alright guys, it's Thursday.

As promised, here's the first post regarding my mysterious "Miniproject" which in all honesty is bigger than AwesomeRPG.

Unlike the AwesomeRPG posts, I won't simply be posting whole classes and explaining the code, but instead will be discussing ideas and plans for the game (Aptly names "Pandaz!") as well as discussing specific functions and snippets of code.

I'll try to include both a bit of discussion and a bit of code in each post, but I can't necessarily guarantee that I'll have new material of both kinds every week.

So firstly to introduce you to Pandaz!

Pandaz! is an online strategy game about growing bamboo (which acts both as food and currency) raising a panda army and doing combat with other panda armies.

It functions both as an Idle game (Such as Cookie Clicker) and as a Strategy game.

The idea is you plant bamboo, and based on how much bamboo you have planted, your bamboo increases at a certain rate.

Thanks to online-ness and servers this happens when not in-game too.
Originally the plan was that the bamboo that is automatically "grown" over time would add to your planted count, and you then had to "harvest" it to turn it into spendable bamboo, but I then realised that this would mean as your bamboo grows, the speed at which it grows increases with it, removing the need to check in every once in a while to plant more bamboo.

So to clarify that there are 2 kinds of bamboo:
Bamboo - Currency, can be turned into planted bamboo
Planted Bamboo - Not currency, cannot be turned back into bamboo but generates bamboo automatically over time.

Bamboo can be spent on Pandas and panda upgrades.

There are currently 5 types of Pandas, originally these were:
Spearman Panda
Cavalry Panda
Archer Panda
Mage Panda
Swordsman Panda

But I felt this was a bit too "western" for Pandas, so now it's:
Spearman Panda
Cavalry Panda
Archer Panda
Monk Panda
Ninja Panda

Each type of Panda is strong against one other type, and weak against one other type.
Here's a professional graphic that I totally didn't use MS Paint for:

In case you can't see that or don't understand it:
Spearman > Cavalry > Archer > Monk > Ninja > Spearman

Pandas receive a 100% strength bonus against the type they are strong against, but suffer a 50% strength penalty against the type they are weak against.

All types have the same strength, difference is purely what they're good against. (For now)

I'll discuss the combat system itself more next week, for now let's talk code!

*Disclaimer: I'm trying out new ways of embedding the code at the moment, because the previous method doesn't "minimize" the code or limit it to a max number of lines (with scrollbar)*

Today I want to talk about something I've never really done before in C#: Launchers.

What is a Launcher?
A launcher is a window, program or form that opens before your main game.
This is more common in online games as it verifies that you are running the latest version and allows you to login etc etc.

Currently the launcher code for Pandaz! is geared towards singleplayer, and simply allows you to either browse to and load a save file, or start a new game.

Here's what it looks like:







As you can see, it's very simple.

I'm not going to discuss how to do the whole Browse... thing and file selection like that, as that's not what we're here to talk about. Instead I'm going to skip the "making of the launcher" and focus on implementing it.

There are 3 main kinds of launcher:
Internal
External
Vendor

Internal Launchers, like the Pandaz! Launcher, is built into the code itself, and runs from the same .exe as the game.

External Launchers, like the Minecraft Launcher, is an external .exe that checks for updates and logs you in (sometimes) and upon clicking "play" launches the game's .exe file.

Vendor Launchers are launchers that also allow you to buy games. A lot of Vendor Launchers these days simply contain all the games made by that specific company.
Examples of this are the Battle.net launcher by Blizzard and the Glyph Launcher by Trion.
Steam is also a vendor launcher.

I'll discuss Internal Launchers now, and External Launchers at a later date.
By the time you have enough products and fans to need a Vendor Launcher of your own, I expect you'll know how to make one.

The Internal Launcher in Pandaz! case is a simple Windows Form. If you've ever used Visual Studio 2010's default Windows Form Application Template, you may have noticed this line in program.cs:

Application.Run(new Form1());

This is pretty self explanatory, it runs the application.
It takes 1 Form as an arg, and that Form is the form that opens first.
In this case we simply change that to

Application.Run(new Load());

Load.cs being the name of my launcher's class.

In Load.cs we have all of the usual button logic and such common with this type of Windows Form.
We also have a helper method:



GameInst is a field defined at the top of the class like so:

public Game GameInst;

and "Game" is the name of the main form; the form I want the launcher to run.
So all this small method does is it hides "this" (the launcher) then creates a new instance of "Game", the form we want to run, then shows it and finally hands it the instance of GameSave that was made by the launcher.
The value of "save" is defined as new GameSave(); in the case of "New Game" being clicked, and the loaded data in the case of a save file being loaded.

As I said, it's a very simple concept.

Anyway that's it for today's post!

Next week I'll discuss the Combat system and talk about some of the mathemagics behind the game's logic.

Don't forget to keep an eye out for the rest of Player.cs explained on Saturday!

Saturday, 4 October 2014

New Domain

Some of you may have just noticed that when you go to my blog via skidsdev.blogspot.com or skidsdev.blogspot.co.uk, it now redirects to www.skidsdev.com.

That's right, I now have my own domain just for this blog! :D

Thankfully domains are cheaper than food, so it didn't really cost much to get it setup.

Unrelated Sidenote: I'm currently working on changing AwesomeRPG's name, feel free to give me suggestions in the comments or, if you like the current name, let me know!

C# Source Code Post #4

Hey guys!

It's Saturday, so it's time for another C# Source Code post!

Last week we started looking at player.cs, but didn't finish it.

So, for reference, here's the code again:





We got up to around line 145 last week, so we'll continue from there.

The next code of note in the file is the LHand property.

This seems like a simple property that stores the ID of the item equipped in the left hand.. until you look at the code.

What's going in in that Set?
Well, it's basically making sure there's a weapon equipped, to avoid errors.

It's ugly, but it works.
First it loads the item into lhandi, and makes sure it's not null. If it is null, the item ID is -1.
Then it checks that it's a weapon, if it is, sure, the ID is value (whatever the code is trying to set LHand to). If it isn't a weapon, ID is -1.
Also, if the value of the item is 1000 or 1001, the ID is -1.
1000 is the Right hand component of Fists (unarmed) and should never be equipped Left hand, 1001 is the Left hand component of Fists.

The code under RHand does pretty much the same stuff.

It's all pretty simple, self explanatory code from there until we get to "public bool CanLevelUp"

This is a property, but acts as a method effectively.
The idea is, for each level, you need a certain amount of XP.
That amount is determined as follows:

for (int i = Level; i > 0; i--)
{
     val += i * 1000;
}

So basically, this is a reverse for loop, it starts at a number and goes down until it hits 0.
The number it starts at is the player's current level, and for every level it multiplied it by 1000 and adds it to val.

So if the player is level 3, to get to level 4 the player needs a total of:
(3 * 1000) + (2 * 1000) + (1 * 1000) = 3000 + 2000 + 1000 = 6000
and if the player is level 327, they would need 53,628,000 XP to level up to 328

Next up we have the Constructor of the player class, which is really very simple.

internal Player() { }

This is a special constructor that takes no arguments, and cannot be called from outside the class.
It's required for XML De-Serialization.

public Player(string name, int maxhp, int hp, int lvl, int exp, int str, int end, int dex, int agi, int wis, int inte, Race race)

Well that's a hell of a lot of args that the Player constructor needs. They're mostly self explanatory, but here's a list anyway:
string name - Name of the player
int maxhp - The maximum health of the player
int hp - The current health of the player
int lvl - The current level of the player
int exp - The current XP level of the player
int str - Strength
int end - Endurance
int dex - Dexterity
int agi - Agility
int wis - Wisdom
int inte - Intelligence
Race race - The race of the player (Brand new feature, WIP)

You may be asking why the intelligence arg is "inte" instead of simply "int". This is because C# doesn't like it when you try to call a variable a keyword. int, string, return, public, private, internal, static, void, double, bool, boolean, long, float and several others are all keywords (case sensitive) and can only be used for their primary keyword function.
In Visual Studio C#, keywords like this are highlighted in dark blue.

Next we move onto what the constructor does, aside from assign arg values to properties and fields.

HasQuest = false;

This line ensures new characters don't have a Quest when first created.

LHand = 1000;
RHand = 1000;
Body = -1;
Boots = -1;
Helmet = -1;
Gloves = -1;

Sets the weapons to fists and the armour to none.
Note that both LHand and RHand are set to 1000, even though 1000 is specifically only the Right Hand component, this is because this code was written before I added separate Fist components, and the LHand Set fixes it automatically anyway.

Inv = new List<int>();

As I said last week, the inventory contents of the player are stored as a list of ints, each int corresponding to the ID of the item.

public List<string> GetInv()

This method simply returns a list of the names of all items in the Inventory, in string format.
The code is fairly simple, it just loops through the inventory and adds the name value of each item in the inventory to a string list, then returns that list.

public void AddItem(int itemID, int amt)

A simple method that allows you to add multiple of the same item to the player's inventory.

public void AddItem(int itemID)

An even simpler method because I'm too lazy to type ", 1" for the amt in the previous method when I only want to add 1 of an item.

public void RemoveItem(int itemID, int amt)

A slightly less simple, yet still very simple method that loops through and removes a quantity of an item from the inventory, this can cause issues with large inventories when you attempt to remove more of an item than the player has, because the game will loop through every item in the inventory.

public void RemoveItem(int itemID)

Another lazy method.

public bool HasItem(int itemID, int amt)

Simply check's the player's inventory to see whether they have a certain quantity of a certain item.

Returns true if the amount of that item in the player's inventory is equal or MORE THAN the amount requested. ("return count >= amt;")

public bool HasItem(int itemID)

Yet another lazy method.

public void EquipItem(int itemID)

Okay, stuff starts to get a little in-depth and complex here, so I'll save the rest until next week >:D

Hope you enjoyed reading how lazy I am at coding, also remember that if you have any suggestions on how any of this code can be improved, feel free to let me know in the comments!

Until then, see ya next Tuesday!

Friday, 3 October 2014

New Schedule

So guys, I've been thinking over the week, and I've written up a simple schedule for posts on here:

Tuesdays - "Translation Workshop"
Thursdays - "Miniproject Tutorials"
Saturdays - "AwesomeRPG C# Source Code Posts"

Translation Workshop -
This is a project I'm working on in an effort to learn other programming languages, to put it simply, I'm converting AwesomeRPG, class by class, into other languages.

I decided I'd start with Java, given the only real difference between C# and Java is .NET and a few differences in the Runtime that cause C# to be more stable, yet Windows only.


Miniproject Tutorials -
This is a smaller project where I take on the task of making small, simple games in C# and writing step by step tutorials on how to do it.

These will not be the same as my Source Code posts, as rather than simply post a class and explain the code, I will actually be going through the process of making the game from scratch.

The first "Miniproject" will be a small Idle game based around Pandas and Bamboo, more info on Thursday.


AwesomeRPG C# Source Code Posts -
The ones you know and love! Once a week I post the code from an entire class file of AwesomeRPG and go through it explaining the code.

In some instances, for example player.cs, the current class file we're working on, a single file can take multiple posts, simply due to the amount of content that needs to be covered.

These posts will not be made at any set time of day, but I'll make sure they'll always be on the right day (GMT)

Also this schedule doesn't mean there won't be other posts, like this one, on the off-days, so make sure to check back daily if you want to stay up to date with all the latest crap in my brain.

Finally, small announcement. When I made my latest C# Source Post last Saturday, we broke my record for most views in a day by hitting a whole 100 views in just 1 day!

Let's see if we can hit 250 next.

Saturday, 27 September 2014

Patreon

Wow! 3 posts in one day!? It's like christmas!

Just a quick update, I realised how much I actually enjoy making these tutorials n stuff, so I made a patreon so those who wish to can support me.

http://www.patreon.com/skidsdev

C# Source Code Post #3

As promised, here's the third exciting installment of C# Source Code!

Decided to try out some new formatting to make reading the code easier, let me know what you think.

So today we will be looking at Player.cs, this class was referenced in InitLoad.cs somewhere I believe, but it's basically the class that defines the Character the player controls.





Well hey, ain't that much easier to read? :D

Alrighty, let's get stuck in!

The start of this is pretty typical stuff, default using statements, a using statement for Game.Items (that's for the next source post :3)
Then we get this:

[Serializable()]

What the hell is this thing!?
Well Jeff, I'm glad you asked, but please vacate the cavities of my empty brain.
This is called a "Label", it's something I never covered in my C# tutorials,  but basically it allows various properties to be assigned to a method, class, or other stuff.
In this case, we're assigning the "Serializable()" property to the entire class.

This basically makes it work in such a way that the XML Serializer mentioned in InitLoad.cs can take an instance of the Player class and Serialize it correctly.

Next up more basic stuff, fields, properties, stat mods.
Wait, these stat mods have some mathemagiks to them, what is this sorcery!?

The basic formula used for the Stat mods comes directly from good ol' DnD (That's Dungeons and Dragons).
Your Stat Mod affects various aspects of the game, for example a higher Strength Stat Mod makes you deal more damage.

The formula is as follows:

(Stat - 10) / 2

So if your stat was 16, your modifier would be 3.
Note that due to rounding in integers a stat level of 15 would also result in a modifier of 3, this is intended.

Here's a quick chart:


So as you can see, every 2 points past 10 increases the modifier by 1.

Next up more boring fields, and then a List.

public List<int> Inv;

I don't think I've mentioned this much before, but every item has a unique ID. This list simply lists all the IDs that are in the player's inventory.

Several equipment fields that store the ID of the item in that equipment slot.

Then one crazy-ass property:





Well 2 crazy-ass properties, Dmg and AtkSpd.

The first is how much damage you deal per hit, the second is how many attacks you do per second.

But what's with all the math!?
WARNING: MATH AHEAD, PREPARE FOR HEADACHES
Damage is calculated a pretty awkward way, firstly, it makes a variable called val and sets it to 0.
Then it makes an Item variable called it, doesn't initialize it.
It then checks ItemIDList, which is a Dictionary List from InitLoad.cs, for the ID stored in the right hand using

InitLoad.ItemIDList.TryGetValue(RHand, out it);

This basically tries to get the item associated with that ID, but it doesn't return an Item instance, it returns true or false, true if it successfully fetches the item, false if it doesn't.
"out it" means it has a secondary output, which it outputs to the arg you specify, in this case it, the Item variable we made.

Next it has to ensure that you're not holding a null item.

if (it != null && it.Name != "NullItem")

There are 2 ways the item can be null:
1) The instance is simply null
2) It is an instance of the item, but it has no stats and it's name is "NullItem"
We check for both, if it is neither, we continue to make sure it's a weapon.

This is a pain in the ass, because ItemIDList stores plain Items, not specific types of items.
ItemEquipmentWeapon extends ItemEquipment, which extends Item, we need to make sure that the item we have is definitely a weapon.

if (it.GetType() == typeof(ItemEquipmentWeapon))

it.GetType() is a default method associated with any object, it returns a Type value.
However ItemEquipmentWeapon isn't a Type it self, it's a class. we need to also get the Type of the class (which returns a Type version of ItemEquipmentWeapon, just as it.GetType() will if "it" is a weapon)
Then it's a matter of making sure their types are the same.
If so we continue.

ItemEquipmentWeapon itw = it as ItemEquipmentWeapon;

Wait whut?
The variable "it" is an item, we know that. We also know that it is a weapon, but it is not stored in that variable as a weapon, therefore we cannot call any Weapon specific functions from "it".
To get around this, we use a cast ("as ItemEquipmentWeapon"). If "it" wasn't a weapon, this cast would crash the program, hence the if statement checking that "it" is a weapon.

"itw" is identical in value to "it", however itw stores it as a weapon, not just an item.
We need this because we need to access the StatMod property and the Dmg property, which are specific to weapons.
it.StatMod will error, because it is an item, not necessarily a weapon.
itw.StatMod will not error.

val =0;

I set the variable to 0 again, even though it's value hasn't changed yet.
Why?
Dunno.

val += itw.Dmg;

Simple enough, get the value of the Dmg property from the weapon, add it to 0 and store it in val.

Now we check the StatMod of the weapon.

the StatMod property defines what player stat the weapon focuses on. The majority of weapons focus on Strength or Dexterity.

Whichever stat is focuses on, the player's Stat modifier for that stat (see above) is added to the damage.

This means a very weak character with a Strength of 8 would have difficulty using a Club because it is a Strength based weapon, and a Strength of 8 gives you a -1 Stat Modifier, and thus a -1 to your damage with all strength based weapons.

However if a character had a Strength of 16, they would receive a +3 to the damage of the Club.

That's basically all the switch statement does.

Then we have an else.
This else refers to the item being null.

Basically, if you have nothing equipped in your main hand, your damage is your Strength Modifier + Dexterity Modifier / 2.

The Average of your Str and Dex modifiers.

So if you're a minotaur, and have a Strength of 18, but a Dexterity of 10, your unarmed damage will be 2 (4 + 0 = 4, 4 / 2 = 2)
However if you were an elf, and had a Strength of only 8, but a Dexterity of 18, your unarmed damage would still be 2 (-1 + 4 = 3, 3 / 2 = 1.5, rounded to 2).

It's at this point at the code I intended to have the following:

if(val < 1) val = 1;

All this does is make sure val can be no less than 1, so you will always do at least 1 damage with your fists.

However I forgot to include this, because as we have already established, I'm stupid.

Next up, attack speed.

This is a bit shorter, and uses concepts we're familiar with.

Firstly however, I'd like to explain how attack speed is calculated and used.

Default attack speed is 100. 100 equates to 1 attack per second.
Higher value = higher speed, so 120 is 1.2 attacks per second.

It's really quite simple, AtkSpd / 100 = Attacks per second

Now, back to the code.

We have the bits we're familiar with by now, that get the equipped item, make sure it's not null, make sure it's a weapon etc etc.

Then we have val += itw.AtkSpeed;

This just sets val to the attack speed of the weapon.

else val = 100;

If no weapon is equipped, attack speed is 100 (1 per sec)

Now, there's still a lot more to go over, but unfortunately that will have to wait until next time.

I will be posting these at LEAST once a week, every saturday, but may also post them at other times, so check back daily!


Been a while, time for more C#

Hey all,

It's been quite a while since I last posted here, I recently got back into working on AwesomeRPG, and while I don't have time for the regular C# tutorials, I can and will continue the Source code series where I show and explain Source code from AwesomeRPG.

After posting this I'm going to start writing the next post for it, so stay tuned!

Additionally, as always, I have a few "product recommendations".
In the past I've told you guys about games, websites, projects and all sorts of other goodies.
I've also been accused of doing it for money, I'd like to quickly clarify that the things I "advertise" in my posts I am not being paid for, I tell you about them simply because I feel like it. In fact, aside from the Ramblon post, most of the time the creators of whatever I'm advertising don't even know I'm doing it.

With that out of the way, today I have 2 new things for you to look at.

Firstly is an amazing game called Factorio.
Factorio is a 2D top down factory based sandbox game, almost like the minecraft mods Industrial Craft and Minefactory Reloaded, but in it's own game.

It's made in C++, and already has an active modding community (mods are made using a LUA based modding interface)
Check it out over at http://www.factorio.com

Secondly, I have something a little different.
A server host that I STRONGLY recommend if you're wanting to start a website or minecraft server, GGServers

They've had some issues with support in the past, but they recently expanded their support team greatly, and now have great response times.

Did I mention they're really cheap? Only $3 per GB of RAM!

Anywho, that's all for now, remember to stick around for the source code post coming in a few minutes!

Tuesday, 8 July 2014

I'm back!

Kind of anyway...

So, my internet is completely fixed, and I now have a part time job, working 2 hours a day in a morning, 6 days a week, for minimum wage. It's about £300/month (roughly $515)

Sadly, due to the enormous amount of things I'm doing in my free time right now, I don't have the time to regularly post here, so the C# tutorials are on hiatus.

Right now, I'm here to do some shameless advertising :3

Firstly, we have EverEmber Online, a game I was involved in the development of back when it first started 2 years ago, but then it stopped, and started, and stopped, and now it's up for good, and seems to slowly be gaining popularity. I'd love to get back into being involved in the development of it, but I doubt my C# skills would be too good as I believe it's written in VB6 (Oldschool :O) Anyway, here's a link:

https://everember.com/

Secondly, we have Spectrum Music, a new music promotion channel that I'm running. I'm trying to upload twice weekly, but I don't always manage it very well. If you're a music producer, or know anybody who is, let me know on the email provided on the channel (spectrumicmusicofficial@gmail.com)

Link:

http://www.youtube.com/user/SpectrumicOfficial

Anyway, that's pretty much it for now, however also remember that I'm always available for things like coding requests. I've received a couple of emails in the past about people wanting my help making games or apps, and I'm always happy to take a look at the projects!

Monday, 5 May 2014

Hope is not lost!

Hey guys! I'm alive!

I'm sure some of you have been missing the semi-daily posts of C# tutorage lately.

Sadly my internet has taken a turn for the worst. It turns out not only is my ethernet port broken (I'm getting that fixed tomorrow) but my ethernet CABLE is also broken D:

And sadly we don't exactly have 20m cables lying around the house.
My plan is hopefully to get a new, more reliable 20m cable to carry the signal from the router to my room, then use an ethernet splitter and 2 short cables to provide that signal both to my main PC and my old, scrappy PC which was recently delivered back from my grandparents.

I'll be using the older, lower spec PC as a server, most likely hosting teamspeak servers on it and renting them out to (for example) minecraft servers and EVE Online corps/alliances.

Obviously it won't be a professional service, people renting the servers won't have access to a "control panel" or anything of the sorts, but they'll be able to contact me via email or skype if anything goes wrong on their cheap-ass server.

I suppose I might as well give y'all that announcement I had planned.

Spot Social, which as some of you may remember completely missed it's launch date, will soon be open.
The delay was due to issues with the hosts SSL and we couldn't get their attention as their support just thought we were some dumb idiots who did something wrong and were trying to blame the host.

Eventually Tim got through to some higher ups who realised there really was an issue, they fixed it and gave us 2 months free service for the inconvenience.

Tim says the site should be up within a couple of weeks, and once it is I'll be sure to let you guys know!

Another little thing I wanna mention, is an amazing browser based unity game by the name of AstroX.
It's made by solo-developer Momoguru, creator of Codelink v2, a multiplayer tribute to the original Codelink.

It's available over on kongregate, and has a fast growing community on it's forums.

Once my internet is fixed, some of my livestreaming will be focusing on this game, simply because of how amazing it is.

Anyway, this is a lot more than I expected to write, given that I'm having to post this from my phone.

Once my internet is all hunky-dory I'll be back to the usual post every other day and livestream 3 days a week (New livestream schedule cos I got burned out doing 6 days a week)

Thanks for sticking with me and for your continued patience through this lull in activity!

Monday, 28 April 2014

C# Source Code Post #2

Given how late last post was, all of my scheduled posts are being pushed to one day later. So this post was originally due yesterday (Sunday) but instead I'm posting it today (Monday), and the post after this will be Wednesday instead of Tuesday.. so on so forth.

So, as promised, this is InitLoad.cs. This class reads whatever gamedata (items, classes, quests etc etc) when the game first runs, and fills in any missing gamedata by creating stock data files.

This is probably one of my favourite classes to make in the game, aside from the combat class.

##File Start##
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//Default using statements for a base class file.
using System.IO;
using System.Xml.Serialization;
//2 extra system using statements I added.

using Game.Items;
using Game.Entities;
//2 using statements pointing to other classes I have made

namespace Game
//Same old namespace
{
    public static class InitLoad
    //Class is static
    {
        static List<ItemEquipmentWeapon> weapons;
        static List<ItemEquipmentArmour> armour;
        static List<Quest> quests;
        static List<Hostile> enemies;
        //Declaring 4 variables of type "list" within the class

        public static Dictionary<int, Item> ItemIDList = new Dictionary<int, Item>();
        public static Dictionary<int, Quest> QuestIDList = new Dictionary<int, Quest>();
        public static Dictionary<int, Entity> EntityIDList = new Dictionary<int, Entity>();
        //Declaring 3 variables of type "Dictionary" within the class.
        //These are used throughout the game to reference items, quests and entities.

        public static void InitInstall()
        //This is the method that runs to fill in missing gamedata
        {
            string path, filePath,
                weaponFile = @"\WeaponsItem.agd",
                armourFile = @"\ArmourItem.agd",
                questFile = @"\Quests.agd",
                enemyFile = @"\Enemies.agd";

            XmlSerializer Serializer;
            FileStream WriteFileStream;

            path = string.Format(@"{0}\AwesomeRPG",
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

            List<ItemEquipmentWeapon> WeaponList = new List<ItemEquipmentWeapon>();
            WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 100, true, 1000, Stats.Dex));
            WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 80, false, 1001, Stats.Dex));
            WeaponList.Add(new ItemEquipmentWeapon("Stick", 3, 110, false, 1002, Stats.Str));
            WeaponList.Add(new ItemEquipmentWeapon("Big Stick", 5, 80, true, 1003, Stats.Str));

            List<ItemEquipmentArmour> ArmourList = new List<ItemEquipmentArmour>();
            ArmourList.Add(new ItemEquipmentArmour("Rags", 0.05, ArmourType.Body, 2001));
            ArmourList.Add(new ItemEquipmentArmour("Sandals", 0.01, ArmourType.Boots, 2002));
            ArmourList.Add(new ItemEquipmentArmour("Hand Wraps", 0.01, ArmourType.Gloves, 2003));
            ArmourList.Add(new ItemEquipmentArmour("Hood", 0.02, ArmourType.Helmet, 2004));

            List<Hostile> EnemyList = new List<Hostile>();
            EnemyList.Add(new Hostile("TestEnemy", true, 20, 1, 100, 1001));
            EntityIDList.Add(EnemyList[0].ID, EnemyList[0]);

            List<Quest> QuestList = new List<Quest>();
            QuestList.Add(new Quest("TestQuest", new List<QuestActions>() { new QuestActions(1001) }, new List<int>() { 1003 }, 250, 0));

            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            path += "\\Data";
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            if (!Directory.Exists(path + "\\Items")) Directory.CreateDirectory(path + "\\Items");

            filePath = path + "\\Items" + weaponFile;
            WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
            Serializer = new XmlSerializer(typeof(List<ItemEquipmentWeapon>));
            Serializer.Serialize(WriteFileStream, WeaponList);
            WriteFileStream.Close();

            filePath = path + "\\Items" + armourFile;
            WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
            Serializer = new XmlSerializer(typeof(List<ItemEquipmentArmour>));
            Serializer.Serialize(WriteFileStream, ArmourList);
            WriteFileStream.Close();

            filePath = path + enemyFile;
            WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
            Serializer = new XmlSerializer(typeof(List<Hostile>));
            Serializer.Serialize(WriteFileStream, EnemyList);
            WriteFileStream.Close();

            filePath = path + questFile;
            WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
            Serializer = new XmlSerializer(typeof(List<Quest>));
            Serializer.Serialize(WriteFileStream, QuestList);
            WriteFileStream.Close();
            //Lot of crazy ass code I'll explain further down
        }

        public static bool PreLoading()
        //This is the method that runs every time the game starts
        //If it functions correctly, it returns true. If it fails somehow, it returns false.
        //If it returns false, the game exits.
        {
            string path, filePath,
                weaponFile = @"\WeaponsItem.agd",
                armourFile = @"\ArmourItem.agd",
                questFile = @"\Quests.agd",
                enemyFile = @"\Enemies.agd";

            XmlSerializer SerializerObj;
            FileStream ReadFileStream;

            path = string.Format(@"{0}\AwesomeRPG\Data",
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

            ItemIDList.Add(-1, null);
            QuestIDList.Add(-1, null);

            filePath = string.Format(@"{0}\Items{1}", path, weaponFile);
            SerializerObj = new XmlSerializer(typeof(List<ItemEquipmentWeapon>));
            ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            weapons = (List<ItemEquipmentWeapon>)SerializerObj.Deserialize(ReadFileStream);
            foreach (Item item in weapons)
            {
                ItemIDList.Add(item.ID, item);
            }

            filePath = string.Format(@"{0}\Items{1}", path, armourFile);
            SerializerObj = new XmlSerializer(typeof(List<ItemEquipmentArmour>));
            ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            armour = (List<ItemEquipmentArmour>)SerializerObj.Deserialize(ReadFileStream);
            foreach (Item item in armour)
            {
                ItemIDList.Add(item.ID, item);
            }

            filePath = string.Format(@"{0}{1}", path, questFile);
            SerializerObj = new XmlSerializer(typeof(List<Quest>));
            ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            quests = (List<Quest>)SerializerObj.Deserialize(ReadFileStream);
            foreach (Quest item in quests)
            {
                QuestIDList.Add(item.ID, item);
            }

            filePath = string.Format(@"{0}{1}", path, enemyFile);
            SerializerObj = new XmlSerializer(typeof(List<Hostile>));
            ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            enemies = (List<Hostile>)SerializerObj.Deserialize(ReadFileStream);
            foreach (Hostile item in enemies)
            {
                EntityIDList.Add(item.ID, item);
            }
            //more crazy ass code
            return true;
        }
    }
}
##File End##

Jeez, if you thought TitleScreen.cs was complex, this one probably blew you away.
This one primarily focuses around XML Serialization, which is one of 2 very basic methods of saving data in C#, and the one I chose to use in AwesomeRPG. The other method is simply writing to plain text.

The reason I chose XML over TXT is because I needed to save instances of classes. For example, every weapon in the game is an instance of the class "ItemEquipmentWeapon" with it's own stats etc. I needed to save those stats, and be able to load them back in and remake them as instances.

While this is possible in TXT, it's incredibly difficult, as you would have to loop through every item, save each individual stat on a new line, then on loading read each line and hardcode where to put each stat on the instance.

With XML, tags are assigned to each stat that the XML serializer can read and figure out where everything belongs. For example, saved weapons in XML format look like this:

##File Start##
<?xml version="1.0"?>  This is a typical XML header
<ArrayOfItemEquipmentWeapon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> This specifies what the file is.
  <ItemEquipmentWeapon> This marks the start of 1 instance
    <IsUsable>false</IsUsable>
    <ID>1000</ID>
    <Name>Fists</Name>
    <Def>0</Def>                                  All the stats are in here for this weapon (Name = Fists)
    <Dmg>1</Dmg>
    <AtkSpeed>100</AtkSpeed>
    <THand>true</THand>
    <StatMod>Dex</StatMod>
  </ItemEquipmentWeapon> This marks the end of that instance
  <ItemEquipmentWeapon>
    <IsUsable>false</IsUsable>
    <ID>1001</ID>
    <Name>Fists</Name>
    <Def>0</Def>
    <Dmg>1</Dmg>
    <AtkSpeed>80</AtkSpeed>
    <THand>false</THand>
    <StatMod>Dex</StatMod>
  </ItemEquipmentWeapon>
  <ItemEquipmentWeapon>
    <IsUsable>false</IsUsable>
    <ID>1002</ID>
    <Name>Stick</Name>
    <Def>0</Def>
    <Dmg>3</Dmg>
    <AtkSpeed>110</AtkSpeed>
    <THand>false</THand>
    <StatMod>Str</StatMod>
  </ItemEquipmentWeapon>
  <ItemEquipmentWeapon>
    <IsUsable>false</IsUsable>
    <ID>1003</ID>
    <Name>Big Stick</Name>
    <Def>0</Def>
    <Dmg>5</Dmg>
    <AtkSpeed>80</AtkSpeed>
    <THand>true</THand>
    <StatMod>Str</StatMod>
  </ItemEquipmentWeapon>
</ArrayOfItemEquipmentWeapon>
##File End##

The "ID" stat is used in the Item Dictionary.
Note that while the file's format is XML, it is actually saved with the extension ".agd" (So this file is WeaponsItem.agd). That is an extension I made up, and it stands for Awesome Game Data. That doesn't change the contents of the file in any way though, and it can still be opened and edited in notepad.

So, at the top of InitLoad, we declared 7 variables:

static List<ItemEquipmentWeapon> weapons;
static List<ItemEquipmentArmour> armour;
static List<Quest> quests;
static List<Hostile> enemies;

public static Dictionary<int, Item> ItemIDList = new Dictionary<int, Item>();
public static Dictionary<int, Quest> QuestIDList = new Dictionary<int, Quest>();
public static Dictionary<int, Entity> EntityIDList = new Dictionary<int, Entity>();

List type variables are very self explanatory. They are a list of variables.
In this case, each list is a list of variables containing instances of each gamedata type.
So the variable "enemies" is a list of instances of the class "Hostile".

Lists are similar to arrays, however they are dynamic, and have no set length.

Dictionaries are a bit more complex. They are a list of a certain type of variables, much like lists. However each "Entry" in the dictionary also has an ID in int32 form attached to it.
This is where the ID field on items comes in.

If you remember, Fists are ID 1000. So to get the stats for fists, for example if you were equipping them, you would check ItemIDList, which is a dictionary (Actually outside of the InitLoad class you would check InitLoad.ItemIDList) for ID 1000, and it would find that an instance of ItemEquipmentWeapon called "Fists" is associated with that ID in the Dictionary.

As far as I can tell, dictionaries are by far the best way to handle Item databases with ID's.

Moving on.
The InitInstall Method, as stated, is the method that creates the Gamedata the first time the game runs.

public static void InitInstall()
{
    string path, filePath,
        weaponFile = @"\WeaponsItem.agd",
        armourFile = @"\ArmourItem.agd",
        questFile = @"\Quests.agd",
        enemyFile = @"\Enemies.agd";

    XmlSerializer Serializer;
    FileStream WriteFileStream;

    path = string.Format(@"{0}\AwesomeRPG",
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

    List<ItemEquipmentWeapon> WeaponList = new List<ItemEquipmentWeapon>();
    WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 100, true, 1000, Stats.Dex));
    WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 80, false, 1001, Stats.Dex));
    WeaponList.Add(new ItemEquipmentWeapon("Stick", 3, 110, false, 1002, Stats.Str));
    WeaponList.Add(new ItemEquipmentWeapon("Big Stick", 5, 80, true, 1003, Stats.Str));

    List<ItemEquipmentArmour> ArmourList = new List<ItemEquipmentArmour>();
    ArmourList.Add(new ItemEquipmentArmour("Rags", 0.05, ArmourType.Body, 2001));
    ArmourList.Add(new ItemEquipmentArmour("Sandals", 0.01, ArmourType.Boots, 2002));
    ArmourList.Add(new ItemEquipmentArmour("Hand Wraps", 0.01, ArmourType.Gloves, 2003));
    ArmourList.Add(new ItemEquipmentArmour("Hood", 0.02, ArmourType.Helmet, 2004));

    List<Hostile> EnemyList = new List<Hostile>();
    EnemyList.Add(new Hostile("TestEnemy", true, 20, 1, 100, 1001));
    EntityIDList.Add(EnemyList[0].ID, EnemyList[0]);

    List<Quest> QuestList = new List<Quest>();
    QuestList.Add(new Quest("TestQuest", new List<QuestActions>() { new QuestActions(1001) }, new List<int>() { 1003 }, 250, 0));

    if (!Directory.Exists(path)) Directory.CreateDirectory(path);
    path += "\\Data";
    if (!Directory.Exists(path)) Directory.CreateDirectory(path);
    if (!Directory.Exists(path + "\\Items")) Directory.CreateDirectory(path + "\\Items");

    filePath = path + "\\Items" + weaponFile;
    WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
    Serializer = new XmlSerializer(typeof(List<ItemEquipmentWeapon>));
    Serializer.Serialize(WriteFileStream, WeaponList);
    WriteFileStream.Close();

    filePath = path + "\\Items" + armourFile;
    WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
    Serializer = new XmlSerializer(typeof(List<ItemEquipmentArmour>));
    Serializer.Serialize(WriteFileStream, ArmourList);
    WriteFileStream.Close();

    filePath = path + enemyFile;
    WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
    Serializer = new XmlSerializer(typeof(List<Hostile>));
    Serializer.Serialize(WriteFileStream, EnemyList);
    WriteFileStream.Close();

    filePath = path + questFile;
    WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
    Serializer = new XmlSerializer(typeof(List<Quest>));
    Serializer.Serialize(WriteFileStream, QuestList);
    WriteFileStream.Close();
}

Straight away this looks confusing. Let's go through it.
Firstly, we're creating 6 String variables.

string path, filePath,
    weaponFile = @"\WeaponsItem.agd",
    armourFile = @"\ArmourItem.agd",
    questFile = @"\Quests.agd",
    enemyFile = @"\Enemies.agd";

The first 2, "path" and "filePath" have no value.
The other 4 "weaponFile", "armourFile", "questFile" and "enemyFile" all have a backslash followed by the name of the file where that data is stored. (The @ simply stops it counting backslashes as in-text commands, for example, \n in a string signifies a new line if there is no @. You can also use \\ to signify an actual backslash)

Next we declare 2 more variables.

XmlSerializer Serializer;
FileStream WriteFileStream;

A variable called Serializer of type XmlSerializer, and a variable called WriteFileStream of type FileStream.

Then we give the string variable "path" a value.

path = string.Format(@"{0}\AwesomeRPG\Data",
    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

Don't be confused by the fact this is on 2 lines, it's just to make is simpler, it could easily be done as one line, however it would be awkward to read.

Anyway, in here, we're saying path equals the output of a method called string.Format and we're giving that method 2 args:

@"{0}\AwesomeRPG\Data"
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

So what does this mean?
String.Format allows some extra functionality. The first arg you give it is the actual string, any you give it after will be put in place of the {X} notations.

So you could do:

string.Format("{0} + {1} = 5", 2, 3);

And the method would return a string that says "2 + 3 = 5"

In this case, we're putting the result of ANOTHER method before a piece of plain text.
So what does the other method do?

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

Long story short, it returns the location of the AppData folder on the users computer. You can find this yourself by going to run (Windows Key + R on Win7) and typing "%appdata%". Minecraft players may be familiar with this folder.

It does this because AwesomeRPG's gamedata is stored in "%appdata%\AwesomeRPG\Data"
Sadly C# doesn't recognize "%appdata%" as a valid location.

Next up we do a bunch of weird stuff with lists:

List<ItemEquipmentWeapon> WeaponList = new List<ItemEquipmentWeapon>();
WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 100, true, 1000, Stats.Dex));
WeaponList.Add(new ItemEquipmentWeapon("Fists", 1, 80, false, 1001, Stats.Dex));
WeaponList.Add(new ItemEquipmentWeapon("Stick", 3, 110, false, 1002, Stats.Str));
WeaponList.Add(new ItemEquipmentWeapon("Big Stick", 5, 80, true, 1003, Stats.Str));

This is actually fairly simple. We're creating the stock data for the game and putting it in the list, ready to be saved to a file.

WeaponList.Add() simply adds an entry to the list. The arg is the instance to be added.

We then do the same for Armour, Quests and Enemies.

if (!Directory.Exists(path)) Directory.CreateDirectory(path);
path += "\\Data";
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
if (!Directory.Exists(path + "\\Items")) Directory.CreateDirectory(path + "\\Items");

This is just making sure the folders and such exist, otherwise the code will error trying to make files inside them.

filePath = path + "\\Items" + weaponFile;
WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
Serializer = new XmlSerializer(typeof(List<ItemEquipmentWeapon>));
Serializer.Serialize(WriteFileStream, WeaponList);
WriteFileStream.Close();

Now we get to start making files.
The first line here is quite self explanatory, so I'll skip to the second.

WriteFileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);

So, we're giving WriteFileStream a value. We're creating a new instance of the class FileStream, whose constructor requires 4 args, the file path as a string, a FileMode value, a FileAccess value and a FileShare value.

For the latter 3 we simply use existing constants.
FileMode.Create means the file stream will forcefully create a new file, this will error if the file already exists.
FileAccess.Write means the file stream will only output data to the file, it will not input data from the file (Read)
FileShare.None means the file stream will fully restrict access to the file.

Serializer = new XmlSerializer(typeof(List<ItemEquipmentWeapon>));

Now we're giving Serializer a value, an instance of the XmlSerializer class, whose constructor requires only 1 arg, a "Type".

Types are rather strange. Variable types, such as List, String, Int, any non-static class you make are not types, however they HAVE types, which must be obtained using the special typeof method.

Well, that's not strictly true, they are types, but also have types which comes under System.Type.
Some common types include:

typeof(int) returns System.Int32
typeof(char) returns System.Char

So on so forth.
However it is often easier to use typeof than to actually find the exact System type constant, especially with specific lists.

After giving Serializer a value, we run a method from it.

Serializer.Serialize(WriteFileStream, WeaponList);

The Serialize method. A non-static method in the XmlSerializer class.
This takes 2 args, a FileStream and a variable of the same type given to the constructor of the XmlSerializer, in this case a variable of type List<ItemEquipmentWeapon>

Serialize is effectively the "write to file" method. It uses the FileStream to access the file, and uses the second arg as a source for the data to be serialized. It then runs through the list (in this case) and runs through all fields etc required for each instance in the list, and sends them through the FileStream, which works out where to put them (What file).

After serializing, we close the FileStream. This is for multiple reasons. Not only is it good practice to always close a filestream, but we're about to change one of the parameters and redefine the value of WriteFileStream, as we do what we just did for weapons, but with armour, quests and entities.

The next method, PreLoading() is very similar to InitInstall() in most respects, I'll briefly cover the main differences.

Firstly, Serializer from InitInstall() is called SerializerObj in PreLoading(). I'm not sure why, that's just how I did it. WriteFileStream is also now called ReadFileStream, this is because we're only reading from a file, not writing to it, so calling it WriteFileStream wouldn't make much sense.

Finally, these parts of code:

ItemIDList.Add(-1, null);
QuestIDList.Add(-1, null);

and

ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
weapons = (List<ItemEquipmentWeapon>)SerializerObj.Deserialize(ReadFileStream);
foreach (Item item in weapons)
{
    ItemIDList.Add(item.ID, item);
}

So, the first part simply adds null entries to the ItemIDList and the QuestIDList with the ID -1.

The second part is a little different.
Firstly, we're giving slightly different args to the FileStream constructor.
FileMode.Open means the FileStream will attempt to open the file, and error if it doesn't exist.
FileAccess.Read means the FileStream can only input data from the file, not vice versa.
FileShare.Read means the FileStream will allow other programs to read the file while it is open.

As for what happens after that... well.

weapons = (List<ItemEquipmentWeapon>)SerializerObj.Deserialize(ReadFileStream);

Here, rather than serializing from a list, we're deserializing to a list.
Deserialization is effectively reading a file through a file stream, therefore we must give it a filestream to use, and catch it's output in a variable. By default the return type of Deserialize is a little odd, so we cast it as a List<ItemEquipmentWeapon>.

Finally, we loop through all the items in the list after deserialization, and add them to the dictionary.

foreach (Item item in weapons)
{
    ItemIDList.Add(item.ID, item);
}

You may notice we didn't close the FileStream, that's because I'm stupid, and forgot to do it.

Anyway, we then run through this same deserialization process for Armour, Quests and Entities.

And then we return true, to say it loaded successfully. Because all the error checking I had in there that returned false I temporarily took out and forgot to put back in, because again, I'm stupid :P

And that's it for today's post.

Next C# lesson will be Friday, because on Wednesday I have a special announcement post for you all.

Saturday, 26 April 2014

Beginner's C# Course, Part 4

The basics of C#: Partial classes and Inherited classes

What is a partial class?
Partial classes are classes that span more than one file. Usually, you would define a class in one .cs file, and it would be contained entirely within that file. However with Partial classes, you can define the class in two or more separate .cs files and have separate methods in each.

I won't be touching on partial classes much in this post, and will mostly be focusing on extended classes. Simply because I have yet to find a valid use other than windows forms for partial classes.

What is an inherited class?
An inherited class is a class that is considered an extension or derivative of another class, some people refer to these as "sub-classes". A common example of inheritance use in game development is entities.
For example

##File Start#
using [Insert usual using statements here]

namespace game
{
    public class Entity
    {
        public Entity(int hp, string name)
        {
            //Do some stuff here
        }
    }
}
##File End##

##File Start##
using [Insert usual using statements here]

namespace game
{
    public class Player : Entity
    {
        public Player(int level, int exp, int hp, string name)
        :base (hp, name) //This runs the constructor for the Entity class, and gives whatever was given to player as hp and name
        {
            //Do some more stuff here
        }
    }
}
##File End##

And the same could also be done for enemies and NPC's.
This lesson was a very short one, and mostly taught by example. Remember if there's anything you don't understand in any of these lessons feel free to comment on them.

Also apologies this one was so late, almost a day late in fact.
On Sunday It'll be another source post, the InitLoad class this time.

Wednesday, 23 April 2014

Beginner's C# Course, Part 3

The basics of C#: Static Classes

What is a static class?
A static class is very similar to a non-static class, except for one single difference; you do not instantiate static classes. This means they do not have a constructor.

If you recall back a whole 4 days to our last beginner's C# course post on constructors and classes, I told you that to instantiate a class, you did something along the lines of:

ClassName VariableName = new ClassName(arg1, arg2);

let's dissect this a little.

The first half, before the = is us creating a new variable.

We're defining it's type (ClassName) and giving it a name (VariableName)
It's no different to this:

int i;

The second half is the actual instantiation.

We are giving the Variable called "VariableName", which currently has no value (We've told it what TYPE of value it can have, but not actually given it one yet), a value equal to "new ClassName(arg1, arg2)"

"new" means we're creating a new instance of that class for the value of this variable, ClassName is simply saying what we're creating a new something of, and "(arg1, arg2)"  are simply the arguments required by the classes constructor (See name and age in the student class from the previous part of the course)

With static classes, we don't need to do this.

Static classes are usually used to store functions that are used multiple times in multiple classes.

For example

##File Start##
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//These are some default using statements put in whenever you make a new class

namespace ExampleProgram
//Here's our namespace
{
    static class Functions
    //Here's our static class
    {
        public static int Add(int a, int b)
        //Note that all methods in a static class must be static.
        {
            return a + b;
            //Yes, all it does is add 2 numbers together
        }
    }
}
##File End##

Simple enough?
To call the "Add" method in another class we would simply do:

Functions.Add(1, 7);

However, remember that we put "int" rather than void for this method, so what does that mean?
Simple, it means the function returns an int value.

So we could do something like this:

If(Functions.Add(1, 7) == Functions.Add(2, 6))
{
    Console.WriteLine("The world is functioning correctly");
}

Which basically says "If 1 + 7 gives the same answer as 2 + 6, the world is working normally"

If you look back to my last post, the first part of the sourcecode posts, I actually used "InitLoad.PreLoading()" (which returns true or false) in an if statement.

So when would you use static, and when wouldn't you?

Well, let's say, for example, you were writing a game.
In this game, you want enemies right?
Okay, make an enemies class (non-static) that stores health, damage, speed etc along with some functions such as OnDamage (a function that lowers the enemy's health when it gets hurt)
Now you can do something like this for the actual enemies:

Enemy baddie1 = new Enemy(argshere);
Enemy baddie2 = new Enemy(argshere);
Enemy baddie3 = new Enemy(argshere);

We have now created 3 separate instances of the Enemy class, if one takes damage, the others are unaffected.

baddie2.Damage(AmountOfDamageYouDid);

Now baddie2 has less hp  left than baddie1 and baddie3.

However, note that you cannot do:

Enemy.Damage(AmountOfDamageYouDid);

Because the class itself has no health, only instances of the class, so you can only damage individual instances of the class.
The same applies to ANY non static method within a non static class, you MUST instantiate it and call the method on the instance, rather than the class.

This is where Static classes have the advantage when you just want to call general functions (Functions in a static class usually take 1 or more arguments and return something). Static methods in static classes don't need an instance to be called.

Also note that you can put static methods in non-static classes, and call them without an instance, but usually you wouldn't need to.

Anywho, that's it for today's lesson. Bit longer than usual.

On friday we will cover Partial classes and Extending classes.

Tuesday, 22 April 2014

C# Source Code Post #1

Hey guys, sorry this post is kinda late. Internet's been broken lately, hoping to get it fixed but to do so I need to buy a new ethernet adapter PCIe card. It's relatively cheap, only around £8 ($13.44), but sadly that's a lot to save up when my average daily income is around $0.02 from ads on this blog :/

Anyway, you don't want to hear my cry about First world problems, you want me to post some big, fat, juicy code :3

So, as some of you may have guessed, I will be posting AwesomeRPG source code.
"But why would we want to see that?" You ask, recalling that the source is readily available on the SourceForge page.

It's quite simple, in these source code posts, I will not only be posting the source code, but heavily commenting it and explaining, in detail, what everything does.

This is TitleScreen.cs, basically the main menu code.
I'm not going to bother posting Program.cs, the class that runs when you run the program, because all that does is run this class xD

##File Start##
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//Default using statements for windows forms classes.

namespace Game
//Imaginative Namespace
{
    public partial class TitleScreen : Form
    //We haven't explored partial classes or extentions yet
    // but this is a partial class that extends the windows class "Form"
    {    
        //Constructor-ey goodness
        public TitleScreen()
        {

            //The InitLoad.PreLoading() method attempts to load all the startup content
            //If it fails it returns false, at which point the game closes
            InitializeComponent();
            if (!InitLoad.PreLoading()) GameExit();
        }
        //If you click the exit button.. Run the "GameExit" method (Guess what that does...)
        private void btn_Exit_Click(object sender, EventArgs e)
        {
            GameExit();
        }
        //If you click the options button the game will troll you.
        private void btn_Options_Click(object sender, EventArgs e)
        {
            MessageBox.Show("The options menu is not currently activated.\nPlease enable this feature in the options menu.", "Feature disabled");
            //Yes, it just told you to enable the Options menu in the Options menu
            //This is because I haven't made the options menu yet, and I like to troll people
        }
        //If you click the NewGame Button, you will be taken to (surprise!) the New game screen
        private void btn_New_Click(object sender, EventArgs e)
        {
            //Hide the main menu
            this.Hide();
            //Find if there is already a hidden instance of the NewGame screen running
            foreach (Form frm in Application.OpenForms)
            {
                if (frm is NewGame)
                {
                    //If there is, un-hide it
                    frm.Show();
                    return;
                }
            }
            //Otherwise, make one and show it
            new NewGame().Show();
        }
        //If you click the LoadGame Button, you will be taken to (surprise!) the Load game screen
        private void btn_Load_Click(object sender, EventArgs e)
        {
            //Hide the main menu
            this.Hide();
            //Find if there is already a hidden instance of the LoadGame screen running
            foreach (Form frm in Application.OpenForms)
            {
                if (frm is LoadGame)
                {
                    //If there is, un-hide it
                    frm.Show();
                    return;
                }
            }
            //Otherwise, make one and show it
            new LoadGame().Show();
        }
        //When this method is run, surprisingly it exits the game
        public void GameExit()
        {
            //Betcha didn't guess that!
            Application.Exit();
        }
    }
}


Woah boy!
There are a few things in that class you might not understand.

InitializeComponent();

Dafuq does this do!?
Well, it does exactly what it says, "Initialize Component". It's actually a default method in the constructor of all windows forms classes.

if (!InitLoad.PreLoading()) GameExit();

This, believe it or not, is a simple if statement.
If InitLoad.PreLoading (The function PreLoading in the static class InitLoad) returns false, run GameExit() (Exit the game)

The code for the InitLoad class will have to wait 6 days I'm afraid >:D

private void btn_Exit_Click(object sender, EventArgs e)
{
    GameExit();
}

This method runs when you click the exit button, and runs GameExit()

        private void btn_Options_Click(object sender, EventArgs e)
        {
            MessageBox.Show("The options menu is not currently activated.\nPlease enable this feature in the options menu.", "Feature disabled");
            //Yes, it just told you to enable the Options menu in the Options menu
            //This is because I haven't made the options menu yet, and I like to troll people
        }

This method is when you click the options button, and it pops up a message saying "The options menu is not currently activated." and on the second line "Please enable this feature in the options menu." The title of the message box is "Feature disabled"

private void btn_New_Click(object sender, EventArgs e)
{
    //Hide the main menu
    this.Hide();
    //Find if there is already a hidden instance of the NewGame screen running
    foreach (Form frm in Application.OpenForms)
    {
        if (frm is NewGame)
        {
            //If there is, un-hide it
            frm.Show();
            return;
        }
    }
    //Otherwise, make one and show it
    new NewGame().Show();
}

Getting tricky now.
This method runs when the New Game button is clicked.
Firstly

this.Hide();

runs the hide method within the instance of TitleScreen.. but wait, there's no Hide method. Remember, this is a partial class and extends the form class, the Hide method can be found in Form.cs

Next, it loops through every Form in "Application.OpenForms" which is pretty self explanatory.
With every form it finds in "Application.OpenForms" if checks if it is the form "NewGame". If it is, it un-hides it, if none of them are, it creates a new one and shows it.

The next method does the same, however it is activated on clicking Load Game, and it opens the LoadGame form, rather than the NewGame form.

And finally, GameExit() which exits the game when triggered.

And thus ends the explanation of the source code for the Title Screen of AwesomeRPG.

Next Wednesday we will discuss Static classes, and Friday will be Partial classes and extending other classes.

For those only interested in these source code posts, the next one will be next Sunday, and it will be the InitLoad class.


Saturday, 19 April 2014

Beginner's C# Course, Part 2

The basics of C#: Constructors and Classes

What is a constructor?
A Constructor is a special method that you must always have in a class. It is the method used to create an instance of the class.

But what does all this mean? What are instances?
Well, whenever you make a variable, you must instantiate it.
For example.

int i;

This creates an int32 variable, but does not instantiate it.
It does not equal 0, it equals null.
If I then do

i = 0;

It is now instantiated as an int32, it has used int32's constructor method.

So how can this knowledge be used?
Well, let's say, for example, we wanted to make a "Student" class.

##File Start##
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//These are some default using statements put in whenever you make a new class

namespace ExampleProgram
//Here's our namespace
{
    class Student
    //Here's our class
    {
        public Student(string name, int age)
        {
        //And here's our constructor
        //This constructor method requires a string variable and an int variable
        }
    }
}
##File End##

This class doesn't actually DO anything yet, but it's a great example of both constructors and method arguments (The string and int required)

So to instantiate this class, we would do something like this:

Student pupil1 = new Student("Billy", 12);

This creates an instance of the Student class, where the name is Billy, and the age is 12. It then stores the instance in a variable called pupil1.

And that's it for constructors.

On Monday I'll be doing something a little different. Part one of a source code series, where I will simply share the source of a project I'm working on. I'll be doing this every third session, to appeal to those who already understand the basics.

So make sure to check back on Wednesday when we will be discussing Properties and fields within classes.