Beware of Bad Tutorials

by Mike 8. August 2011 18:37
You know what really bugs me? Copying and pasting code. Why? Because sometimes you, or a friend, get a first hand lesson on how evil it can be... Why just the other day I was asked to take a look at some code for an XNA 2D camera class. Fair enough, I've written one or five in my day, what's the problem? He sends me to the site where I see ugly double-spaced code snippets littering the page. I ask him if he copied and pasted. He said yes so I did the same. I could complain about the formatting of the code, but that's not really a problem here so I won't. What I will complain about, however, is the numerous errors in the code. Missing using statements. Missing variable declarations. Missing or mismatched braces leading to code outside of a method body. Method calls with spelling errors. Seriously, there were a ton of errors in this article which was supposed to be teaching less experienced people how to make a 2D camera. I feel sorry for the beginners trying to sort out the code for themselves... And, the most unholy copy/paste error I've encountered thus far: Replacing a hyphen (-) with a DASH (I don't even know how to make a dash without Word doing it for me) so you get the awesome error message in Visual Studio telling you the "-" is unexpected. WTF do you mean I can't subtract scalar values within an if? How's a less experienced debugger going to figure that out? They look the same in the editor. Why? Why would the author do this to his/her readers? What do you mean that MathHelper.ToRadions isn't a valid function call? Everyone makes mistakes now and then. An error or two in a tutorial is acceptable. 10+ errors over the course of 50 lines of code is not.</rant>

Tags: , ,

Neoforce: Application vs Manager

by Mike 15. July 2011 13:24
Introduction As you may have noticed, many of the other Neoforce tutorials tell you to drop in a Manager while the tutorial(s) on this site tell you to use the Application class. So, what exactly is the difference in the two approaches and how should you decide which approach is best for your needs? This article will attempt to answer those two questions. The Manager The Manager class provides all the functionality you need for loading Neoforce skins, drawing controls, and handling input for the controls. If you need to add UI support to a project/game in later development stages, you'll probably find it's easier to throw a Manager into your code than it is to use the Application class. However, if you want the UI to work nicely with your world rendering code, I still suggest you go take a peek at the Application class to see when and where the call to DrawScene is taking place. Otherwise, you may run into issues where the Manager wipes out the game world when drawing the UI or you'll end up with the game and UI fighting over Z-order. The Application As the name suggests, the Application class is better suited for building applications. It's derived from the Microsoft.Xna.Framework.Game class so that should give a little indication on its intended use. If you're planning to build a tool for your game, or even a PC game with a lot of UI elements, it may be a better idea to start with the Application. It has all the features that the Manager has, because the Application contains a Manager object. The Application class also handles Manager initialization, handles mouse event hook ups for the manager, has a fully functional exit dialog, handles creating and initializing the main application window (if used), handles graphics device resets, and sets up the Manager's input offsets for you. In terms of ease of use, the application already handles all the Manager drawing calls and provides a method called DrawScene that you add your world rendering code to (so the UI and the 'other' render code play nicely together.) How Do I Choose? In terms of which approach to use, it depends on a few factors. Here's my current breakdown of how I choose: Late stage project: It's easier to drop a Manager in where you need it. You'd probably have a hell of a time trying to convert to the Application class in later development. Multi-player game: It's probably easier to use multiple Managers for each player/viewport depending on how far into development you are. That's not to say you couldn't modify the Application to use multiple Managers and Viewports. Single player game: I'd go with the Application class on this one, but either approach works. Your preference really. Application/Editor/Tool: I'd start with the Application class. Either would work, but the Application already handles much of the stuff you'd need to do anyway. What Have We Learned? After set up, both approaches are functionally equivalent. Using the Manager class directly does require more initial work but it is far easier to add this to a project that is already under way. However, depending on your project, you may find yourself duplicating code that's already implemented by the Application class. If you're doing a more complex, form-based application, definitely choose the Application approach if you can. I figure most of you Neoforce users are probably pretty comfortable with the Manager approach already. That's why I've chosen to show the alternate path, and, sometimes it's just easier to copy/paste and strip out what you don't need than it is to constantly write the same code for every project. :P Any other more-experienced NF user out there want to weigh in on this topic? Hit up the comments. :)

Tags: , , ,

Tutorials | Useful "Stuff"

Documented Neoforce Source Code Available!!!

by Mike 19. May 2011 04:49
I have spent the past few weeks documenting the Neoforce Source Code, and, while not 100% complete, I'm about to post what I have until someone like Tom Shane tells me I can't. Follow the link to find the documented source to Neoforce. Download Documented Neoforce Source Code Now! There will be at least one more update to the zip file as I finish up a few undocumented sections that remain. However, once first pass is complete, I'm working on other things. There are improvements that can be made to it, especially if someone wanted to create compiled help for it. Errors in the documentation? Problems with the download? Leave a comment. (File name + Line # + Correction will suffice.) And finally, just so we're clear on this matter: I did NOT create Neoforce. I do NOT take credit for anything other than adding comments and doing a bit of housekeeping. I do NOT claim that all the comments are 100% accurate, nor do I claim to have used the best wording. Fuck it! Enough chit-chat. Grab the source code and let me know how I did. And while you're at it, a few bucks for the two weeks of time I put into figuring out how everything works and documenting what's going on in the Controls project files would be greatly appreciated, especially if it helps you out. :) [Edit: 6/7/11]I did start documenting the remaining undocumented sections of Neoforce today, but, I'm juggling a few projects at the moment. First pass on documentation should be officially complete by 6/24/11. I do plan on doing a second pass on the code and add a few comments in some of the more complicated methods. I'll edit this post when new releases are available.

Tags: , , ,

Projects | Useful "Stuff"

Neoforce Tutorial: Demystifying Layout Files

by Mike 20. April 2011 13:26
Introduction Let me just start off with a question: Why the hell isn't there some kind of UI designer for Neoforce? Can't we at least make some kind of app to parse the InitializeComponent method of a form class or an XAML file and extract and convert supported control types to a Neoforce layout file? At least that way we'd be able to use the designer in VS and run the files through said program to generate layout files. Sounds like a complicated undertaking...But I digress. So you want to figure out those damn layout files, eh? Perhaps you were poking around in the Neoforce Central project code and stumbled upon line 256 in Logic.cs:   Window tmp = (Window)Layout.Load(Manager, "Window");   Wow, that's a hell of a lot better than the few hundred lines of code it took to initialize a window in the Layout.cs file of the same project. Go have a look at it if you want, it's pretty horrendous, and I'm not cluttering up this post with screens of code we don't even care about. So, can all windows be loaded in one line? Well, not exactly. You'll still have to wire up events and initialize some controls, but you won't have to set up the properties for each control in code. The Layout File With the lack of documentation, it seems the best place to start looking for some clues is in the previously referenced "Window" asset. Open up that XML file and you see this:   <Layout Name="Window" Version="0.7"> <Info> <Name>Window</Name> <Description>Sample window layout.</Description> <Author>Tom Shane</Author> <Version>0.7</Version> </Info> <Controls> <Control Name="frmMain" Class="Window"> <Properties> <Property Name="Left" Value="300"/> <Property Name="Top" Value="200"/> <Property Name="MinimumWidth" Value="300"/> </Properties> <Controls> <Control Name="btnOk" Class="Button"> <Properties> <Property Name="Left" Value="100"/> <Property Name="Top" Value="100"/> <Property Name="Text" Value="btn!"/> </Properties> </Control> </Controls> </Control> </Controls> </Layout>   Aw hell, that doesn't look so bad. A simple file for a simple window. And, according to the Layout class, lines 2-7 aren't even supposed to be there. Seems the Info tag is more for Skin files. There isn't a whole wealth of information to be gained by looking at this sample file though, so I think we should go check out the parser and see what's going on there. The Layout Class The Layout class is responsible for parsing these layout files, so checking out the code here should resolve many of the mysteries surrounding the XML Layout files. Let me just clean up this source code and post it here as a reference:   namespace TomShane.Neoforce.Controls { public static class Layout { public static Container Load(Manager manager, string asset) { Container win = null; LayoutXmlDocument doc = new LayoutXmlDocument(); ArchiveManager content = new ArchiveManager(manager.Game.Services); try { content.RootDirectory = manager.LayoutDirectory; #if (!XBOX && !XBOX_FAKE) string file = content.RootDirectory + asset; if (File.Exists(file)) { doc.Load(file); } else #endif { doc = content.Load<LayoutXmlDocument>(asset); } if (doc != null && doc["Layout"]["Controls"] != null && doc["Layout"]["Controls"].HasChildNodes) { XmlNode node = doc["Layout"]["Controls"].GetElementsByTagName("Control").Item(0); string cls = node.Attributes["Class"].Value; Type type = Type.GetType(cls); if (type == null) { cls = "TomShane.Neoforce.Controls." + cls; type = Type.GetType(cls); } win = (Container)LoadControl(manager, node, type, null); } } finally { content.Dispose(); } return win; } private static Control LoadControl(Manager manager, XmlNode node, Type type, Control parent) { Control c = null; Object[] args = new Object[] {manager}; c = (Control)type.InvokeMember(null, BindingFlags.CreateInstance, null, null, args); if (parent != null) c.Parent = parent; c.Name = node.Attributes["Name"].Value; if (node != null && node["Properties"] != null && node["Properties"].HasChildNodes) { LoadProperties(node["Properties"].GetElementsByTagName("Property"), c); } if (node != null && node["Controls"] != null && node["Controls"].HasChildNodes) { foreach (XmlElement e in node["Controls"].GetElementsByTagName("Control")) { string cls = e.Attributes["Class"].Value; Type t = Type.GetType(cls); if (t == null) { cls = "TomShane.Neoforce.Controls." + cls; t = Type.GetType(cls); } LoadControl(manager, e, t, c); } } return c; } private static void LoadProperties(XmlNodeList node, Control c) { foreach (XmlElement e in node) { string name = e.Attributes["Name"].Value; string val = e.Attributes["Value"].Value; PropertyInfo i = c.GetType().GetProperty(name); if (i != null) { { try { i.SetValue(c, Convert.ChangeType(val, i.PropertyType, null), null); } catch { } } } } } } }   The first thing to notice is the fact that Layout.Load does NOT return a Window. This leads me to believe that you can use any Neoforce container control as the root control in a layout file. (Console, GroupBox, GroupPanel, Panel, SideBarPanel, StackPanel, TabControl, Window, and any derivatives) That's cool. Next you'll see that 2nd if statement in Layout.Load. Considering it's looking for ["Layout"]["Controls"].HasChildNodes, we can assume that Layout files require a Layout tag, and a Controls tag with at least one Control tag as a child. Given our previous discovery, we can assume that the 1st Control tag must be a container type. Inside the if statement we just discussed, it shows that a Control tag must have a Class attribute and following the code into Layout.LoadControl, we can see that the Name attribute is also required. Though you can leave the string empty if you'll never need to access the control from code. The Properties tag in a control is optional if you don't need to set properties, or if you plan on setting them in code, however, if the Properties tag is there, it must have at least one Property child tag. Each Property tag is required to have a Name and Value attribute. The Name attribute's value can be any public property that the class defines.  Each Control tag can have a number of children specified in its own local Controls tag. An assumed requirement is that any Control with child controls is, itself, is derived from the Container class. Sample Layout Structure Applying what we have learned, it appears that the most basic Layout file will be structured as follows:   <Layout> <Controls> <!--Root control: MUST be a type derived from Container.--> <Control Name="" Class="ClassDerivedFromContainer"> <!--Optional, but you'll probably want to set a few values here in most cases--> <Properties> <Property Name="AnyPublicPropertyOrField" Value="SomeNumberOrString"/> </Properties> <!--Optional in most cases, but, you do want child controls in the root container right?--> <Controls> <!--You can insert more Control tags here if needed.--> </Controls> </Control> </Controls> </Layout> And there you have it. I'm going to attempt to get a sample project put together by the end of the weekend. But, until then, I hope you found this information useful.

Tags: , , ,

Code | Tutorials

Neoforce Tutorial: Easy Setup.

by Mike 10. April 2011 03:57
Introduction Neoforce is a UI control library compatible with XNA. The project is, unfortunately, no longer being supported but it works with XNA 4.0 and is pretty damn sweet. However, I found (or didn't find) the documentation to be a little non-existant so I'm documenting my initial struggles with Neoforce in the hopes of saving you a headache. A quick Google turns up very few Neoforce tutorials and what does show up in the search results are usually a rewording of the example on CodePlex.  Building the Source Like I said, Neoforce is compatible with XNA 4.0 but you gotta work for it. Compiled binaries are available for XNA 3.1, but that doesn't help us much. You shouldn't have much of an issue compiling it since I have already spent the time debugging my build process. If you're super lazy, scroll down. The 4.0 binaries are available at the end of the article. So, open up the solution and start the build. If you have no errors, consider yourself lucky. I had quite a few to deal with. You need 7 zip installed in order to execute BuildSkins.bat properly. And you have to set up the correct folder structure and copy a few files. Long story short, it should look like this: Neoforce--Bin*--Skins*--Source--Tools*----7zip------7za.exe Starred items need to be created and I could not find "7za.exe" in the 7zip installation directory. Instead, I copied 7z.exe to the Tools/7zip folder and just renamed it to "7za.exe" (which seems to have worked properly.) Run the build again. If it still fails, crack open BuildSkins.bat and make sure the paths are correct. Now What? What I would normally do from here is look up some tutorials and explore the documentation and sample code. Unfortunately, much of those things are missing. So I suggest you start poking around in the Central project's code to get a feel for how things are done with Neoforce. What I noticed was the fact that Central was derived from the Application class. Makes sense. Project Setup Normally, the Neoforce tutorials tell you to add a Manager field to the Game1 class. I feel like "if there's an Application class, why wouldn't I want to use that as the base for my Application?" So it takes a little more work, but it just feels like the right thing to do. Lazy readers, may I suggest you download the Neoforce Project template I have created for you? Check the end of the article. It takes care of all but one of the setup steps. (If you don't know where to stick the template file, it's "My Documents/Visual Studio 2010/Templates/Project Templates/Visual C#") Otherwise: Create a new Windows game project. Delete Game1.cs, GameThumbnail.png, and Game.ico. Add a reference to "TomShane.Neoforce.Controls" in the game project. Add a reference to "TomShane.Neoforce.Importers" in the content project. (Note: You only need this reference if you're building a skin from scratch.) Add the "using TomShane.Neoforce.Controls;" statement as needed. Add a new class to the game project. "GUIApplication.cs" (or something similar) derived from the Application class. (Explained below.) Add the dependent content files to the content project. (Content/Skins/Default.skin at minimum.) Set the .skin file's build action to Content. Here is the code that needed to get Neoforce running: using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using TomShane.Neoforce.Controls; namespace NeoforceProject1 { /// <summary> /// The GUI application class your application will be built upon. /// </summary> public class GUIApplication : Application { #region Constructors /// <summary> /// Creates an application using the Default skin file. /// </summary> public GUIApplication() : base("Default") { Content.RootDirectory = "Content"; Manager.SkinDirectory = "Content/Skins"; Manager.LayoutDirectory = "Content/Layouts"; ExitConfirmation = true; } #endregion #region Initialize /// <summary> /// Initializes the application. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } #endregion #region Load Content /// <summary> /// Loads any additional content. /// </summary> protected override void LoadContent() { // TODO: use this.Content to load your application content here } #endregion #region Unload Content /// <summary> /// Unloads all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } #endregion #region Update /// <summary> /// Allows the application to run logic. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { base.Update(gameTime); } #endregion #region Draw /// <summary> /// This is called when the application should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { // TODO: Add your drawing code here base.Draw(gameTime); } #endregion } } That will get Neoforce initialized and ready to go. Update Program.cs to run the GUIApplication instead of the Game1 class.   static void Main(string[] args) { using (GUIApplication app = new GUIApplication()) { app.Run(); } }   And there you have it. A barebones Neoforce application up and running. Sure, it may take a little bit more work than just slapping a Manager object into the game class, but whatever. If you're lazy, or just like setup to be easy, grab the zip file at the end of this article. It contains the compiled binaries for Windows and a handy dandy project template you can use that does all the above work for you. If you put the assemblies in a folder like "C:\Bin" for example and update the reference paths in the project files, you can have a one click project setup. ;) The next article in the series will discuss adding controls and making Neoforce do something interesting. Hope you enjoyed the article. Feel free to buy me a beer if you think the time I spent on this was worth $3. Download: Neoforce Tutorial Files

Tags: , , , ,

Code | Tutorials | Useful "Stuff"

Visual Studio 2010 Tip #2

by Mike 4. April 2011 18:19
Have you ever needed to reference a section of code in the same file? Has that code been hundreds of lines away, off-screen, far from where you're currently working? Have you put up with the frustration of constantly scrolling back and forth between those two sections of code?Are you sick and tired of the zone-breaking scrolling activities? Well then, I have just the tip for you. I was just putting up with a similar scenario. I was copying and pasting summary comments from class fields to class properties (because I like to have my code all documented). This class had quite a few fields, 40+. And 40+ fields with summary comments adds up to quite a bit of lines. (160 lines actually, but the point is that you still have to scroll back and forth between code sections.) You may ask: "Why don't you just write the properties and fields in the same place?" I think that looks cluttered, so I throw all fields in one region and all properties in the next region. Alright, enough fuckin' around here, just get to the point. You can actually split view the same file! Another not so well documented feature. Again, maybe I'm just slow...but, I've never heard about it before. Similar to the cleverly hidden (and practically undocumented) Vertical Split Views feature I wrote about a while ago. So, how's it done? See the little splitter button just above the file's scroll bar?   Just click and drag it.   When you're done with the split view, just drag the splitter bar all the way back up to the top of the file to return it to normal. Happy coding! Hope someone else also finds this to be a useful tip.

Tags: , , ,

About Me

Contact Email: last name backwards + 84 + at symbol + verizon [dot] net
Messenger: last name backwards + at symbol + retrostorm [dot] com

Month List

Page List

    Money = Motivation

    Feel free to send me some cash if I helped you out in some way and you want to show your apprecation. I could really use some help over here. Thank you comments are okay, but, they don't pay the bills. Every dollar helps and you'd be surprised at how much work I get done when there's money involved.

    Click the button below. :)