A Programmers Reference

Tutorials for the Xbox version of Halo 2.
Post Reply
User avatar
Prey




Connoisseur Snitch! Pyre Articulatist 500

Posts: 1026
Joined: Wed Dec 27, 2006 6:49 am
Location: UK
Contact:

A Programmers Reference

Post by Prey »

Well with having done VB for one year, C# for two, reading a 900 page book on C++ one and a half times, reading a 400 page book on DirectX, writing several crappy games with DirectX, writing one game in GSE for the 360, and making about a million applications and only releasing about a tenth, I think it's time to pass on some of the knowledge that I have gained. Understandably there are people here with a lot more than 3 years experience, so feel free to pull this apart if it is total shit in your eyes ;o>

This isn't a full blown tutorial, but more of something you can look back upon as a reference, it'll only be focusing on some core and some not-so-core subjects but by keeping these things in mind, you've just made your application about a hundred times better :P

Anyway lets get to it shall we?

Getting Started
This is something that isn't going to be explained here. About a million books and online tutorials exist these days, more often then not made by top professionals who know exactly what they're talking about. So you should find most to be very useful indeed, I know I did.

One thing I will note here though is that we will be primarily focusing on Microsofts C#, but many of the topics covered can pertain to VB and C++ also. C# can be downloaded from THIS page on their website. Alternatively you could buy Visual Studio 2005 from HERE on their website. VS comes with VB, C# and C++ as well as a few other pieces of software.

The Vision
This is where it all starts, the idea. A short sentence or small paragraph, it is what will drive you during the course of development on your new program, and is one of the most important parts of the development cycle.

With the realization of this new idea comes a very important choice: either you decide to let it pass by and continue on with your life, or you decide to realize this idea and do everything in your power to do just that.

Now let me quickly list 2 very important don'ts:
  • The program must simplify some sort of process. In the case of Halo2, inserting a longer string into the unicode table means shifting a lot of data, which manually means one hell'uva lot of work. But with a program doing all that work for you the process has just been dramatically simplified. Thus such a program is a good idea.
  • If your idea has already been realized in some sort of other application, you should not continue unless you honestly feel that the job could have been done better. In the case of a calculator, theres no point in making it if the eventual result is not going to be better than the one Windows comes with for free.
So assuming you took choice #2, and your idea is not a don't; it's time to move on to the next stage.

Planning
Time to get out your pen and paper, or open up some sort of word processor, and begin writing the basis of your application. What is it going to do? Look like? Who is it aimed at? How are the internal workings going to be ordered?

Don't ever just jump into it, that is a very foolhardy thing to do, and believe me I know as I've done it quite a few times myself. With planning comes good structure, which means a good, robust application at the end of it all. It also means then when you open the project back up a few months later, you can quickly get back up to speed with the inner workings and quickly progress on whatever update you wish to implement.

Once you've got down a basic plan for your application, the next step is to start teasing out the possible loopholes.

Scenarios
Things that may happen during runtime that you've got to look out for. For example if the application resigned Halo2 maps; you may have one button to open the map and one to resign the open map. But what if the user presses the resign button without first opening a map? You have two choices in this case:
  • Either have a boolean value indicating whether a map has been opened or not. If one has not either do nothing or MessageBox the user telling them what they have done wrong. or just be rude ;o
  • OR the resign button is disabled until a map has been opened, in which case it becomes enabled allowing for the map to be resigned.
Whilst the first option would work, it is also misleading. For someone who has no idea what resign means, you have already managed to confuse with even the most basic of programs. But with only one button enabled on the form, it is obvious to anyone that first a file has to be opened to continue.

With larger applications theres bound to be a lot more scenarios, but remember you only need to take note of the ones that do present loopholes in your application. You should have also started going back to the model you created in the planning stages and noting down the precautions that will have to be taken at certain points in your program, to ensure that any loopholes you've found cannot be exploited.

Moving On
I've covered the basis of planning here, as it's beyond the scope of this 'tutorial' to go any further in-depth, but if you do feel the need to, there are several books on offer pertaining to just those stages and that also delve into applying your plan to an object-oriented environment.

Moving on to the actual creation, here are now a few points to keep in mind when making your application.

UI - User Interface - What you SEE
Think of it in stages, first everything is disabled apart from the button that opens the map. But once a map is opened the treeview comes to life displaying the tags of the map. On selecting one of them the meta editor comes to life with the properties of the selected tag. Simple, although this has left a bug in the application: What if the user selects a tag class? (such as 'weap'), we know that a class is not a tag and thus doesn't contain any defining properties/meta. In this case you would instead disable the meta editor. Note that this is also something you should have considered when thinking out possible scenarios.

Multiple windows are generally a bad idea, and you should definitely avoid having very many at all. Tabcontrols on the other hand are better for when you need to display multiple pieces of information about something, but have limited space to work with. There is one thing I should mention though about tabcontrols; their disabled state.

Image

It looks crap. Please never disable a tabcontrol! A more interesting way of doing things is to actually remove the tabpages on startup, and then add them back in when needed. Note that the following code is C#, but should be easily transferable to both VB and C++. If you can't convert then google a converter; theres a lot of them around on the net these days.

C#

Code: Select all

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            tabControl1.TabPages.Clear();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Open the map here..

            if (tabControl1.TabCount == 0)
            {
                tabControl1.TabPages.AddRange(new TabPage[] { 
                    tabPage1, tabPage2 });
            }
        }
    }
Code assumes TabControl is named tabControl1.

And as you can see if you try it out, a much better effect is achieved.

TextBoxes
Just one small quiff with these, I have no idea why but for some reason the makers of the almighty textbox for VS2005, decided to not add in the Ctrl + A shortcut. Which in my eyes is one of the best shortcuts a textbox could have. Anyway, to implement it modify the PreviewKeyDown event of the textbox as follows:

C#

Code: Select all

        private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.A)
                textBox1.SelectAll();
        }
Code assumes TextBox is named textBox1.

Commenting
Comments are the nice little green lines that explain whats going on where, but sometimes it is possible to over do it quite spectacularly (again, something else i have fallen trap to).

C#

Code: Select all

            //declares 'num' to be an integer that is equal to 0
            int num = 0;
            //increments 'num' by 5
            num += 5;
There is two things wrong with these comments. The first being they rely on the code too heavily. You should never go that in-depth, as you can see the first references the name of the variable and its initial value. Very bad practice. If either changes the comment also has to change otherwise it won't make any sense. This is a pointless bother.

The other problem with these comments is that they are not needed. It seems as if you are trying to teach someone the language here, but in reality they are expected to already know it. What comments should actually be telling you is the why, there should also be a gap after the slashes for clarity, and the comment itself should be written as a proper sentence/paragraph.

C#

Code: Select all

            int num = 0;

            // We increment the number as such to make 
            // things a little more interesting.
            num += 5;
Accessors

C#

Code: Select all

public int num;
Red light.

C#

Code: Select all

private int num;
public int Num { get { return num; } set { num = value; } }
Green light.

Accessors should always be uses because it allows you to separate the details of how the data is stored from how it is used. By using accessor functions, you can later change how the data is stored without having to rewrite any of the other functions in your program that use the data.

Although accessors are a pain to implement (we'll come back to this..), they make your program so much easier to manage and maintain, plus add such a layer of professionalism that'd you'd by silly to not use them =|

I haven't exactly mentioned it yet, but the get and set do actually act as functions. There's no limit to how many instructions they can hold but as a general rule you want to keep it pretty small. As an example we will make an accessor that stores the first four letters of the map, which we know to be 'deah':

C#

Code: Select all

#region Instance Data

private string __head__;

#endregion

#region Accessors

///<summary>
/// Head
///</summary>
public string Head { get { return __head__; } set { if (value.Length <= 4) __head__ = value; } }

#endregion
You see just a tiny instruction to make sure the new string is no bigger than four letters. Much easier to implement here, than in every method that gives 'Head' a value.

Going back to they're a pain to implement (and you can't deny they aren't :twisted: ), I have gone and laboured over, well, an application that will generate them for you 8)

Image

Click HERE to download. We will now quickly go over the screenshot:
The first thing you may notice is the rather nice layout ( Image ).. the 2nd is that two underscores have been added to each side of the private member. This is done with the built in macros in C++, so to not get in the way of any of your own custom names. I think it's a good idea and not to over the top thus its implementation.

Summaries
The next thing you may have noticed is that each accessor has it's own summary. By default the app will insert the name of the accessor, but feel free to change that. Summaries are always useful for explaining properties:

Image

They can also be used to explain methods too:

Image

..and classes and structs..the list goes on and on...

The BinaryReader and BinaryWriter
They're great classes, but there are a few things that may not be so obvious at first:

1.

C#

Code: Select all

            string str = "hello";
            bw.Write(str);
Code assumes BinaryWriter is named bw.

This will not just write the string, but just before the string the length of the string will actually be written as well. To avoid this, do the following instead:

C#

Code: Select all

            string str = "hello";
            bw.Write(str.ToCharArray());
Code assumes BinaryWriter is named bw.

2.

C#

Code: Select all

            char[] chars = br.ReadChars(4);
Code assumes BinaryReader is named br.

The ReadChars method has a tendency to trot off down the stream if at the current position there is not a valid char. This usually results in unexpected, and unwanted results (one of them being the app crashing as the reader tries to continue past the stream). To avoid:

C#

Code: Select all

char[] chars = Encoding.ASCII.GetChars(br.ReadBytes(4));
Code assumes BinaryReader is named br.

I have written 2 classes that expand upon the BinaryReader and BinaryWriter, that fix the above 'errors' and add more functionality, and have dubbed them BitReader and BitWriter. You can download them HERE. Enjoy =)

Classes vs Structs
I'm not going to go into it here, but I will point you to a place that explains it in detail. Again the code is C#, but can be applied to both VB and C++ (the .nf2.0 or higher C++ that is). LINK

Security
With visual studio your application is compiled into the Intermediate language (IL). But the thing is it is very easy to reverse engineer this language to get at the original source code, the applications that do this are known as decompilers. To battle them we have what is known as obfusticators. These powerful applications take the source code and scramble it wherever possible, giving the lowlife that is trying to read your source code a real hard time at it.

Buy Visual Studio and you'll get a pretty good obfusticator as an extra, but for those of us with the express editions the best freeware obfusticator I could find was HERE. Its a 'light' version of the proper one being sold on that website, but I have found it to be actually rather good.

End
If I think up anything else I'll be sure to add it in, or if you feel something's missing feel free to post and I'll look into it.

You might wonder why I felt the need to write such a 'reference'. The answer to that, if I'm being honest, is because that many of the applications posted here on halomods have lacked any 'professionalism' in my eyes, including my own, and so I thought by putting up a reference that examined a few 'essential' points, we could stop with the crap (don't take that personally) and move on to the good :P

Enjoy,
~Prey

Update1 - Link to BitRW.
Last edited by Prey on Wed Nov 07, 2007 12:07 pm, edited 1 time in total.
Halo 2 Prophet - Skin with ease with the simple 3D point and click interface.
Halo 3 Research Thread - Contribute to the research into Halo 3.
Supermodder911




Connoisseur Coroner

Posts: 1262
Joined: Sun Sep 03, 2006 10:43 pm
Location: Michigan

Post by Supermodder911 »

wow prey good job man thanks this will come in handy.
Edit: i think this should be stickied but nobody will ever read it because most programmers already know this and new people to programming barly ever get this far so i i know im gonna read it but later good job prey.
Image
C Wizzle
User avatar
xzodia




Translator Connoisseur Coagulator

Posts: 1981
Joined: Sun May 15, 2005 10:31 am
Location: UK
Contact:

Post by xzodia »

Very Good.
Image
Halo 2 Plugins | Lock-on To Just About Anything | My Sites | Snow Hog
Old Plugins you have, upgrade you must...
Always Maintain a High Quality-To-Crap Ratio.
OwnZ joO




Articulatist 500

Posts: 980
Joined: Thu Nov 10, 2005 4:24 pm

Post by OwnZ joO »

Yes, better than a lot of the tutorials in scripting section. Another reason for accessors and private variables is so that no outside class can directly change the variable.
User avatar
Prey




Connoisseur Snitch! Pyre Articulatist 500

Posts: 1026
Joined: Wed Dec 27, 2006 6:49 am
Location: UK
Contact:

Post by Prey »

Updated with the BitReader and Writer classes, sorry about the delay!
Halo 2 Prophet - Skin with ease with the simple 3D point and click interface.
Halo 3 Research Thread - Contribute to the research into Halo 3.
OwnZ joO




Articulatist 500

Posts: 980
Joined: Thu Nov 10, 2005 4:24 pm

Post by OwnZ joO »

I actually just looked at this the other day to add some tabs to a private nonhalo(don't wanna make people think i'm withholding research) program because I would rather just take your word on what looks best than tinker with tabs a bunch, so thanks for that.

Also, on the note of accessors/properties, you might wanna pick up visual studio 2008(you can make it target 2.0 framework), as it has automatic properties, so you don't have to go through and make all the fields every time.
Post Reply