Buckle Up, Lock Down, and Stand By 5
The Mechwarrior RPG
This post took a long time in coming, but that's just because blog post play-by-plays of a Battletech battle aren't exactly exciting, at least not when you're only covering three or so rounds per week.
The rules integration I was testing out went really well; I like how much flexibility it gave the players, at the cost of making Battletech a little less crunchy (my other option was to make it much more crunchy, but there's a limit to the book-keeping I want to manage). Part-way through, I decide to quit rolling initiative for each NPC combatant and broke them into their lances, rolling initiative on a per-lance basis. The players could still seize initiative whenever appropriate (the lance wasn't treated as an inseparable initiative block), but that change still dramatically improved the speed of play. My current frustration, though, is trying to figure out how I should handle the LAMs; I need to reference Aerotech some more, because it's got some comments on this, but the simple problem is that straight Battletech really doesn't handle aerospace fighters very well. They're introduced in the rules compendium, but only for bombing and strafing operations, not as active battlefield combatants. Most of the integration is actually really straightforward, except for one thing: elevation. See, the rules in Battletech don't seem to consider elevation when calculating ranges. For your average fight, it doesn't matter: a battlemech standing on a hill or a building isn't meaningfully higher than their surrounding terrain. But an aerospace fighter (or a LAM, particularly one in fighter mode) is a different sort of beast. They're screaming around at an elevation that's several times the height of a battlemech at high speeds. I currently calculated the elevation difference and halved it to calculate effective range (strictly speaking, I should be calculating the hypotenuse of the right triangle, which I might do if I decide I want to leverage technology to the task). The halving was important because it meant that not everything was at impossible ranges. But one of the players had picked up their own copy of Aerotech and discovered an interesting note: while in flight, a fighter's energy weapons are treated as having double their normal effective range (this is explained by a superior heat dissipation due to their speed). That would address the range issue reasonably well, so I'll probably be looking at that for the next battle.
The players have (finally) succeeded in their sprawling combat. It lasted a lot longer than a normal fight because, in most cases, the enemies will surrender long before everyone is disabled, but since this was just a simulated combat (well, mostly, as I'll get to later), everybody stayed in the fight the whole time (though a house garrison might have stayed in to the end anyway; depending on when and where they're defending). Partway through the battle, we brought on a new player. How exactly they tracked the other player characters was sort of glossed over, but this new character paid the points to be the owner -- authentic, deed-holding owner -- of the unit's dropship. That was an interesting and unforeseen twist. Of course, since we've got this character just showing up in the middle of a simulated battle, her weapons were live, and there was a bit of pointless drama while the NPCs threatened to pull out and order an airstrike before she integrated her 'mech into the simulation. After a prolonged battle, the players came out ahead, though their group leader got very quickly ganged up on and was knocked out of the fight by the end (though he was finally getting into the tactical side of the fight shortly before he was taken down), and their assault 'mech was pretty close -- he actually managed to survive an "ammunition explosion" (simulated, of course), but it left him pretty wrecked. The LAMs did a generally good job of harassing everyone, and I think on the whole it really worked for getting people thinking more seriously about their tactical options in the wargame side.
After the battle, they met back up at the "ski lodge" -- the Officer's Lounge at the Marik military base -- and celebrated their victory. By the end it had seemed pretty definite, but there was a period of time in there that I thought I'd have the upper hand. They did have an advantage, both in terms of numbers and tonnage over their enemies, and the poor weather conditions probably hurt their opponents slightly more (at one point, the weather went from "snowing" to "severe blizzard," which significantly diminishes the combat effectiveness of the Trebuchets and Hermes II 'mechs that they were facing), but it was still a well-fought battle, and they earned the "Jumping Jack" they won in the wager on the fight. The next session will finally be the planning briefing for the mission on Hyde, which will kick off the meat of the campaign. I'm looking forward to that finally getting underway.
By Brian On 2017-03-08 17:47:02 Permalink
Buckle Up, Lock Down, and Stand By 4
The Mechwarrior RPG
*grumble* Always so far behind.
So by this time I found a set of rules for a tighter integration between Battletech and Mechwarrior in my Mechwarrior's Companion. I'd kind of skipped over them before, but they actually do a number of cool things: they are essentially rules for playing Battletech with the Mechwarrior initiative system, and they actually tend to favor Mechwarrior characters a little. Which is good because the base Battletech rules are kind of punishing for these poor role-playing game characters and their relatively low skill levels. Even the greenest Mechwarriors from the random tables in the Compendium of Modern Warfare are significantly more experienced than the player characters, which makes things more unbalanced than I'd like.
Anyway, the grand challenge from last post ended up much to-do about nothing. Jaguar learned an important lesson -- heat is your enemy. He took the risk of firing all his weapons at once, and then failed his shutdown roll. The shutdown roll changes to a Computer check in the new rules set, probably the only thing that really caught us by surprise and made things harder for the player characters. Fortunately, the important lesson on thermal management was learned during this match (which, hilariously, Jaguar insisted be live-fire instead of simulated) risking only a whole lot of money and not with higher stakes. The party had split betting for and against him (Jaguar is a...polarizing character), so some characters actually ended up making money on the deal. They also forced Jaguar to pay for his lost stakes and the repairs to his mech from his own private fortune, which is, or at least was, rather considerable. I made a strategic error in the fight: I had Jaguar fighting a "pinball machine," that is, a heavily-customized mech. Now they know they can do it (though I've got reasonably strict rules about mech customization and how it affects piloting); so Jaguar also jumped on that bandwagon. That said, he very carefully went over what he wanted to do in order to minimize the impact of the customization on his mech's performance.
The following day, the mercenaries went to contact Bynjo Han, and get ahold of that replacement arm for Emma's Wasp LAM. Bynjo is based largely on the Outlaw Star character Fred Lau. Fred is the arms dealer who supplies the protagonists with weapons and equipment in the show. Also, Fred is flamboyantly gay and crushes hopelessly on the protagonist, Gene Starwind. So of course, Bynjo gave them a great deal on what they needed...in exchange for Sir Zeke agreeing to go out with him on a date. So after a fairly amusing and awkward dinner, the mercenaries got the equipment they needed and headed to the dropship to take off to Amity, the Marik world from which they'd be staging the objective raid they signed up for.
Amity is a frozen world, whose best days are behind it. The mercenaries met up with the local garrison and managed to not make complete fools of themselves in the bar; though they did give it the old college try. They also met the strike team that they'll be working with on the mission. They learned that the mission plan is to hit the Steiner world of Hyde (Marik has been raiding Hyde regularly for a long while; it's a very strategically valuable world for Steiner as a source of water for the surrounding systems). Because I didn't want to work out a company-sized force, they're going in as a small expeditionary band, to cause as much damage as they can and then pull out. I'm planning to give them a bunch of different small objective "missions" that they can do once they're on Hyde which will affect what enemy forces they'll face as they move around. The Tactical Handbook has some advice on running this kind of a scenario set, so I'll be consulting it some more as things shape up. But before they go to do their real mission, they had the (pretty good) decision to play a little war game with the rest of their raiding party against the local garrison; to familiarize each other with their tactics and capabilities and make their actual mission go more smoothly. This is a much larger battle than they've deal with before. I think the Mechwarrior Companion ruleset is actually making it play a little bit faster than Battletech normally plays, but it's still going to be a long battle. With the holidays we've been on a bit of a break, but the holidays are about wrapped up, so it'll be Battletech time again soon.
By Brian On 2016-12-30 16:22:21 Permalink
Buckle Up, Lock Down, and Stand By 3
The Mechwarrior RPG
Sorry I missed a few weeks there. I'm going to put the last couple sessions together as a result.
It's interesting that salvage, a very important part of running a mercenary unit, and something that's been included in the computer games since the very first, original Mechwarrior game, is so poorly handled in the table top games. I think it's different in every book that bothers to cover it, and it's usually pretty hard to actually find the section that covers salvage -- I didn't find it in any of my books until after I'd had to divvy salvage out. Most of the time, it's not even done in terms of percentages -- it's something like "Payment in Kind" or "Prize Court" and these are then vaguely described, leaving it up to the poor GM to try to figure out how the employer is going to determine what values to use for this. I did it as a percentage of tonnage, which isn't actually correct: once I finally found a discussion of percentage, it turned out to be a percentage of value by C-Bills, which makes sense. I'll probably be doing a hybrid in the future: negotiated percentage of value, filtered through the mechanism of payment (mercenary keeps, payment in kind, payment in cash, or prize court).
Mostly the last few sessions have been lessons in how players are how they are, even when they don't mean to be. Despite intentionally stating that he doesn't want to be in charge, one of my players (our normal GM) just can't resist being the face. He makes nods to not being the leader of the group, but he still does most of the talking. We can't resist playing to our strengths and the things we enjoy -- I do the same thing; which sometimes results in groups having...unusual "face" characters (like our D&D 4th Edition group that was nominally led by a Gnoll Shaman). The character that's been designated the leader has been pretty quiet, but I'm going to try to draw him out a little bit.
The mercenaries, having completed their contract with the planetary authorities on Issan, went to finalize payment, and also to try to negotiate some resupply. They're very concerned about replacing the arm on the Wasp LAM (which is a fair concern), but getting a LAM arm takes time and effort, so they put a purchase order in at Galatea. Given a month's lead time, they expect that somebody there will be able to fill the purchase order (which is a completely reasonable assumption). The group splits up for their negotiations, with Galen and Jaguar visiting the bandit's blackmarket contact to get some equipment for repairs, and Ions, Zephyr, and Emma heading to the planetary governors to finalize the contract completion. Jaguar has been billed as a country bumpkin, good with a wrench and a welder, but innocent in the ways of the world. The reality of the situation is more that he should be placed somewhere on the autism spectrum, which makes it pretty funny to involve him in negotiations with a black market contact. The arms dealer offered to cut Galen in if he was allowed to negotiate with Jaguar alone; that's how crazy that went. The meeting with the planetary governing council went better, and the mercenaries sold off their salvaged units (they salvaged the Bulldog tank and the Commando mech along with some other arms and equipment from the bandits) to the planetary militia forces for a tidy profit. Then they were off to Galatea to establish their presence as a real mercenary unit and take their first "real" contract -- or the first contract that they'd get to choose and negotiate for themselves.
Doing some research, it was clear that the trip from Issan to Galatea would take pretty close to a month. They'd taken a fair amount of damage in their fight with the bandits on Issan, but between their salvage and the equipment they purchased from the black market, they were easily able to complete their repairs during the journey, except for replacing the arm on Emma's Wasp LAM. The travel time also gave them an opportunity for some training and rest.
The mercenaries set down on Galatea and got the address of the temporary office space that they were renting with some of their overhead money. They reviewed the responses to their purchase order for the arm, and they had two good options: an eager-sounding arms dealer named Bynjo Han and the proprietor of one of the proving grounds on the planet, named Marko Kurrov, who offered to buy the LAM from them for a little better than market price if they didn't want to buy an arm. Ions and Zephyr contacted Kurrov to get a proposed price tag, planning to take that number to Bynjo in hopes of getting a better price. Jaguar proposed talking to both of them -- he thought he might be able to win the arm from Kurrov in an exhibition battle. Ions tried to dissuade Jaguar from leaving to execute this plan by shooting him in the back with a sonic stunner, but Jaguar shrugged it off, bought Ions' explanation that he was just making sure Jaguar was tough enough for this, and took the monorail into Galatea City. The rest of the mercs kind of shrugged their shoulders and took the next monorail themselves.
Jaguar couldn't remember exactly where he was going, so he stopped in a nearby bar, where he spoke to a drunken old man. Their conversation was...probably confusing for everyone involved. It ended up with the old man suggesting Jaguar head to a little blood pit nearby named Aries ("It doesn't have as many 'e's in the name as you think"). The fight organizer/bookie at Aries then agreed to set Jaguar up on a match, with Jaguar continuing to insist on payment in the form of an arm. The bookie took this in stride; everybody seemed to enjoy that much of Jaguar chewing the scenery, since the bookie was non-stop fast-talking glibness, and Jaguar was as impenetrably clueless as ever. I, at least, had a lot of fun in that conversation.
The rest of the mercenaries went to the hiring hall to find their next contract. I presented them with four options, which is way more than a starting unit of five mechwarriors should get, but, hey, this is for fun. It was really two branching storylines, with the ability to play either side of each conflict. They eventually decided to take on an objective raid sponsored by House Marik. For the most part, their negotiations went well; though they were really focused on support costs, and ended up taking kind of a bath on jump compensation. I haven't calculated the route yet to know exactly how bad that's going to be for them yet (it only makes sense to charge jump costs for getting to the staging area and back -- jumps from the staging system to the target system ought to just be part of the operation). Then they met back up with Jaguar at Aries, the actual match will be in the next session. I haven't yet decided what I'm going to have him confronting -- Jaguar pilots a Stalker, so it's actually a more complicated decision than if he was piloting a lighter 'mech. I'm going to break out my Solaris VII maps though; I think that the blood pit will be loosely based on one of the Solaris arenas.
By Brian On 2016-10-18 18:00:16 Permalink
Buckle Up, Lock Down, and Stand By 2
The Mechwarrior RPG
This post is so long in coming because I wanted to actually get through the Battletech combat before I posted it. Battletech is Battletech, and with a bunch of inexperienced players (and a very rusty GM), it is even slower going than normal. On top of that, I had two weeks when I couldn't run the game, hence the long delay. It's interesting to see that even the greenest skill numbers in Battletech are often quite a bit better than the best my Mechwarrior players had. The worst gunnery skill you can roll on the random Battletech table is 4. None of my players had a gunnery skill even approaching a 4. That...caused some hard feelings. Fortunately, I had thrown them against a pretty easy encounter of mostly low-powered vehicles (though I tormented them with a VTOL also). Even so, it was pretty rough; we had a few critical hits, an arm was destroyed, and I kept managing to shoot their 'Mechs in the head with machine guns. But nobody died, nothing's too wrecked, and I think we all learned a lot about the system. I'm also awarding a lot of gunnery skill points in hopes of getting them leveled up once or twice in gunnery before their next combat.
When we last left the newly minted mercenaries, the Black Stars, they'd captured the bandit Frank Cross, and had gotten some questionable intelligence that the main bandit force was in a box canyon to the northeast. Galen Amador had been working on getting into the bandits' group, so he signaled to Ions Clarke that he was going to fake a rescue of Cross and cement his way in. Then, before Ions could prepare anyone else, Galen came flying in and shoulder-checked Jaguar Takedownriser. Ions did his best to play along and clandestinely inform the others of the plan. After some pratfalls, Galen managed to pull his "rescue" off, and Cross revealed that the bandits weren't camped in the box canyon -- he was hoping to ambush the mercenaries there, and he invited Galen to join them in the ambush. Galen reported this all back to his mercenary companions and moved up into an ambush position ahead of the rest of the Black Stars. The Black Stars didn't enter the box canyon by an ordinary route, and mostly stayed hidden outside it; but they did finally have to go in to try to "trip" the ambush. Mostly, the result of this was a drag-out fight where the heavies and the assault mech took too long to get into the fight. But eventually, they managed to shoot down the VTOL, blow up the APC (which hit Emma Desmond's mech in the head with its machine gun twice), and kick the whole front end of the Wheeled Scout into the back end (it went up agaisnt the Stalker -- and shot the Stalker in the head with its machine gun). The only units left in the fight on the side of the bandits was a Commando and a Bulldog tank. But the crew of the Bulldog, who had done their share of damage, though they hadn't taken a lot themselves, seeing their friends all get blown up, fled. The Commando continued to move around and cause trouble, but eventually it got cornered between Jaguar's Stalker and Galen's Crusader, with Ions' Phoenix Hawk LAM, in fighter mode, strafing it, and the pilot ejected. This process took three sessions.
Investigating the now unoccupied Bulldog, the mercenaries discovered a map to the bandit's hideout. They surprised the few sentries left there, and took the encampment without a fight. They ended up setting the bandits loose into the surrounding badlands (mostly because they didn't really care; they'd accomplished their goals of stopping the bandit attacks). The mercenaries then looted the encampment, finding a few odds and ends, and a bunch of weapons, ammunition, and spare parts in crates which were apparently from an arms dealer going by the name "Ciroc." Next session, the mercs will probably close their contract with the planetary government, and officially meet their dropship crew. Maybe they'll pay Ciroc a visit, or check out the Comstar facility. In any case, next session should involve some training and leveling of skills while they ship out from this planet and head towards Galatea, the current Mercenary's Star.
By Brian On 2016-09-07 17:58:47 Permalink
Buckle Up, Lock Down, and Stand By 1
The Mechwarrior RPG
January 2nd, 3028
I think I want to make a run out of these; we'll see how long I can keep the series up. The title comes from a bit of fiction in one of the Battletech sourcebooks, I unfortunately don't remember which one. We discovered last night exactly how poor at everything a starting character is (though that's okay, because you should actually "level" those early skills up pretty quickly). I appreciate that the game book actively encourages the GM to award skill experience points generously (you get skill experience any time you roll a two or a twelve on two D6, but the book notes that happens once every eighteen rolls on average "so it is more common to get skill points from the GM" -- I should be awarding skill points more often than once every twenty times they attempt a skill). I also realized that I don't have to award skill experience to skills the player characters have, I can award those points to skills they try to use, even if they're using them unskilled. I'm probably doing unskilled use wrong; I need to review those rules again. Several people took "Wealth" as an advantage, so I'm working out a very basic "stock market" system for them to invest their money in. We also discovered that, since it was a game designed well before personal cell phones became ubiquituous, the idea of a personal commlink isn't as ingrained in the books as you'd expect: everything's still kind of "military radio" oriented.
The game session itself was astounding. Part of it was my fault: I wasn't well equipped for the party to want to do bar-like things in a bar. (Buying cigars? That was totally unexpected.) Then, the adventure proceeded to fly off of the rails, before finally ending up back on track. Pretty much how a role-playing game session ought to go, if I'm honest. Everyone had a good time, with one player even saying "this is a gritting setting that I don't actually hate!" So let's break it down:
I'm starting the game on January 2, 3028. That's just after the end of the Third Succession War. The Fourth Succession War will start in August at the wedding of Hanse Davion and Melissa Steiner but for now, the Inner Sphere is in a period of tense peace. The player characters have recently "left" the employ of a self-styled Pirate Lord, "Fatty" Wick. Wick had a "Menagerie" of 'mechs that he used to extort worlds and try to establish himself as a big-time pirate. Most of the menagerie is now in the hands of the players, who have fled three jumps away to the small world of Issen, in the Magistry of Canopus. Issen is predominantly a mining world, digging up bauxite, but with recent discoveries of titanium and palladium. However, their mines haven't done the world much good lately: bandits have started to raid resource caravans, leaving the planet impoverished. After their militia fails to prevent these losses, the planetary governor takes a risk on a band of would-be mercenaries, offering generous salvage terms but nothing up front and little hard currency even after the job is done. The players have tracked a member of the militia, who their sources suggest is feeding information to the bandits, to a very seedy bar called "The Atlas Shrugged." The player characters are the wealthy "bumpkin" technician "Jaguar Takedownriser" (who insists on that alias, which he cobbled together from various technical read outs), a Stalker pilot; Sir Zeke Zephyr, a nobleman piloting a Catapault; Galen Amador, a Crusader pilot; Ions Clarke, who pilots a Phoenix Hawk LAM, and Emma Desmond, who pilots a Wasp LAM.
In the bar, the players start with Galen buying a box of cigars and Ions ordering a drink. They settle in to watch for their target, the militiaman Alexander Mark. It is then at this point that things go a little...odd. Jaguar marches up to the bartender and orders a milk. Yes, that's right. The bartender, of course, tells him to get out of the bar, because seriously, a milk? Jaguar slaps a hundred C-Bills down on the bar. This gets everyone's attention, because this is a terrible hole in the wall where most folks don't have that kind of cash to throw around. Especially not for a glass of reconstituted powdered non-dairy creamer. Then, just to further play the part of a diversion, the character wanders off to fix the broken jukebox. All this excitement startles an already nervious Alexander Mark, and his furtive glancing around catches the attention of the other members of the party. Ions sneaks up close to Mark and the man he's talking with, a bandit named Frank Cross, to listen in on their conversation. The others fan out to watch the exits.
Cross and Mark chat for a bit; it seems that Mark is starting to get cold feet on this deal, especially since the governor has hired some off-world mercenaries to solve the bandit problem. While Ions listens in, Galen is watching the back door, located in a hallway near the bathroom, and because he's loitering back there, he's propositioned by an aging prostitute. He's not interested, but he pays her to go give Jaguar "an education." I am surprised as this proceeds to happen, and I abandon describing the situation as quickly as I am able. Alexander Mark and Frank Cross continue their conversation. Cross eventually talks him into handing over data on the next convoy in exchange for a pay-off. Mark goes to leave the bar, and Ions tries to use his communicator to tell the others to let him go -- Cross is the real target. That's when it is discovered that only Ions has a personal communicator, everyone else just uses the radios in their 'mechs, so they have no idea he's even trying to tell them anything. Sir Zeke steps smoothly up behind Mark at the door and holds him at gun point. Shockingly, Cross doesn't actually notice that going on. Sir Zeke tries to extort Mark for the payoff, and while he does a good job, he's just not quite convincing enough, so instead of the payoff, Mark hands him a much smaller wad of cash; less than 20CB, folded up to look like more, and then Sir Zeke lets him go.
Abandoning the back door, Galen sits down at Cross' table and offers him a cigar, asking for a job interview. Surprisingly, Frank Cross has heard of Fatty Wick, so having Galen tell him that he's a 'mechwarrior who worked for the pirate gets Galen in good graces with the bandit. Cross tells him to return to the bar the following day; the bartender will have a message for him after the bandit are able to check on Galen's reputation. Galen agrees and leaves to go buy a personal communicator, having realized that a "phone" is a pretty good thing to have. He's planning to come back and watch the outside of the bar's back door from the alley. After a short time, Cross leaves the bar, and Ions sets off in pursuit, hoping to shadow the bandit. This is pretty much according to my own plan for the adventure. Having Ions be spotted by Cross and then fail to appear nonchalant, so it's obvious that he's following Cross was less according to plan. Cross darts into an ally, and Ions follows, shooting at him with a sonic stunner. He finally catches Cross with the stunner as Cross tries to run out the other end of the alley. Ions searches Cross and ties him up, gathering the rest of the party (except for Galen, who is watching from hiding nearby), to interrogate the bandit. After being sullen and unhelpful for a time, Cross tells them that the bandit can be found in a box canyon twenty kilometers north, and then demands to be let go. The party is wary that Cross is simply lying to them, but they have the data that Mark sold to Cross, so regardless they have that advantage.
We'll see where things go from there, that was the end of the first session. Right now, they're talking like they want to have Galen stage a rescue, to cement him as an inside man among the bandits. I probably could have had Cross escape, as I fudged a few things that were questionable to be in the players' favor in that combat, but I think that having him be captured is a more interesting scenario. They also did a decent job of tying him up -- Cross has already failed an escape artist check that I didn't tell them about. I'm pretty happy with the way the game went though. It was a nice, mostly-roleplaying session. I didn't award as much skill experience as I'd have liked to, so I'm going to do more of that. It seems like awarding one or two adventure points per session (with a whole bunch more awarded when missions are completed) is what the book recommends too. It costs a lot of AP to increase attributes and edge, but surprisingly little to buy or increase skills, so even these small awards do matter. I'm pretty pleased with the advancement system right now, we'll see how I feel once the players actually get enough points to advance some things. Combat was a little rough, but should go easier the next time. Right now, I'm still really stoked, and we're still in what is essentially the prologue: the "real" game won't start until they get done on Issen and head to Galatea, the Mercenary's Star (in 3030, Davion gives the world of Outreach to the Wolf's Dragoons, and they quickly transform Outreach into the new Mercenary's Star, completely eclipsing Galatea, but that's a few years out). If I can keep up the level of excitement and engagement, this is going to be a great game.
By Brian On 2016-08-03 14:24:22 Permalink
Buckle Up, Lock Down, and Stand By
The Mechwarrior RPG
Bah! It's terrible that I haven't been posting here. I've still got that 3D printer post to make (and no excuse for why I haven't, since it's mostly written even), and I'd better do that before I have another post on the 3D printer to put up.
But this post isn't about 3D printing. Oh, no. No, this is another role-playing games post. See, after a dearth of running games for a year or so (since scheduling conflicts have sent my long-running Spycraft game on another hiatus until I sort out a way to solve the geographical and temporal challenges facing my long-suffering Spycraft players), I'm going to be GM'ing a game again. My Tuesday night group is usually a house-ruled Second Edition Player's Option AD&D game (which is probably my favorite D&D variation; Fifth Edition is good, but Second Edition Player's Option is better), but after we beat the big bad in such a way that our characters didn't all die, the DM wanted a break to plot out the next part of the campaign. Another player stepped up and ran a short campaign segment in Planescape (also Second Edition Player's Option, where the tieflings are awesome and unique, unlike modern versions), and it got over just the other week. I volunteered to run the next game and we're going to be taking a break from D&D.
Tonight, we will run the first session of Mechwarrior, second edition. Mechwarrior is probably my first RPG, growing out of my love for Battletech, my first war game (I started playing Battletech and got into role-playing games from there). Truth be told, I'm not totally certain if Mechwarrior, West End Games' D6 Star Wars, or Top Secret was the very first role-playing game I played, but Mechwarrior was definitely the first one I owned. (Star Wars was almost certainly the first one I ran.) The book is a well-worn favorite of mine. It's got some problems: notably the "power packs" that run a fair amount of equipment aren't actually in the book and Edge is poorly described, but it has one of the best GM guide sections I've ever read. It includes stuff on when and how to say "yes" to your players and when and how to say "no" so that the game is satisfying; which is not something that usually gets covered.
I haven't played Mechwarrior in most of twenty years. Hopefully I'll get the rules back in my head fairly quickly. Fortunately, the mechanics are very straight-forward (mostly so that they play nicely with Battletech). The character initiative system is really unusual though. It's a blend of Battletech's very tactical initiative (going last is best because you know what your opponents are going to do) and standard role-playing initiative (going first is best because you do your things before the other characters get a chance to). I know I'll be spending a fair amount of the first character combat working through that.
Everybody's really excited, which is great news. I'm letting things be a little atypical: they're playing a mercenary unit because I think that'll be more fun, even though it's a lot more work. A House unit would probably make more sense (especially since they're running two LAMs -- Land Air 'Mechs, what FASA adapted the Veritech fighters they lifted from Robotech into -- which is just ridiculous), but I've always had a soft spot for mercs. We're also playing in 3028, because 3025 is my favorite time period; though 3050 was such a big deal that everything is filled with 3050 gear and it's pretty tough to know what is and isn't really allowed based on the time line except for mech designs and obvious high tech equipment. I'm pretty rusty at my wargaming, but talking with the group makes it clear that they're all role-players through and through...so I'm probably going to have to pull my punches at least a little bit to keep things fun. That's okay though: I'm building a chart to describe the general disposition and tactical expertise of each individual adversary they'll face in the Battletech sections of play, and I'll play to the role instead of just execution on my best approximation of tactical perfection each time.
All in all, I'm really looking forward to getting back into the GM's chair, and I've got some interesting ideas that I'm hoping to be able to pull off. Now I just have to make sure that I take the time to actually do the prep work.
By Brian On 2016-08-02 11:37:01 Permalink
Blog Logins Fixed (And Why This Is Not Wordpress)
So I did finally fix the login issue with the blog. Not that there's anyone but me who has any reason to log in at this time, but it sure is nice for me! The 3D printer post is still extant simply because I want to post a video of the thing working, which I have, but I don't have uploaded to the Internet yet. I did learn that I need to find the power adapter for the camera, because its batteries last abount a minute and a half (I am not exaggerating) when it's recording 1080p. Ah well...
You know, I occasionally wonder to myself, especially when I consider the feature list I'd like to implement and how little time I spend (or am able to spend) implementing it, if rolling my own blog software is really worth it. I mean, I got what I wanted out of it: I learned the basics of MVC design. I could just take that information, file it away, and replace this silly thing with a "proper" blog CMS. The temptation's there. There are probably Wordpress plugins to do the stuff that I want to do, and if there aren't, I'm fully capable of making them. I'm not much of a developer, but I'm reasonably competant at PHP, certainly more competant at PHP than I am with C++, and I'm writing a game in that. A blog plug-in is not going to be more complicated than a game.
Fortunately (I guess), I'm offered the occasional instructional moment by my job. We're implementing Wordpress at work to provide a way to roll better-looking websites for our customers more quickly and less expensively than we have been. I, as the schmuck who must keep the CMS up to date so that we don't invite the entire world into our database or web server, have insisted that we use a "Network," a multi-site install, so I only have one, easy-to-find set of Wordpress implementation files to keep updated. We've been taking the first site live, importing it from a designer's test implementation, over the past two weeks. And wow, I'm now pretty happy with my choice to make a half-implemented, partially-broken thing which I know because I built it myself, rather than installing a half-implemented, partially-broken thing used by thousands-if-not-millions of people across the web. I have been forced to learn more about Wordpress' innards than I ever wanted to know.
First, if you don't know, Wordpress pretty much never generates error messages, whether to the user or in the log. Usually, it just doesn't work. Often that means you'll get nothing, a plain blank "page" of no content, not even basic HTML tags; sometimes you get the theme's default content and none of your own. So you don't know what's wrong, or where it's wrong, and occasionally you don't even realize that something's wrong until later. Then, you learn that everything is stored in the database...somewhere (usually, it appears, in wp_options). Which row? Well, I guess you'll be looking. Then you discover how clever the Wordpress devs are. I mean, their solution to the very hard problem of storing configuration parameters in the database is sort of smart. And sort of "they'd better not get caught near a dark alley with me and a half-brick." I'll get into their solution in a minute, but I do want to make it clear that this is a difficult problem. See, you've got a static database format. You really can't store these options in anything but text. Unfortunately, you don't know what options any given theme or plugin, or whatever, might need. You don't know what the options are, what types of things they are, or even how many options there might be. You're stuck storing a completely arbitrary set of things as text with no idea what it's going to be coming in or what it'll be coming out. So you have to serialize it somehow. There are a lot of ways to do this; it's a difficult problem, but a blessedly solved one. Personally, I'd stick to a data-representation language like XML or YAML. There are plenty out there, and PHP even has a few XML translation layers in it. Unfortunately, doing that is very slow. XML is super slow (though since you're just reading it out and not searching it, it's not that bad; you're only going to parse it the once). They're also varying amounts of verbose; one of the things I'm not thrilled with about XML is how much space it wastes. Of course, there's another option, and it's what the Wordpress devs used: PHP's built-in serialize() function. See, PHP itself needs to serialize data, notably for session variables. So it's got to have a reasonably robust serialization handler, which can convert arbitrary, basic objects into a plaintext string and then back into an equivalent basic object. Wordpress just serializes option objects with this thing and stores the resulting data in the database.
But here's the problem: if there are any issues with the data, due to corruption, or it not being what you expect, or intentional fiddling, everything is totally broken. PHP can't even tell you what's wrong, just that there's an error in the data somewhere (it's usually pretty good about "near the beginning" or "near the end," but that's about all you get). Wordpress, with it's "never bother telling anyone anything" motto, doesn't even try that. And this serialized data is very sensitive. All of the content has expected sizes (counts for arrays, byte length for strings), and if this is wrong, everything breaks. I have now spent days correcting imports. See, these imports often have things like domain names in them. And if your designer hasn't been clever enough themselves to trick their computer into matching the expected production environment, then you have to fix those domain names or Wordpress won't serve that content correctly. And your designer won't want to redo everything by hand, so you have to do a batch conversion in the database. There are tools to help you do that, and they are supposed to correct the string lengths. They don't always succeed. And sometimes they screw up the string lengths on strings that they aren't supposed to be fiddling with. This leaves you with data which is broken somewhere inside it, and the systems guy or girl has no choice but to walk through the data by hand correcting the serialized data which was never meant to be seen by human eyes. Needless to say, this is very unpleasant. Add on to this general problem the fact that your designer may have used a different character set in either the database or their editing tools than the production environment (which might mean that characters do not use an easily predictable number of bytes because, just for instance, they didn't bother to even try to make their dev environment even remotely resemble production) or they put in line breaks which inexplicably work on their system but totally mangle everything after export and import, which are all problems that your find/replace tool isn't going to fix even if it doesn't break things on its own. So as systems, you're going to spend a lot of time doing real systems dev work to fix it, all the while your designer wrings their hands. You're going to walk through the serialization data piece by piece, because there are no error messages, there's no logging, you only know if it works or doesn't work.
If I ever have to even think about doing that again, I'm going to write a tool that fixes PHP serialized data stored in a database. It'll be a really unpleasant tool to write, but it's going to be a hell of a lot more pleasant than doing it by hand for another eight hours.
As nice as plugins and themes are, and as cool as they can be, this experience has pretty well and truly spooked me away from wanting to use Wordpress outside of my professional life. It's still our best choice, professionally, so I'll have to live with it. But I don't have to live with it here. I'm also really grateful that I went with a more sane serialization option for TD -- using YAML instead of some machine-oriented approach. Processor cycles are cheap these days. Programmer time and brain capacity is very expensive. I'll make that trade gladly.
By Brian On 2015-10-01 13:56:15 Permalink
> GET YEAR
While Father Time is distracted in shouting at some children to vacate his grassy front yard, you quickly snatch a year from the bowl on his credenza.
You now have 32 years.
So today is my birthday. I haven't done a very good job of keeping up on this blog. Not as good of a job as I'd like anyway. I've been busy: still in physical therapy from my motorcycle accident, three times a week. I'm down from two-and-a-half hours sessions to being just under two hours, so that's definitely progress, if not as much progress as one could hope for. I have done a little development on my game, but mostly I've been distracted with work on the house. My wife and I (with a little help from our families) put up a garden shed from scratch over the course of the summer months. It's a pretty great little shed, but man, was it a lot of work: pouring concrete, building and raising the walls, attaching the rafters, covering it in sheathing, shingling, and then the fiber cement siding. It looks awesome, but I'm glad I don't need to build another one anytime soon.
Also, it would appear that I put off fixing the OpenID login stuff for too long and now logins are broken (not that they mattered for anyone except me). I'll have to set aside some time once the printer is finished to fix logins, and maybe finally implement comments. I'd really like to have comments available for some of my coming posts, particularly the role-playing post, in case people had their own opinions on the matter to offer. And there's no way I'm going to allow anonymous commenting. Too many spam bots. By strapping a Google account to it, I can at least limit the number of people posting to something that I might be able to manage and have some slight confidence that they're actually people. I've also been told that there's something up with the way that post signatures are being generated, so I guess I should look into that when I have time too. Ah well...
For whatever it is worth, I'm tired, but generally fairly happy with my life as it stands. I've had my ups and downs in the last year (okay, at least one really big down), but on the whole, I can't say as it's been a terrible year all around. You all haven't been able to get rid of me yet. ;)
By Brian On 2015-08-31 18:26:46 Permalink
My Friends Have a Great Game on Kickstarter
So some good friends of mine are launching a game on Kickstarter. I've played a little of playtesting for it, and I've gotta tell you, it's going to be quality.
The game is called Adopted. In the game, you play a dog and you do the things that dogs don't really do, but that we imagine dogs do for us in our lives. Though, when you think about it, maybe dogs actually do these things *because* we imagine that they do these things.
So while you're a dog, this isn't a game about hydrant sniffing. You can throw a ball and play catch with yourself (which is way more fun than it could possibly sound; I now understand why my dog actually does this, because it is amazing). This is a game about humans. You're a dog, but this is a game about humans, because, let's face it, pretty much every story we tell ourselves is about us -- or about something that's standing in for us. Stories help us learn about ourselves or the world we live in.
The great thing about having a dog as the protagonist is that you can be involved in human problems while still also being an outsider. The player identifies with the human characters, but isn't compelled to *be human* around them. After all, you're a dog. But because you're a dog doing the things we imagine dogs to do, you're a dog that helps humans solve their problems.
Maybe that's something that people who don't own pets won't understand. I know how silly it sounds. But trust me, if you own a pet, this is what having a pet feels like. Your pet understands you, or at least is there to listen. You believe, true or not, that your pet is involved in your life and helps you solve your problems. Now imagine a game where YOU are the pet and you DO help solve your owner's problems; or at least, have the capacity to do so. That's what Adopted is all about. I'm super excited about the game, and I have a lot of confidence in the folks who are working on it. There's no way I can do justice to the concept, the game, and the team, so just please believe me that it's worth your time to head to the Kickstarter and check it out for yourself.
By Brian On 2015-02-24 14:09:33 Permalink
First Threatened Destiny Screenshot!
This is a big moment. I've finally gotten the game engine to the point that I can render some level geometry, for a suitably simple level map. The render code is largely temporary stuff still -- I'm going to eventually do a scene graph like a reasonable person inside the Render System, but I have to figure out how I need to handle sorting the scene graph to make sure that the level geometry is rendered underneath the entities that are on that level, and above the entites that are below that level. (There's a lot of other considerations, like selective transparency for walls so they don't obscure important entities and stuff, but those considerations can wait.) I'm currently putting the entire z-level of the stage map into one entity (and in fact, into a single renderable component on that entity). I don't like that approach; in part because the stage map will have to eventually have things like that selective transparency that I mentioned earlier. It's pretty likely that I'll end up moving to an approach where the stage map decomposes into special scene nodes that are unrelated to the the usual entity-component architecture, and I may end up storing the stage map with an abstract metadata form like I do in the editor. However, this does serve as a demonstration that the CES setup is working, and my message handling code is working as intended.
At first, I forgot to adjust for the fact that each tile is actually three-times the height of a grid square -- this allows the tile to have "vertical space" in it. Not a big deal for these floor tiles, so they just have a bunch of empty, transparent space there, but when I get some walls in, that area will be very important. The result looks sort of like a Q*bert level to me, as the tiles squash in away from each other:
After I finally figured out what was going on, I was able to get the game to actually display the level that I'd created in the editor. It's really exciting for me, though it's really not very exciting for anybody else.
The next step is to go back into the editor and start adding the ability to set up tile properties. That will enable me to do things like mark tiles as blocking movement -- it lets me make walls, basically. Once I've got a couple walls in a sample stage map, I'll bring it back over to the game side, implement a player character that can move around, and then make it respect the tile properties that block its movement. I'm also going to tweak a few things in the export stage to make importing the completed stage maps a little easier. Of course, I (finally) return to work on Monday, so it might be a bit before I get more work done on this.
By Brian On 2015-01-16 16:40:47
Last Edited 2015-01-16 16:42:24 Permalink
Installer Problems With Windows 8?
So my wife just got a new laptop (a pretty boss Lenovo Yoga 2), with Windows 8.1 on it. The thing runs at a resolution that I'm torn between describing as "unlimited cosmic power" and "hilariously large numbers". You'd have to add both of my monitors together to get that many pixels. Anyhow, this comes with some interesting side effects. One of which is this: Some software will have a tiny installer window, so small that you can't see the licensing agreement or the radio buttons to agree to it. Being an installer window, it's of a fixed size and you can't resize it. Suddenly, you can't install your software. In my wife's case, this was Cricut Design Studio's plugin, and their support staff, while very nice and extremely well-meaning, will have you download the plugin from every browser under the sun, but -- and you may have already guessed this -- the browser you download the .exe file with doesn't really matter when your problem is that the installer itself won't let you install the plugin. Perhaps which browser downloads the plugin matters for which browser it gets installed to, but installing to the wrong browser is a problem to be solved after you can install the software at all. I've also seen this mentioned on the internet in regards to Open Office, and I'm guessing a lot of people on shiny new laptops have issues with install windows that are too small and can't be made bigger.
So here's the solution: Open up your display properties by right clicking the desktop (or typing Display in the Start Screen and clicking on the thing that comes up). There's going to be a slider or a series of radio buttons for adjusting the scaling, or it might even call it "DPI" depending on your settings. If you've got a resolution with really big numbers, that scaling is probably in the maximum setting; just so that you can see your mouse cursor without needing reading glasses. Unfortunately, your fixed-size installer window requires eensy-weensy-eyestrain-o-vision to work right. So you need to either click on the minimum radio button or drag the scale slider all the way to the right (100% is the smallest you get to scale to in most cases). Now, once you've done that and hit apply, you'll get a mouse cursor that's so tiny as to be impossible to see on the screen, and it probably will display text and buttons and icons so tiny that they need a magnifying glass to be witnessed. However -- and this is the really important bit that I initially overlooked -- you aren't done yet. Windows might pop up a little box that says you'll need to log out for all the changes to occur. I've been around the block a few times, and generally consider those boxes to be liars. Most of the time, Windows is just fine implementing your changes now, and the logout/login stuff is just making sure everything works and can be safely skipped. Not this time. If you don't actually sign out, Windows won't think you're totally serious about making everything unreadably tiny, and it won't fix the information in the install window, so sign out.
Once you've signed back in, everything is so small you can't find it. But if you can fumble around until you find the installer file you were trying to run before, you'll discover that it now actually will display all of its contents. Sure, you'd need bifocals or maybe binoculars to actually readthe license agreement, but at least you can actually see the "I agree" button, and that's what we're trying to solve here. So go through the install process, and then, for the love of your squinting eyes, set the scaling factor back up to whatever value it was before and do the whole sign out/sign in dance again. Finally, the software is installed and all is right in the world. And it just goes to show you, sometimes these things befuddle even a computer programmer and her system administering husband, so don't feel too dumb when "Why is it so tiny?! I just wanted to be able to use this software on my new computer!" and you can't solve it on your own.
By Brian On 2015-01-15 17:23:54 Permalink
I'm out of my sling finally and my hand brace came off last week, but my motion is extremely limited in my right arm yet, and it's taken to hurting fairly often. All that said, I am finally able to do a little limited typing, not for long periods, but enough to keep me from going crazy. And I've been putting that ability, however limited, to good use. I've actually gotten some programming done.
To that end, I hit a major milestone with TD the other day, checked in at revision 110 (though several of the last revisions were changes to the blog, I'll discuss those in a bit.) I added a third dimension to my StageMaps. It didn't require too much in the way of course changes, but it's at least conceptually significant. I wanted the ability to allow players to move around -- above and below -- obstacles, and have the chance to get high ground advantage over opponents. Plus this starts roughing in the framework for parallax elements. At present, the editor is locked to the bottom Z level, but all I needed was multi-Z support to start building test StageMap files. Now I can finally start working on the actual game!
Before I Get Too Excited About Writing a Game
Essentially, it's a very "pure" CES approach: Entities (or game objects) are little but a handle and a list of handles to Components. They live in a big std::vector (or something similar, but I'm going with a std::vector) inside of some sort of an object factory (all of that's going to be pretty new to me). The Components are pure data, and they live in std::vectors (or whatever) inside of the Systems that actually operate on them. The slightly weird separation and use of vectors are to help with memory locality. When a System wakes up, be it procedurally or in a thread, and it fetches everything it needs from memory, this way it'll get everything it needs to work on (or at least most of it) at one time without needing to search around memory for associated bits and pieces. That's the theory anyway. I've got to figure out how various Systems can easily reference the same Components -- Physics and Rendering both need "position" and Rendering and Animation both need to reference "sprites" and "textures," for instance, but I'll tackle that when I come to it. I'm also going to have to consider how I render "non-object" stuff -- the StageMap being a good example. I don't feel like the physical space the characters occupy really rates as an actual Entity (at least not in the same way as other game elements), but I'm still hashing out how I'm going to deal with it.
At least I can finally do something instead of just sit uselessly around the house; even if I can't do it for very long.
By Brian On 2014-12-10 11:20:05 Permalink
I am a Christian. Don't worry, I'm less of an evangelist and more of an apologist. (But don't get me wrong, an apologist doesn't offer apologies. They make arguments. The two words just happen to look alike.) I just wanted to say that as a way to explain this post. There are a lot of agnostics and atheists that I respect and admire, and the thing that keeps them in those camps is a lack of evidence for the existence of God. There aren't any verifiable miracles.
FoundationsA believers' life is filled with tiny anecdotes, small miracles that affirm their faith, but these are useless as proof to the unbeliever. Most of them don't matter. My faith was forged on prayers of "help me get through this part of the video game." You can't get sillier than that for answered prayer, but that was seriously the foundation I started on.
My Little MiracleMy biggest and more recent little miracle was actually substantial and was seen as answered prayers by my family as well as myself. In the hospital, I had some of the best surgeons in the state. The man who worked on my shoulder is particularly skilled, and he didn't think he'd be able to save it. The plan was, I think, to pack whatever was left of the shoulder bulb back into the socket and see what it would do. The other option, which he thought I'd get stuck with, was a total shoulder replacement. You get three or four of those in a lifetime, and they last less than a decade each: I'd lose the use of my right arm before retirement age. When I got into surgery, he opened the shoulder up and discovered that the pieces were bigger than expected. They'd hold screws. He was able to reconstruct my shoulder and I will regain almost full use of it. A small miracle. (My wife would like to point out that me being alive and not paralyzed is also something of a miracle. My vertebra broke in such a way as to not threaten my spinal cord at all. If it'd broken differently, I might have no use of my legs. While those are good abstract miracles, and I'm grateful for them, they don't illustrate my point as well.)
Small miracle it may be, that's just an anecdote. It's no evidence. There's plenty of explanations outside of "Man in the Sky put together bigger pieces when the radiologist wasn't looking." What the well-meaning and open-minded agnostic wants and needs is a big miracle. Make the sun's shadow stand still on the stairs sort of miracle. I don't believe that will happen for a couple reasons.
A Dearth of Proof -- Why Abscence of Evidence is NecessaryTheologically, this is about faith and love. Love must be freely given to mean anything. Now imagine that the God of Christianity is real and an active, obvious interventionist. He's always doing some obvious miracle: ending starvation or curing cancer. Doesn't that compel or at least obligate adoration? But such "love" isn't freely given, and is thus worthless and meaningless. Not even our parents or kids get love that's not freely given -- there are plenty of folks who don't love their parents or don't live their children, as hard as that might be for some of us to imagine. To love a good, omnipresent, omnipotent being demands that being choose not to exert their will obviously. God cannot work big miracles without jeopardizing the thing He wants: our love and praise, freely and thankfully given.
Personally, I also believe that God created a universe based on laws and rules -- physics, biology, science in all its forms -- and populated it with beings of curiosity and intellect -- us, humans -- because it gives Him joy and pride as we figure the universe out. In ignorant times, He has more freedom to bend and break His own rules that govern the universe because doing so would not undermine the knowledge and understanding His beloved humans had developed of His creation. In the modern era, a big, physics-defying miracle would not earn belief. It would just hurt our understanding of the universe and confuse us. That doesn't seem like something that God would want.
Let's Not FightI guess I'm saying that there something of an impasse. An individual may experience something which they cannot explain outside of a miracle, but that experience will never be enough to convince everyone of miracles. I'll just have to be happy and grateful for the miracles in my life and not worry if anyone else believes them or finds them significant.
By Brian On 2014-12-04 14:55:45
Last Edited 2014-12-04 14:56:37 Permalink
"They Hit Me With a Truck"
Ah, the immortal words of Brock Sampson, the huge bodyguard character from Cartoon Network Adult Swim's Venture Brothers." Brock, like me, was born in Nebraska, and now I, like him, have been hit by a truck. Okay, technically, I hit the truck, but the police report puts the guy in the truck at least mostly at fault.
The Sharp Stop at the End
I was on my way home from my Second Ed. game when the truck pulled out in front of me and I couldn't avoid him. Being on a motorcycle, the resulting collision did not go well for me. I broke my left hand in three places, dislocated and shattered my right shoulder, suffered a concussion and a lung contusion, and fractured one of my vertebrae. My (now missing) backpack of roleplaying paraphenalia may have helped prevent further back injury; something which one of my nurses was quite amused to chalk up to D&D saving my life.
I'm not exactly an invalid, but I'm not really useful for much right now either. I can't do anything around the house as I have a weight restriction of a single pound. I can watch Netflix, which has only underscored how little I enjoy watching hours of TV these days, despite how good the shows might be.
Of Lights and Tunnels
I have every confidence that someday, I will find value in this experience. If my past is any guide, I will be able to use my experiences to offer advice and consolation to someone else suffering injury. Unfortunately, that confidence is cold comfort for a self-described computer nerd who can now only barely type. I am virtually unable to play any computer games, a most frustrating predicament for me. I can't program, I can't play games; I am barely able to get on the computer at all. So I certainly have goals to aim for.
I'm working mostly on getting off my pain medication. See, it can cause constipation, and the one suppository in the hospital is enough for a lifetime, thanks. I'm also slowly getting some motion back into my hand and shoulder. Recovery won't be a short road, but at least I'm on it.
By Brian On 2014-11-14 15:41:37 Permalink
Fictional Games In Fictional Worlds
I heard you liked playing games, so I put a game in your game.
Worldbuilding is a subject near and dear to my heart. It's probably my favorite part of running roleplaying games. It's also vital to many exercises for writing, movie-making, comics, and video games. Pretty much any time that you have a creative endeavor which is meant to take the audience out of their own lives or own world-view, you need to do some worldbuilding. There are a lot of approaches and degrees for constructing a world, depending on how many of the audience's assumptions you can rely on, among a plethora of other factors. Personally, I like to work from the bottom up -- after I have the top-est of top level views of what I'm vaguely shooting for, I'll crawl down into the details (since, in my experience, that's what players and readers are going to spend the most time with) and build the rest of the world out of those details.
So I'm going to approach this (maybe) series of posts on worldbuilding in a similar manner. Rather than giving a broad-view of what it's like to build a world (feel free to check out Rutskarn's posts on this from Chocolate Hammer if you're interested in that; he does a great job), I'm going to concentrate on some small things that can be used to explore a world and make it come more alive for an audience; and hopefully tie this to my own world with TD.
Games are a Window
I recently finished reading Edgar Rice Burrough's The Chessmen of Mars, which brought this topic back to the front of my mind; though it's been one I've been considering for some time: The use of games of skill and chance within a fictional universe. The right choice for a game of skill can chance can flesh out a character or a world, or it can shattter the audience's suspension of disbelief and undermine their involvement with a story. This is as true in video games as it is for books or movies.
For instance, for a game that defines a character, James Bond plays Baccarat, a hilariously complicated card game of almost pure chance, with extremely little skill actually involved. It also significantly favors the house, even for a casino game. This informs us about James Bond's character. One could believe that he is so good at reading people that a game of pure chance is the only way he gets a thrill (Lie to Me has Dr. Lightman play Roulette for that reason), but since the game actually has a startlingly high probability of the house winning I think a different explanation is more likely: it's used as a way to demonstrate how reliably lucky Bond is. Bond beats the house; even against the worst odds, Bond can win. Either way, Baccarat tells us more about his character than Texas Hold 'Em tells us in Daniel Craig's Casino Royale.
That said, in this post we're less interested in what a game of skill and/or chance can tell us about a character and more about what it can tell us about a world. And frankly, looking at the fictional games of fictional worlds is much more interesting. You'll note as we continue that very few fictional games are invented whole cloth. Not only is it easier on the aspiring writer, developer, or game master to create a game analagous to one of our universe, it gives the audience a touchstone to the game and helps them understand it better.
A World Through The Window of a Game
We'll start with a classical example. Edgar Rice Burroughs created "Jetan" or "Martian Chess" to add flavor to his world of Barsoom. I don't remember how much it was mentioned in the first few books, but it was a key piece of The Chessmen of Mars, and he went to a great deal of effort to explain the rules. Several times, in fact. Part of that's because as the Barsoom books continue, Burroughs uses them to explore ideas and concepts as much as to have an adventure, but it also gives us a really solid bit of world building. Chess is an interesting and unusual choice for the basis or analogue of a fictional game. It's seen as intellectual and erudite. It represents a conflict in a war, with the players as generals, requiring strategy more than a simple ability to read your opponent (though that's certainly useful) or just plain luck. Those qualities actually make it idea as a game for Barsoom: Martians hold war in extremely high regard, and a game that is based on military conflict and educates a person on strategy would be valued in that kind of a culture. Martians are also fairly intellectual, for all they treasure martial acts, with a distinct focus on both nobility and learning. So an intellectual game of war really fits the universe. It's something that characters would believably play, and reinforces the cultural concepts we've already developed concerning Martians.
Star Wars has "sabbacc," a somewhat poorly described game of chance. But the feeling of it is something much like "space poker." That helps convey the "big wins, big losses" aspect of the space opera, and gives us insight into a universe filled with characters who get by on a combination of skill and luck. It's the sort of game that you bet your starship in. Betting like that in a table game plays to the high adventure of Star Wars, and continues to convey the larger than life aspects of the world.
The first video game that I remember exploring this concept was Moraff's Stones. Way back when, an enterprising man named Steve Moraff made a series of shareware games all based around a fantasy game he called Moraff's World. Moraff's Stones was a simple poker-like gambling game, set in Moraff's World, and purporting to be a couple nights of play of this game in a pub or two of that universe by the player. The game was a believable adaptation of a card game for a universe that didn't have playing cards (or for which playing cards were too expensive for tavern gamblers), and various monsters from the game would step up to the table to play against you. Each race had a particular playing style, which, as you learned it, you could use to your advantage. This really captured my imagination. Knowing what characters did when they weren't taking a sword to one another made the entire original fantasy game feel more real -- more immersive. And even though it was based on poker, there were enough differences to the game to know that it wasn't just simply reskinned poker -- it was a game that really belonged to the universe it was set in. Done right, a game in a fictional universe does exactly what Moraff's Stones did for me: it makes the universe its set in more immersive for the audience.
The Right Game for the Right Universe
Unfortunately, you can't just throw a game into a universe and expect the audience to faint over it: "Oh, it's sooo deep! It's got characters spending down time in it," said no one ever. You have to know your universe and choose something appropriate. Let's consider collectable card games. It's currently very popular to put a collectable card game inside your video game. It helps pad out the game's play time if the player has more things to chase down and collect.
We can see this done right in the Final Fantasy series. In many Final Fantasy games, there's a collectable card game that the player can involve themselves in. This actually provides sidequests and a gold sink/source (a place to spend or win money, which helps drives the player's personal economy). The card game is often a somewhat tactical game of placing cards on a grid, which actually helps compliment the usual combat mechanics of the game; giving the player a tactical game based on field position, as well as a tactical game based largely on actions chosen. By electing to give their game a complimentary mechanic, the developers of Final Fantasy made their card game interesting to play (and therefore more likely to be played). On top of the gameplay aspects, Final Fantasy presents an often somewhat cartoonish world. The characters are "big" and "fun." I can envision them going to play a collectable card game in a casino: it "feels" right in that universe. Final Fantasy often tells serious stories, but the games don't always take themselves seriously. This is the sort of place that everybody would play a collectable card game, and a warrior out to save the world might pocket these cards.
On the other hand, we have Id's RAGE. Like Final Fantasy, there's a collectable card game in RAGE. Like Final Fantasy, the card game in RAGE is lavishly illustrated. But unlike Final Fantasy, it feels utterly ridiculous. RAGE is set in a dusty post-apocalypic universe. It's hard-edged, with death lurking around a lot of corners, nasty gangs of guys wearing whatever they can find and pretend is armor, and sewers full of mutants. It features, and is the perfect place for, a minigame of Bishop's Game (or the Knife Game, if you'd prefer). But why in the world would my death-dealing BAMF take time from shooting mutants on live television to collect playing cards? It's also a fairly uninspired game which is more based on deck building than clever play; I guess that's supposed to drive the player to collect better cards, but for me it mostly just made the game a frustrating question of what I'm going to draw next. The player character is kind of a lone wolf, generally working by themselves to wipe out their adversaries, which are homogenous in any given encounter (for example, you might fight Wasted in one instance and Mutants in another, but you're generally only fighting one or the other). A mixed team game of mostly simple number comparision doesn't complement or call back the normal shooter gameplay. I find that the card game falls flat, and it actually pulls me out of the universe, because I can't figure out for the life of me why hard-bitten survivors of the apocalypse have decided that the best way to relax is to play a simplified Magic: The Gathering. The game concept and game play don't seem to fit the feel of the greater game world.
In Which I Prattle On About Myself
Moraff's Stones had such an effect on me, I can't imagine trying to build a universe without giving the people who exist in it games of their own to play. TD is somewhat limited though: unlike a fantasy or true science fantasy game, TD is based on the conceit that it's a semi-believable future of "our world." So I don't want to go too far flung for a game that humans are going to play hundreds of years in the future. Fortunately, poker is a fantastic game to base an analogue on. There's a long, proud history of "space poker" in science fiction for good reason: poker is a game that combines chance and skill, and gives a rough-and-tumble feeling to any universe where it's played ("space Texas Hold 'Em" is a little less so, due to the "community" aspect of the table's cards). But I can't just go with regular poker. That would be lazy and sad, and wouldn't convey the feelings of "the space future" and "pulp adventure" that I want to express in TD. So I'm playing with draw poker. I've got a ruleset I want to playtest for my hypothetical game (which I'm calling "Five Star"); based on having an additional royal suit, which acts as wild for purposes of determining suit, and the addition of what I'm calling "The Devil's Draw," a completely luck based option to discard one's entire hand and redraw right before the cards are layed out. I've got a couple decks of cards to mutilate for this purpose, and if it plays well in real life, I think I'll explore putting it into a Flash game for general playtesting on the Internet. Yes, it's kind of a distraction and/or a "waste of time" when I could be working on the actual game, but I feel like having a solid world-building mini-game, ready to drop into the game proper when the time comes, will help flesh out the universe and give the player something more to do. For a game based on player driven sublots attached to a vague storyline, having different things for the player to do is pretty important.
The Inspiring Speech at the End
If you're writing a novel or running a roleplaying game, especially in fantasy where you can't necessarily lean on traditional card and dice games, don't be afraid to spend the time to invent a game for characters (even side characters) to play. It'll help draw your players or readers into the game world, and it helps gives your world its own flavor. The less generic your universe, the better it's going to hook your audience. Having a fictional game that your fictional characters play helps liven up their universe and makes it more than just another setting where people play Texas Hold 'Em for some reason, but don't have any games of their own (I'm a little hard on Texas Hold 'Em because it's become so popular recently). Don't be afraid to experiment. Even if the game winds up totally broken, that doesn't mean that it doesn't give flavor or interest; after all, James Bond plays baccarat of all things. Hard to get more broken or convoluted than that. Good luck, and good gaming!
-- This post has been edited; correcting a spelling error and removing some extra padding. --
By Brian On 2014-10-20 12:05:56
Last Edited 2014-10-20 17:24:52 Permalink
State of the Project
October 8th, 2014
I hit what I consider an important development milestone the other day: I finally got both saving and loading working for complete StageMap (that is to say "level" or "stage") files. Once I had that in, I adapted it into an export functionality for generating "finalized" game map files (though I've been considering coding in the slight difference in functionality that it will take to load these files back into the editor). That means that I'm finally in a position that I could actually touch the game engine. Of course, I get that done and I immediately decide I need one more feature (which will break everything I've done) before I'm ready to actually go to work on loading data into the game.
See, right now, everything is on a 2D plane. Which is fine, except that I'd kind of like elevators and catwalks. Which means that I need to be able to represent space in 3D. That's not that hard -- mostly I have just have handle the map as a set of 2D planes stacked on each other. Strictly speaking, the data structure to represent that isn't any harder than what I've already got; I'll just add another extent to the Boost::Multi_Array that underlies the map. However, that change is so basic and far-reaching, it affects every place that StageMaps are modified, created, saved, loaded, or rendered. So it's really just a lot of work, and it won't give me an immediate reward, because I won't actually want to do anything with multilayer maps for a long time.
Rendering is its own special problem that I'll have to figure out. It's easy enough to do stuff with a z index less than the current layer: render it all, but behind the current layer with all the usual culling. Stuff with a z index greater than the current layer is the hard part. Cat walks should probably be rendered, and just go alpha-transparent when "important" things are under them. But a full floor above the player should simply be invisible. XCOM did it by just making everything above you invisible unless you moved your view up to that level. I don't think I can get away with that, unless I also go to being a turn-based game (jury's still more or less out on that, but I'm leaning toward real-time). (That being said, it's probably how the editor will work, at least for now, but that's okay.) Now consider the case where the character is crawling through a vent underneath a floor. That floor should probably be mostly visible, again an alpha-blending situation. So maybe I'm looking at needing to have each tile have a property on it which controls whether it's always displayed, or only shown when its visible. I don't like that solution, but I can't think of anything better at present. Fortunately, I'll have some time to figure that out; other things, like walls that block movement -- and movement -- are much higher priorities.
I also need to add in some more administrative things, like version control on the map files. Then the editor will be able to adapt and update existing map files and I don't have to worry about trying to load a testing file and breaking everything. If I get in on that now, it won't be that bad to implement going forward.
In any event, I'm happy to have taken what I see as a huge stride forward after getting back to programming for just a couple days. I'd been looking at trying to get LLVM's Clang compiler working, since it's supposed to be faster and generate more useful error messages than GCC, but so far, that's been a giant waste of time. Getting Clang to work at all on Windows is something of a chore; and I've had zero luck getting it to know where my standard libraries are, or at least where all my standard libraries are -- sometimes I can find some of them. While Clang's largely turned into a dead end, it got me messing with my programming again, and as a result, I got some forward motion on TD.
By Brian On 2014-10-08 17:28:33 Permalink
A Pulp Serial of Mars
I started reading A Princess of Mars by Edgar Rice Burroughs on my recent business trip. Since then (a week ago tomorrow), I've devoured the first four Barsoom books and can say without a doubt that they are the finest examples of the pulp serial format that I have ever experienced. I didn't even like the "sword and sandals" or "sword and planet" genre of science fiction before reading A Princess of Mars and now I'm seriously contemplating looking outside Bourrough's work in that genre. The first three in the series in particular, which are written in first person and directly concern John Carter, are very strong, extremely readable stories. Granted, they're a lot like reading a cartoon: so much of John Carter's life is filled with remarkable contrivance and coincidence, and he's pretty much better at everything than almost everybody else. There's seriously a whole bit in the second book where he meets a character who is obviously his son, and every time the kid says, "My father is..." he's interrupted before he can finish. This happens, almost word-for-word, several times. But I forgive the contrivance for one overwhelming reason -- Barsoom is so much fun. These books are some of the most fun that I've read in a long time. Sure, it's a pulp serial, so there's just this escalating stair-step of threat and danger, always cranking up the tension, but never really calling into doubt that the main character will succeed in the end. It's larger than life, with a veritable superman for a main character: faster, stronger, and more honorable than any foe. But it never stops being a hugely enjoyable amusement park ride of a book. And on top of it all, Burroughs knew exactly what he was writing, and not only did he execute perfectly, he knew when he could wink at the reader, he knew that we were all in on the same ridiculous ride. At one point in time, after a heady analysis of some of the science fiction underlying Martian technology, Carter flat out then states "But what do I know, I'm a fighting-man, not a scientist." The juxtaposition can mean nothing other than self-awareness and it's beautiful.
As much as I love it, there are a few elements of the formula that always make me laugh out loud.
I appreciate how Burroughs tends to solve problems using Martian culture. They have crazy-powerful guns, so why use swords? Culturally they both value swords, and consider it the height of dishonor to attack a man with a more powerful weapon than he attacks you with; the entire way of war is cultural and encourages swashbuckling. Since everything is solved by violence and John Carter is the best at violence, why can't he (or whoever) just kill any suitor of the woman he loves (being a princess, Dejah Thoris et al. sometimes got betrothed for political reasons, particularly when she thought her true love was dead)? Culturally, she can't marry the man who kills anyone she's bethrothed to -- to do otherwise would be the height of dishonor. It's a clever way to get around such questions, and is actually applied surprisingly carefully, so it doesn't feel like a cop-out.
The fourth book is in third-person and follows Carthoris, Carter's son, and while it's still fun, it's not as solid a novel. For one thing, it sort of just stops. It ends at kind of an appropriate point (Carthoris gets the girl), but it notably doesn't end the onrushing war (though the end of the story would result in the war ending), and it never addresses comeuppance for the villain. It's profoundly weird for a Barsoom novel to have not just one but two separate cities be left in the hands of tyrants by the end -- Carter usually defeats whichever tyrant is in charge and one of his friends of the appropriate ethnic group takes over. That said, the people of Lothar, with their psychic projections, are a very interesting addition to the mythology of Barsoom, and the story ended well, if somewhat abruptly.
I was never expecting to fall so utterly in love with the books. I'd picked up a Kindle collection of the first five Barsoom stories for a buck, partly out of a sense of obligation, as I'd never read them but I knew they were genre-defining, much like why I read Stranger in a Strange Land; and partly because pulpy science fiction is what I'm aiming at for TD and I thought that this might help inspire me. It has, though I'm pretty limited in what I can lean on here: Barsoom is a lot pulpier than the feeling I'm going for in TD. TD shares more with modern science fiction and less with the adventure stories that claim kinship with John Carter, but that doesn't mean it's wasted. I want to tell stories that focus around a main character, who lives larger-than-life and impacts the world around them. That's exactly what I have here, and how easily I happily laugh at the contrivance of Carter bumping into his friends every time he ends up wandering around the Martian countryside and just carry on reading gives me hope that players will except my plans for a similar engine of contrivance to keep characters they interact with at the forefront.
Of course, now that I've had a taste, I've got to work my way through the whole series. I've never had any real interest in the Tarzan series, but, quite frankly, I'm going to run out of John Carter stories all too soon, and now my interest in Burroughs' writing has been piqued.
By Brian On 2014-09-22 15:38:51 Permalink
I keep an SVN repository for all of my code (like some odd, never-finished projects, this blog, and my game). I've been asked if I would open it up for public access...which probably wouldn't hurt, and maybe I should do (certainly for the blog code at least) at some point in the future. Right now, I'm too embarrassed by the code to want to put it out where people might see it. I'm not a great programmer, and my projects suffer from some cruft. I'm bad at remembering YAGNI (You Ain't Gonna Need It), so I'll stub in or partially write up (or sometimes actually finish) bits of code that will never be used, and that's not a good thing. So I haven't gone through my codebase to clean it up yet, and I'm still too embarrassed (and a little too protective) to actually open up access to the repo just yet.
In any event, 100 revisions on a personal SVN repository is a pretty cool milestone, and makes me sound much more productive than I actually am. So this blog post is just celebrating that milestone. Last night I committed changes to the Threatened Destiny editor that allow it to save StageMaps (though that's probably incomplete, since it will need to know the actual filenames of TileSets that the StageMap depends on to load them, and it only stores the actual StageMap data at this stage), and to save and load TileSets and Tiles, which I think I mentioned writing earlier. File management is a pretty important part of an editor, since it's got to produce files that the actual game is able to use. Once I have general saving and loading in place with StageMaps, I'll be able to add an "Export StageMap For Game" option, which is just a special case of saving: it also builds a minimal TileSet for the StageMap and includes that minimal TileSet in with the StageMap data. That's the minimal functionality I need before I can start working on the game itself. Of course, that's just the tip of the iceberg for editing StageMaps; there's a lot more than just the tile's image data to a tile location in an isometric game, but once I've got that working, the rest will follow.
By Brian On 2014-06-18 15:18:25 Permalink
Watch_Dogs, A Review
Well, I've been spending all my time playing Watch_Dogs, so I might as well write a review of it. The quick version is "I got what I wanted, so I'm pretty happy." The much longer version follows:
The open world is largely improved, though I feel like it's got less personality than Hong Kong, more repeats on the canned conversations, there's a lot of little touches that help bring it to life. NPCs get into car accidents and get mugged, all without your intervention. I once walked into a coffee shop to play chess, and discovered a dude was trying to rob the place. Until I pressed F to win at beating people with a police baton anyway. They added several fast travel systems to the game, and put in more vehicles, as well as a way to always summon a vehicle near by, instead of making you hoof it to a garage as in Sleeping Dogs. Those are definite improvements and help speed up the game play and keep the flow going.
When they originally pitched Watch_Dogs, Ubisoft also talked up the moral choices the player could make about hacking people and stealing their bank account information. This might have more of an impact if people ever reacted to it, but they don't. There's no indication (at least that I've seen; maybe if you steal earth-shattering amounts of money?) that your thefts have any impact on the world at all. So maybe you feel a little bad because the RNG decided this person has the tag "Single Mother" by their name, but since there's no change in the world, how she acts, or how the world acts, that's just a tiny pang of guilt. It also ignore the far more important thing: money is completely meaningless and there's no reason to steal anything. See, you don't need to buy guns: you'll unlock the best ones by playing side missions anyway. You don't need to buy cars, because owning the best bar no longer really matters in the game proper. For the most part, you won't go through gadgets fast enough to need to constantly be buying crafting components, so those are only a very occasional drain. Your clothing no longer provides any kind of bonus, and nearly all of the outfits are hideous anyway. There's just no reason to spend money, and without a reason to spend it, you can easily keep yourself quite wealthy just by doing Fixer Contracts.
Despite those oddities and missteps, and the completely yawn-worthy protagonist, the game still manages to be fun. I enjoy all the little games, and the hacking minigame you play sometimes is very good; it gives me the right feel for a "Hollywood hacking" game. The driving sections aren't perfect, but they're very good -- better than most shooters manage. The character's story isn't the most terribly compelling, but the world, a Chicago run by a magic computer system, is interesting and a really enjoyable playground. I like Watch_Dogs, and I feel like I'm getting out of it what I wanted to get out of it.
By Brian On 2014-06-17 16:55:57 Permalink
State of the Project
May 29, 2014
Been far too long since I put a post here. So let's catch up. I've been spending more time consuming entertainment lately, which is a large part of the reason I haven't been keeping this very up to date. I might post a review of Watch_Dogs, but the other thing I've really been playing is Metal Gear Solid, and there's already been so many wonderful things written about it that I really can't add much more. (In point of fact, the Super Bunny Hop retrospectives on the MGS series really drove me to decide to finally play the games that would run on systems that I own. I'm actually really excited to play MGS3, because there's so many really cool systems in it, and it's very menu driven, but still very fluid to play; important things to draw inspiration from as I explore my own game mechanics in the coming months. Of course, being the ridiculous person I am, I am trying to play the games in order, and I'm still on MGS1 (and I'm hoping to get to play the ported MG1 and MG2 off of the MGS3 disc, but I was going to start with MGS anyway). Apart from the painfully drawn out sophistry (which I know I won't escape in a Metal Gear game), the game is mostly fun. I just wish I wasn't so damn bad at it. The game really really shines as a stealth game, but the forced combat sections (goddamn comm tower stairs, I'm looking directly at you) are not as much fun, and I am super duper terrible at. I also really sucked at the first sniper battle, which should have been easy, but there's no good way to quick pan the sniper rifle, which I'm used to in most games. Very frustrating. However, the torture section, which I ended up having to do a couple times because I forgot to call Otacon after the first round, which is historically considered very hard, I found to be incredibly easy. I guess I can mash a single button with the best of them. I haven't finished the game yet, but I'm in what is probably the third act (getting the key cards entered in).
Anyhow, you're all probably more interested in my progress with Threatened Destiny. As usual, I've had more frustrating difficulty with the frameworks that I'm using than with any of my actual code. I ended up using a boost::multi_array to represent my StageMap in memory. It's got some generally convenient growth functions, and after some tinkering, getting the boost::multi_array to grow and shift the way I wanted it to wasn't so bad. Then I ran into another fundamental problem with the frameworks. If you grow the in-memory representation of the StageMap, logically, you'd want to grow the graphical representation too, right? It wouldn't be much good to increase the storage area for the StageMap if the level designer can't actually drop tiles into that area. I'd thought that this would be fairly easy: since my drawing area is based on a wxScrolledCanvas, I should just need to adjust the SFML::RenderWindow size and the wxScrolledCanvas virtual size, and I'd be good to go. However, for reasons I cannot fathom, this doesn't work correctly. As I think I've mentioned before, wxScrolledCanvas objects have two sizes: a ClientSize, which represents the actual size that can be displayed on the screen, and a VirtualSize, which represents the entirety of the available drawing area, which is commonly larger than could possibly be displayed at one time on an ordinary monitor. So if you're going to change the drawable area (as opposed to the viewed area), you adjust the wx::VirtualSize. This works just fine. The problem is that the sfml::RenderWindow size never reports a size greater than the wx::ClientSize (which should be the size of the sfml::View, not the RenderWindow). This is in spite of the fact that you actually can draw over the entire wx::VirtualSize. I'd been doing my math for drawing the isogrid based on the sfml::RenderWindow size, because I thought it'd be most reasonable to base the drawing math on the actual drawing area, but since the RenderWindow never reports the correct size after growing the StageMap area, my math was always incorrect. In the end, I just ignore the sfml::RenderWindow's claimed size and base all my calculations on wx::VirtualSize, so everything actually works.
I'm now into saving and loading, which is the next step toward being able to actually get content from the editor into the game engine. I really wanted to use gzipped YAML files for my data files, which turned out to be a major factor for me rolling my own save/load-serialization/deserialization routines instead of using boost::serialization. I appreciate boost::serialization's goals, and I really kind of like it, but it's strength is definitely when you can have symmetric serialization (that is to say, you're using primitive member variables, so that serializing your object and deserializing your object are pretty much the same operation, just with the direction of the data flow reversed). Unfortunately, since I'm dealing with image data in SFML objects, the serialization and deserialization stages are asymmetric (getting image data out of memory is a different process than putting image data into memory). I use std::unique_ptr's throughout my code, and boost::serialization can't handle them out of the box, I'd have to either switch to std::shared_ptr's (which are not semantically what I want) or write the approriate adapter to allow boost::serialization to handle std::unique_ptrs. I found some information online for doing that, so it wouldn't be incredibly difficult, but it's still non-trivial. I also would have needed to write my own handler to utilize gzipped YAML files, which looked like more effort than I wanted to put into my first pass implementation. Fortunately, building the YAML objects was very easy, and I'd developed a gzipped YAML handler before I even started on any of this real work, so producing basic save/load stuff for tileset metadata (and the tiles they contain) was not terribly difficult. But getting the tile atlas image data in and out did its best to make up for any apparent ease the metadata offered. SFML gives you the ability to get a pointer to the memory location that an SFML::Image is stored in. I thought that all I'd need to do was iterate over this pointer, base64 encode the resulting data, and shove that into my YAML file, and that part of the process actually worked perfectly well, albeit inefficiently in terms of storage space. It took me a couple days of struggling with the data loading stage before I finally realized that SFML doesn't have any capacity to allow you to accept that data however. SFML::Images have a loadFromMemory() function, which I naievely assumed would read in the same data that the SFML::Image stored in memory. Oh, assumptions. If only I'd listened to Samuel L. Jackson.
Turns out, SFML::loadFromMemory() expects to receive a well formatted image in a standard image format, just like SFML::loadFromFile() only pointing at a memory location instead of a filesystem location. That's very frustrating, because it means that the data I'd saved out was completely useless. The only way to make the save/load work would be to save the data into an intermediate form; storing the data into either a completely different image format in memory and writing that out, so that I can load a complete image later (which requires me to include a new library to support that image format) or using SFML::Image's built-in ability to write the image to a "physical" file, and then loading from that file. I didn't want to have files other than the TileSet file required for TileSets to load, but even using an intermediate file, that's solvable -- I can read the file in, base64 encode it, and put the resulting string into the YAML file. Then I base64 decode the string in the YAML file into a chunk of memory, and hand that memory pointer to SFML to load. That's the solution I eventually settled on, because it's ever so slightly less odious than needing to bring in another image library and trying to figure out how to get a good copy of that data into memory to base64 encode, but I'm still not very happy about needing to create a temporary file and then delete it. I've made my peace with the method because it actually works, but I see it as kind of an awkward hack. My base64 library supports reading filestreams easier than memoryspace anyway, so that was at least one convenient aspect of this approach.
The next step is to allow the creation of new StageMaps, and save and load those StageMaps. Once the editable StageMap can be saved, I'll be ready to build the functionality to "export" StageMaps, which will pack a minimal TileSet inside the StageMap and allow the entire StageMap to be contained within a single file.
By Brian On 2014-05-31 01:20:31 Permalink
There's Always More To Say On Player Agency
Duff, cool guy that he is, was reading my last few posts and sent me another video to watch on the subject (or a subject that's incredibly tightly related). I highly recommend a watch, MrBtongue makes some really good points. The phrase I use, "Player Agency," is more of a tabletop roleplaying concept -- the idea that players get to make decisions and perform their own actions, as opposed to "railroading," where the player is "on a track" to just experience the story as the Gamemaster has laid out. MrBtongue uses the term "Choice and Consequence," which is a very video game expression of the same sort of concept: the player makes choices which have consequences in the narrative. He specifically notes that there are two forms of this "choice and consequence" theory. It can be used as a form of simulation: "How does the world realistically respond to the actions of the character," which helps reinforce suspension of disbelief and makes the player consider their actions more carefully, factors which should be desired in any role-playing game. It can also be used as a transparent ploy for replayability, which he regards as a more negative aspect. The player's choices really don't change anything except for branching the storyline, often in non-intuitive ways. Finally, MrBtongue's guide on how to do choice and consequences the right way at the end of the video is absolutely worth a person's time.
I don't entirely agree that choice/consequence systems that emphasize replayability are always bad things. I will agree that the choices which do nothing but branch the storyline in a way that doesn't really relate the choice at hand are, well, "non-optimal," to put it nicely. Situations like the one MrBtongue mentions in Mass Effect 2, where doing a character's loyalty mission is the difference between the character meaninglessly dying in a cutscene at the end of the game from a stray bullet are very silly. That's pretty much just a way to pad game length, call it a choice, and get another bulletpoint on the back of your game box. I guess I could say I'm in support of the "type two" or "replayability" choices when they can at least masquerade as "simulation" choices. Think about the difference between Open Palm and Closed Fist in Jade Empire. In a way, that morality system is mostly one about replayability, but it also affects how your character acts and is perceived by the world. It's a way to add replayability while appearing to be a simulation. It changes events in an intuitve manner, rather than a non-intuitive or unrelated way. I'm also a little more generous as to the idea that a choice which is really just a character choice, one that affects the way your character perceives or acts within the world is a good choice, not just a choice that affects how the world perceives or acts around your character. In the hands of an adept storyteller or developer, that difference may mostly be a matter of semantics (is the world a little darker, or does the character merely perceive the darkness in the world more starkly, for instance).
Another point that MrBtongue brings up is that consequences are much more powerful (and in fact, are only powerful at all) when they affect a character that the player cares about. In Fable 2, there's a scene where the player is given the choice between having their character be aged to an old age (visually; this consquence has no bearing on game mechanics and apart from any visual attachment you have to the character, it is completely meaningless), or "tricking" an NPC generated solely for this scene into having their youth stolen instead (this is, of course, the "evil" option). Shamus Young talks about how, when confronted with this choice, he didn't even feel a pang of guilt into making the peasant woman NPC be aged. That consequence affected an NPC who you've never seen before and will never see again, which reduced its impact on the player to near nothingness. The only meaningful effects of that change were "do you want to look old, or have your evil-number get bigger?" In other words, this choice has effectively no consequences (due to Fable's mechanics, it's not terribly difficult to mitigate morality effects, at least in the Fable games I've played, which, granted, do not include the second, as it was never ported to a game system I owned). Fable does feature at least a little focus on allowing the player to customize their character's appearance, so there could, depending on the player, be a consequence to growing old, but that's hardly a compelling consequence that affects either replayability or how the world treats the player. It is neither a simulation, nor does it increase replayability. (Technically it's a "simulation" choice, since the morality system affects how NPCs treat the PC, but as I mentioned before, this is easy to mitigate and so is effectively meaningless.) There is a rule in tabletop playing which not every GM lives by, but the good ones do: don't make the player roll dice unless failure is interesting. Similarly, it's not a great idea to give a player a choice that doesn't matter in a video game. A player quickly loses faith in a narrative that gives them choices, and then disregards those choices. I've almost beat The Bureau: XCOM Declassified, but the way the game simply disregards every choice that I've made has caused it to be something of a chore to play. When you chose the "let's not kill all the humans" option, and then everybody acts as though you picked "hey, let's kill all the humans," you start to wonder if the game developers intended to actually let you choose anything.
Like MrBtongue points out, you don't need choice and consequences for every narrative. It can be enough, especially for non-RPG genres, to just give the player a good experience. A player doesn't need to always make choices. A player might be disappointed if they don't have player agency, but it's better to just flat out not have player agency than it is to pretend you have player agency and then not actually have any player agency. Then the player feels betrayed by the game and the narrative. "Hey, I turned that guy good! Why is he now suddenly evil for no reason?!" "Hey, I just said that we would find a peaceful way out of this, why are we arming the nukes?" Disregarding the player's choices is a worse sin than never giving the player any choice at all, because then at least the developer and the player are on the same page of the narrative. Once you betray the player's choice (at least if you do so without a really good reason), you've done a lot of damage to the player's trust in the narrative and, as a result, broken the player's suspension of disbelief. The player's trust in the game and the game's narrative can be a very difficult thing to win back, so unless there's a very good reason, it's not going to be worth disregarding the player's choices just for the sake of them being able to make choices in the game. Skip the bullet point and just make the narrative stronger. A player is much more likely to replay a game because it had a great, really solid narrative experience, even if they didn't make any meaningful choices, than they are to replay a game that had a bunch of choices for them to make which are ultimately meaningless or ignored by the game's narrative structure.
By Brian On 2014-04-24 16:42:35 Permalink
I just managed to get Tom Francis' latest video watched. What I found very interesting was the end, where he discusses that the best way to handle a "main objective" is to simply pepper what the player is already doing with things that get the main objective done. He specifically brings up how cool of an idea it'd be in Oblivion and Skyrim -- rather than having a main storyline that distracts you from the fun things you can do, the fun things you can do give you bits and pieces of hints as to how to complete the main quest. Needless to say, this was particularly interesting to me because it was someone who really knows his stuff saying what a good idea one of my goals for TD is: make the actions the player chooses to do propel the narrative, rather than giving the player a narrative that they must follow, regardless of what they'd otherwise choose to do.
Don't get me wrong, I'm sure player agency (or an authentic feeling illusion thereof) is very hard. It's almost downright impossible if you live in the frankly dangerous place that game developers tend to exist in right now. At present, game developers are chasing cinematic experiences. They want to make movies that you play (the recent Metal Gear and Kingdom Hearts games are the exemplars of this). Compelling narratives with complex characters and beautiful cut scenes. These are not bad things. But there is an inherent danger in cinematic experiences. Ultimately, cinema (movies) is about the "director's vision." Games are not supposed to be about the director's vision, they are supposed to be about the player's experience. That's a wholly different goal. It's why people who are much smarter and more experienced than I always say that unlike movies, game makers should concentrate on "do, not show." This fascination with cinematic experiences has other side effects. Since the main story is the same, wonderfully told thrill ride every time the player plays, developers have to add achievements, unlockables, and New Game+'s to get replayability. If, instead, the narrative derives from the gameplay, then the player will replay the game on their own to experience how the narrative changes in response to their choices. Even the most simplistic of these systems; the good/evil metrics of Fable or paragon/renegade choices of Mass Effect or the Light side/Dark side of Knights of the Old Republic, will generate in many players the desire to beat the game one way and then play it again to see how the other side lives. If it wasn't so personally difficult for me to play evil characters, I'd certainly be one of those individuals. By giving the player agency, you've effectively increased replayability.
Of course, to give players agency requires putting in a bunch of extra work. You have to build out all the different options that a player might choose, knowing full well that most players won't see most of this content. Building content that players won't see (or might not, which is pretty much the same thing as "won't" to a creator) is creatively exhausting and expensive in terms of time and budget. It's easy to see why a developer might rather spend that time and money working on cooler cutscenes that a player will definitely get (read: "have") to watch. But I feel that the effort is worth the work to make an experience that's really special for that particular player. The best stories that players tell each other are the ones that they shaped. Players can be impressed by a narrative invented by someone else, but the narratives that they helped shape themselves live on in their imaginations forever.
By Brian On 2014-04-23 13:47:24 Permalink
Threatened Destiny: Narrative Themes
I've been doing a lot of reading on plot, theme, and narrative development lately, especially as I consider how these elements will affect Threatened Destiny. Of course, TD is far from needing those elements yet...I'm still working on a StageMap editor (though that's getting very close: I need to finish growing the map space as you place tiles near the edges, and then it's just a matter of saving and loading all the pieces and I'll have the first blush of the system together), but it's worth thinking about and planning out these elements, so that whatever story structure and universe appears in the final product; it's thought out and not rushed.
A lot of TD is still based on the ideas I pondered nearly twenty years ago as I mowed my parents' lawn. The Fermi Paradox ("If intelligent species exist in the universe, where are they?") is answered with the question of "they're just behind." In TD, Earth is the most Goldilocks of Goldilocks worlds, and has experienced remarkably few extinction events. As a result, Humans are ahead of the curve. By the time we were able to receive signals from other intelligent races (remember, space is unbelievably big), we'd developed FTL travel and could go visit them. There are a few alien species that are mostly on par with humanity, but nobody that's astonishingly more advanced across the board. But that's all less of a theme and more of a narrative conceit, or a touchstone for the setting.
For various reasons, I want a more "pulp" like emotional feel to the game. The player character is larger than life and their actions have far-reaching effects. It's a small universe -- you see a lot of familiar faces wherever you go. Style reigns over substance; drama claims victory over hard science. If the player wants to wear a leather jacket instead of a flight suit, that's a valid choice rather than a suicidal one. In other words, by making a pulp comic universe, I get to keep a lot of the tropes of sci-fi action games without the need to over-explain every little thing. There are some really great hardcore sims in development right now (check out Rogue System for a great example of the hardest of hard sims). I don't have any real desire to tell that kind of a story. I'd rather tell a fun story about a spacefuture badass than a dry tale of astronaut survival. I'm not against that kind of story -- hell, I love playing those -- it's just not the kind of story that I have the most fun telling.
The primary theme that I want in TD is that it's a personal story. The game's narrative will be about the player character; not about the galaxy. I'm specifically not going to tell some epic story where the player has to zip around space, recruiting a crew of hardasses to stop an existential threat to all life everywhere. Not only has that story been told, it's been told a lot. I want TD to be something a little different. I'm not saying that the galaxy won't be saved (after all, like Shamus Young says, saving the galaxy never gets old); I'm saying that the biggest reason the galaxy gets saved is because it has the good sense to stand in the same place as the player character's ass, and while the player's saving their own ass, the galaxy is along for the ride. My goal is to have a story that the player really feels a part of; that the story is actually about them. By giving TD a pulp comic essence, I can tell a story that's primarily about the character, but has consequences for the universe. Think about Star Wars: was it about the Rebellion and the Empire, or was it about the larger-than-life characters of Luke Skywalker, Leia Organa, Han Solo, and Darth Vader, which became wrote large into the Rebellion and the Empire?
One of the other main themes of TD is "the more things change, the more they stay the same." This is both very optimistic and very pessimistic. Humanity is humanity. Our nature as humans, for better or worse, doesn't change that much. While that removes the optimistic future of Star Trek, where there is no want, it also bars the worst of the dystopian societies, where the strong simply roll over the weak. Humanity is united...sort of. Human kind is still as fractured and sectarian as ever, but a universal governing body tries to mediate the various nations and corporations: more like the UN or the EU than the Federation. It's a massive slow-moving bureaucracy with more power than good sense. The military controlled by the bureaucracy operates largely on its own; managing to generally keep the peace among the nations of humanity and defend human interests, but they can't be everywhere or save everyone. Even though traditional racism is largely a thing of the past (humans are pretty tolerant of other humans), humanity as a whole is still xenophobic, there are just better targets than obvious natural humans between transgenic races, engineered humans, and actual aliens. Even with fantastic technology, people are still people. Some people are good and some people are bad. Science fiction literature traditionally has a particular theme that the universe explores, and this is probably mine.
I know every RPG talks about how great they are at player agency -- letting the player make decisions which matter or feel like they matter -- but that's a theme and concept that still fascinates me, probably because of my deep roots in table-top roleplaying games. I'd like to avoid Besthesda's tendency to make NPCs invincible, so you don't "accidentally" kill a story NPC, and instead make the story able to handle NPCs getting killed. Like, certain parts of the story would require a "Special" NPC to pass the information along, or come to the player's rescue, or what have you; you all know the general tropes of RPG story lines. Rather than me, as the writer, deciding that this particular NPC is special, why can't the game decide "hey, the player talks to this NPC a lot, and they're appropriate for such and such reasons, so I'm going to tag them as 'Special' and let them do this thing?" I'd really like to do that. Maybe it's not possible. But it's something that I want to explore.
I also want to explore something that I generalized from Kevin Pease: Since a story is ruled by narrative and drama, anything that the players/characters spend time on should either be important or a deliberate red herring. I try to apply this principle when I run tabletop games, and the results have been some of our best, most memorable moments in playing. A computer game, where the computer can track everything that the character does, should be able to do something similar. In other words, the actions that the player takes are considered important by the game. Do you do mostly smuggling? Smuggling should be rewarded with getting to do more of it, and it should (ideally) take a more central role in the narrative. Maybe the player is more of a bounty hunter. Then those behaviors should be rewarded. Rather than making the player do every mission, or forcing them to do things that they don't enjoy or are bad at, I would like (and again, maybe this isn't possible but I want to try) the game to recognize the things that the player has their character do and emphasize doing those things as part of the overarching narrative. After all, this is a story about that character. The story should focus on the things that they tend to do. In a perfect world, the game would be aware of things that the player is really bad at, and create missions where they are expected to fail and that failure is part of the mission parameters: "Take this load of mildly illegal contraband through the checkpoint at such and such time. When the military picks you up, that should distract the customs agents long enough for our actual shipment to get through. Legal expenses will be paid in addition to your rewards." That's probably too ambitious, but wouldn't it be cool?
Since failure could be an important part of the game, I'll probably offer a "hardcore" option, where the game would remove the player's access to saving and loading, and would instead auto save the game at very frequent intervals (and when quitting). I'm not planning on character death being a significant disadvantage. I expect to give the character a cybernetic implant (which I'll probably call "an insurance card") that plugs into the character's head. This implant could be removed (if the player desires permadeath), therefore freeing up a cranial cybernetic slot. On death, their consciousness is transferred into a clone and all their gear is matter-transported back into the clone's inventory. The penalty for death will probably be a simple monetary fee and the need to hoof it back to wherever they were when they died, and that's it. I respect real death penalties, but I understand why some people don't care for them, and I don't think the pulp-action feel I want for the game is diminished by bringing the character back right away. That eliminates the need for complicated save/restores taking the player out of the game world, and makes the idea of a "hardcore" option that removes the ability to save the game on command possible. Since you don't need a recent saved game in case of death, and I have frequent autosaves, hardcore just eliminates save-scumming, which is the point.
A character story should consider the possibility of failure as a setback, not as a show-stopper. If our story was about saving the galaxy, setbacks would have to be part of the narrative, rather than emergent experiences: if you fail at saving the galaxy, you fail at saving the galaxy, so setbacks need to be added by the writer. If the story is about the character, then they, as fallible human beings (or whathaveyou), are permitted to make mistakes and sometimes not succeed. In the case of a character-driven story, failure on the part of the character can (and should) make the story more interesting and relatable, rather than less. In a traditional game narrative, you'll have missions that you "fail," but the failure will be inexplicable or written in. I remember one truly infuriating sequence in Final Fantasy 9, where I had to last through a very difficult fight, using up all my healing items in the process, until the bad guy used a move to simultaneously just knock everyone out at once. If I lost the fight on my own, that was game over. I had to lose the fight after "winning" the fight. That's intensely frustrating and, to my mind, wrong. I'd much rather have a setup like the old Wing Commander: if you failed at a mission but survived, you had to deal with the consequences of failure; it wasn't just a game over (eventually it could be, but not right off the bat for failing one mission). That gives player agency: they're allowed to fail. And in a player-driven story, player agency is king (even if the game dev is still the Grey Eminence).
By Brian On 2014-04-11 16:09:13
Last Edited 2015-10-08 11:48:30 Permalink
Being Sick and Playing Alan Wake
Well, I got back from the auction and ended up with what seems to be a terrible viral sore throat. It's gone from just crippling pain when swallowing to include the additional symptoms of constant sinus drainage and congestion, and frequent coughing. Fortunately, the symptoms are manageable, but it's slowed down my work on TD. That said, I've run across the boost::multi_array, which does most of the magic I needed my big, dynamic, multidimensional array to do, and has the bonus of being written by people much smarter than me. I've started to get that implemented, though I don't have the resize-and-shift operations in place yet. Being able to make a single resize call on the array and having all the pieces end up the same, correct size is going to be a great bonus though.
One of my problems is that when I'm sick, I don't really feel very creative or interested in doing work that involves thinking. As a result, I just consume content when I'm ill. I watch TV and movies, and catch back up on game playing. My game of choice this time was Alan Wake. I'd been putting off playing it to some extent because the promotional materials didn't exactly sell the mechanics as interesting or cool: "I'm Alan Wake and I fight with light" sounds ridiculous. However, the game turned out to be really enjoyable. It's a solid port, with mostly tight controls and fluid mechanics. The dodge mechanics were a bit awkward -- very much like the dodge mechanics in Arkham Asylum, actually. However, dodging wasn't such a game-critical mechanism to drag you out of the game. The writing is enjoyable and evocative, with a narrative that answers the right questions and challenges the player with others that it leaves unanswered: was Hartman really a villain, or just a guy Wake didn't like so Wake made him a villain? Is Tomas Zane just a character in Wake's story, or is Wake just a character in Zane's story? Or maybe the real answer is somewhere in between? Were the people who were Taken by the Dark Presence returned after the end of the game, or did they just disappear, never to be seen again? We don't see anyone who was Taken in the ending cinematic, so we can't know. The character writing and voice acting is just as solid. Barry in particular got a wonderful treatment -- he starts out as the obnoxious agent, but really does care about Wake. Even though Wake doubts Barry's capability, Barry always steps up and stands beside Wake at worst of times.
But the cutscenes are hilarious. The models and textures are all adequately high res to look great. It's a shame that their facial animation system is so silly. It reminds me so much of the old "hinged jaw" animated sprites of my youth. The characters' mouths move when they speak, but not in any way that pertains to the words they're saying...or even to words at all. Fortunately, as I mentioned, the writing and voice work are so solid that you quickly gloss over the weird faces people make when they talk and you're absorbed by the game.
The survival horror aspect is treated quite well, with combat usually being filled with tension, even though I rarely had a time that I was actually that short on resources. I was a little frustrated that you always started over with your gear each new "episode" or chapter of the game's story; I tend to hoard items and equipment and so I had to struggle with the game discouraging long-term hoarding even as the mechanics encouraged me to manage my resources tightly. The frustration I felt with the dodge mechanic was always amplified by the poltergeist sections; I usually found it easier to hide behind objects during those parts, where I could be more or less safe until I'd destroyed or moved past the flying objects, rather than trying to dodge around them; especially as the gentlest carress would take a quarter of the health bar.
I haven't played through the two optional episodes which are unlocked after completing the game yet. I'm partway through the first one, but it's just not nearly as much fun as the game proper. I appreciate actually being introduced to Mr. Scratch, Wake's evil alter-ego, theoretically loose in the real world as Wake is trapped in the Dark Place, but the combat encounters are very different in tone. While appropriate for the Dark Place, it's very jarring to go from a situation where I only ever got close to running out of ammunition and the encounters were very cut-and-dried: wipe out all the Taken, and then move on (you could sort of run from the Taken, but most of the time they'd just keep spawning nearby after you left a safe zone until you finished them off) to a situation where the Taken often appear to spawn infinitely, and ammunition is extremely rare. The Taken are tireless and faster than you, which makes running from them particularly difficult. As a result, I die a lot more frequently in the bonus episode and have less fun -- it's tiresome to deal with combat encounter after combat encounter where your only choice is to try to run away and then turn to shoo off any Taken that get too close. I still really want to finish them because the game's story still has its hooks in me, but as I very gradually feel more myself and my own game calls to me, the frustration of dealing with tedious combat encounters makes it hard to get back into the game.
In any event, I got Alan Wake for a song off of GOG during some sale, and if you run across it on GOG or Steam for cheap, I highly recommend it, because it's a really good game.
By Brian On 2014-04-03 14:08:45 Permalink
On The Path to Discovering an Abstract Game Map Representation
Well, I didn't quite get my weekend goal. I actually played some games this weekend, and losing hours into Smugglers V didn't help me achieve my own programming goals. Speaking of that, it's a fun little game. Reminds me a lot of Space Rangers, only there's less to do on-planet (very Sid Meier's Pirates-style on-planet stuff), and the way that combat is handled is very different. Combat is done in a 1-on-1 style separate combat system, with turn-based, action-point-oriented, ability-driven mechanics. Frankly, it plays a lot like a card game, where your abilities are cards that you play on the table. It's fun. Very sandbox-y, and should play very well in small bites, which is something I have come to enormously appreciate in a game.
Anyway, I didn't quite reach my goal. I do have the ability to select tiles from the tileset working, and when you select a tile, it becomes your cursor on the tile map, where eventually you'll place it and it'll be rendered. I spent some time struggling with an odd problem. wx, for fairly understandable reasons, has their own string objects, but they encourage programmers to use std::string or std::wstring in their own stuff that interacts with wx. As a result, I spend several places converting wxStrings to std::strings. This mostly works just fine. Unfortunately, when retrieving data from a custom dialog (and dialogs in general, but custom dialogs -- wx::TextCtrls -- seem to have this problem worse than standard dialogs), I can't seem to get a good std::string back out of it. I can get the wxString just fine; it outputs the expected data. But when I use wxString::ToStdString() to convert it to a std::string, I end up getting an empty string back. I finally had to do an incredibly stupid workaround: I called the std::string constructor on wxString::mb_str(). I suspect that it might have to do with the transient scope of the converted String, but I'll have to do some more testing with it to see if I can fix the problem. If so, it's really just a matter of needing to clone or copy the string instead of trying to use its reference. Guess I'm learning that the copy constructor isn't always such a terrible thing. :P
For reference, I'm going to use the word "StageMap" for the representation of the game's playable area (i.e. "map," "level," "stage," "floor," or "zone"). That helps me differentiate it from any other word "level" or "map" (like the datastructure).
So the other problem I'm trying to tackle is getting a good grip on the data structure I need to store the stagemap data in. I spent a lot of time trying to decide if I was looking at the situation, and deciding the various pros and cons of different data structures. The problem is really sort of two-fold. I need to have an abstract version of the stagemap stored, which can easily be saved independently of the tilesets contained in the stagemap. I also need to have a renderable version of the stagemap, where the tiles are stored in sfml::VertexArrays. Traditionally, the abstract form of a game grid is a two-dimensional array. However, unlike a chess board, my stagemaps might be different sizes, and I really want to make it dynamic -- you don't have to know how big the stagemap is going to be when you initially create it; it'll grow to fit what you draw. That means it's really more like a two-dimenional vector; or a vector of vectors. (I don't know how practical that is, and I might have to make a vector of vectors class that can do all the work of keeping the vectors unified sizes for each dimension (all x vectors are the same length, all y vectors are of the same length); we'll see). If the stagemap only grows in the positive directions, that's not that bad; we're just pushing abstract tiles onto the ends of each vector. But it won't just be growing along the axes, sometimes I'll be placing tiles near the 0-position of an axis, and then I need to shift all of the vector contents down that axis, effectively "growing" the low-index part of the gridspace. In just the abstract datastructure, that's also not terrible, even if those operations are fairly slow.
I've been trying to decide if that's the right method, or if I'd be better off storing the abstract representation in something like a linked list, where I'm only storing the actual placed tiles instead of storing a whole bunch of empty space. I'll need to do some math to figure out how bad storing everything, including empty space, in these big crazy vectors is going to be. In the vector representation, the position of the tile is pure metadata. I know by the indices of the vectors where the tile exists in space. So all I have to store is two integers (more or less) -- the std::map keys of the tile set and the tile within that tileset (I use std::hash() on the names of the tileset and the tile to build the std::map key values, which produces std::size_t type values). For this thought experiment, we'll place a 10x10 room in a 15x15 gridspace, and use 4-byte ints as the std::size_t values. The room will require 10 * 10 * 4 * 2 = 800 bytes. However we don't just care about the room, we also have to store all the empty squares around the room. As a result, we're actually storing 15 * 15 * 4 * 2 = 1800 bytes. Our storage requirements scale linearly with the gridmap size, not the stagemap size. Due to the vector growth formula, this will actually end up being something more akin to growing exponentially with the stagemap size.
If I use a linked list (or similar) representation, I'm only storing the actual placed tiles, which dramatically decreases the virtual space being stored. However, I have to separately store metadata like the gridspace area (so that I can grow it when appropriate), and each of the abstract tiles has to know its x,y coordinates, which is another two integers, bringing us up to a total of 4 integers. For our 15x15 space, we only store the 10x10 room: 10 * 10 * 4 * 4 = 1600 bytes. That's a modest savings of 200 bytes. It's maybe that's worth while, because that value scales linearly with the size of the stagemap itself, not the grid; it doesn't care how big the grid is.
For fun, let's use something bigger. Say 1000 x 1000 gridspace, with 75% of the tiles contained in that gridspace actually having useful tile data in them (the rest is space around the stagemap, or "holes" in the stagemap between rooms and the like). The vector representation requires the full gridspace to be stored: 1000 * 1000 * 4 * 2 = 8000000; about 8 Megabytes (how "about" that is depends on how pedantic you are concerning metric prefixes). The linked list representation is 1000 * 1000 * 0.75 * 4 * 4 = 12000000, or about 12 Megabytes. Wow, those two extra ints made a big difference.
The VertexArray department is not without its problems, which are pretty much shared with the linked-list version of the abstract stagemap. The VertexArrays store exact position data on the placed vertices, and so moving things around is not as easy as just applying a transform to an sfml::Sprite. When I insert to the front of an abstract stagemap vector, I'll have to iterate through all the vertexes in all the VertexArrays and move all of them appropriately. I get to pick between the easy relocatability of Sprites (I could seriously just make them children of a Transformable object, and then transform that object to move all of them around; it'd be pretty easy), or the much more efficient drawing capability of the VertexArray approach (only one draw() call per VertexArray; remember theres one VertexArray per tileset, so on some/many stagemaps, that's a single draw() call to render all the tiles). Considering that the average stagemap will probably be hundreds or thousands of tiles (a 10x10 room is 100 tiles alone), efficiency in draw calls is an optimization I need. So iteration over the tileset is the way it's going to have to work. I guess the lesson to take from this is "don't grow the map up or to the left if you can help it."
But the similarities between the VertexArray and the linked-list version of the abstract stagemap gives me pause: maybe I don't need an abstract version at all. I'm already storing location data for each tile quad in the VertexArray, each VertexArray already knows its tileset, and I can theoretically back-calculate the tile from the (u,v) coordinates of the first vertex in the quad. That means I should be able to reasonably serialize the VertexArray to create a composite tileset containing only the tiles used from each component tileset (I know that I want the finalized, "game-ready" stagemap to only contain a single tileset for performance reasons). I'm already going to have to iterate over the VertexArray to move the quad coordinates around when I change the gridspace's size. While another datastructure might be convenient, I don't think it's necessary. The real problem then is replacing tiles. With a separate data structure, you just look the tile up in it (which is at worst O(n) and at best constant time), then you know which VertexArray contains the original tile quad (which can be removed). Without that separate data structure, we'll need to walk every VertexArray and look for the existing tile to replace. Here's the kicker: without a separate datastructure (which can know if that gridspace it represents is empty) every tile placed is treated like it's replacing a tile. That means checking every single quad in every single VertexArray for an overlap. That's going to get slow in a hurry. In order to address that, I'd be back to a list or a std::set, which would at least have to know the location and the tileset (and then we could search the tileset for the tile); so I'm back to eating up a bunch of memory.
Sorry for rambling on you all there; I was thinking through the problem out loud, and frankly, this was a big help, even if I'm still trying to sort the problems out and decide what's going to be best. I'll have a lot of time for thinking this week, but not much time for writing code: I'm on a trip for work for a big chunk of the week. Hopefully I can at least figure out how I want to tackle this.
By Brian On 2014-03-24 17:31:57
Last Edited 2014-03-24 17:43:01 Permalink
State of the Project
March 21, 2014
GUI programming is much less fun that I expected. Code::Blocks has a presumably nice wx layout widget thing (wxSmith) which I probably should have set my project up to use (and I might still, because this has been a drag, and there's a lot of editor pieces left to write). Instead I'm coding everything by hand. I've finally started to get the hang of Sizers, which are great, as long as you're trying to make your window the minimum size it can be. Of course, some windows should be the maximum size that fits in their parent window, and I haven't quite figured out the best way to approach that yet. Fortunately, that's a fairly minor issue, but writing just this basic functionality into the editor has taken much longer than I'd hoped.
I never was much of a C++ dev. I was a servicable C programmer (Computer Engineering classes don't get much higher level than C, you know), but certainly no rock star. And I'm using C++11 concepts (especially std::unique_ptr<>, which is pretty great), and when I learned C++, that was called "C++0x" and nobody supported any of it. As a result, there's been kind of a learning curve. That's a major factor in how slowly my code has been coming together. I'm also largely ignorant on a lot of key programming tools and concepts, and I'm not entirely sure how to remedy that ignorance. Notably, testing (which I gripe about a little more below) and actually using the debugger. I only barely understand the debugger and can't do much more other than add watch variables and breakpoints. So learning to recognize when I'm doing things right and when I'm doing things wrong has been part of this process. I didn't even know what an Initialization List was before this project began, and those are amazing language features. It alone solves a bunch of the things that I've always wondered how to properly do.
I'm still trying to figure out how to write unit tests, so I, uh, don't really have any tests in the code now. Partly this is because I don't understand how to write unit tests for GUI code at all, but mostly this is because I haven't spent the time to sit down with some proper unit test documentation explaining how to approach writing various kinds of unit tests.
Don't get my griping wrong though -- I'm having a lot of fun writing and debugging this software. It's more exciting than most things that I've spent time on lately. I've barely even played any games in the last few weeks because I'd rather be working on my own; which is a great sign, as far as I'm concerned. I love doing what I'm doing, even the grindy parts where I spend two hours debugging what turns out to be a fairly minor mistake on my part. At the point of this writing, I've got my editing grid, the ability to create tile sets, and the ability to add tiles into those tilesets, complete with controls that represent the tiles in a "palette" window. My goal for this weekend is to allow a user to select a tile and place it on the tile map. Maybe I'll even get removing tiles from tilesets or saving tilesets implemented. It's an exciting time to be alive!
By Brian On 2014-03-21 12:14:32 Permalink
SFML with WX
One of my primary goals with Threatened Destiny is that I won't hard-code behaviors and objects, even for testing purposes (if I can avoid it). That means that the editor has to lead the game, certainly at first anyway. Since TD is built with SFML, it makes sense that the windows in the editor that represent the game should also be in SFML, but the need for an editor to have a "traditional" GUI makes me not very eager to write the whole thing in SFML, even though there are some GUI libraries for SFML which I'll probably use in the actual game.
Specifically, I'd like the usual sort of menus, split screens, and tabbed representations that we see in normal applications; which makes Qt or wxWidgets a natural choice. I decided I'd run with wx; I've had slightly more experience with it, and the SFML site has a few examples of wx/SFML integrations on it. That meant it was easy just to take somebody else's work instead of having to reinvent this particular wheel (yes, I do actually pick-and-choose which wheels I care to reinvent).
Turns out there are some gotchas with this (I'm using the wsSFMLScrolledWindow from the wiki, but these would probably crop up with the panel tutorial too). First and most important; SFML RenderWindows don't resize the way you think they should. When you resize the window (RenderWindow::setSize()), it tells the RenderWindow that it has a new size, but (my guess is due to the complexity of changing an OpenGL context's size) the window doesn't actually change its size yet. The window has been notified of its new size, but it can't take the new size on its own; you have to recreate the window, just by calling RenderWindow::create() again. An important note is that this can cause the scroll bars to move around, if you have them always drawn and the RenderWindow is smaller than the container window's available area. (That is, instead of drawing the scrollbars at the edges of the available area, it moves the scroll bars to the outside of the drawable area; which is probably more correct anyway. I'll worry if this is actually a problem once I have a RenderWindow that is larger than the available area -- the far more common case than what I have now).
Another snag is that, at least when you're dealing with a RenderWindow which is smaller than the available wx ClientSize area, when a resize event fires, the SFML View is resized. Which is all well and good and correct...except that it is trying to project the same size RenderWindow in a new, larger view, rather than believing that the area it should be displaying is larger. That causes scaling and "stretching" in the appearance of the RenderWindow. This problem can be corrected by recreating the RenderWindow in the resize event again. That seems to prevent the RenderWindow from stretching due to the change in the wxClient area.
One big issue that I'd struggled with for a few days was that the RenderWindow seemed to have some very strange drawing behavior. When I'd draw into the RenderWindow, it'd move (0,0) somewhere into the middle of the allowable space in the containing wxSplitWindow frame, and it'd draw the whole side of the frame black (as though the RenderWindow had suddenly taken up the entire frame, except that the rectangle of the RenderWindow wasn't the size of the whole frame). When the RenderWindow was simply allowed to be constructed, but nothing was drawn to it, it'd be the proper size with (0,0) in the upper-left hand corner. I did some experimentation based on a conversation from the SFML forums between a guy with a similar problem and the guy who created SFML. By calling getDefaultView() after I recreate the RenderWindow in a resizing situation (specifically when I initially resize the drawing area for my grid), I guess I refresh the default view of the RenderWindow to match the window's new properties. It still turns the whole containing frame the "clear()" color, but that's a pretty minor issue; the important thing is that it now actually places the drawing at the correct (0,0) location.
I also finally finished my math for drawing my gridlines. Why am I doing math instead of just tiling an image? Because I'm not that bright. Also, I want to be able to dynamically grow the map area during editing, and I feel like actually drawing the lines might make that easier. And since I'll have to do a bunch of math to determine the square grid locations of tiles on my isogrid, familiarizing myself with the isogrid math is probably a good idea. (As I mentioned before, I'm planning to use a classical 2:1 symmetric axiometric perspective, what we gamers usually call "three-quarters isometric" or a really common form of "2.5D") For a long time, I had a mostly accurate but somewhat buggy implementation based on my intuitive grasp of the isogrid. The other night I actually went to the effort of reviewing my trigonometry and building the correct math formulas. They turned out to be extremely similar to my intuitive version, I'd just messed up some of the line calculations. Now that the isogrid is drawn, it's time to turn my attention to the actual image tiles and containing tilesets, and then I'll be able to actually generate a map.
I suppose I should start considering if I can develop a Boost::serialization setup for my desired data formats, and if I'll code the serialization or try to use introspection to automatically generate the serializations....
By Brian On 2014-03-04 15:04:37
Last Edited 2014-03-04 15:36:28 Permalink
You may have noticed that these early blog posts sort of look different from each other -- the font sizes are all over the place, some of them have odd line spacings or extra blank lines where they shouldn't. It might not bother readers, but it certainly bugs me. I'm not especially excited to go through them all and correct them, but I probably will once the look of them drives me enough up the wall. See, I think I figured it out: Some of the posts I stored in Evernote before publishing them: I just copy and pasted them out of Evernote, or in some cases, out of the editor on the blog into Evernote and back. I suspect that Evernote applied some of its own stylization (font size in particular) to the post, and the result is that the posts got a little mangled. I guess that's going to be something that I have to keep in mind if I keep storing entries elsewhere during the writing process. Part of this gets back to how the blog is unfinished on the back end: while I do have Draft functionality, getting back to the drafts of posts and publishing them is inconvenient, as I don't have the page which lists draft messages for easy editing. Someday, oh someday...
-- Edit --
So the visual inconsistencies finally did get to me; and I went through and corrected everything. Part of the problem was a difference between TinyMCE3 (which the first two posts used) and TinyMCE4, but most of the issue was indeed due to copying and pasting in and out of Evernote. I'm glad to have that sorted out now, rather than later. This also should correct the issue that the RSS feed validator was complaining about with "potentially unsafe styles."
By Brian On 2014-03-03 15:05:54
Last Edited 2014-03-04 15:24:25 Permalink
RSS Feed Online
Since I personally consume most of the blogs I read via RSS (since the loss of Google Reader, I switched to hosting my own Tiny Tiny RSS instance and am quite happy), having an RSS feed available has always been on the roadmap. But after I started making "we should blog more" challenge noises at Josh, he pushed me to get RSS up immediately, as he consumes all his blog content via RSS, and I promised I'd do my best.
Frankly, I'm disappointed that I had so much trouble finding an RSS feed generator that was both free and good. Everything out there either costs money, produces a hilariously barebones feed, doesn't produce completely valid RSS, or some combination of those. That means I might as well write my own, which I'd actually wanted to avoid. Ah well... So now I have my own semi-valid barebones feed. At least I can grow the features of the feed as I add those features to the site itself. I do have the feed validating through an RSS validator, though it complains about some of my older posts (the new version of TinyMCE, which I use for post editing, produces way less spammy style garbage; and the validator is warning me about some of those old style attributes). I haven't decided if I want to leave two posts with dodgy style attributes in the feed, or if it's worth my effort to go in and sanitize and re-sign the posts in question.
I'm also debating if I want to include my GPG signatures for articles in the feed. I probably also should work out a cache on the feed itself, so that it doesn't have to regenerate this growing XML file at every request (which is dumb). Ah well, dumb and working beats smart and broken, so at this time it'll do. Fixing that will be reasonably high on my list. Right now, I don't have too much content, so rebuilding the XML is no big deal. But in the future, if I manage to keep after writing in this blog, that'll become more resource intensive than I'd like.
By Brian On 2014-03-03 14:50:01
Last Edited 2014-03-04 15:06:01 Permalink
Threatened Destiny: Underpinnings
Some Wheels Don't Need to be Reinvented
Before I get into the more interesting aspects of developing a game, or specifically my game, I want to take a look at the technological underpinnings -- that is, which wheels I'm reinventing and which giants I'm willing to stand on the shoulders of. I've noted before that I take great inspiration from Sea of Memes, partly because the developer, Micheal Goodfellow, also learns by doing, and is therefore willing to redo work that's been done before by others, partially so that he understands it better. That tendency to learn by doing and my general contrarian nature cause me to reinvent a lot of my own wheels. Unfortunately, I'm not always the only one saddled with my educational decisions -- a chunk of my company's webpages are driven by an Ajax library I wrote myself to learn how Ajax works, and we have only begun the task of replacing it with something better.
That said, I'm not willing to do all the work. Low-level input handling is something I just don't really care to ever do, and I'd like to limit my graphics card wrangling to stuff that I decide I want to do rather than "everything." So I'm perfectly willing to use some libraries and frameworks to support me, even if I'm building the engine myself. Fortunately, I'm working in 2D, where building an engine is still somewhat socially acceptable (as if I really care about that :P ). I decided a while ago that I wanted to use open system abstraction layers rather than tying myself to DirectX; so I was going to use OpenGL and the SDL. I started looking at languages based on their support for the SDL; which happens to be "pretty much whatever you want has a binding to the SDL."
I'm nominally a PHP dev, but I'm not enough of an idiot to try to write the game in PHP. The only other languages that I've had any great experience with are Java and C/C++, and I hadn't written much C++ in years. As terrible as I was with Java, it was my "best" language, and according to the Programming Languages Shootout, the new Java is darn close in performance to C++. Unfortunately, I also have played Minecraft, and for better or worse, soured me on games written in Java. I thought about LISP, as I've always wanted to learn LISP, but considering that adding two numbers together makes me feel smart, it'd be too much of a leap for me to grasp. Python is too slow. I seriously considered Pike, as I really like that little language, but as I started to explore using the SDL with it, I discovered that the SDL had more-or-less recently gone through a major revision and its documentation had not caught up to the change. So I thought, hey, maybe there's something better. And lo, there was SFML.
SFML covers input, windowing, and audio; and it does it all on top of OpenGL and OpenAL. It's object-oriented, which is attractive. But it's a C++ library, so that'd have to be my language of choice. I'd already been wanting to use YAML for data storage anyhow, and having an existing library for it would save me a lot of trouble; I'd have to write my own in Pike. In the end, that's what tipped the balance: libraries. In C++, I could get introspection libraries, compression libraries, and data language libraries; bindings for scripting languages, all kinds of features. And I used to have a grasp of it, so it wouldn't take too much work to pick the language back up.
So I ran with C++, and I've picked up Code::Blocks with MinGW for my IDE. I'd originally planned to use Eclipse, since I had the most experience with it, but I had a lot of trouble getting SFML to set up and compile right with Eclipse. Besides, C::B is a pretty solid C++ IDE, which makes it a little easier to do what I need to do with than with a "Swiss army knife" IDE like Eclipse.
Sorry for the rambling, but it helps establish certain things which I'll build on in future posts.
By Brian On 2014-02-27 15:24:51 Permalink
Living the Dream
So I mentioned in my last post that I gave myself the dubious gift of making a game. I guess I should expand on that a bit.
"Oh, wait," I imagine someone might hypothetically say, "if you tell us too much, someone might steal your game!" Considering that everybody has a dream game, I imagine that this supposed someone will likely make their dream game before they decide to make mine. Besides, the only reason I want to make a game is because nobody seems to want to make it for me. If I end up being able to play more than one game that is my dream game, isn't that better? So, frankly, idea theft here, when it is just an idea, is not a concern. Many game devs say the same thing: everybody has ideas. There's really no risk of someone swooping in and taking yours. And even if they do; ideas aren't things. If someone takes your idea, hey, you've still got your idea.
That all aside, let's explore what I've decided I dream about. See, ever since I was a kid, I've dreamed of two games. The first was a platformer, with 3D models and environments, but in an orthoganol perspective, so it still behaved like a traditional 2D platformer (keep in mind, that this was right when 3D was just starting to be a thing; so I was already being optimistic about the technology). When I got into my teens, Duke Nukem: The Manhattan Project came out. Hell yeah, dream come true. It's awesome when somebody makes your dream game. So maybe someday I'll explore that dream too, but frankly, I feel like I was given a great gift with TMP. That means I'm focusing on the other game dream: a science fiction RPG. A true RPG, set in a sci-fi universe.
When I say "true RPG," I mean it. In recent years, that field has been somewhere between vacant and lonely. Mass Effect is about the only thing that fits in that category, and it isn't everything I could want in the game of my dreams -- but I'll save my gripes for another post or a video. There's fantasy RPGs a plenty, but science fiction is pretty rare. Maybe it's harder -- it takes more world-building work to make up something that's supposed to be a projection of the future rather than a whole-cloth universe (though I'm doing "future projection sci-fi" myself, it occurs to me that there's no rule that you couldn't do your sci-fi setting from whole cloth either; the X series kind of sort of does this). Science fiction seems reserved for "action RPGs," which actually means "action game with a couple largely meaningless stats and a pointless inventory system." That's not what I want. I want a game where you actually play a character, solve problems in-character, talk to other characters in-character, and have to make hard decisions as you guide someone down a narrative path of at least partially your own choosing. Shadowrun, Fallout, and the upcoming Wasteland 2 kind of scratch that itch, but I want something set in more of the Spacefuture, rather than post-apocalypse or just near-ish future cyberpunk (much as I like cyberpunk). So I feel like I am going to have to do this myself in order to get it done.
I've always been enamored by what I used to call "three-quarters isometric perspective." Visually, I still can't get over Ultima 8 and Crusader: No Remorse. So I think I'm going to shoot for a visual style not unlike those. But the science fiction RPG that always sticks in my head, what I'm going to try to honor "spiritually," as it were, is MegaTraveller: The Zhodani Conspiracy. It was a phenominal RPG, with a fun adventure hook, Traveller's crazy character creation system, and a great combination of both on-planet and off-planet movement. Maybe it's just my nostolgia, but the game was very formative for me. I'd like to honor that experience, with some tweaks and choices of my own. So that's kind of what I'm aiming for.
And let's be honest: I'm making this game for me. If nobody else likes it but I do, then I'll be a little disappointed, but still happy. After all, I made my dream and it was good for me. If other people like it, so much the better. I'm setting this in a universe I invented when I was 14, so for now, I'm going to start with the name I came up with for it then. Will the name change? Maybe, I dunno. But for now, it'll do: Threatened Destiny.
By Brian On 2014-02-27 13:07:03
Last Edited 2014-03-04 15:07:03 Permalink
What's All This Then?
So what's the point of all of this? And by "this," I mean the silly custom blog. Why not use something reasonable, like Drupal or Wordpress or Joomla or something? (Feel free to stretch "reasonable" to mean whatever CMS you have as your favorite, those are three arbitrary choices.) Especially since I'm already hosting Wordpress for a friend, and have a Drupal install that I'm already ignoring? Well, like I said before, it's mostly "because I'm contrary." But also I like to reinvent the wheel to learn how wheels work, so to speak.
In this case, I wanted to learn how MVC (Model-View-Controller) design worked. The easiest way for me to learn something is to do it. I'm not alone in learning that way -- I find myself in the company of Micheal Goodfellow, whose Sea-Of-Memes project is a constant inspiration, for instance. So I picked something inconsequential, but complex and useful enough to actually be educational: my blog.
I had a couple specific goals when approaching the blog too. I wanted a built-in way to use my GPG key to sign my posts. I like, from the perspective of being a technology guy, that my friend Aesir Delcroath signs his blog posts and I wanted to do the same thing. Unfortunately, the procedure for signing posts is a real drag: write the post in something else, feed it into your encryption utility, sign the post, and copy that whole block into the blogging engine. Heaven forbid you have to update or change your post, and if your post isn't just textual data, it's an even bigger pain. So I wanted my blog to be able to sign my posts on its own.
I also used to flirt with drawing comics (I am being exceedingly generous with that statement), and I'd still like to have the ability to post that kind of thing, particularly in a sequential form, if I felt like doing so. Right now, that's pretty awkward -- either your blog engine is designed for sequential content, or it's not, and doing one in a system designed for the other is, at best, awkward.
Finally, like I mentioned earlier, I have a Drupal install that'd theoretically be used for posting content for my gaming groups. That install uses a post-style called a "book" -- posts can be related to each other as parents (chapters/subchapters) and siblings (adjoining pages). I want to preserve that kind of capability, and it ties in nicely with doing sequential artwork. I've also got a variety of domain names for various personal projects, and I've considered allowing them to cross-post on each other (like letting most content show up here on my blog, but having those individual sites showing just the content that pertains to them). That gives me some goals to shape my development, and help me continue to learn.
Unfortunately for this blog, I recently picked up another project, so it's not getting much love in the development department. For my thirtieth birthday, I gave myself the gift of writing my dream computer game, since it would appear that nobody else seems to want what I want. In other words, I've become tired of waiting for someone else to invent my dream game, and I might as well take a crack at it myself. I've been spending a lot of time with that, though I'll save those details for later posts.
By Brian On 2014-02-27 12:09:50
Last Edited 2014-03-04 15:09:50 Permalink
Welcome to the New Deviant Paradigm
Welcome to the new and improved Deviant Paradigm!
The old "eye-searing red" site was definitely showing its age, and I hadn't really been keeping up with it in...well...many, many years. It was long due for an update. In fact, this is something like the third update that I've attempted, though this is the first one to actually end up replacing the old site.
Of course, there's not much here yet. I'm hoping to change all of that in the near future. I've been tackling a lot of new projects, and still fiddling with some old ones.
I'll write up a post later detailing some of the reasons I decided to write my own ridiculous little CMS instead of using one of the well-respected names in the field. Hopefully they'll be better than just "I'm a contrary old cuss," but that's probably the main reason.
Since this is still very much a work in progress, there's a long, long to-do list for it yet, but I couldn't wait just to get something up and available. Fortunately, most of the heavy lifting that's yet to be done is on the posting and post administration side, so it's invisible to users. I hope to, in future, support some actual searching, certainly by tags (which requires a lot of rewriting, actually, as I did tags in probably the dumbest way I possibly could initially, and need to rework them), and also probably by full-text. I'd like to support commenting (which is why there's a "Login" link up there), and some neat user features like Favoriting and Watching posts. Not like that's going to matter for a while, but it's stuff on the roadmap anyway.
Anyway, welcome back! It's a new beginning, and I'm glad to have you with me.
By Brian On 2013-11-19 22:55:38
Last Edited 2014-03-04 15:18:47 Permalink
·"They Hit Me With a Truck"
·Fictional Games In Fictional Worlds
·State of the Project
·A Pulp Serial of Mars
·Watch_Dogs, A Review
·State of the Project
·There's Always More To Say On Player Agency
·Threatened Destiny: Narrative Themes
·Being Sick and Playing Alan Wake
·On The Path to Discovering an Abstract Game Map Representation
·State of the Project
·SFML with WX
·RSS Feed Online
·Threatened Destiny: Underpinnings
·What's All This Then?