Making an RPG in C#: An Indepth Tutorial

An indepth tutorial by frostydowns in C#



The concept and ideas behind an RPG game from my point of view.

Hey all,

I'm here today writing this tutorial up, because I think what I have to say will be of some use to someone (Knowledge is power, so many people take it for granted).

In this tutorial I will be explaining the concept behind my form project, compare the idea to other RPGs, just to give you starter people out there some ideas behind it.

But before we begin the programming language is c#, but the ideas behind everything SHOULD be about the same in any language, that being said, you can comment after wards about it if I'm incorrect after wards PLEASE keep in mind that this is my personal overview what I say there will be people that disagree on things and what not, while viewing this tutorial while the game is BASIC and may look dull, the idea behind it is how, RPG's are basically done from my POV.

Also not ALL of my code will be included, you STILL have to have basic knowledge, I'm just not going to hand feed you all my code, it's, as I said examples and how to go about it.

Now i've that's out of the way lets get one with it!

Contents:
1. The Beginning.
2. Character Screen
3. The mainform
4. Combat
5. Win Screen

1. The Beginning

When designing and RPG, It's always a good idea to plan out your story, character development, not necessarily  the whole game, but, to give you an idea of what you and your team are doing, if you're doing it solo and just a project to learn from, and you're a person like me plannings not necessarily, I know I plan it all up in my head then put it to paper, it's how I work, it's what works for me.

First of all when designing an RPG, you might want to start, with a menu system, something basic, so that it's not overly complicated leave save and load till later, just have new game / exit game for now, if you have a look into my program I have globalized just about every array, this IS bad programming for OOP, but this isn't a business ap, it's a game, so in my books it's ok to globalize things like money, exp, level, damage .etc things that you will use through your whole program to get yourself setup with, how would you go about this? you need another class file, this file makes it possible to 'cache' all your forms on load up, set up the important variables that you need to keep things organised! as seen in this part of code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BattleArena
{
static class Varz
 {
// Declairs the public variables
public static frmMainMenu menuform = new frmMainMenu(); // Main menu form
public static frmChar charform = new frmChar(); // Main menu form
public static frmMain mainform = new frmMain(); // Main gameform

// Game variables for gold .etc
public static int mygoldamount;
}
}


Notice how the 'static class Varz' is named you will be using this to call your variables, why wouldn't I use form1.show();? because when I was setting this up at the time it would just create an entire new form, say i clicked town then back then back to town i'd have 2 town forms open and 2 main forms open, with globalizeing them it's like setting the forms up into memory so you can use this.hide(); and form1.show() with minimal complications.

Now lets go back to the menu part, you should have 2 buttons, new game and exit game, you want to double click the new game so we can have the initial start up proccess of it all here's the following code for the new game;


public void btnNewGame_Click(object sender, System.EventArgs e)
{
// Hide this form
this.Hide();

// Setup all the variables for the new game click
Varz.mygoldamount = 0;

// Finally show the form
Varz.characterform.Show();
 }


Now to call on our variable that we just created, I called mine Varz it's the name that comes after the static class in your class file that i mentioned before, because all of that is globalized anything you set will be set permanently so be careful it's perfect for resetting values such as out gold amount here, you want to hide the form first then do your code the show the next form, let me elaborate;

User click on new game
|
v
Hide the menu
|
v
Setup all your code, reset values behind the doors
we just don't want the user to see the code we're out putting
|
v
show the character select/setup screen

Now because forms don't use alot of memory and you can use it on a 486 you can store just about as much as you like, just keep things hidden like I've done to setup up, if you do manage to "bog down" the form then you may have to consider a loading screen, I hope that's been indepth enough for everybody on the initial start up of everything.

2. Character Screen
After a user click new game it's a goo idea to go a character menu for character creation, which I haven't done, you could probably have a form placement there, then onto the main form, which is where i'll be explaining int he next part what i've done for this.

But if you are incline to make a character setup screen with a name and what not, you will want to add it to your varz file, and make a new varz for name, and character selection if you are to have multiple characters, so we can 'call' what character you have, maybe set up a radio button then if the user clicks on said radio button the varz.charselected you can have as 'bill' or 'harry'.

For the name it's pretty straight forward string value to setup and because it's globalized you can call upon it in ANY form, because if you have what I have setup here, you will goto the main form next then another form for the battleground where as on this for you want to have something like this for when your character attacks: lisbox1.items.add(Varz.Charname + " Hits " + Varz.BaddieNaem + " for " + Varz.Mydamage " Damage!");

This will out put into a list box, "Harry hits rabbite for 10 Damage!".

Global variables are super handy in a game makers perspective, you'll notice I use a listbox that's because it's just a handy way to keep things tidy in my point of view, you could use anything you like really, you will also notice I globalize the damage, that's so I can refer to it for various things with out making a ton of referrals, it's just wayyy easier to do it this way.

Now when you click ok you will want to stick the character name, and the selected character into you're new globalized variable you can do this by:

Varz.Charname = txtCharname.text;

And that's it, it's like any other variable but it's globalized, remembering "Varz" is how we locate our variables you can also, for what ever reason declare the same name variable so you could have "string Charname;" but this wouldn't be global and just like a normal variable, now remember to show our name mainform after you do all of this setup, When displaying to another form you will have to call it like this "Varz.Mainform.txtCharName.Text = txtCharName.Text" this makes it so you call the form then the char name of that form and make it state that it's the characters form name, this will only ever change now if you change it by Varz.CharName, and you can now call upon it like anyother vars.

We will also need to load your selected character in, if you have him displayed in the next form, if you don't want it in the next form use this to load an image for when you do want it, I'm going to use the next form as an example, what you do is make a "pictureBox" int he next form, now draw something in paint, to represent said character and what your going to do is add this into the "Resource" file to do so in your solution explorer, click the properties folder (mines greyed out) and then double click Resources.resx, then click and drag your new painting into this and give it a name.

Now go back to that next button we were doing just a moment ago, and add in:

Varz.mainform.piccharimage.Image = Properties.Resources.charBill;

And that's it! What we have done is preload the image into the resource file and then referring to it, I'm not sure on the memory useage of this, so just use jpg's or something small, the good thing about this is we can refer to it where ever we like it's all preloaded much like your forms, you will need to fix the attributes of the picture to suit what paints is, you can locate that in paint via "image/attributes..." and the width and height is what the size of your character is, so if it's width 50 height 75 then for your image it'll be 50, 75 so H, W.

3. Mainform
You may want to display your character here, his name several stats, you can set these up on your own, one would consider this to be your home where you prepare before battle! Try setting up some button health and mana and int he variables do the same, here's the variable file I use


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BattleArena
{
static class Varz
{
// Declairs the public variables
public static frmMainMenu menuform = new frmMainMenu();
public static frmMain mainform = new frmMain();
public static frmtalents talentform = new frmtalents();
public static frmTown townform = new frmTown();
public static frmItemShop itemshopform = new frmItemShop();
public static frmInventory inventoryform = new frmInventory();
public static frmChar charform = new frmChar();
public static frmArmory armoryform = new frmArmory();
public static frmAbout aboutfrom = new frmAbout();
public static frmWinScreen winfrom = new frmWinScreen();
public static frmBattleGround battlegroundfrom = new frmBattleGround();
public static frmJunkYard junkyardform = new frmJunkYard();
public static frmHobby hobbyform = new frmHobby();
public static frmItemBreaker itembreakerform = new frmItemBreaker();
public static frmItemMaker itemmakerform = new frmItemMaker();

// Equipped stats
public static string headEQ;
public static string sholderEQ;
public static string chestEQ;
public static string golvesEQ;
public static string legsEQ;
public static string feetEQ;
public static string mainhandEQ;
public static string offhandEQ;
public static string twohanderEQ;
public static string weapontypeMHEQ;
public static string weapontypeOHEQ;
public static string weapontypeTHEQ;
public static string weapontypeEQ;
public static int minOHWepDam;
public static int maxOHWepDam;
public static int minMHWepDam;
public static int maxMHWepDam;
public static int minTHWepDam;
public static int maxTHWepDam;
public static int bonArmEQ;

// Stats
public static int TotalGold;
public static int TotalHP;
public static int myMinHP;
public static int myMaxHP;
public static int myMinMana;
public static int myMaxMana;
public static int Strength;
public static int Intellect;
public static int BonusArmor;
public static int BonusArmorEQ;
public static int myCurLevel;
public static int StrStat;
public static int IntStat;
public static int HPStat;
public static int fightNo;
public static int fightNoAmount;
public static string EquippedItem;
public static string EquippedMHItem;
public static string EquippedOHItem;

//public static int Agi;
//public static int Resist;

// Spell
public static int SpellCrit;
public static int SpellDamage;
public static int intlblSpellDam;
public static int manaTicker;
public static int RegenMana;
public static int SAbCrit;

// Heal
public static int healamount;

// Melee
public static int MHDamMin;
public static int MHDamMax;
public static int OHDamMin;
public static int OHDamMax;
public static int MinAvMDam;
public static int MaxAvMDam;
public static int MAbCrit;
public static int MeleeCrit;

// Level thing
public static int nowLevel;
public static int BLvlMin;
public static int BLvlMax;
public static int BLvl;
public static int BLvl2;
public static int CBLvl;

// Other stats
//public static int overkilldmg;
public static int Attack;
public static int RAttack;
public static int Randy;
public static string attackType;
public static int AbilityPointsUsed;
public static int AbilityPointsTotal;
public static int Crit;
public static string lastItem;
public static int level;
public static int abpointsHP;

// Baddies stats
public static int BHPMin;
public static int BHPMax;
public static int BMinDam;
public static int BMaxDam;
public static string TName;
public static int BAttack;

// Exp, Gold stuff
public static int CExp;
public static int NExp;
public static int MaxExp;
public static int ExpGold;
public static int WinExp;
public static int CGold;
public static int WinGold;
public static int NLvl;

// Hobby
// Item Breaker
public static int itemBExp;
public static int itemBNExp;
public static int itemBLevel;
public static int itemBJunkFillSelect;
public static int itemBProgress;
public static int itemBProgressSkip;
public static int itemBCreateMin;
public static int itemBCreateMax;

// Item Maker
public static int itemMExp;
public static int itemMNExp;
public static int itemMLevel;
public static int itemMJunkFillSelect;
public static int itemMProgress;
public static int itemMProgressSkip;
public static int itemMCreateMin;
public static int itemMCreateMax;
}
}



As you can see yes it's huge, but it's within reason, this place players should be preparing for battle, with various 'chilling' style activities to do there's not a lot going so let goto the next chapter of this tutorial.

4. Combat
Right now if we click enter the arena, you will want to up date the variables respectively for the beginning fight, I have a timer on the next form, for when it's enabled it will update all my graphics, then switch itself to disable, doing this allows me to stick that where ever, rather than do a bunch of variables in here I can utilise the timer feature, it will also randomize the bad guy selector and place that into combat and set up a new fight for me.

Then you will want to show the form, it looks a little over whelming but all of this code is quiet easy, first off when you hit attack, i have it check if you have an attack selected if not then display the message, then it will scan for an attack, i'll post part code for you to see what i'm talking about:


public void btnAtt_Click(object sender, EventArgs e)
{
// If no skills are selected
if (lisSkills.SelectedItem == null)
{
lisLog.Items.Add("Select an ability to use");
}
else
{
btnAtt.Enabled = false;
DeclairInts();
// Select which spell you used
// Random my hit from MAX DAMAGE and MIN DAMAGE for now we add both
// the main hand and off hand as a joint damage **NEEDS IMPROVEMENT
// add extra damage for bonus's .etc
if (lisSkills.SelectedItem == "[DPS] Melee 1")
{
attMelee1();
}


I disable the attack button to prevent players from spamming it while the timer's not going through and renable at the end of the regen timer, good thing about this I can create another attribute for attack speed to knock .1 second off or half a second off the cooldown timer allowing players to double hit, pritty neat huh? as you can see also I have "if selected item is equal to [DPS] melee 1 to the code now that code consis of:


public void attMelee1()
{
// Melee damage
Varz.MinAvMDam = Varz.MHDamMin + Varz.OHDamMin;
Varz.MaxAvMDam = Varz.MHDamMax + Varz.OHDamMax + 1;

crithitmelee();
}


 Yes, because we globalized everything you can still use all the attributes! without the fuss so i can make as many of these as I like, this will generate my damage, pritty simple stuff there then check if I have critted which is the following code:


public void crithitmelee()
{
// Did the melee Varz.Attack crit?
// Randoms your melee crit
Random CRand = new Random((int)DateTime.Now.Ticks);
Varz.MAbCrit = CRand.Next(1, 100);

if (Varz.MAbCrit < Varz.MeleeCrit)
{
Varz.SAbCrit = 2;
Varz.Crit = 2;
}
}


And that's it, first off we random 1 - 100 (%) then we check if MABCrit is less than your ability to crit, give the crit value for 2, why do we want to do that? well if it's 0 and I add it on the end of my attack it won't affect the damage at all, if it's value is 2 it will double the damage, at the end of the attack I reset this value to 0 so it maybe check again.

Now if we go back to when you first click a button past allt hese checkers you will get:



// Does your damage calculation
MyDamage();
lblMDam.Text = Convert.ToString(Varz.Attack);
lblMDam.Visible = true;
tmrMDam.Enabled = true;



The code will do my damage, that is as follows


public void MyDamage()
{
string skillset = (string)lisSkills.SelectedItem;
tmrRegen.Enabled = true;
if (skillset.Contains("[DPS]"))
{
// Randoms your Varz.Attack
Random RandAtt = new Random((int)DateTime.Now.Ticks);
Varz.RAttack = RandAtt.Next(Varz.MinAvMDam, Varz.MaxAvMDam);

Varz.Attack = Varz.RAttack * Varz.Crit;
Varz.BHPMin = Varz.BHPMin - Varz.Attack;
lblBMinHp.Text = Convert.ToString(Varz.BHPMin);

// if the baddies HP is above or equal to 1
if (Varz.BHPMin >= 1)
{
updatebaddieshp();
}
// if the baddies hp is under or equal to 0
else if (Varz.BHPMin <= 0)
{
Varz.BHPMin = 0;
updatebaddieshp();
}
}
if (skillset.Contains("[Heal]"))
{
Varz.myMinHP = Varz.myMinHP + Varz.healamount;
MaxHPchecker();
lblHPMin.Text = Convert.ToString(Varz.myMinHP);
lisLog.Items.Add("You healed for " + Varz.healamount);
}
}

All this code really does is check if the attack was a heal selected or a dps selected because we don't want the damage to display when we heal, we probably could at some stage to give the healer base classed something to do, but right now, we're not going to, next if the skillset.contains, dps do this. This part of code is interesting because with it I can call things like item level or any text I need to grab, not we random the attack, then my normal attack * crit? (remember if it got set to 2 or 0? ;)) we minus the baddie hp from my attack then do a checker to see if the baddie has any health left, if it's below or equal to 0 then we make it 0 for fear of it being like minus and creating error within the hp bar.

The healing is pritty simple we just add the heal amount, do a checker to check if it's over your max hp, again to avoid errors, and display the healed amount, now lets go back and continure downt he attack line.


// Re-Randomize
Offset();

// Checks to see if you're alive
MeAliveChecker();

// Target loses hp and check if it's below 0
if (Varz.BHPMin <= 0)
{
Varz.BHPMin = 0;
//Do the win the game routine
Winthegame();
Varz.mainform.tmrRefresh.Enabled = true;
goto Outofloop;
}

// Re-Randomize
Offset();

// Does the baddie damage
tmrBWaitHit.Enabled = true;
}
Outofloop:
ScrollDown();
}


We off set the ranomizer, this may of been old code, I just letf it in anyway, we next check if we're alive, if hp min <=0 thing, then do if mob hp <= 0 aka dead we display the win the game routine and then goto outof loop to bypass the baddies doing damage, we re randomize again (old code) then do the baddie timer, to hit, now i have a few timers to deal with all of these they will activate with in 1 second and display damage, you could agian decrease this, then close it up and scoll the list boxes down. Providing everything is updated and ready you should be ok to go, now onto the win screen!

5. Win Screen

When you win the game this has a chance to pop up, if you die a button pops up and you click to exit and then have to heal at the temple, winthegame(); a snipit code is displayed below:


public void Winthegame()
{
LeaveCombat();

// Exp calc and to see if you dinged
if (Varz.CExp >= Varz.NExp)
{
ding();
}

MessageBox.Show(lblBName.Text + " defeated!");
lblBName.Text = "";
this.Hide();

// If there is loot on the mob
int lootyn = randy.Next(1, 10);
if (lootyn <= 5)
{
// Populate the other side with loots
populateLoots();
Varz.winfrom.Show();
}
else
{
Varz.mainform.Show();
}
}


We leave combat to clear up unwanted things to enable/disable buttons .etc, then we do the exp/gold calculationw hich i'm not mentioning because it's too easy, then if current exp is greater or equal to next exp we run the ding code and add stats, we display to the user next that the mob was defeated and then we hide it this screen soon after they click ok.

We random 1-10 I like working with larger random intervals, id it's below or equal to 5 then we display the winscreen if not display the main form, and then we open up the winscreen if we suceeded doing so, we populate the loots on the next screen, the code for that is as follows:


// Convert the money over
Varz.armoryform.lblGold.Text = Varz.mainform.lblGold.Text;

// Declair the ints
int levelEq = Convert.ToInt32(Varz.mainform.lblLvl.Text);

// Randomizers
// Randoms the generator both name selects
Random ArmorGens1 = new Random((int)DateTime.Now.Ticks);
Random ArmorGens2 = new Random((int)DateTime.Now.Ticks);
Random ArmorGens3 = new Random((int)DateTime.Now.Ticks);
Random WeaponGens1 = new Random((int)DateTime.Now.Ticks);
Random WeaponGens2 = new Random((int)DateTime.Now.Ticks);
Random WeaponGens3 = new Random((int)DateTime.Now.Ticks);
Random JunkGens1 = new Random((int)DateTime.Now.Ticks);

// Randoms the gerator to output x amount of Armoritems to the shop
int itemArmorAmount = 0;
int itemArmor1 = ArmorGens1.Next(0, 3);


Just a bunch of random declairingsm converting over the gold amount to be displayed.


// Generate x amount of items to fill out the armorlist
do
{
Varz.nowLevel = levelEq;
ArmorPartSel = ArmorGens1.Next(1, 7);
Namesel = ArmorGens2.Next(1, 4);
Namesel2 = ArmorGens3.Next(1, 4);

// Picks the names
nameArmorPart();
name1partArmor();
name2partArmor();

// Displays the names
Varz.winfrom.lisBDrop.Items.Add(ArmorPart + " " + Name1 + " of " + Name2 + " Level " + Varz.nowLevel);
itemArmorAmount++;
} while (itemArmorAmount < itemArmor1);


Here is part of the name generator, just now level = the level the use is now, and then the ranomizer will pick a value between 1 and 7 if value = 1 then display name bandit, and so on thats what the pick the name part does, then we add the display item into the list box, we loop untill itemArmorAmount  is greater than the generated itemamount which is held in itemarmor1, let me explain in more depth:

The amount to displayed gets randomed between 1-15 or how ever many you want to do
|
v
Each loop will fill the list box with 1 item (we have a generator picking if the generated item is either armor, weapon or junk, same method as this)
|
v
Keep looping untill do-while is finished


Pritty simple stuff, repeat this for weapons and junk items or what ever items you want randomly populated use it for shops too, continueing on furthur we have:


// Fill the inventory with this listbox
// Loop into x for the array
int x = 0;
object[] oldArmor = new object[Varz.inventoryform.lisAInv.Items.Count];
for (x = 0; x < oldArmor.Length; x++)
oldArmor[x] = Varz.inventoryform.lisAInv.Items[x];
// Loop the array to fill out
for (int i = 0; i != (x); i++)
{
Varz.winfrom.lisAInv.Items.Add(Varz.inventoryform.lisAInv.Items[i]);
}


This will loop through a list box from your inventory and populate this next screen, give x a value of 0 this will be out loop counter, objact old armor is our length grabber, on the coutned items in the inventory form lisAInv is the armor inventory, then we do the loop of i, x is now the maximum items in our list box.

We go on to clear out inventory now, because our 'new' inventory is on this next screen just put in:

// Clears our inventory
Varz.inventoryform.lisAInv.Items.Clear();


Simple stuff, now ontot he next screen you will want to grab the items, becaus ethey're all in 1 list box, how do we do this? lisBDrops.Contains("[Head]")! if the drops is a head item then you stick it in then other list box with the following code:


// Set up selected items
string lisBDrops = (string)lisBDrop.SelectedItem;

if (lisBDrop.SelectedItem != null)
{
if (lisBDrops.Contains("[Head]") || lisBDrops.Contains("[Shoulder]") || lisBDrops.Contains("[Gloves]") || lisBDrops.Contains("[Chest]") || lisBDrops.Contains("[Legs]") || lisBDrops.Contains("[Feet]"))
{
// Add item tot he head slot
lisAInv.Items.Add(lisBDrop.SelectedItem);
// Remove said item
lisBDrop.Items.Remove(lisBDrop.SelectedItem);
}
if (lisBDrops.Contains("[Main Hand]") || lisBDrops.Contains("[Off Hand]") || lisBDrops.Contains("[Two Handed]"))
{
// Add item tot he head slot
lisWInv.Items.Add(lisBDrop.SelectedItem);
// Remove said item
lisBDrop.Items.Remove(lisBDrop.SelectedItem);
}
if (lisBDrops.Contains("[Junk]"))
{
// Add item tot he head slot
lisJInv.Items.Add(lisBDrop.SelectedItem);
// Remove said item
lisBDrop.Items.Remove(lisBDrop.SelectedItem);
}


See? all i'm doing is seperating the scanned item, and sticking them in the appropreate box! when you leave can you guess what you can do? you populate you're inventory because it's cleard now, and then clear this on leave.

Now you have a fully working inventory.


Thats it for now, i'm a little teird and a bit burnt, this is a bit to take in but it's more or less this simple. I'll stick more chapters in later, with the trade system, and getting an item level, which isn't that hard, it's all scanning list boxes with a looped number variable.

Review on Unity

From Tuah of gaiaonline.com:


Unity 3D isn't a simple game-maker. It is a full-blown grade-A game engine. For those who don't understand what a game engine is, it is a data-handling system, a Rendering engine (for drawing things on the screen, an Audio engine (for playing sounds), and a Physics engine (handles all the physics). There are many more sub-topics in these, but this is the gist of it. There is a free version available with a couple of features locked, and a professional version.

The graphical power is better than many other engines, shown here, and supports all the major visual effects that games are using these days.

Game Makers of various sorts have you make the art and do light scripting, as most of the difficult parts are already handled in the maker itself. Unity is not a game maker in that you can't just open it up, put in a few models and call it a game.

That said, it is one of (if not) the easiest-to-use game engines out there, with its own advanced Editor and Prefab system. The editor automatically imports all your assets (models, textures, sound-effects) for you, so no time is lost. It also allows you to press a "play" button to see exactly how your stuff works instantly. No long waits for compiling like in other engines.
And Prefabs are basically objects that are already set up with everything needed to work. A model, physics components, and some scripts; no need to re-add everything every time you make a new object.
The component system also allows you to take your scripts (even free ones from online), slap 'em on an object, and watch 'em work. Much better than the older methods of inheriting behavior.

Now, while you might be able to assemble your stuff and have it work great, you still need to put a lot of work in to actually make the stuff.

Luckily, Unity's importing system allows for seamless input from Blender and 3D Studio Max, among others. Open your modeling program, make your object and save it, and Unity automatically imports any changes you've made.

The scripting languages Unity uses are C# and a custom dialect of Javascript (not Java). It also uses Boo, but that doesn't seem as popular.
If you're a newbie, go with Javascript. If you're fairly experienced, go with C#.

And the last thing I have to say about Unity 3D is the documentation and community. It far surpasses all the others I've seen out there. The documentation is freely available online (and automatically accessible by double-clicking on something in the editor), and incredibly well-organized. The Unity forums are also bustling with friendly Indie developers and hobbyists who all look out for one-another. If you need help, you're sure to be pointed in the right direction.


Unity 3D is a great tool for hobbyists or indie developers alike. Even EA is starting to use it. It's flexible, powerful, and easy.

Making an RPG in VB.NET: Tutorial 1

If you haven't already, make sure to get a copy of Visual Basic Express 2010. It's free of charge- just register (also free) within thirty days of downloading. Today's lesson will involve preparation of your game, and starting off with your basic movement script. This will allow you to get a feel of how to code responses to key presses (we'll be using the up, down, right and left arrows) to move your character around the map.

Preparation: Outlining Your Game

Before we get to any coding, we need to have all our information. Look at the list below. You should have:

  • A drawn map of the area(s) in the game (preferably with detailed maps drawn of sub-areas)
  • A fully written storyline (writing it like a play script is helpful)
  • A list of all characters and their sprites (sprites are images of things in the game that are not tiles)
  • A list of all your tiles (tiles are images of map pieces, such as grass or dirt or water)
  • Shops, items, and other gear
  • Monsters or other enemies and their sprites
  • A level system, class system if you wish (fighter, mage, cleric, etc)
  • A stat system (this can be rough, since we'll be going over it in detail later on)
Once all of this is done, we can start coding. Don't worry too much if you're a little unsure of some parts of the list. All will be addressed throughout the tutorials.

Starting VB.NET and creating your First Application


Installing VB Express 2010 is fairly simple. Follow the instructions and once installed, go ahead and start it up. Your screen should look something like the picture on the right. You can click any image throughout the tutorial to enlarge it.

In the top left corner, select File - New Project - Windows Form Application.

A windows form application is our choice because we're going to be interacting directly with Windows as we code, as well as while the game is running. It allows us to call on responses directly from your computer, such as when you press a key. Most of the time, VB.NET programs are made using a windows form application.

In the center window (the largest) there should be a box window. It will be labeled "Form 1". Should you click on it once, you'll see some information in the Properties window at the lower right corner of your screen. Toward the top of the list of items in Properties, you should see "(Name) Form 1". Let's change that and give our application a proper name. Clicking the part that says Form 1, type "mymap" in replacement, then hit Enter. This should save what you wrote. Scroll down the Properties box to "Text       Form 1" and clicking the Form 1 part, change it to My Epic Game. Hit enter and you may notice that in the box in the center window, the title will now read "My Epic Game".

What We Did:
The Properties section represents the properties of whichever item we are selecting in the center screen, which is our work space. When selecting a new item in the work space, such as the form (the box window) we have access to its specific properties. Changing the 'text' attribute will change the title text of the item. You can adjust many things in the properties window, from the size of the object to the color, and more.

From here on we're going to be referring to the form we just edited as mymap, since that is what we have officially named it. Names are important so that we don't get mixed up when we have many items in our project. When giving something a name, it is best to give it a short, easy to understand name that clearly represents the object at hand.

So far, this is what we should have:










Making Your Player Character

Pretty plain, isn't it? Let's make it a bit more interesting by putting our character in there.
Right now we're just going to use a block to represent the character. The great thing about using VB Express 2010, is that there's a whole list of clickable objects we can insert without any code needed. These are available in the Toolbox. If you look at the image above, you'll see the toolbox on the left of the screen. It's a long list full of a number of things, and that's where we'll grab our PictureBox. If it isn't open already, click the little arrow beside Common Controls to drop down a list, and then grab (click and hold) and drag PictureBox into mymap. Release and you should have a rectangle with a dashed outline sitting in your mymap form.
Clicking on the PictureBox once, you should see some new information in the Properties panel, which is now displaying attributes of the new PictureBox.

Note: if you accidentally double-click you'll be brought to the code view window. Just switch back to the design view by clicking the tab at the top of the workspace window.


As we did with mymap, we're going to change the name of the PictureBox. Scroll the Properties list to "(Name) PictureBox1" and change PictureBox1 to myplayer. Again, we're changing the name because it makes it easier to recognize later on. If we see script that simply says "PictureBox1", we're less likely to remember what it represents, rather than myplayer.
Scrolling down a little in the Properties window, you'll see BackColor and a gray box beside it. Where the gray box is, there's a little arrow. Click it and a drop-down list will display a number of possible color selections. The three tabs above the selection will be Custom, Web, and System. Choosing the Custom tab gives you an array of colors to choose from. Web and System have a smaller and generally less vibrant list of colors, so I usually prefer to always choose my color from Custom. Do so now. I chose blue. When you pick a color by simply clicking it, the myplayer box will change to the selected color. It's that simple.
Note: Later on we'll get to using actual images for our characters, but for now, let's keep to the basics.

We've got one last thing to change before we delve into coding. You'll notice that our little player is rectangular in shape. Personally, I've never seen a character who was horizontally elongated, so let's fix that. If you look at myplayer, you should notice some re-sizing dots. Grab the bottom-right one and resize your player into a decent cube shape. If you prefer, you can go to Properties (make sure myplayer is selected) and scroll to size. Adjust this to 50, 50 by clicking and typing the numbers (don't forget the comma) in.


And now we're ready to code! So let's refill our coffee, have a snack, and get into that scripting!

Coding Your First Script - Character Movement

Currently we're in design view, and in order to see or write code, we need to go to code view. At the very top of your screen, where it says File, Edit, View and so forth, select View - Code. This should open a new tab in the workspace. The following text will be displayed:


Public Class mymap


End Class


Do you recall when we named our form mymap? We can tell that we're working with that specific form because of how we labeled it. It's easy to recognize, and later on if we wish to call on mymap in a different form, it will be very easy to remember. 


Breaking down the code
Public Class means that anything used between Public Class and End Class will be wholly available to the entire page of code, rather than a Private Class. Objects in a Private Class are only usable within that specific Private Class. There are a number of Classes, such as Public, Private, Friend, and Protected. Most of the time, Public Class is the preferred choice.

The class we are using is public because we want the objects in it to be accessible anywhere. We are referring to mymap, meaning all the information we put between Public Class mymap and End Class will be held within the form that is mymap.

Lamens Terms: You have two baskets. One is big and one is small. The big one is called mymap and can hold the smaller one, as well as other things. You've got a bunch of apples (your code relative to the map) you want to keep together and separate from the oranges (code not relative to the map), so you put them in your mymap basket to do so. This is important when you have a whole lot of fruit and baskets later on, and just want to grab the apples.

Assigning Arrow Keys to Movement
Let's go back to our design view by selecting its tab at the top of the workspace window. Make sure mymap is selected (you can always tell, because it will show the name mymap in the properties window) and have a look at the properties window. You will notice a small lightning bolt (see reference image) which when clicked, will show a new list of Events. An event is just that- an event that takes place when something happens. Scroll to KeyDown and double-click it. You'll be sent back to the code view in the workspace, and a new line of code has appeared. We now have:


Public Class mymap

 Private Sub mymap_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown

    End Sub


End Class


I know it looks like a lot, but if we go through and break it down, it's quite simple. Private Sub, the opposite of public class, is a sub-class within the public class that is mymap. It's like a smaller basket in your mymap basket, able to hold an event and the information pertaining to this event. The information is ONLY pertaining to that event. This is why it's private. mymap_KeyDown is the kind of event. It is simply saying that if the user presses a key while mymap is running, the event is triggered to happen.
(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown is assigning two new values to variables. A variable is a word that represents, or holds a line of information that can and is usually changed throughout the script Variables are also used to shorten large lines of code so that we don't have to keep typing them out.
 ByVal means "by value". The code is stating that the value of the variable sender is System.Object, and the value of the variable e is System.Windows.Forms.KeyEventArgs.

You may have noticed we're using Windows based terms because we're creating a windows application, thus why we chose to make a Windows Form in the beginning. 


Basically, what this script is doing is translating windows language and functions so they can be used in VB.NET. Pretty nice, huh? 
The important part of the script is the variable e. Luckily, we don't have to type out System.Windows.Forms.KeyEventArgs every time we want to see if a key is pressed, because this line of code has simply been assigned the variable 'e'. That's what makes variables so simple. Every time we refer to 'e', we are really referring to the above blue text, unless 'e' gets assigned to something else. So now that we have this, it's time to make a Case.


Creating a Case
A case is a kind of event that says, "if one of these things happens, do this." For each case, there is a possible event. In our situation, we want four cases. The case of the down-key pressed, the up-key pressed, the right-key pressed, or the left-key pressed. 


Let's begin adding that in. First we must make a Point. A point is like a variable that stores an x/y coordinate. We will use this to hold the coordinates of our player. Let's call our point Loc; short for location. The term Dim Loc as Point will be used. Dim basically means, "create". Thus, we create the variable Loc, and the type of variable is a Point. 



Public Class mymap

 Private Sub mymap_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Dim Loc As Point
        Select Case e.KeyCode
            Case Keys.Up

            Case Keys.Down

            Case Keys.Left


            Case Keys.Right

  End Select

    End Sub
End Class

You must always start your case with Select. Select Case e.KeyCode just means that we are beginning a Case statement, and that we are checking to see (e.KeyCode) what key was pressed. The keys we want to find are arrow keys Up, Down, Left, and Right. Any other keys pressed will be ignored, as they are not given a Case.
However, if we were to run the program, nothing will happen should we press a directional key. This is because the individual cases do not have any executable code as of yet. It's time to change that and make something happen should one of the keys be pressed.

If Statements
An If statement is much like a Case. The concept is, "IF this happens, do this." Have a look at the following, and what I've added to our code.



Public Class mymap

 Private Sub mymap_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Dim Loc As Point
        Select Case e.KeyCode
            Case Keys.Up
If Not myplayer.Location.Y - 5 < 0 Then
                    Loc = New Point(myplayer.Location.X, myplayer.Location.Y - 5)
                    myplayer.Location = Loc
                End If

            Case Keys.Down

            Case Keys.Left

            Case Keys.Right

  End Select

    End Sub
End Class



Breaking this down, in "If Not myplayer.Location.Y - 5 < 0 Then" what we have is, "If myplayer's Location, minus five, is not less than mymap's minimum height value, run the following code."
We don't want our player to go off the map, so we need to first be sure that if they move up by 5, they are still within the parameters of the map. Should that be the case, we will next move the character (myplayer) in a set direction. We start with Loc = New Point, meaning we are changing the Location of myplayer's coordinates to a new coordinate. We then define that new coordinate with (myplayer.Location.X, myplayer.Location.Y - 5). The parenthesis () will always hold the information that the variable (currently Loc) is being assigned. As you can see, myplayer.Location.X is not changed. It's merely reassigned as itself, with no new math. But, with myplayer.Location.Y - 5, we are taking away the value of 5, thus moving myplayer by 5 on the Y axis. myplayer.Location = Loc is just stating that we are officially setting the Location of myplayer to the new coordinates (Loc).


TEST!
Have you gotten it down so far? Try on your own to set the code for the remaining cases (Down, Left, and Right). Save your project and try running it by pressing the green arrow at the top of your screen (shown in the image to the right).




Complete Code: 



Public Class mymap


    Private Sub mymap_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
        Dim Loc As Point
        Select Case e.KeyCode
            Case Keys.Up
                If Not myplayer.Location.Y - 5 < 0 Then
                    Loc = New Point(myplayer.Location.X, myplayer.Location.Y - 5)
                    myplayer.Location = Loc
                End If
            Case Keys.Down
                If Not myplayer.Location.Y + 5 < 0 Then
                    Loc = New Point(myplayer.Location.X, myplayer.Location.Y + 5)
                    myplayer.Location = Loc
                End If
            Case Keys.Left
                If Not myplayer.Location.X - 5 < 0 Then
                    Loc = New Point(myplayer.Location.X - 5, myplayer.Location.Y)
                    myplayer.Location = Loc
                End If
            Case Keys.Right
                If Not myplayer.Location.X + 5 < 0 Then
                    Loc = New Point(myplayer.Location.X + 5, myplayer.Location.Y)
                    myplayer.Location = Loc
                End If
        End Select


    End Sub


End Class

powered by Blogger | WordPress by Newwpthemes | Converted by BloggerTheme