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.