Monday, October 04, 2010

October and November

So October, much like September, is going to be very busy for me and Tanya. Game development is on hold until November. I'm going to be busy every single week leading up to the move down to MD which I am scheduling for the weekend of Oct 22nd.On the plus side though October is Metal Month. Which means tons of metal, and as much Castlevania SotN as I can cram in. Fuck Yeah.

November is going to be fucking AWESOME.

  • Nov is "Man Month: No Shave November". Start growing your beards gents.
  • Nov 2 WoT Book 13 comes out, I'm pumped as hell for this.
  • Nov 6 is Learn to Homebrew Day. Me and Andrew Tasso are setting up a pair of burners and doing two batches that day. I'm doing a Spiced Ale for the holidays and Andrew is doing a Nut Brown. Good times are to be had.
  • Nov 23rd Colonel Roosevelt by Edmund Morris comes out.
  • and finally Nov 29th I turn 26. (I'm closer to 30 than 20 these days, that's for sure.)

Wednesday, July 28, 2010

StarCraft 2 Release: The Beer

SC2 was finally released which means I can officially start enjoying my special batch of homebrew with my friends.

The beer is a blonde ale (enkel) and it came out fairly well. It is light and crisp up front with a bit of a banana-like fruity esters type of taste on the back end. Its got decent mouthfeel since it carbonated ok. I have no meaningfull sense of smell so I wont comment on aroma. The color is something around goldish or straw, very nice to look at.

Can't wait to share it with my =)v(= 

Tuesday, July 13, 2010

So beer happened

"StarCraft2 Release: The Beer" has been conditioning for a bit over two weeks now. It's a little flat, but another 2 weeks should help. My initial taste showed that it was refreshing with a taste of bananas. Great golden color. I think when we officially crack the batch open ~the 27th it will be very tasty.

Now if I could just get

  1. Labels
  2. Some indication of who wants some
  3. Are we having some sort of sc2 launch party at anyones place?

Abilities (Extending the XNA Content Pipeline)

Over the past few weeks I have been learning how to extend the XNA Content Pipeline.

XNA has a central component to handle importing content like fonts, 3d models, images, audio etc. This is called the Content Pipeline. When we want to define a new type of content, for example a map file or an ability file we need to extend the pipeline.

Before I go into the explanation of how to do this, let me explain some of the pros and cons that I have found. This is probably not definitive, and definitely subjective. One of the reasons I would rather bring in an ability through the pipeline rather than any other way is that content gets processed at compile time rather than during runtime. When the game is compiled the original file gets processed into a proprietary file that is more difficult to hack/edit. This helps stop people from editing an ability file to make it do more damage, or edit a character class to give it abilities it shouldn't have. One of my favorite pros is that you can add all your content files right into the content folder in Visual Studio and organize them in folders. This makes it easier to maintain things for me. The main con is that it can sometimes be a lot of work to learn how to extend the pipeline and you need to extend it every time you add a new content type. Furthermore you need to edit a few files if you decide to make changes to what is held in a file (like if you decide that now an ability file also needs to hold another bit of info you didn't think of before.)

So what does it take to extend the pipeline? Lets walk through the files I made for holding and processing ability information.

XML Example - WolfsHowl.abil
<Ability>
  <Name>Wolf's Howl</Name>
  <Description>
    Frightens Nearby Enemies.
  </Description>
  <Type>Attack</Type>
  <Cost MP="5" HP="0" />
  <Effects>
    <Effect Attribute="Def" Modifier="-2" />
  </Effects>
</Ability>

Here is the sample ability "Wolf's Howl". As you can see it holds information like the name, description, cost, and effects of the ability. In the future I want to expand this to hold the "shape" and range of an ability and other things, but this is a sample.

This xml file is saved as an ".abil" file. Therefore in my trpgProcessors project I need to define an importer that tells the project how .abil files should be handled.

AbilityImporter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;

// TODO: replace this with the type you want to import.
using TImport = System.Xml.XmlDocument;
using System.Xml;

namespace trpgProcessors.Ability
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to import a file from disk into the specified type, TImport.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    /// </summary>
    [ContentImporter(".abil", DisplayName = "Ability Importer", DefaultProcessor = "AbilityProcessor")]
    public class AbilityImporter : ContentImporter<TImport>
    {
        public override TImport Import(string filename, ContentImporterContext context)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filename);
            return xmlDoc;
        }
    }
}

This file just tells the content pipeline that .abil files are xml docs that get processed by "AbilityProcessor", shown below

AbilityProcessor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

// TODO: replace these with the processor input and output types.
using TInput = System.Xml.XmlDocument;
using TOutput = trpgProcessors.Ability.AbilityContent;
using System.Xml;
using trpgData;

namespace trpgProcessors.Ability
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to apply custom processing to content data, converting an object of
    /// type TInput to TOutput. The input and output types may be the same if
    /// the processor wishes to alter data without changing its type.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    ///
    /// TODO: change the ContentProcessor attribute to specify the correct
    /// display name for this processor.
    /// </summary>
    [ContentProcessor(DisplayName = "trpgProcessors.Ability.AbilityProcessor")]
    public class AbilityProcessor : ContentProcessor<TInput, TOutput>
    {
        public override TOutput Process(TInput input, ContentProcessorContext context)
        {
            AbilityContent abilityContent = new AbilityContent();
            List<AbilityEffect> effects = new List<AbilityEffect>();
            AbilityEffect ae;
           
            foreach (XmlNode node in input.DocumentElement.ChildNodes)
            {
                if (node.Name == "Name")
                {
                    abilityContent.Name = node.InnerText;
                }
                if (node.Name == "Description")
                {
                    abilityContent.Description = node.InnerText;
                }
                if (node.Name == "Type")
                {
                    abilityContent.Type = node.InnerText;
                }
                if (node.Name == "Cost")
                {
                    abilityContent.CostMP = Convert.ToInt32(node.Attributes["MP"].Value);
                    abilityContent.CostHP = Convert.ToInt32(node.Attributes["HP"].Value);
                }
                if (node.Name == "Effects")
                {
                    foreach (XmlNode tNode in node.ChildNodes)
                    {
                        if (tNode.Name == "Effect")
                        {
                            ae = new AbilityEffect();
                            ae.Attribute = tNode.Attributes["Attribute"].Value;
                            ae.Modifier = Convert.ToDouble(tNode.Attributes["Modifier"].Value);
                            effects.Add(ae);
                        }
                    }
                    abilityContent.AbilityEffects = effects;
                }
            }
            return abilityContent;
        }
    }
}

This function goes through the xml file examining the nodes and processing the information into an AbilityContent file.

AbilityContent.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using trpgData;

namespace trpgProcessors.Ability
{
    public class AbilityContent
    {
        public string Name;
        public string Description;
        public string Type;
        public int CostMP;
        public int CostHP;
        public List<AbilityEffect> AbilityEffects;
    }
}

This while then gets sent to the AbilityWriter which writes the information out into an xnb file.

AbilityWriter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;

// TODO: replace this with the type you want to write out.
using TWrite = trpgProcessors.Ability.AbilityContent;
using trpgData;

namespace trpgProcessors.Ability
{
    /// <summary>
    /// This class will be instantiated by the XNA Framework Content Pipeline
    /// to write the specified data type into binary .xnb format.
    ///
    /// This should be part of a Content Pipeline Extension Library project.
    /// </summary>
    [ContentTypeWriter]
    public class AbilityWriter : ContentTypeWriter<TWrite>
    {
        protected override void Write(ContentWriter output, TWrite value)
        {
            output.Write(value.Name);
            output.Write(value.Description);
            output.Write(value.Type);
            output.Write(value.CostMP);
            output.Write(value.CostHP);
            output.Write(value.AbilityEffects.Count);

            foreach (AbilityEffect effect in value.AbilityEffects)
            {
                output.Write(effect.Attribute);
                output.Write(effect.Modifier);
            }
        }
        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return typeof(trpgData.AbilityReader).AssemblyQualifiedName;
        }
    }
}

All the above processing happens when the game is compiled.


Now let's switch our attention to what happens at runtime when the game goes to load the actual content that was processed and created at compile time.

Ability.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;

namespace trpgData
{
    public class Ability
    {
        //Info
        public string Name { set; get; }
        public string Description { set; get; }

        //Can be: Attack, Buff, Util
        public string Type { set; get; }

        //Cost
        public int CostMP { set; get; }
        public int CostHP { set; get; }

        //Attack shape


        //Attack effects
        public List<AbilityEffect> AbilityEffects = new List<AbilityEffect>();


        public Ability()
        {
        }
    }

    public class AbilityEffect
    {
        public string Attribute { set; get; }
        public double Modifier { set; get; }

        public AbilityEffect()
        {
        }
    }

    public class AbilityReader : ContentTypeReader<Ability>
    {
        protected override Ability Read(
            ContentReader input, Ability existingInstance)
        {
            Ability m = new Ability();
            m.Name = input.ReadString();
            m.Description = input.ReadString();
            m.Type = input.ReadString();

            m.CostMP = input.ReadInt32();
            m.CostHP = input.ReadInt32();

            int effectCount = input.ReadInt32();

            List<AbilityEffect> effects = new List<AbilityEffect>();
            AbilityEffect ae;

            for (int i = 0; i < effectCount; i++)
            {
                ae = new AbilityEffect();
                ae.Attribute = input.ReadString();
                ae.Modifier = input.ReadDouble();

                effects.Add(ae);
            }
            m.AbilityEffects = effects;

            return m;

        }
    }
}

As you can see this file contains 3 classes. The first class is our ability class. The second is our AbilityEffect class that we use to make lists of effects. The last is the important one, the AbilityReader. This class goes through the xnb file and populates our Ability.


All of this stuff might seem like a lot but when we load the actual abilities into the game the actual code just looks like this:
Ability WolfHowl = Content.Load<Ability>(@"Abilities\\WolfHowl");

Sorry if this post was really code heavy, but code is what has taken up a lot of my time lately making all these files for both maps and abilities. Next I will be doing the same for Unit and CharacterClasses.

My next post will be focused more on design than code, so stay tuned.

Thursday, June 17, 2010

Reading

Sorry for the lack of posts as of late. I've been spending a large amount of spare time reading. Mays book was 'Guns, Germs, and Steel' by Jared Diamond. This month I am reading 'The Rise of Theodore Roosevelt' by Edmund Morris.

On the brewing front:
Almost out of American Wheat. Loved this one, will be brewing it again many times.
Gotta bottle 'Starcraft 2 Release: The Beer' this weekend I hope.

On the coding front:
Got maps to import through the content pipeline but the list of tiles is coming up blank, an odd problem. I'm having trouble figuring out why this is happening. Going to post my code to see if people on the XNA forums can help.

On the personal front:
Spent last weekend looking at towns in MD. Getting excited to go house hunting. Looking forward to the move.
Also, reading about TR has me wanting to keep a journal, so I'm keeping one using Evernote. I doubt it will last, frankly. Lastly, kettlebells and situps have been paying off, I've lost about 10-12 pounds over a very slow amount of time, (i started with pushups and situps in January). My pants and shirts are all fitting better lol. Still got a long way to go on the beer belly though.

I think my hobbies are rather well rounded lately. (reading, brewing, working out, coding: mind and body both very active) Tiring as hell though, feels like I'm always at full speed. Possibly part of why I really like reading about TR.

Wednesday, May 12, 2010

Norse TRPG

As I mentioned in my most recent post, I am working on a game in my spare time. I have been a full time developer for years now, but this is the first time I am truly working on something for myself. The game is an amalgam of some of my favorite things: tactical rpgs and Norse mythology. 

I am currently working on the engine a few weeknights a week. I am also trying to work on the earliest pieces of documentation, including: a concept document, a proposal document, and a technical design doc.

I'll discuss some story concepts in my next post, but until then I'll leave you with some concept art drawn up by my babyboy Bryan Glynn:

This is the concept for the main character, yet to be named.


Wednesday, April 21, 2010

Getting in the Game (what a corny title!)

My first gaming system was the NES. I got my first computer when I was 9. It was my xmas gift, not a family PC. I've always been a geek. Me and Dan started trying to make games using shitty 'make your own game' apps when we were in grammar school. I started learning c++ and html when I was in about 6th grade. I've been coding ever since. I've been gaming and I've been coding. So why haven't I started learning actual game development until now?


Back in November 2009 I was listening to the first episode of 1ups Oddcast and heard a fantastic interview with James Silva. James is an experienced developer from Ska Studios, the team that made The Dishwasher: Dead Samurai. He talked about how he made the game: I MAED A GAM3 W1TH Z0MB1ES 1NIT!!!1 in just a few days using the XNA framework. He talked about how all you need is the free version of Microsoft Visual Studio C# Express, the free XNA framework, and some knowledge of coding (c# in particular would be good.) Well Shit. I've been making webapps in C# at work for a while now, and I've got at least 10 years of coding under my belt (although the first 5 years are bullshit lol). I headed out to B&N and picked up a book about XNA and started learning about how the whole thing works.

Most tutorials are really boring. I learn a ton, but it is never focused towards what I want to make. So sometime around the end of March or so I started working on my own project. It's not pretty, and it's not good, but it's mine. I'll keep working on other tutorials as well, but I'll keep feeding everything I learn into my game, and I'll focus on learning things in such a way that it moves my game forward. I'm working on My game idea for once.

More to come.



American Wheat

This weekend I am bottling my latest batch of beer. I made an American Wheat from Northern Brewer. I'm hoping is comes out well as an excellent treat to enjoy this summer. Anyone available for bottling this weekend? The more the merrier, we can drink (other beers) while we work!


p.s. I also just ordered another kit: Twisted Enkel Blonde

Tuesday, April 06, 2010

Refocusing

So it's pretty obvious I don't post often, and when I take a look back most of the posts are garbage. Time for a re-focus.

Right now out of my hobbies 2 have taken the forefront: Games (in a new way) and Brewing.

I got rid of the posts about whats going on in my life and whatnot because frankly, who cares. I'm not gonna be so much of a narcissist as to think anyone cares about what I'm up to on a day to day basis. This is the same reason I've pretty much dropped off the map on twitter too.

I'm not going to b.s. and say that I will be posting often either, we've seen how that worked out last time. (I've had this blog since 2006 and only had about 26 posts, I just deleted like 20 of those.)

Alright back to the main issue, from now on my posts will generally be about 2 things: 1. brewing 2. games.

You've already seen some of my brew focused posts, I hope to expand on those a bit eventually.

My other major project right now is learning some game development. I've been a developer for years, but only in the application and web-app side of the house. I've started self teaching myself the game-dev side of things since December and have some ideas for a project. I'll get into this in later posts.

That's all for right now.

-Ray

Friday, January 15, 2010

How I Brew [Part 3]

Now that I told you about the equipment I use and the ingredients needed, it's time to learn about the actual brewing process.

I should note that I don't currently know hot to do all-grain brewing, so this will be an explanation of how extract brewing works.

The night before brewing day I take my Wyeast Pack and pop the inner bag that has yeast food in it, then I let the yeast start getting busy over night. Then I go to sleep, dreaming of beer.

Here is the way brewing day goes.

First I take my brewing kettle and put like 3 gallons of water in it. I start heating it up. Meanwhile I crush my specialty grains a bit to make sure the oils are free. I put the grains in a mesh bag and steep them in the water like I am making tea. I do this for about 30 minutes, keeping the water hot but not boiling. Once I am sure that most of the oils and sugars and other goodies have been imparted to the water I remove the bag. I then take the malt extract and add it all to the water. Now I bring the water to a boil. When the water hits a boil I add the first batch of hops. I keep the water at a rolling boil and stir it a bit to keep the malt from sticking to the bottom and burning. I keep an eye on the time, and add the rest of the hops at the time the recipe calls for. Total cooking time is usually an hour.

When the hour hits I fill my sink with ice and cold water. I take the kettle off the heat, keep it sealed tight, and place it in the ice. The goal is to bring the temperature down to a cool temperature the yeast can survive, as quickly as possible. Eventually I am gonna get equipment to to this faster and more efficiently.

While the wort is cooling I take the carboy I am going to use for fermentation and make sure its sanitary. I do this by cleaning it free of dust and gunk and make sure it's super clean, then I fill it with warm water mixed with sanitation solution. I also sanitize the airlock and hydrometer, and anything else that will touch the wort.

Once the wort is cooled I add it to the carboy and I add enough cold filtered water to fill the carboy to about 5 gallons. I take some of the wort and take a reading of its original gravity to check it against what the recipe thinks the O.G. should be. Then I add the yeast, seal it with a bung and an airlock, and put it in a cool, dry, dark place.

All done! Brewing day should take about 2-3 hours including setup and cleanup.

Questions?