Jump to content
  • Advertisement

Eck

Member
  • Content Count

    599
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Eck

  1. I'm Chris Eck, and I'm the tools developer at HBS for the Battletech project. I've recently been given permission to write up articles about some of the things I work on which I hope to post on a semi regular basis. Feel free to ask questions about these posts or give me suggestions for future topics. However please note, I am unable to answer any questions about new/unconfirmed features. I've been tackling Unity 2018 upgrade issues as they come my way, and I've been chugging along with my data driven enumeration refactors. I've done four or five now so I'm starting to gain a deeper understanding of the process. I find all references to the hard coded enum and identify where any code decisions are being made. Then I create data fields to drive that logic instead. After I have all those bits defined, I create the table/columns in the database and then populate it. Creating the C# classes and functions that interface with the database is not quite copy/paste grunt work. There needs to be a class with the fields, and functions to select, insert, and update those rows in the database. But the fields for the different enumerations are all different. The work isn't difficult, but it's time consuming and a bit fiddly. When I started writing this final set I told myself, "Self... Writing this code is boring and repetitive... There has to be a better way..." Enter Code Generation I had several completed examples so I the kinks already worked out. I used all the AmmoCategory classes and functions and just copied them into a text file. I then replaced anything that had AmmoCategory specific items with some keys that I could find and replace. I ended up with a template file that looked like this: public class %ClassName% { %FieldList%} #region %TableName% public static List<%ClassName%> SelectAll%PluralTableName%(this MetadataDatabase mdd) { string query = "SELECT %TableAlias%.* FROM %TableName% as %TableAlias%"; List<%ClassName%> %LowerTableName%List = mdd.Query<%ClassName%>(query).ToList(); return %LowerTableName%List; } public static %ClassName% Select%TableName%ByID(this MetadataDatabase mdd, int %LowerTableName%ID) { %ClassName% %LowerTableName%Row = mdd.Query<%ClassName%>( "SELECT * FROM %TableName% WHERE %TableName%ID=@%TableName%ID", new { %TableName%ID = %LowerTableName%ID }) .FirstOrDefault(); return %LowerTableName%Row; } public static %ClassName% Insert%TableName%Value(this MetadataDatabase mdd, %TableName%Value %LowerTableName%) { mdd.Execute("INSERT INTO %TableName%" + " (%InsertFieldList%)" + " values(%InsertValueList%)", new { %InsertAnonymousTypeList% }); %ClassName% %LowerTableName%Row = Select%TableName%ByID(mdd, %LowerTableName%.ID); return %LowerTableName%Row; } public static %ClassName% Update%TableName%Value(this MetadataDatabase mdd, %TableName%Value %LowerTableName%) { mdd.Execute("UPDATE %TableName% SET" + " %UpdateFieldList%" + " WHERE %UpdateWhereFieldList%", new { %InsertAnonymousTypeList% }); %ClassName% %LowerTableName%Row = Select%TableName%ByID(mdd, %LowerTableName%.ID); return %LowerTableName%Row; } public static %ClassName% InsertOrUpdate%TableName%Value(this MetadataDatabase mdd, %TableName%Value %LowerTableName%) { InsertOrUpdateEnumValue(mdd, %LowerTableName%); %ClassName% %LowerTableName%Row = Select%TableName%ByID(mdd, %LowerTableName%.ID); if (%LowerTableName%Row == null) { %LowerTableName%Row = Insert%TableName%Value(mdd, %LowerTableName%); } else { %LowerTableName%Row = Update%TableName%Value(mdd, %LowerTableName%); } return %LowerTableName%Row; } #endregion // %TableName% Then I defined my WeaponCategory table in the database (that's the new one I was working on). The table has the various column names and their data types defined and Sqlite has a PRAGMA command that can pull that information for you. Once I have that data, I can start with my substitution. Here's what the code generating function looks like /// <summary> /// Given a table name, pull that table's info from the database and generate code for /// the DTO, Select, Insert, and Update functions. /// </summary> /// <param name="tableName">The name of the table to generate code for</param> /// <param name="pluralTableName">The pluralized name. I didn't feel like writing code to figure out when to drop the y and ad ies. :P</param> /// <returns>The generated code for the DTO, Select, Insert, and Update functions.</returns> public static string GenerateCode(string tableName, string pluralTableName) { MetadataDatabase mdd = MetadataDatabase.Instance; string lowerTableName = char.ToLower(tableName[0]) + tableName.Substring(1); string className = string.Format("{0}_MDD", tableName); string lowerClassName = string.Format("{0}_MDD", lowerTableName); List<SqliteTableInfo> columnInfoList = mdd.GetTableInfo(tableName); string tableAlias = ""; for (int i = 0; i < tableName.Length; ++i) { char c = tableName[i]; if (char.IsUpper(c)) tableAlias += char.ToLower(c); } // Load up our template file. string generatedCode = File.ReadAllText("SqliteCodeGen\\CodeGenTemplate.txt"); StringBuilder fieldList = new StringBuilder(); StringBuilder insertFieldList = new StringBuilder(); StringBuilder insertValueList = new StringBuilder(); StringBuilder insertAnonymousTypeList = new StringBuilder(); StringBuilder updateFieldList = new StringBuilder(); StringBuilder updateWhereFieldList = new StringBuilder(); // Loop through each of our column names and build the data that we need for (int i = 0; i < columnInfoList.Count; i++) { SqliteTableInfo columnInfo = columnInfoList[i]; fieldList.AppendLine(BuildFieldLine(columnInfo.name, columnInfo.type)); insertFieldList.Append(BuildInsertField(columnInfo)); insertValueList.Append(BuildInsertValue(columnInfo)); insertAnonymousTypeList.Append(BuildInsertAnonymousType(columnInfo, lowerTableName)); if (columnInfo.pk > 0) updateWhereFieldList.Append(BuildUpdateWhereField(columnInfo)); else updateFieldList.Append(BuildUpdateField(columnInfo)); } // Remove the extra ", " from each of these lists. insertFieldList.Remove(insertFieldList.Length - 2, 2); insertValueList.Remove(insertValueList.Length - 2, 2); insertAnonymousTypeList.Remove(insertAnonymousTypeList.Length - 2, 2); updateFieldList.Remove(updateFieldList.Length - 2, 2); // Remove the extra "AND " from this list updateWhereFieldList.Remove(updateWhereFieldList.Length - 4, 4); generatedCode = generatedCode.Replace("%TableName%", tableName); generatedCode = generatedCode.Replace("%PluralTableName%", pluralTableName); generatedCode = generatedCode.Replace("%TableAlias%", tableAlias); generatedCode = generatedCode.Replace("%LowerTableName%", lowerTableName); generatedCode = generatedCode.Replace("%ClassName%", className); generatedCode = generatedCode.Replace("%LowerClassName%", lowerClassName); generatedCode = generatedCode.Replace("%FieldList%", fieldList.ToString()); generatedCode = generatedCode.Replace("%InsertFieldList%", insertFieldList.ToString()); generatedCode = generatedCode.Replace("%InsertValueList%", insertValueList.ToString()); generatedCode = generatedCode.Replace("%InsertAnonymousTypeList%", insertAnonymousTypeList.ToString()); generatedCode = generatedCode.Replace("%UpdateFieldList%", updateFieldList.ToString()); generatedCode = generatedCode.Replace("%UpdateWhereFieldList%", updateWhereFieldList.ToString()); // If you want to write out a file instead of use the copy/paste window, uncomment this line. //File.WriteAllText(string.Format("SqliteCodeGen\\{0}.cs", tableName), generatedCode); return generatedCode; } public static string BuildFieldLine(string fieldName, string fieldTypeText) { string fieldType = "string"; // INTEGER can mean a few different things in SQLITE if (fieldTypeText == "INTEGER") { // We're identifying bools by convention. See if this starts with one of the common bool words. if (IsBool(fieldName)) fieldType = "bool"; else if (fieldName.EndsWith("ID")) fieldType = "long"; else fieldType = "int"; } else if (fieldTypeText == "REAL") fieldType = "float"; else if (fieldTypeText == "TEXT") fieldType = "string"; else Debug.LogError(string.Format("Unsupported Field Type [{0}] - defaulting to string", fieldType)); string fieldLine = string.Format("\tpublic {0} {1} {{ get; private set;}}", fieldType, fieldName); return fieldLine; } private static bool IsBool(string fieldName) { if (IsBoolWord(fieldName, "Can")) return true; if (IsBoolWord(fieldName, "Force")) return true; if (IsBoolWord(fieldName, "Has")) return true; if (IsBoolWord(fieldName, "Is")) return true; if (IsBoolWord(fieldName, "Include")) return true; if (IsBoolWord(fieldName, "Should")) return true; if (IsBoolWord(fieldName, "Use")) return true; if (IsBoolWord(fieldName, "Uses")) return true; return false; } public static bool IsBoolWord(string fieldName, string boolWord) { if (fieldName.StartsWith(boolWord) && fieldName.Length > boolWord.Length && char.IsUpper(fieldName[boolWord.Length])) return true; else return false; } private static string BuildInsertField(SqliteTableInfo columnInfo) { return string.Format("{0}, ", columnInfo.name); } private static string BuildInsertValue(SqliteTableInfo columnInfo) { return string.Format("@{0}, ", columnInfo.name); } private static string BuildInsertAnonymousType(SqliteTableInfo columnInfo, string lowerTableName) { string annonymousType = string.Format("{0}={1}.{0}, ", columnInfo.name, lowerTableName); return annonymousType; } private static string BuildUpdateWhereField(SqliteTableInfo columnInfo) { return string.Format("{0}=@{0} AND ", columnInfo.name); } private static string BuildUpdateField(SqliteTableInfo columnInfo) { return string.Format("{0}=@{0}, ", columnInfo.name); } Since Sqlite only has a few data types INTEGER, REAL, TEXT, BLOB - it doesn't have types for bool. In the database, we use integer based fields for those. On the c# side though, I want to use bools. I identify which fields are bools by naming convention. If it starts with something like "Is" or "Has" and the next letter is capital, then I call it a bool. It may not be perfect, but it's easily fixed if I misidentify a field. Running it against this table CREATE TABLE "WeaponCategory" ( "WeaponCategoryID" INTEGER NOT NULL UNIQUE, "IsBallistic" INTEGER NOT NULL, "IsMissile" INTEGER NOT NULL, "IsEnergy" INTEGER NOT NULL, "IsSupport" INTEGER NOT NULL, "IsMelee" INTEGER NOT NULL, "CanUseInMelee" INTEGER NOT NULL, "IsAffectedByEvasive" INTEGER NOT NULL, "ForceLightHitReact" INTEGER NOT NULL, "DamageReductionMultiplierStat" TEXT NOT NULL, "ToBeHitStat" TEXT NOT NULL, "DesignMaskString" TEXT NOT NULL, "TurretDamageMultiplier" REAL NOT NULL, "VehicleDamageMultiplier" REAL NOT NULL, "MinHorizontalAngle" REAL NOT NULL, "MaxHorizontalAngle" REAL NOT NULL, "MinVerticalAngle" REAL NOT NULL, "MaxVerticalAngle" REAL NOT NULL, "UIColorRef" TEXT NOT NULL, "FallbackUIColor" TEXT, "Icon" TEXT NOT NULL, "HardpointPrefabText" TEXT NOT NULL, "UseHardpointPrefabTextAsSuffix" INTEGER NOT NULL, PRIMARY KEY("WeaponCategoryID") ); yields the following code. #region WeaponCategory public static List<WeaponCategory_MDD> SelectAllWeaponCategories(this MetadataDatabase mdd) { string query = "SELECT wc.* FROM WeaponCategory as wc"; List<WeaponCategory_MDD> weaponCategoryList = mdd.Query<WeaponCategory_MDD>(query).ToList(); return weaponCategoryList; } public static WeaponCategory_MDD SelectWeaponCategoryByID(this MetadataDatabase mdd, int weaponCategoryID) { WeaponCategory_MDD weaponCategoryRow = mdd.Query<WeaponCategory_MDD>( "SELECT * FROM WeaponCategory WHERE WeaponCategoryID=@WeaponCategoryID", new { WeaponCategoryID = weaponCategoryID }) .FirstOrDefault(); return weaponCategoryRow; } public static WeaponCategory_MDD InsertWeaponCategoryValue(this MetadataDatabase mdd, WeaponCategoryValue weaponCategory) { mdd.Execute("INSERT INTO WeaponCategory" + " (WeaponCategoryID, IsBallistic, IsMissile, IsEnergy, IsSupport, IsMelee, CanUseInMelee, IsAffectedByEvasive, ForceLightHitReact, DamageReductionMultiplierStat, ToBeHitStat, DesignMaskString, TurretDamageMultiplier, VehicleDamageMultiplier, MinHorizontalAngle, MaxHorizontalAngle, MinVerticalAngle, MaxVerticalAngle, UIColorRef, FallbackUIColor, Icon, HardpointPrefabText, UseHardpointPrefabTextAsSuffix)" + " values(@WeaponCategoryID, @IsBallistic, @IsMissile, @IsEnergy, @IsSupport, @IsMelee, @CanUseInMelee, @IsAffectedByEvasive, @ForceLightHitReact, @DamageReductionMultiplierStat, @ToBeHitStat, @DesignMaskString, @TurretDamageMultiplier, @VehicleDamageMultiplier, @MinHorizontalAngle, @MaxHorizontalAngle, @MinVerticalAngle, @MaxVerticalAngle, @UIColorRef, @FallbackUIColor, @Icon, @HardpointPrefabText, @UseHardpointPrefabTextAsSuffix)", new { WeaponCategoryID = weaponCategory.WeaponCategoryID, IsBallistic = weaponCategory.IsBallistic, IsMissile = weaponCategory.IsMissile, IsEnergy = weaponCategory.IsEnergy, IsSupport = weaponCategory.IsSupport, IsMelee = weaponCategory.IsMelee, CanUseInMelee = weaponCategory.CanUseInMelee, IsAffectedByEvasive = weaponCategory.IsAffectedByEvasive, ForceLightHitReact = weaponCategory.ForceLightHitReact, DamageReductionMultiplierStat = weaponCategory.DamageReductionMultiplierStat, ToBeHitStat = weaponCategory.ToBeHitStat, DesignMaskString = weaponCategory.DesignMaskString, TurretDamageMultiplier = weaponCategory.TurretDamageMultiplier, VehicleDamageMultiplier = weaponCategory.VehicleDamageMultiplier, MinHorizontalAngle = weaponCategory.MinHorizontalAngle, MaxHorizontalAngle = weaponCategory.MaxHorizontalAngle, MinVerticalAngle = weaponCategory.MinVerticalAngle, MaxVerticalAngle = weaponCategory.MaxVerticalAngle, UIColorRef = weaponCategory.UIColorRef, FallbackUIColor = weaponCategory.FallbackUIColor, Icon = weaponCategory.Icon, HardpointPrefabText = weaponCategory.HardpointPrefabText, UseHardpointPrefabTextAsSuffix = weaponCategory.UseHardpointPrefabTextAsSuffix, }); WeaponCategory_MDD weaponCategoryRow = SelectWeaponCategoryByID(mdd, weaponCategory.ID); return weaponCategoryRow; } public static WeaponCategory_MDD UpdateWeaponCategoryValue(this MetadataDatabase mdd, WeaponCategoryValue weaponCategory) { mdd.Execute("UPDATE WeaponCategory SET" + " IsBallistic=@IsBallistic, IsMissile=@IsMissile, IsEnergy=@IsEnergy, IsSupport=@IsSupport, IsMelee=@IsMelee, CanUseInMelee=@CanUseInMelee, IsAffectedByEvasive=@IsAffectedByEvasive, ForceLightHitReact=@ForceLightHitReact, DamageReductionMultiplierStat=@DamageReductionMultiplierStat, ToBeHitStat=@ToBeHitStat, DesignMaskString=@DesignMaskString, TurretDamageMultiplier=@TurretDamageMultiplier, VehicleDamageMultiplier=@VehicleDamageMultiplier, MinHorizontalAngle=@MinHorizontalAngle, MaxHorizontalAngle=@MaxHorizontalAngle, MinVerticalAngle=@MinVerticalAngle, MaxVerticalAngle=@MaxVerticalAngle, UIColorRef=@UIColorRef, FallbackUIColor=@FallbackUIColor, Icon=@Icon, HardpointPrefabText=@HardpointPrefabText, UseHardpointPrefabTextAsSuffix=@UseHardpointPrefabTextAsSuffix" + " WHERE WeaponCategoryID=@WeaponCategoryID ", new { WeaponCategoryID = weaponCategory.WeaponCategoryID, IsBallistic = weaponCategory.IsBallistic, IsMissile = weaponCategory.IsMissile, IsEnergy = weaponCategory.IsEnergy, IsSupport = weaponCategory.IsSupport, IsMelee = weaponCategory.IsMelee, CanUseInMelee = weaponCategory.CanUseInMelee, IsAffectedByEvasive = weaponCategory.IsAffectedByEvasive, ForceLightHitReact = weaponCategory.ForceLightHitReact, DamageReductionMultiplierStat = weaponCategory.DamageReductionMultiplierStat, ToBeHitStat = weaponCategory.ToBeHitStat, DesignMaskString = weaponCategory.DesignMaskString, TurretDamageMultiplier = weaponCategory.TurretDamageMultiplier, VehicleDamageMultiplier = weaponCategory.VehicleDamageMultiplier, MinHorizontalAngle = weaponCategory.MinHorizontalAngle, MaxHorizontalAngle = weaponCategory.MaxHorizontalAngle, MinVerticalAngle = weaponCategory.MinVerticalAngle, MaxVerticalAngle = weaponCategory.MaxVerticalAngle, UIColorRef = weaponCategory.UIColorRef, FallbackUIColor = weaponCategory.FallbackUIColor, Icon = weaponCategory.Icon, HardpointPrefabText = weaponCategory.HardpointPrefabText, UseHardpointPrefabTextAsSuffix = weaponCategory.UseHardpointPrefabTextAsSuffix, }); WeaponCategory_MDD weaponCategoryRow = SelectWeaponCategoryByID(mdd, weaponCategory.ID); return weaponCategoryRow; } public static WeaponCategory_MDD InsertOrUpdateWeaponCategoryValue(this MetadataDatabase mdd, WeaponCategoryValue weaponCategory) { InsertOrUpdateEnumValue(mdd, weaponCategory); WeaponCategory_MDD weaponCategoryRow = SelectWeaponCategoryByID(mdd, weaponCategory.ID); if (weaponCategoryRow == null) { weaponCategoryRow = InsertWeaponCategoryValue(mdd, weaponCategory); } else { weaponCategoryRow = UpdateWeaponCategoryValue(mdd, weaponCategory); } return weaponCategoryRow; } #endregion // WeaponCategory That's quite a bit of boilerplate code. And not only is generating the code way faster than I could do it by hand, I can count on it being bug free. Or if there is ever a bug in it, I can fix it in my code generation and rerun it against my table entities to fix the same problem everywhere. I had been putting this off for a while. Any time I was making a new table for the database, time pressures were always high. It was faster to do the one-off table by hand than to do the code-gen system (in the immediate short term). Now that I finally have some breathing room I was able to put this system in place. It didn't take very long and it will probably pay for the time investment after I do one more of these enumerations. Personal Project Update - Car Wars A friend of mine invited me to participate in his company's game jam. They all use Unreal so I've been putting my free time into running through Unreal tutorials. I don't want to be a boat anchor on his team. >.< So Car Wars is going to be postponed probably a couple of weeks while I participate in that. Tips From your Uncle Eck Keep an eye out for code generation opportunities. If you're writing the same type of code over and over and Generics aren't quite the right fit, consider writing some code generation. It probably doesn't take as long as you might think and you'll save yourself time in the long run. Links Twitter Post: https://twitter.com/Eck314/status/1162755432592683008
  2. Eck

    Eck's Car Wars Clone

    Steve Jackson's Car Wars was a game I fell in love with back in High School in the late 90's. I bought the deluxe edition and picked up any supplements I found at game stores and used book stores. I was in college by the time I found anyone willing to play Car Wars and it wasn't nearly often enough for me. Twenty-five years later and I only have between five and ten played games to my name. I figure, the only way I'm going to get to play enough Car Wars to really scratch that itch is if I code the game myself. I've been working on a Car Wars port off and on throughout the years. XNA, OpenGL, DirectX, etc. I never was skilled or dedicated enough to see the project through to the end. This time, I'm going with Unity. There are still plenty of skills that I lack: modeling, animation, sound engineering, (mainly content creation skills). But with the Unity Asset Store there are free and paid for assets that I'll be able to use without having to resort to "programmer art". Plus I've only mentioned this project in a couple of places and I already have an offer from a die-hard Car Wars fan to help out with some 3d Modeling and Animation. I guess we'll have to see how far I get this time. I really just want to play some Car Wars. - Eck
  3. It's been a while since my last developer journal. Mainly because I've been doing lots of things besides development. I've been playing lots of video games: Borderlands 2, Battletech, Master of Orion 2, and Blood Bowl 2. I've been doing lots of Blood Bowl and Twilight Imperium stuff including writing after action reports, twitch streams, and podcasts. I've also been completing some home improvement projects, learning German, working out, and just working. In short, I haven't made Car Wars a priority and so it doesn't get any of my time. Even though I've been productive in other "useful" things, my goof-off time hasn't really been a conscious decision and so I feel a little bit down from slacking off. This is something I've talked about in previous journal posts. It's okay to goof off so long as you prompt yourself, "Hey self. Instead of playing Blood Bowl, I could be working on my side project... Am I cool with goofing off and messing around instead of making progress?" If you ask yourself that and the answer is yes, goof off with a clear conscious. Otherwise you'll binge several hours of a video game and before you know it, that's one more day without any progress. Anyway, I actually HAVE made some progress. It's just not as much as I'd like. Most of this was working when I posted the last Car Wars journal. I worked out a few design decisions and fixed a few bugs. I also spent quite a bit of time cleaning up my object pooler, commenting the heck out of it and making the code asset worthy. I still need to do a few things like record a demo video, and create some store page assets for it before I can publish it on the Unity asset store, so expect that in a week or two. Here's a video for what I have so far: I have no skills in modelling, animating, or basically anything creative. So I franken-bashed a bunch of free assets together including different animations, a model, and making my own animation controller. I think it looks pretty cool for the prototype stage. I create the move order ghosts by instantiating a copy of the pedestrian through my object pooler, and make them translucent by turning the alpha of the materials down. To get the highlight effect, I just change the material color to yellow. // A couple of cached references to the renderers protected MeshRenderer tokenMeshRenderer = null; public MeshRenderer TokenMeshRenderer { get { if (tokenMeshRenderer == null) tokenMeshRenderer = GetComponentInChildren<MeshRenderer>(); return tokenMeshRenderer; } } protected SkinnedMeshRenderer modelMeshRenderer = null; public SkinnedMeshRenderer ModelMeshRenderer { get { if (modelMeshRenderer == null) modelMeshRenderer = GetComponentInChildren<SkinnedMeshRenderer>(); return modelMeshRenderer; } } private void SetTransparency(float transparency) { Color color = TokenMeshRenderer.material.color; color.a = transparency; TokenMeshRenderer.material.color = color; color = ModelMeshRenderer.material.color; color.a = transparency; ModelMeshRenderer.material.color = color; } public void SetColor(Color newColor) { Color color = TokenMeshRenderer.material.color; newColor.a = color.a; TokenMeshRenderer.material.color = newColor; color = ModelMeshRenderer.material.color; ModelMeshRenderer.material.color = newColor; } So now I have the very basics of turn-based mechanics worked out. I was lost in the weeds for a few days as I thought about all the different possibilities of how to tackle this problem. Do I let everyone plan everything and then execute in the correct sequence? What about collisions? How about allowing units to plan future phases out? What about keeping information from the other player hidden. How about when two cars are moving really fast and they're nearby each other? Should I present a timeline and allow the user to scrub through it for their planned movement and their opponent's approximated movement? ... and so on. Eventually I came to the conclusion that I need to just pick a direction and go. So I decided on something a bit simpler for now. Units will move in initiative order, and complete their movement for the phase before the next unit is allowed to go. This keeps the problem space much simpler and lets me work the kinks out of a turn-based mechanics system. As I code this simpler version, I'll try to make design decisions that consider some of the other problems I identified. Hopefully, that will make future refactors and features easier. Tips from your Uncle Eck If you don't make your game dev project a priority, then you won't make any progress on it. When you get overwhelmed by a complex design, take a step back and try to focus on a subset of the problem. Then expand on that as more of the problem gets solved. A decent solution now is far better than a perfect solution that never happens. Charity Fund Raising I'm helping raise money through Extra Life which is a charity that helps sick kids. Give a little something if you can. And share the links below if you have time. Thanks! My Extra Life page - https://www.extra-life.org/index.cfm?fuseaction=donorDrive.participant&participantID=367649 Twitter Post for sharing Facebook Post for sharing Notice/Disclaimer Car Wars is a registered trademark of Steve Jackson Games, and the Car Wars logo is copyrighted by Steve Jackson Games. All rights are reserved by SJ Games. This logo is used here in accordance with the SJ Games online policy. Computer Games based on SJ properties are prohibited so I'll never be able to release this project to the public (not even for free). It's just a fun personal project for myself and the most I'll be able to share is my experiences while working on it. In my pipe dream I'll get this into a cool enough state that SJ Games contacts me to publish the game. But what's more likely is a cease and desist letter. We'll just have to see how things go. Here's hoping. If you're interested in legit Car Wars products, I recommend Warehouse 23: http://www.warehouse23.com/products/car-wars-deluxe-edition
  4. Again we had a 6-player game planned but our 6th player canceled a few days before Game Day. One of these days we'll get a 6-player game going, but today was not the day. We did random races for everyone but the newest player who we gave Federation of Sol. These were the races: From left to right Alexander - Universities of Jol'Nar (purple) Mike - Naalu Collective (yellow) - can't see him but he's the guy sitting behind Alex Dom - Federation of Sol (blue) Devin - Nekro Virus (black) Eck (and his beard) - Embers of Muaat (red) We used the TI4 balanced map generator here: https://ti4-map-generator.derekpeterson.ca/ using the 5 player "notch" style. Here's what it rolled up: Mentak (#2 on the map) changed out to be Nekro Virus the night before. I showed it to everyone and they thought it was fine. I felt like I had a pretty sweet setup with that 5 resource system right next door, but it was my ONLY system and since I was Embers of Muaat, I didn't mind taking it. The person I was worried about the most was Naalu (#9 on the map), but I was under the impression he was a veteran player. With him running Naalu, I didn't mind a tougher start for him. He wanted to offer Alex and me a trade good for our notched starting position. I turned it down. The Embers of Muaat are a proud people and do not need your charity! Jol'nar happily took the trade good. Later on I found out Mike was a newer player so felt kinda bad for his start. I set everything up the night before so we'd be ready to hit the ground running, first thing. TI 4 is such a grand game. Round 0 Round 1 Normally round 1 is only marginally interesting so I'd summarise and skip the picture. But this is what happened. The Nekro virus chose Warfare and expanded to two systems adjacent to Mecatol to secure a point. Embers of Muaat became neighbors to Jol'Nar to trade. And Federation of Sol researched Gravity drive and took one of the only good systems in range of Naalu. Dom (Federation of Sol) was kind of new and I explained how aggressive a move that was, but he and Mike (Naalu) said them fighting was a common theme in their games. I made sure to reiterate that the goal is victory points. I actually started out with Contstruction, so I could have a decent star dock a bit closer to the action. Round 2 I took Construction for the second time in a row to solidify the borders everyone was politely agreeing on. I also traded my War Sun promissory note to Jol'Nar in exchange for his research agreement and Hyper Metabolism to help with my Command Counter addiction. Since I had been trading so much money with Jol'Nar and he was able to expand so quickly to his planets he was able to put start a substantial and mobile fleet. Federation of Sol Consolidated his holdings on the Naalu border and pushed towards Mecatol Rex. At this point Naalu was feeling the pressure and realized how resource starved he was. Also, Naalu and Jol'Nar kept taking Leadership and Technology so Nekro was a little token starved and so was I. Round 3 You'll notice a lot of black plastic disappeared in this shot. Nekro took Mecatol Rex this round. I had given him my Cease Fire earlier for something and I wanted it back. After upgrading my 4 PDS adjacent to Mecatol I activated the system and asked for my Cease Fire back. He declined and the fight did not go his way. This did two things. It left the airspace of that 4 PDS system open and so Jol'Nar was able to fly through that and claim another tech specialty planet from Nekro and blow up the recently built space dock. That double whammy really started the downfall of the Nekro for the rest of the game. People didn't feel too bad at this point since Nekro was at 4 points and the rest of us were at 0-2. I was so engrossed in my side of the board I only vaguely remember some of the Naalu/Sol agression that went on. I remember there was some betrayal and Naalu was reeling from the fights. He had a couple of fleets but couldn't strike into Sol territory without being very exposed. At that point he pleaded for the benevolent Embers of Muat for aid. In exchange, he would give me one trade good every time he got refreshed. So I gave him the blueprints for my Peace Spheres (War Sun is an extremist propaganda term used by the space media). I even helped fund his first one later on. He roleplayed up the whole vassal thing a few times during the game which was cool. During the Agenda phase I also pushed the vote to give Naalu the Prophecy of Ixth giving him +1 to his fighter rolls. A few people even put riders on it, and Nekro picked up Spec Ops 2 so everyone was somewhat appeased (and I was sitting on Mecatol with a decent fleet). Muahaha or... Muu a a a aat! Round 4 This was another tense round. Look at that purple fleet! He looked me square in the eye and said, "It's not for you." And I had a choice to make. I had a decent shot at taking that fleet out right then, but I'd probably have to give up Mecatol to do it. I pride myself on not being the first to backstab so I rolled the dice and trusted him. At this point I think I picked up Cruiser two and solidified my Mecatol position. If anyone came at me, it was going to hurt. Naalu was able to finally bloody Federations of Sol's nose and was back in the game. Everyone started scoring victory points on tech/planet objectives now. Round 5 At the start of the round I decided to make my move and I chose Imperial. I knew I wouldn't be able to hold everything, but the game was going to be a glorious fireball of awesomeness. Everyone was already deciding who was going to try and engage me, and then the Federation of Sol player played his Imperial Arbiter title to take Imperial away from me. And just like that, the table went back to a tense-mostly peace. Naalu started moving in on Jol'Nar's territory but didn't attack anything yet. Still there was some implied pressure from his crystal fighter II's with a +1. Definitely not insignificant. With Mecatol rex, a few influence planets, and Hyper Metabolism I was gaining 7 command counters a round. I kept pumping more and more into fleet. At this point I think I was at 7 or 8. The stage 2 that got flipped last round was own 6 planets with the same trait. A nigh impossible task... But with nearly all my Cruiser II's on the board that meant I could strike out anywhere I needed to. I stalled until everyone had passed to make my move. I even gave away my support for the throne for my Naalu (my loyal vassal) to retreat away from the hex he was originally retreating to. Then I flew out from mecatol rex and snagged up the last two planets I needed. Round 6 Jol'Nar kept his word. The fleet was actually for destroying Nekro's flagship for a secret objective. Naalu struck at Jol'Nar, Jol'Nar fought back. At one point Jol'Nar had a decent fleet go after Naalu's Homeworld but the stacks of fighters there held off the space nerds and their -1 combat rolls. Federation of Sol destroyed my sacrificial cruisers to get back his planets I snagged at the end of last round and he was prepared to assault Mecatol next round. At the end of this round, everyone but Nekro was at 8 or 9 Victory Points and it was going to come down to initiative order. Next round. Round 7 Jol'Nar had the Naalu Promissory Note so he was going to go first. Nekro was speaker so he got to choose the first card. If he chose imperial, that effectively meant Jol'Nar won. If he chose something else, that meant I'd choose imperial. Devin is a great guy and he didn't want to king-make either way. Jol'nar gave him a way out and said don't worry about it, he had it under control. I looked through my action cards cause I knew what was coming. I didn't have a sabotage... I chose Imperial so I could score this round. He played Public Disgrace which means I have to put it back and pick a different card... I asked if anyone wanted to play a Sabotage? Naalu... my glorious vassal locks eyes with me. I tell him, I'll give him my support for the throne so he can be tied for second place... He plays a Sabotage and the table goes wild. I tell Alex he can have the victory but he laughs and says nah. Then he hands me the Gift of Prescience so no one else can steal the victory out from under me. This was one of those rare (extremely rare) instances where being honorable and kind actually clinched the victory instead of throwing the victory away. TI 4 can be an amazing story generator. In the early years we were all emerging from our home systems while the Nekro Virus empire threatened the galaxy. We united against that galactic crisis (Sorry Devin!) and entered an intense cold war period where everyone was building massive fleets including several war suns. After several minor conflicts, it came down to the two super powers on the board racing for the custodian's approval. In the end, Jol'Nar, Naalu, and Muaat chose to work together and ushered in a new age of peace. I picture Sol reluctantly agreeing to abide by the council's decision, but claiming as much territory as they can in the upcoming peace accords. Good game everyone! Previous Game: https://www.gamedev.net/blogs/entry/2265456-twilight-imperium-4th-edition-game-2/ Next Game: Stay tuned!
  5. Yeah, sometimes this is just a public journal/diary of sorts. It's still mostly development related but every once in a while, it's just something cool that's happening in my life. Stay tuned for more programming either this week or next week. Borderlands 2 has its hooks into me pretty good. it was $5 for EVERYTHING so my wife and friends picked it up and we've just been goofing off with it.
  6. It takes a special group of nerds, but when you get a good group going it's an absolute blast. It has a very grand space opera feel to it. If you haven't ever played Master of Orion 2, I highly recommend it. It's an old-school title but it's still my favorite in the 4X genre followed by Stellaris.
  7. Setup Game 2 was supposed to be a 6-player game, choose whatever race you wanted, balanced map. That dropped to a 5-player game when one of the players couldn't make it. Then a 5th player bailed last minute and his phone didn't send the message. It's worth noting that he felt terrible about this and apologized multiple times. So instead of having the map setup and ready to rock and roll right at game time. We started 30 minutes late and had to build the map the old fashioned way. I think it's a testament to the streamlined improvements that we were still able to finish in a reasonable 8.5 hours (including pizza phase). Here's what happened... Race selection method - choose whatever you want. Speaker - roll randomly and Sardakk N'orr got it. Devin - Mentak (green) - Playing Mentak again. Damn pirates Dalton - Federation of Sol (blue) - New player - came super prepared and even had notes for early strategies after listening to Space Cats and Peace Turtles. Javi - Letnev (purple) - New player Eck - Sardakk N'orr (black/me) - I won the last game, so for this game I was going to go for more role-playish fun. I planned to go combat focused and support others who did the same. The 5th player - no show was supposed to play Embers of Muat. I was hoping to trade the War Sun tech with him, and I'd have payed silly prices to make that happen. Ah well... Some other time! Instead we randomly built the map, and I didn't take a clean pic of it because I was focused on analyzing the new board. Sorry about that! One thing to keep in mind for a 4-player game is every strategy card gets picked so every secondary action is possible on your turn. This is super useful for counting on secondaries as part of your grand plans. I only mention this cause I took too long to write up this after action report, so I don't recall all my strategy card picks. Round 1 - I told the table my idea of me wanting to take the game a little less seriously. I'd still try to win but my goal was to be a warlike bug race. Everyone else was welcome (and encouraged) to play their best. They were game so the first proclamation I made was - whoever wins the first combat, gets my support for the throne! The table snickered and agreed. Other than that, it was a pretty standard early turn, Sardaak N'orr (black/me) got Warfare and expanded towards Letnev (purple) for some early trading partners. Everyone else expanded a bit. 0 - Mentak (green/Devin) 0 - Federation of Sol (blue/Dalton) 1 - Letnev (purple/Javi) 0 - Sardakk N'orr (black/Eck/me) Round 1 end Round 2 - Federation of Sol (blue) was poised to take Mecatol this turn and chose Imperial. The rest of the table agreed this was a bad idea (once Sol gets on Mecatol, it's hell to kick him off) so Mentak (green) blocked him with a couple of cruisers. Blue took our shared border planet without even talking about it. Though I respected the move as a combat-focused-space-bug, I planned my counter strike for this transgression. 1 - Mentak (green/Devin) 0 - Federation of Sol (blue/Dalton) 2 - Letnev (purple/Javi) 0 - Sardakk N'orr (black/Eck/me) Round 2 end Someone offered me a stick of gum... It made me laugh pretty hard. Round 3 - This was an exciting turn. Lots of combat so the space-bugs were pleased! The Federation (blue) kicked those pesky Mentak (green) pirates off of Mecatol. A bug of my word, I gave him my support for the throne. Letnev (purple) lost two ground forces trying to take a border world I said he could have. Blue had blocked the only access into his undefended world... That is, it was the only way if you were unwilling to risk the Gravity Rift... Sardakk N'orr (black/me) hurled a carrier past the gravity rift successfully to take the Federation's (blue's) richest world. For those that are unfamiliar with the rule, every ship you send out of or through a Gravity Rift gets a +1 to their speed. However on a 1d10 roll of 1-3, the ship is destroyed. It could have been the Federation's undefended homeworld, but Blue was a new player and I didn't want to be THAT mean. 3 - Mentak (green/Devin) 4 - Federation of Sol (blue/Dalton) 2 - Letnev (purple/Javi) 1 - Sardakk N'orr (black/Eck/me) Gravity Rift Snipe Round 3 end Round 4 - I forgot to take a picture cause so much stuff was going on. And it's been too long to remember ALL the details. Sardakk N'orr (black/me) managed to kick the Federation (blue) off of Mecatol through a combination of action cards, bombardment, and a ton of ground forces. I got back, gave up, and got back my Support for the Throne. I think it wound up in Mentak's (green's) hands. This time I think it was for destroying someone's Dreadnaught? Sardakk N'orr (black/me) had a massive fleet on and around Mecatol Rex when the agenda Ixthian Artifact came up. I had lots of influence but definitely not enough to win the vote. I put down 19 against, other people put 24 for. Then I played the action card to get +5 votes. Since I was the speaker, I broke ties... We rolled the die anyway as a what-if and it came up 5. WHEW! Mentak (green) snagged a poorly defended Federation (blue) world and blew up a space dock. And people also started building up their fleets.<score guess> 6 - Mentak (green/Devin) 5 - Federation of Sol (blue/Dalton) 4 - Letnev (purple/Javi) 3 - Sardakk N'orr (black/Eck/me) <pic missing> Round 5 - Lots of fleet massing! Sardakk N'orr (black/me) had nearly ALL their plastic out on the board at one point. More massive battles, Mentak (green) jumped ahead to 8 during the round, but I used the Silence of Space action card to sneak through the overly defended wormhole and snipe his homeworld. Now Mentak(green) was in a weird position. To get his homeworld back he'd have to attack me, which would lose his support for the throne... 8- Mentak (green/Devin) 6 - Federation of Sol (blue/Dalton) 6 - Letnev (purple/Javi) 5 - Sardakk N'orr (black/Eck/me) Round 5 end Round 6 - Sadakk N'orr (black/me) wound up playing Diplomacy on Mentak(green's) home system, meaning he couldn't take it back this round. He still scored a secret objective though which brought him up to 9. People tried desperately to kick Sardakk N'orr (black/me) off of Mecatol, but just couldn't do it. There was too much plastic on the board. 9 - Mentak (green/Devin) 7 - Federation of Sol (blue/Dalton) 6 - Letnev (purple/Javi) 7 - Sardakk N'orr (black/Eck/me) Round 6 end Round 7 - With a point for mecatol, and a 2 point tech objective, Sardaak N'orr(black/me) was able to clinch the victory. Had I been unable to score mid-turn, Mentak (green) would have won without owning his home system by scoring his last secret objective. The picture of the board was pretty much the same, since my first action ended the game. Final score 9 - Mentak (green/Devin) 7 - Federation of Sol (blue/Dalton) 7 - Letnev (purple/Javi) 10 - Sardakk N'orr (black/Eck/me) VICTORY!!! Final thoughts This was a long and crazy ride. I think I wound up giving my support for the throne away about 4 times? I really shouldn't have won this game, but the second half of the game lined up perfectly as far as agendas and objectives were concerned. Other people just couldn't score those big 2 point objectives and I barely managed to eek out a victory. I am now 2 for 2 in my Twilight Imperium 4th games! Wish me luck for the next game. Other Notes Here was our cool 5 player map setup. This took quite a while to balance and even though we didn't actually use it, I thought others might be interested in a balanced Twilight Imperium 5 player map. The red hexes are impassible, and the 2 trade goods were a suggestion online. I'm not sure the trade goods are necessary though. Special thanks to my daughter for helping me tweak the board. Prev Game: https://www.gamedev.net/blogs/entry/2265302-twilight-imperium-4th-edition-game-1/ Next Game: https://www.gamedev.net/blogs/entry/2267551-twilight-imperium-4th-edition-game-3/
  8. Your first question was a bit too vague to help with. But this question is specific enough for some guidance. Here's an algorithm assuming each actor (NPC or player) knows where its position is. // loop through each actor: currentActor (I assume you have a list of these) // for each actor, loop through all the other actors: otherActors // compute the distance and store it in the currentActor That's the basics to get that working. Once you have that working you can worry about optimizations. Like realizing once you've computed the distance from currentActor to otherActor you also know the distance from otherActor to currentActor. That means your outer loop goes from 0...n, but your inner loop can go from currentActor's index to n.
  9. If it isn't following the ball at all, my guess is target may not be set. If you want to also follow in the z direction, add in the z components the same way we did for the x components. The second line of the function where we set desiredPosition.x = desiredPosition.x + target.position.x is where we copy over the x component. Try to figure out what the line is for the z component on your own. If you can't figure that out on your own, you may want to take a step back from game development and focus your learning back on just programming. This isn't a slam on your abilities. We were all new at one point. - Eck
  10. Eck

    Quadplay Console Released for Free & Open Sourced

    Very impressive. I love the idea of virtual console hardware apis. The one that sticks out in my mind the most is Exapunk's RedShift console. I wound up coding a simple side scrolling shooter in it. Another cool feature of their game was that it imbeded the code for the game in an image of the cartridge.
  11. You say you just want the x? Well, target.position has all 3 components (x, y, and z). So if you just want the x of the target.position, take just the x. private void FixedUpdate() { Vector3 desiredPosition = offset; desiredPosition.x = desiredPosition.x + target.position.x Vctor3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed); transform.position = smoothedPosition; } - Eck
  12. For this short holiday week, there wasn't really much to talk about on the Battletech front. I'm fixing minor/safe bugs and waiting on QA to run my Dynamic enum through the ringer. But on the personal project front, I do have an announcement. I started working on a computerized port of Car Wars during my free time over the last couple of weeks and I'll be sharing my progress as I have interesting things to show. Notice/Disclaimer Car Wars is a registered trademark of Steve Jackson Games, and the Car Wars logo is copyrighted by Steve Jackson Games. All rights are reserved by SJ Games. This logo is used here in accordance with the SJ Games online policy. Computer Games based on SJ properties are prohibited so I'll never be able to release this project to the public (not even for free). It's just a fun personal project for myself and the most I'll be able to share is my experiences while working on it. In my pipe dream I'll get this into a cool enough state that SJ Games contacts me to publish the game. But what's more likely is a cease and desist letter. We'll just have to see how things go. Here's hoping. If you're interested in legit Car Wars products, I recommend Warehouse 23. It's what the Car Wars site links to and it seems a bit cheaper than DriveThru RPG http://www.warehouse23.com/products/car-wars-deluxe-edition Why Car Wars? Steve Jackson's Car Wars was a game I fell in love with back in High School in the late 90's. I bought the deluxe edition and picked up any supplements I found at game stores and used book stores. It can be a little on the fiddly side - each turn is 1 second that is broken down into 5 phases. You move paper tokens around on a map an inch at a time performing maneuvers that affect how in-control your driver is. I love this kind of fiddly complexity but it isn't for everyone. I was in college by the time I found anyone willing to play Car Wars and it wasn't nearly often enough for me. Twenty-five years later and I only have between five and ten played games to my name. I figure, the only way I'm going to get to play enough Car Wars to really scratch that itch is if I code the game myself so I can play vs. the AI. I've been working on a Car Wars port off and on throughout the years. XNA, OpenGL, DirectX, etc. I never was skilled or dedicated enough to see the project through to the end. I'm hoping that's different now. This time, I'm going with Unity. There are still plenty of skills that I lack: modeling, animation, sound engineering, etc, (mainly content creation skills). But with the Unity Asset Store there are free and paid for assets that I'll be able to use without having to resort to "programmer art". Plus I've only mentioned this project in a couple of places and I already have an offer from a die-hard Car Wars fan to help out with some 3d Modeling and Animation. I guess we'll have to see how far I get with this attempt. I really just want to play some Car Wars. Early Goals/Mission Statement In my past attempts, I focused on the math and weird game mechanics for a typical Car Wars game. Getting a car token to move around on the screen, dropping a mine counter, detecting collisions, etc. This time, I want to focus on polish and all the last minute crap you have to do in order to transform your shitty prototype into an actual game. I also want to prioritize finishing a feature before starting a new one. I'm not sure if other developers are like this but here's what happens to me. In professional projects, my coding method works something like this - 1. Think about the problem 2. code something that works (hacky is okay) 3. refactor the hacky code into decent code (hacky rarely okay) 4. test the heck out of it 5. call the feature done and move on. In personal projects, I tend to execute steps 1 and 2, then skip straight to 5 so I can work on something else that's cool and exciting. Eventually my code becomes a mountain of technical debt and doing anything in the project becomes a nightmare. As the code base becomes more and more painful to work in, motivation becomes less and less until eventually I stop working on the project altogether. Not this time! With these things in mind, I started my project with the Main Menu screen. It's not sexy but it's where every game starts and it's a simple problem to solve. It took longer to find the assets than to throw the code together. After I got the quit button working and some free music playing for the main menu, I realized I needed to give credit to the composer and provide a link to their asset. That meant a credits screen. Here's what I have so far. Writing the credits screen, I used it as an excuse to code up a simple object pooler. Each line of text is its own text control that spawns in at the bottom and moves itself to the top of the screen and turns itself off. The object pooler reuses those items. It's overkill for such few items, but it's something I know I'll use in the future when spawning bullets and other high count items. Future Plans What's the first thing that pops into your head when I say Car Wars? A gang of motorcycles swarming a big rig on a desolate stretch of highway? A half dozen vehicles shooting the heck out of each other in an arena battle? Two rival duelists starting a grudge in the middle of town? Well too bad. The first thing I'll be concentrating on is Pedestrians. Why pedestrians? For their basic mechanics, they are relatively simple. This will let me focus on the turn-based game state and let me get that working in a clean way. Once I get the basics down, there are tons of special case rules that I can dive into. Entering parked vehicles, picking up and moving obstacles, jumping onto moving vehicles, etc. Next time I'll be showing some pedestrians planning/exectuing their turn-based movement. Personal Update This weekend the family and I went camping at Green Lakes. The place was beautiful. We went hiking on a few trails, swam in the lake, and even rented kayaks. Of course with camping came grilling out and having smores so it was a good time. Expand the spoiler for some camping pics. Links Twitter Post: https://twitter.com/Eck314/status/1147966512818458625
  13. I'm Chris Eck, and I'm the tools developer at HBS for the Battletech project. I've recently been given permission to write up articles about some of the things I work on which I hope to post on a semi regular basis. Feel free to ask questions about these posts or give me suggestions for future topics. However please note, I am unable to answer any questions about new/unconfirmed features. We shipped Urban Warfare and the launch was relatively smooth. There were only a few critical bugs we needed to patch out and we did so in a timely manner. After that, the team focused on the upgrade to Unity 2018. The day after most of the team was upgraded and many of the kinks were worked out... Unity released a new 2018 version. >.< Still there's lots of cool features and editor performance improvements that I'm looking forward to. Data Driven Enumerations With the team focused on the Unity upgrade process, things were settled down enough for me to finally cram my Enum replacement into the project. It's something I've been wanting to do since last year. I was hoping to get it in during the 1.4 release in December, but some DataManager optimization refactors took priority and caused some stability issues which made testing my code impossible. Why replace enums? Aren't they a good thing? - At first glance, it does seem like enums are great. It's a simple type you can pass around and it gives your code clarity over using an integer or string. Plus it's built into the language so it takes very little effort to implement. In very simple cases, I think they still have their use. But the second you start tying logic to individual values, I think you should strongly consider a data driven approach. I decided to tackle ContractType as my first enum in our code base to replace. It is probably the most complex enum in our game: it touches the Sim Game, the Combat Game, Content Creation, Serialization, and several other systems. If my Dynamic Enum can replace this guy, then it's safe to use it for everything else in our system. Requirements 1. Easy to use in Unity - In Unity enums are drawn as drop down controls and I don't want to lose that. 2. Support int or string as key - I want to be able to use either of these types. Integers if performance is a big deal or strings to keep things human readable. 3. Don't break save games - There needs to be some kind of upgrade path for loading old saves. 4. One place to edit the data - There were at least a dozen places you had to go to add a new Contract Type. I want exactly one place. And I want it in a format that a developer (specifically me) doesn't have to get involved. Getting Unity to draw my data like a drop down was pretty easy. I found an excellent code sample for something similar here: https://gist.github.com/ProGM/9cb9ae1f7c8c2a4bd3873e4df14a6687 So I created my own DynamicEnum attribute and wrote a PropertyDrawer for it. And that knocked out the first two requirements. Here's what the code looks like: To make sure old save games were supported, I created a new constant for ContractType called INVALID_DEFAULT. Any place that stored the old ContractType now got a new ContractTypeID field which defaults to INVALID_DEFAULT_ID. Since this is a new field, old saves wouldn't have it yet. After deserializing these classes, we just check to see if the new field is the INVALID_DEFAULT_ID and if it is, we convert the old Enum value to the integer ID. Any new content created, would serialize correct values while old save games get upgraded to the new way of storing it. I also protected the ID and wrote a property to make sure we were always pulling the correct data. [DynamicEnum(ContractTypeEnumeration.TypeName)] // This is protected so people are forced to use the property. protected int supportedContractTypeID = ContractTypeEnumeration.INVALID_DEFAULT_ID; private ContractType_MDD supportedContractTypeRow = null; public ContractType_MDD SupportedContractTypeRow { get { // If we're loading from an old version, convert the old value to the new value. if (supportedContractTypeID == ContractTypeEnumeration.INVALID_DEFAULT_ID) { supportedContractTypeID = (int)supportedContractType; } // If the cached row is null or out of date, pull the correct one from the database. if (supportedContractTypeRow == null || supportedContractTypeRow.ContractTypeID != supportedContractTypeID) { supportedContractTypeRow = MetadataDatabase.Instance.GetContractTypeByContrctTypeID(supportedContractTypeID); } return supportedContractTypeRow; } } Number four took the longest even if it wasn't the toughest. The concept is simple. Create a class that represents one line item in the original enumeration like ContractType.SimpleBattle. As you identify different code decisions based on individual enumeration values, create fields to store that data. My class cor ContractType wound up looking like this: public class ContractTypeValue : EnumValue { public ContractTypeValue() : base() { } public ContractTypeValue(EnumValue_MDD enumValueRow, ContractType_MDD contractTypeRow) : base (enumValueRow) { Version = (int)contractTypeRow.Version; IsSinglePlayerProcedural = contractTypeRow.IsSinglePlayerProcedural; IsStory = contractTypeRow.IsStory; IsRestoration = contractTypeRow.IsRestoration; CustomMusic = contractTypeRow.CustomMusic; IsMultiplayer = contractTypeRow.IsMultiplayer; UsesFury = contractTypeRow.UsesFury; ContractRewardMultiplier = contractTypeRow.ContractRewardMultiplier; Illustration = contractTypeRow.Illustration; Icon = contractTypeRow.Icon; } public int Version { get; private set; } public bool IsSinglePlayerProcedural { get; private set; } public bool IsStory { get; private set; } public bool IsRestoration { get; private set; } public string CustomMusic { get; private set; } public bool IsMultiplayer { get; private set; } public bool UsesFury { get; private set; } public float ContractRewardMultiplier { get; private set; } public string Illustration { get; private set; } public string Icon { get; private set; } public bool IsStoryOrRestoration { get { return IsStory || IsRestoration; } } } // Old code looks like this bool usesFury = (Combat.EncounterLayerData.SupportedContractType == ContractType.ArenaSkirmish); // New code looks like this bool useFury = Combat.EncounterLayerData.SupportedContractTypeRow.UsesFury; // It's subtle, but makes a big difference. Before we had one hardcoded type that used fury // to change our mind about that we'd have to touch several places in the code where this // fact was coded (UI, game logic, resource loading, etc). If we wanted to add a new contract // type that used fury we'd have to add that with code. With the new system, we just flip // a bit from false to true and now that ContractType uses fury instead. I now have a single json file that contains a list of all the contract types and their associated metadata. Instead of having decisions hard-coded to individual enumeration values, we drive our decisions off the data. This gives us exactly one spot to edit the data and it means designers (and modders too!) can add a new ContractType without getting engineers involved. Before, this was a process that took a while to get right because we would forget ALL the places that ContractType values were being used to drive logic. All in all this refactor touched 88 files and had dozens of different places with hardcoded logic. A big change like this reduces complexity while increasing flexibility which are two big steps in the right direction. Personal Project Update - Car Wars I've wanted a computerized version of Car Wars since high school (which was a few years ago now). Since then, I've started my own version several times but never really made it anywhere of consequence. I have the itch to start it again so I've been working out some decisions on paper and chipping away at things the last few weeks. There's not much to show off yet, but I wanted to announce it as a self-motivational thing. Now that YOU know I'm working on it, I have to KEEP working on it. Otherwise, I'll be letting you down. Tips From your Uncle Eck Be careful with your use of enums, they can be a code smell that something isn't quite right. If you find yourself hardcoding logic to specific enum values, you should definitely consider switching to a data driven system. That way when people change their minds, they can just change the data in a file instead of having to change code and cut a new build. Plus it makes modding your game that much easier. Links Twitter Post: https://twitter.com/Eck314/status/1145358891141738501
  14. Eck

    Eck's Car Wars Clone

    Album for Eck's Car Wars Clone
  15. Eck

    TableTopCarWars.jpg

    From the album: Eck's Car Wars Clone

  16. Eck

    OpenGLCarWars.JPG

    From the album: Eck's Car Wars Clone

  17. Eck

    CarWarsUnity.JPG

    From the album: Eck's Car Wars Clone

  18. And I'm just saying this in case it isn't obvious yet. The resolution of the height map doesn't have to be (and usually isn't) the resolution of the visible terrain textures. - Eck
  19. We've been on Unity 5.6 for a loooong time. Mainly because that's what we shipped on. With a lull in the action it's a good time to upgrade. I know for sure there are development side improvements like editor speed/memory/optimizations. As for what features the players will see - I'm not sure. I haven't been following the upgrade discussions much. I've been laser focused on this coding straight for 8+ hours a day. This will almost definitely break mods that had custom contract types, depending on how they implemented it. However, I think the new system will be simple to upgrade to. Basically they'll just need to put a new row in the StreaminAssets/data/enums/ContractType.json and process that file into the MDDB. If there are any serialization issues with save games, they'll have to code up a similar "upgrade path" as I spoke about above. But all of that is relatively simple so they shouldn't be broken for long. Plus I'm on a few Battletech modding discords and will answer questions if anyone runs into some serious issues.
  20. Eck

    Game creation

    Most games lose money. If you're going into the games industry to get rich, you might want to take a step back and think about it. Also, I really like @Tom Sloper's post about the idea guy. http://www.sloperama.com/advice/idea.htm He has a bunch of other great articles too.
  21. Eck

    Proof of the project

    If you're talking about keeping a developer journal, I think this site (gamedev.net) is a good place to do it. It's were I write my journals: If you're talking about releasing your game in a playable state - normally you just release the executable. Sure other people can decompile your code, but in general it's more trouble than it's worth. Plus there are plenty of better projects to steal from than a beginner's indie pong clone. From an employer's point of view, I want to see that the programmers I'm hiring have a passion for game development. If they don't have a portfolio showing what they're working on in their free time, I'm less interested in them. During the interview process I'll ask about some of these projects and ask the interviewee about different problems they had to solve. At first - just tell me about the project - and then I get more specific getting the person to talk about how they solved some of the tough problems, etc. - Eck
  22. Something similar to this was done back in 1991 by Omnitrend Software with it's "Interlocking Game System". The first game "Rules of Engagement" had you flying around in your starship and doing starship captain-y things. Squad based tactical battles were then auto-calculated if you sent your away team to fight on another ship. However, if you owned Breach 2, instead it would fire up Breach 2 and let you fight out the squad based mission. After the Breach 2 scenario was completed, the results were reported back to Rules of Engagement where you continued playing. It's not quite the same thing, but I thought it was super cool at the time and relevant to the discussion. Right now your question is a bit too general to give any meaningful answer. Basically the companies would agree on an API for what data to communicate and how to communicate it. But the problems to solve would be very different for say two First Person Shooter games. Or one is a first person shooter while the other is an amusement park sim.
  23. Note: This article is based on an entry originally posted in Chris Eck's developer journal (blog) here at GameDev.net, which was itself based on an email conversation with an aspiring game developer named Riley about becoming a tools developer for a video game studio. Summary This turned into a pretty long post so I'll start with a quick summary. When you're learning to be a game developer you have a choice to make every time you sit down at your computer: You take the blue pill - you play some video games, cruise the internet, and wake up the next day no closer to your goal. You take the red pill - you put in some effort, learn some new skills, work hard, and achieve your dream. Another thing to say is there isn't a single "best" formula for how to get into the games industry. All I can say is that this worked for me. Learn Unity Make simple games to learn Write a dev journal (blog) about your experiences/plans Start working on your game / applying in the industry About Riley Riley has been programming for a while and dabbling in game development. After watching some GDC Vault videos, they became more interested in becoming a game developer - specifically a tools programmer. They were polite and appreciative of me taking the time to talk with them. Riley asked me for some good resources to better understand how tools development works and for advice on looking for jobs. They also asked about what kind of work I did on Battletech and other games. Eck's First Email Hello Riley, Let me tell you a little bit about myself first. Originally I was a regular developer working on business applications. I started out with C++ and then moved over to C# and SQL as the technology shifted that way. I dabbled with game development as a hobby since college keeping a few projects spinning but never really did anything major. I started working on my own engine and saving up money so I could quit my job and make a serious attempt at game development. After about a year, I participated in a game jam and saw what amazing things people were doing with Unity and I was just floored. I really should have used something like Unity or Unreal instead of working on my own engine. Then I quit my job and switched to Unity. I started writing a weekly Developer Journal about the things I was working on here: https://www.gamedev.net/blogs/blog/1922-ecks-journal-still-flying/ - This helped me stay motivated with my learning efforts, and also served as a portfolio to show potential employers I had serious passion, and it would also serve as a form of marketing for my game if I remained an indie developer. The indie dev plan was the way I was leaning towards but then I saw Harebrained was hiring for Battletech. My wife made me apply even though I knew I wouldn't get the job. Long story short, I did get the job even though I had 0 professional game dev experience and didn't live in Seattle. So I gave away most of my stuff, packed up my family, moved across the country, and have been working there ever since. A tool developer's job is to make everyone else's job possible, easier, and faster. It's about creating easy to use "tools" like a map editor, or a mech editor. It's about making those tools intuitive, fast, and automating repetitive tasks. It's about identifying the pain points that people are dealing with and eliminating them. The best advice I can give you on how to learn to be a tools developer is to make games on your own and try to drive them with data. You'll quickly become aware of the annoying parts of game development. Figure out how to automate those annoying tasks where possible or reduce it to as few clicks as you can. I also recommend starting a developer journal. It's motivational - especially if you end your posts with what you plan to accomplish next week. It makes you feel like you've committed to something and other people will be disappointed in you if you don't. And then a few years later, it's nice to have a historical record of your time. You said you were interested in seeing what work I did. I started doing the developer journal thing before I got my job so you can see exactly what I was working on leading up to that. Lately, I've been writing up journal entries about the kinds of stuff I've been working on for Battletech. So click the link above and read all about it. Feel free to ask any questions on the game dev site and I'll be happy to answer them. Finding a game development job is super hard. And even when you do find one, there's a decent chance that job could suck. There are plenty of sweatshops out there that just squeeze every hour they can out of employees and then boot them after the game ships. One thing I found out working at HBS is that I'm happy just being a programmer. If this wasn't Battletech, I probably would have gone back to Business Application development to make way more money so I could retire sooner. But HBS is an amazing company to work at and I'm working on an IP that was a HUGE part of my teen/college years so I'm super happy. #LivingTheDream Do your research on the companies, apply lots of places, and prepare yourself mentally for quite a bit of rejection. I hope this helps Riley. Good Luck! - Eck P.S. - Watch Collateral (Jamie Fox, Tom Cruise). It's the movie that really lit a fire under my ass to go follow my dream. Riley's Response Hello Eck, Firstly, thank you so much for responding, it really means a huge amount! Unity is an amazing piece of technology indeed and some of the incredible work I see on twitter is honestly amazing. However I've been rather weary of it for a while, due to mostly varying issues I've heard about it. Though I should just get on with some tutorials and learn things! C# / C++ / SQL is a good set of techs to learn as you allude to later on, business applications are big money! My main language is C# / PHP! How far did you get with the work on your own engine? I've attempted that a few times and it is a rather big challenge especially when you are brand new to it all. I have just noticed in your first blog post you were using XNA / MonoGame, it's my current go to as well (well FNA) but it's a good toolset. It is rather awesome your wife and family were so supportive of your move when you did get the job, thought I can imagine that it was a big move and stepping into an unknown. It's also awesome that you did end up getting the job even with 0 professional game dev experience. That is a massive thing that does end up worrying me when looking to apply "At least 2 games shipped", "At least 5 years in the industry" etc. Though Harebrained sounds like it must rather be an awesome company. I shall have to give that a go, but literally everything you described is what I absolutely adore doing, creating systems and tools, to make peoples lives easier, automate things. In almost all my jobs, I end up building tools of some form to help others out, in one job I build a dashboard to monitor SSL certificates alongside website up time and in another, I built a whole framework to help developers write importers that were fail safe and powerful in the reporting side of things, so literally anyone could find out what went wrong. Any suggestions for sites to use for creating a journal? Would be interesting to see if it does help, cause I struggle massively with motivation and keeping going at projects though having any form of record of things I've done / am doing is a really nice thing to be able to look back on and see how / where you have grown. I shall be giving your blog a read over the next few nights and will definitely drop a few questions into the comment section, will be nice to talk more about how you have done things etc. The industry does seem like a few fast turn over area and yeah, I don't have the energy left in me for a sweatshop kinda company, we've all read the horror stories. I'm really glad to hear that you do love it so much at HBS and you feel so happy there, it's always nice when you do find places like that. Lots of research to be done and oh I've had my fair share of No's (including being ignored by a somewhat indie games company I looked up to, which sucked, but oh well). Thank you again, seriously this is honestly a massive help to me and I appreciate you taking time to read and respond to my emails, also Kiva, thank you also Hope you both have a lovely day! Kind regards Riley P.S. I shall have to go watch it indeed, thank you for the suggestion Eck's Response This email could sound a little cranky/confrontational. Tone is lost in text so please keep that in mind. At worst it should be received as "blunt" which is a quality I've been known to have. I'm just trying to help. Being wary of Unity: Originally I was in the camp of people that thought people using Unity were "cheating" and weren't real developers. You were only a REAL game developer if you wrote your own engine. That's the main reason I worked on my own engine. And quite frankly - that's a stupid camp to be in. Instead of working on low level stuff that's been done a million times by a million developers for nearly 2 years, I could have actually been working on a game and possibly released it. I'm not sure what issues you've heard about Unity but they are definitely able to be dealt with. I mean look at Battletech and Shadowrun. Both of those were made with Unity. If the engine can handle a professional studio's ability to produce games for 7-8 years, then it can definitely handle a one-man indie's dive into game development. Stop using that as an excuse and start going through the tutorials. Then start making games - simple ones. Specifically, make clones of other simple games. For a road map of what games to make and why - give this article a read. I can't recommend it enough: https://www.gamedev.net/articles/programming/general-and-gameplay-programming/your-first-step-to-game-development-starts-here-r2976/ How far did I get with my engine: I worked on it off and on as a side project for quite a while - starting, stopping, scraping, restarting. But then I got serious on it for about 1.5 years. I focused on 2D stuff and had an object hierarchy complete with translation, rotation, and scale. I got some post-processing glow effects, sounds effects, music, input management, particle systems, etc. Basically, I got to the point where I could make a simple game. I entered a week-long game jam where the theme was "The toys are alive". Here's a tech demo of my entry: I was super pleased with what I was able to produce, but that game jam was a wakeup call. I saw all the crazy awesome things other people were doing with Unity and I kicked myself for not learning it sooner. Since C# is your main language, then I strongly recommend jumping into Unity yourself. Worse comes to worst, you further your C# skills a bit more. So if game development doesn't work out, the skills still translate into a well-paid career. Your experience so far: Making tools in business software and making tools in games is pretty much the same thing (and that's how I sold it in my interview). Writing an importer for customer data instead of weapon data has all the same problems. It just sounds less cool to talk about. If you have the skills and can show the passion for game development - at least some companies will take a look at you. Being able to prove that you can walk the walk is what those experience requirements are all about. If you're looking for a good site to start a blog on, I highly recommend GameDev.net. It's an awesome community of game developers of all experiences. From the 0 xp newbie who wants to make an MMO to the elite pros who have written low-level graphic card drivers. There are forums to ask questions, and articles that explain tons of topics. They also have occasional game jams or challenges which is a great way to learn in a group of supportive people. Just recently they did a side-scrolling shooter challenge which was fun. Motivation: Motivation is something many people struggle with. It's so easy to stay in your comfort zone, play video games all day, and keep those dopamine sensors fed. You have to CHOOSE to learn a new skill. And it's extra difficult for programmers because the same device we use to be game developers is the same tool we use for recreation. Every time you sit down to work... WORK. Every time you sit down to play - ask yourself if you've worked enough today (or this week). If the answer is no, then you have a choice to make. You can choose to be responsible and work. Or you can choose to goof off and play a game. Choosing to goof off every once in a while is okay. But if you ONLY choose to goof off, you're never going to reach your goal. That's just how that works. As I have gotten older, I realized that time is THE MOST VALUABLE ASSET you have. You have a finite amount of time in this life. You are going to leave this world one day. Make your peace with that and accomplish what you want before you do. Thanks: You're welcome. Summary: Learn Unity (or a similar engine) Make simple games to learn Write a dev journal (blog) about your experiences/plans Start working on your game About Chris Eck: I was a professional C++/C#/SQL developer for about 15 years, but game development has always been a hobby of mine. After spending a year of working on my own stuff, I landed my dream job at Harebrained Schemes working on BattleTech.
  24. Ahhhh. The NeHe tutorials... so good!
  25. We shipped Urban Warfare last week (the new Battletech DLC) along with the 1.6 free update. Things have calmed down enough that I only worked on some simple bugfixes which isn't really much to write about. But I did have an interesting conversation. Kiva asked me if I could talk to a friend of hers and answer a few questions about becoming a tools developer. This isn't the first time I've been asked this question so I thought I would turn our e-mail chain into an article. Summary This turned into a pretty long post so I'll do a quick summary. When you're learning to be a game developer you have a choice to make every time you sit down at your computer. You take the blue pill - you play some video games, cruise the internet, and wake up the next day no closer to your goal. You take the red pill - put in some effort, learn some new skills, work hard, and achieve your dream. Another thing to say is there isn't a single "best" formula for how to get into the games industry. All I can say is that this worked for me. 1. Learn Unity 2. Make learning games https://www.gamedev.net/articles/programming/general-and-gameplay-programming/your-first-step-to-game-development-starts-here-r2976 3. Write a dev journal about your experiences/plans https://www.gamedev.net/ 4. Start working on your game / applying in the industry About Riley Riley has been programming for a while and dabbling in game development. After watching some GDC Vault videos, they became more interested in becoming a game developer - specifically a tools programmer. They were polite and appreciative of me taking time to talk with them. Riley asked me for some good resources to better understand how tools development works and for advice on looking for jobs. They also asked about what kind of work I did on Battletech and other games. Eck's First Email Hello Riley, Let me tell you a little bit about myself first. Originally I was a regular developer working on business applications. I started out with C++ and then moved over to C# and SQL as the technology shifted that way. I dabbled with game development as a hobby since college keeping a few projects spinning but never really did anything major. I started working on my own engine and saving up money so I could quit my job and make a serious attempt at game development. After about a year, I participated in a game jam and saw what amazing things people were doing with Unity and I was just floored. I really should have used something like Unity or Unreal instead of working on my own engine. Then I quit my job and switched to Unity. I started writing a weekly Developer Journal about the things I was working on here: https://www.gamedev.net/blogs/blog/1922-ecks-journal-still-flying/ - This helped me stay motivated with my learning efforts, and also served as a portfolio to show potential employers I had serious passion, and it would also serve as a form of marketing for my game if I remained an indie developer. The indie dev plan was the way I was leaning towards but then I saw Harebrained was hiring for Battletech. My wife made me apply even though I knew I wouldn't get the job. Long story short, I did get the job even though I had 0 professional game dev experience and didn't live in Seattle. So I gave away most of my stuff, packed up my family, moved across the country, and have been working there ever since. A tool developer's job is to make everyone else's job possible, easier, and faster. It's about creating easy to use "tools" like a map editor, or a mech editor. It's about making those tools intuitive, fast, and automating repetitive tasks. It's about identifying the pain points that people are dealing with and eliminating them. The best advice I can give you on how to learn to be a tools developer is to make games on your own and try to drive them with data. You'll quickly become aware of the annoying parts of game development. Figure out how to automate those annoying tasks where possible or reduce it to as few clicks as you can. I also recommend starting a developer journal. It's motivational - especially if you end your posts with what you plan to accomplish next week. It makes you feel like you've committed to something and other people will be disappointed in you if you don't. And then a few years later, it's nice to have a historical record of your time. You said you were interested in seeing what work I did. I started doing the developer journal thing before I got my job so you can see exactly what I was working on leading up to that. Lately, I've been writing up journal entries about the kinds of stuff I've been working on for Battletech. So click the link above and read all about it. Feel free to ask any questions on the game dev site and I'll be happy to answer them. Finding a game development job is super hard. And even when you do find one, there's a decent chance that job could suck. There are plenty of sweat shops out there that just squeeze every hour they can out of employees and then boot them after the game ships. One thing I found out working at HBS is that I'm happy just being a programmer. If this wasn't Battletech, I probably would have gone back to Business Application development to make way more money so I could retire sooner. But HBS is an amazing company to work at and I'm working on an IP that was a HUGE part of my teen/college years so I'm super happy. #LivingTheDream Do your research on the companies, apply lots of places, and prepare yourself mentally for quite a bit of rejection. I hope this helps Riley. Good Luck! - Eck P.S. - Watch Collateral (Jamie Fox, Tom Cruise). It's the movie that really lit a fire under my ass to go follow my dream. Riley's Response Hello Eck, Firstly, thank you so much for responding, it really means a huge amount! Unity is an amazing piece of technology indeed and some of the incredible work I see on twitter is honestly amazing. However I've been rather weary of it for a while, due to mostly varying issues I've heard about it. Though I should just get on with some tutorials and learn things! C# / C++ / SQL is a good set of techs to learn as you allude to later on, business applications are big money! My main language is C# / PHP! How far did you get with the work on your own engine? I've attempted that a few times and it is a rather big challenge especially when you are brand new to it all. I have just noticed in your first blog post you were using XNA / MonoGame, it's my current go to as well (well FNA) but it's a good toolset. It is rather awesome your wife and family were so supportive of your move when you did get the job, thought I can imagine that it was a big move and stepping into an unknown. It's also awesome that you did end up getting the job even with 0 professional game dev experience. That is a massive thing that does end up worrying me when looking to apply "At least 2 games shipped", "At least 5 years in the industry" etc. Though Harebrained sounds like it must rather be an awesome company. I shall have to give that a go, but literally everything you described is what I absolutely adore doing, creating systems and tools, to make peoples lives easier, automate things. In almost all my jobs, I end up building tools of some form to help others out, in one job I build a dashboard to monitor SSL certificates alongside website up time and in another, I built a whole framework to help developers write importers that were fail safe and powerful in the reporting side of things, so literally anyone could find out what went wrong. Any suggestions for sites to use for creating a journal? Would be interesting to see if it does help, cause I struggle massively with motivation and keeping going at projects though having any form of record of things I've done / am doing is a really nice thing to be able to look back on and see how / where you have grown. I shall be giving your blog a read over the next few nights and will definitely drop a few questions into the comment section, will be nice to talk more about how you have done things etc. The industry does seem like a few fast turn over area and yeah, I don't have the energy left in me for a sweatshop kinda company, we've all read the horror stories. I'm really glad to hear that you do love it so much at HBS and you feel so happy there, it's always nice when you do find places like that. Lots of research to be done and oh I've had my fair share of No's (including being ignored by a somewhat indie games company I looked up to, which sucked, but oh well). Thank you again, seriously this is honestly a massive help to me and I appreciate you taking time to read and respond to my emails, also Kiva, thank you also Hope you both have a lovely day! Kind regards Riley P.S. I shall have to go watch it indeed, thank you for the suggestion Eck's Response This email could sound a little cranky/confrontational. Tone is lost in text so please keep that in mind. At worst it should be received as "blunt" which is a quality I've been known to have. I'm just trying to help. Being wary of Unity: Originally I was in the camp of people that thought people using Unity were "cheating" and weren't real developers. You were only a REAL game developer if you wrote your own engine. That's the main reason I worked on my own engine. And quite frankly - that's a stupid camp to be in. Instead of working on low level stuff that's been done a million times by a million developers for nearly 2 years, I could have actually been working on a game and possibly released it. I'm not sure what issues you've heard about Unity but they are definitely able to be dealt with. I mean look at Battletech and Shadowrun. Both of those were made with Unity. If the engine can handle a professional studio's ability to produce games for 7-8 years, then it can definitely handle a one-man indie's dive into game development. Stop using that as an excuse and start going through the tutorials. Then start making games - simple ones. Specifically, make clones of other simple games. For a road map of what games to make and why - give this article a read. I can't recommend it enough: https://www.gamedev.net/articles/programming/general-and-gameplay-programming/your-first-step-to-game-development-starts-here-r2976 It explains what you need to make and why. If you're thinking to yourself "Pfft - Pong. I'm a better developer than that. I want to make a REAL game." - you're wrong. I don't care how awesome you are. Until you actually start making games, you're ignorant of at least SOME of the problems. So suck it up, and crank it out. - "you don't know what you don't know" How far did I get with my engine: I worked on it off and on as a side project for quite a while - starting, stopping, scraping, restarting. But then I got serious on it for about 1.5 years. I focused on 2D stuff and had an object hierarchy complete with translation, rotation, and scale. I got some post processing glow effects, sounds effects, music, input management, particle systems, etc. Basically I got to the point where I could make a simple game. I entered a week long game jam where the theme was "The toys are alive". Here's a tech demo of my entry. I was super pleased with what I was able to produce, but that game jam was a wakeup call. I saw all the crazy awesome things other people were doing with Unity and I kicked myself for not learning it sooner. Since C# is your main language, then I strongly recommend jumping into Unity yourself. Worse comes to worst, you further your C# skills a bit more. So if game development doesn't work out, the skills still translate into a well paid career. Your experience so far: Making tools in business software and making tools in games is pretty much the same thing (and that's how I sold it in my interview). Writing an importer for customer data instead of weapon data has all the same problems. It just sounds less cool to talk about. If you have the skills and can show the passion for game development - at least some companies will take a look at you. Being able to prove that you can walk the walk is what those experience requirements are all about. If you're looking for a good site to start a blog on, I highly recommend https://www.gamedev.net/. It's an awesome community of game developers of all experiences. From the 0 xp newbie who wants to make an MMO to the elite pros who have written low level graphic card drivers. There are forums to ask questions, and articles that explain tons of topics. They also have occasional game jams or challenges which is a great way to learn in a group of supportive people. Just recently they did a side-scrolling shooter challenge which was fun. Motivation: Motivation is something many people struggle with. It's so easy to stay in your comfort zone, play video games all day, and keep those dopamine sensors fed. You have to CHOOSE to learn a new skill. And it's extra difficult for programmers because the same device we use to be game developers is the same tool we use for recreation. Every time you sit down to work... WORK. Every time you sit down to play - ask yourself if you've worked enough today (or this week). If the answer is no, then you have a choice to make. You can choose to be responsible and work. Or you can choose to goof off and play a game. Choosing to goof off every once in a while is okay. But if you ONLY choose to goof off, you're never going to reach your goal. That's just how that works. As I have gotten older, I realized that time is THE MOST VALUABLE ASSET you have. You have a finite amount of time in this life. You are going to leave this world one day. Make your peace with that and accomplish what you want before you do. Thanks: You're welcome. Summary: 1. Learn Unity 2. Make learning games https://www.gamedev.net/articles/programming/general-and-gameplay-programming/your-first-step-to-game-development-starts-here-r2976 3. Write a dev journal about your experiences/plans https://www.gamedev.net/ 4. Start working on your game
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!