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.

Thursday, 17 April 2014

Beginner's C# Course, Part 1

The basics of C#: OOP

What is OOP?
OOP stands for "Object Oriented Programming" and is a term used to describe programming languages such as C# or Java, who's entire code structure depends on everything being derived from some form of "Object"

In C#, code is written into files suffixed *.css (C Sharp Source not Counter Strike: Source). These are most commonly made as "classes" (although sometimes made as "interfaces", but that's a different topic). Classes are how you define your own types of objects. (For examples, integers, Strings, booleans etc are all types of objects. Whenever you define a variable, that variable needs an object type, so it knows what it's supposed to be.
Here's how most classes are structured:

##File Start##
//Using Statements go here
using system
using system.blah

using mycode.myclass

//You declare the namespace here
namespace mycode
{

        //and here we name the class
class myclass2returnoftheclass
{
                //Your class code goes here
                public myclass2returnoftheclass()
                {
                        //Your constructor code goes here
                }
        }
}
##File End##

But what does all this mean? What's a namespace? What's a constructor?
Well, constructors we'll get onto in the next part of the course, as for a namespace, they're akin to packages in Java.

A namespace is how you organize your code. Generally, all code for a certain program comes under one namespace, and then things such as input from other programmers and mods usually go in sub-namespace.

For example, let's say I make a program called "appy"
I would use the namespace appy
So if the main class file was main.css, the code directory of it would be appy.main
And if another programmer made a mod called smartappy, it would probably come under appy.smartappy

Anyway guys, that's pretty much it for the first part. Next part coming on saturday :D

Tuesday, 15 April 2014

Blog Updates

Hello all.

I've decided recently to become a bit more seriously about this blog.
What this means is that I will now be posting a blog post every other day.

Also, I've had several people contact me asking to develop games with me or asking me to teach them programming.

I am willing and happy to do both of these, however if you want me to teach you programming, you no longer need to look any further than this blog, as the bi-daily posts will now be primarily focused around teaching the readers programming, C# specifically.

I'm also waiting to hear back from clientsfromhell.com about their freelancer kit.
It includes a freelancer's guide PDF and a zip of professional freelancer contract templates, both of which they've sent me, along with 6 months free web hosting for a professionally setup and maintained wordpress site and a free domain, courtesy of their partners, site5.

I'm still waiting to hear back about the hosting, but when I do, I will be migrating this blog over to the wordpress site. Wordpress is simply far more open ended and professional than Blogger. The only advantage of blogger being fast and easy integration with Google AdSense, and the fact that it's owned by google so I can login with my google account. (I use google chrome so blogger automatically detects my login).

When I move to the new site, I will be posting a link here, of course, and until then I will post some C# goodness every other day!

So make sure you watch this blog on thursday for the first part of the course.

Friday, 4 April 2014

Ramblon, a new social site

Hello loyal minions *cough* I mean blog readers :3

Today I discovered an interesting new site, sent to me by the admin of an old game server, who is now one of the owners of this site.

The site is called ramblon, it's a discussion boards type site, similar to reddit, although currently without separate boards.

It's very new, with only 11 registered users (one being me) and 20 posts (one being mine) as of the writing of this post, and it's currently in open testing while they continue developing and adding features.

I don't really know why I'm posting about this, I just like it's design and idea, and given how new it is, I want to help out. I'm considering contacting their staff to discuss the possibility of developing a ramblon mobile app, which would be mutually beneficial, but we'll see I guess.

But until then, get yourselves over to the site, get registered, and get.. ramblin'!

Ciao!