Game Objects - My Design

I thought I would share one of the core concepts I implemented in Perenthia that has been working quite well. Early on in development I decided to create templates and instances in regards to game objects. A template would define common, unchangable properties of an object whereas an instance would be the opposite. An example would be a Sword; there is a template for a Sword that defines its damage value, price, required skill level, etc. 

I have one table that stores all the objects for the game. Since objects being actively used are loaded into memory and the table is indexed for those queries it runs pretty fast. Since I store all of the objects into one table I make heavy use of the XML data type in SQL 2005 to provide a bunch of XML Serialized Key/Value pairs that define the properties of an object. On the code side of things a dictionary provides the underlying data store for properties of the object. For instance, the Sword example above has a Power property that is used in combination with the wielder's skill in swords to determine damage. The Power property just fetches the Power value from the properties dictionary using the property name. This works a lot like the dependency properties, just my collection serializes to XML for database storage. When an object is loaded from the database the xml from the template is retrieved and added to the object, then the object instance xml is dropped into the object, overriding any template properties of the same name.

This property dictionary also allows me to store whether or not the property belongs to a template or instance. If the property belongs to a template then when the instance is serialized and saved to the database those template properties are excluded. Likewise saving a template does not serialize and save the instance properties. This structure allows for a lot of flexibility with my objects and has been working out quite well. I probably would not have used serialization and xml the way I am if I was doing a typical call to the database qith each request as the extra overhead would not have been worth the effort. However, since my objects are loaded into memory and my saves are background threaded I experience a lot of benefit of an easy to use object.

I shuld note that players character data is stored in a separate table from the core objects table. It follows the same design buy allows me to migrate and change data in the objects table without overwriting player data, since players are essentially the same as mobiles. 

5/15/2009


LINQ Queries

I have spent the last three days writing LINQ qeueries over object collections and have to come to rely on LINQ pretty heavily for most query operations. I have played around some with LINQ to SQL and LINQ to Entities but I mostly use it to just query over some good old fashion collections like so:

 

var groups = proposal.Lines.Where(kvp => kvp.Key.Equals(key.Quarter))
                                           .Select(kvp => kvp.Value.Where(l => l.AvailType.Spot == "N" && l.AvailType.Type == "RE"))
                                           .FirstOrDefault()
                                           .GroupBy(l => new { l.NetworkId, l.UnitLength, l.BrandId });

            List<TimePeriod> weeks = proposal.GetWeeksFromOrderFlightDates(key.Quarter);
            foreach (var group in groups)
            {
                BudgetRow row = AddBudgetRow(budgetDefinition,
                    new List<string>(new string[] { group.Key.NetworkId.ToString(), group.Key.UnitLength.ToString(), group.Key.BrandId.ToString() }),
                    budgetRows, BudgetDefinitionType.WeeklyNetworkAvailTypeImps);

                foreach (var week in weeks)
                {
                    var units = group.SelectMany(l => l.Units.Where(u => week.contains(u.AirDate)));

                    row.setRawValue(week, units.Sum(u => (decimal?)u.Demo1Imps));

                    row.setLockedValue(week, units.Where(u => u.IsLockedOutOfUnitAllocation).Sum(u => (decimal?)u.Demo1Imps));
                }
            }

5/7/2009