SummerJammers Update #8: Clip Show

It's a time-honored television tradition: a holiday arrives or the budget dries up or the writing staff just can't be bothered to put together a new episode, so they write a few minutes of setup and run a clip show featuring bits and pieces from earlier episodes. In many ways, that's what this long-overdue SummerJammers (a Giant Bomb themed WindJammers homage) update feels like. About a month ago, I finished up the last work on building the basic rendering and timing framework for SummerJammers, and around that time, I, exhausted by the process and struggling to change gears from technical design to gameplay implementation, took a few weeks mostly-away from the project to work on a few other things (writing comics, designing a board game, and (barely) working on that job situation). As a result, there's not a month's worth of new stuff to talk about here, so instead I'd like to look back at what I've learned since I started this thing in November and cover whatever other small miscellaneous fun facts have either popped up in the last month or slipped through the cracks in previous updates.

If At First You Succeed, Try Again Anyways

For me, working on SummerJammers is about two things. First, it's about creating a finished product, a well-produced and well-designed game where Brad and Vinny throw frisbees at each other (if you'll allow me to borrow the ontological argument here, such a game is the best possible thing, and a good thing is better if it exists). Second, it's my attempt to learn how to make a computer game, to take my modest but non-zero knowledge of computer science and programming and stretch it to a meaningful level. That second point is why I've chosen to shoulder such a large part (all, so far) of the coding and design burden despite being knee-deep in talent here at Giant Bomb.

It's also why progress is slow. Someone somewhere probably once said "amateurs practice until they get it right, professionals practice until they can't get it wrong," and if they did, then they've pretty much summed up my experience so far. It's not enough for me to write code that works; I need to understand why it's a good (November 2013 would have demanded "perfect," but more on that later) solution to the problem at hand, and that can be a lengthy process. It usually entails trying a different approach, even when I've got something that already works. It's sort of a "breadth first" approach to programming; I try two seemingly viable paths until one of them presents a massive issue, at which point I look back and say, "oh, right, that's why I liked it the other way." It's no way to make a game, but it's a hell of a way to learn. I've developed a much better eye for potential roadblocks as a result, and that's exactly what I'm looking for in this - a chance to learn my shit while I'm not necessarily on the clock or the payroll.

That'll Do, Pig

I've definitely toned it down in the months, though. On day one, I was satisfied with nothing less than the One True Design that would make everything as elegant as possible. However, the thing about working on a big program like this is that there are so many moving parts that no one solution will be universally optimal. Understanding -- or rather, accepting -- this has been the slowest and most painful part of this for me, and if it weren't for the constant reassurances of ol' college buddy, computermancer extraordinaire, and all around decent guy Adrian, I probably never would have accepted that something, somewhere, will inevitably have to give. A corollary of this is that the most exhausting problems for me are the "easy" ones with plenty of good solutions because I'll invariably dissect each and every implementation thinking that one them must be a magic bullet.

The good news is that I've loosened up a bit in this regard, and I'm far more comfortable hacking together a quick solution and refining it as I go along. I still do the occasional bit of pre-optimization (a cardinal programming sin), but overall I'm OK saying "I want this thing to do that," writing some code to make it happen, and then just fixing whatever other code I just broke until everything compiles again (the magic of a strong compile-time language like C# is that 99% of the time, just getting the code running will also get it doing what you intended). I've moved away from spending hours of planning before coding (and remember, we're just talking about software design here, not even game mechanics) and have largely moved to an on-the-fly iterative process. It's great. Do that.

Git On Up

It's also helped that (at the behest of, and with much help from Adrian) I've set up my first-ever version control repository. I'm doing all the things the cool kids do. I commit and I push and I oh holy hell I just borked my program, revert, revert! In addition to being a good thing to know about if you want to do big-time game making, getting acquainted with version control has actually helped me focus on smaller goals while I program. What would I like to put in today's commit notes? Great, start working on that. It also gives me an excuse to more frequently check in with myself and assess what's getting done and where I'm over-thinking things. And now there is a permanent record on the internet of how I've implemented and removed the Avatar class at least three times. Yeesh.

Learning, remember. Learning.

Also, all this Gitting nonsense has made me realize that, hey, fuck it, lets get some more hands on this project. I originally planned to do an overwhelming amount of the SummerJammers code on my own, outsourcing just the asset creation and a few tasks like networking and AI. However, now that I have a better big-picture view of the whole process, I feel a lot more ready to have folks contribute more of the nuts-and-bolts code. I've learned a hell of a lot, almost enough for one project, so I'm looking forward to rallying the troops, putting together something we can be proud of, and playing that young SummerJammers, son. After all, the first thing I'm going to do once SummerJammers is done is make another game, so there's no point in holding up production in the hopes that if I do enough of it on my own that I will become a Master Programmer/Designer/Casnova.

So give me a month or two (let's aim for two final solo updates in March) to tie up some loose ends and clean up... well, a lot of code, and we'll put this thing into overdrive. Considering that I've already written most of the collision detection, animation, and player input frameworks, there's only so much that could go wrong from here. Right? Right? I mean, come on, it's already a thing where circles throw a smaller circle at rectangles. And in a way, isn't that all we are? Just circles throwing circles.

1 Comments

SummerJammers Update #7: A Matter of Time

In case you missed it, I'm working on a Giant Bomb game inspired by that old chestnut, Windjammers. And it needs your help!

Yeah yeah yeah this update is a few days late. But oh man, is it worth it.

Interestingly enough, this is the first time that I've ever written a program with time dependency. My other work has mainly been logical and computational stuff or tools for working with turn-based board games, but nothing that actually has to keep an eye on the clock. So the past week and a half gave me my first ever real-time challenge: animations. This was something I wanted to come at blind, so I didn't look up how to code animations or anything like that. I just read up on XNA's clock features (which are simple yet robust) and got to work. The result is an Animation class that holds a list of AnimationFrame objects that hold references to an image and a TimeSpan object indicating how long the frame lasts. The original implementation had each Animation keeping track of when it was being started in absolute time (for example, 3 minutes and 14 seconds after the program launched) and then attach that information to its frames (so frame 3 knows that it should start at 3 minutes and 14.2 seconds). This worked, but came with a number of problems, the biggest of which was the need to be continually creating and destroying new Animation objects (since they referred to an absolute start time). The system also didn't present a neat solution for mid-animation speed changes, so getting it to behave properly when, say, a player's run speed drops mid-stride, was cumbersome.

But praise the sun for showers, because it was in the shower that I got the idea to do the obvious smart thing and instead use XNA's built-in ability to see how long it's been since the game last updated itself. Accordingly, I changed each animation to simply keep track of how far along in its progression it is (.7 seconds since it started, for example). This immediately solved the issue of speed changes; if it's been .02 seconds since the last update (which was .7 seconds into the animation) and the animation needs to run at half speed because the player became dazed on that very frame, then it simply cuts the time jump down by a factor of two and sees which frame it needs for .71 seconds instead of .72. This system also eliminates the need to be constantly building new animations, since you can just reset an animation's progression when you need to start it (instead of building a new one with a new absolute start time). I've also built in support for one-off and looped animations.

The player on the left has thrown the (fully collision-enabled) disc to the player on the right. The "2" indicates that the players are on the second frame of their standing animation.

Working with animations has given me a good sense of how most time-based issues will be handled in the game. Essentially, it's one big application of Euler's Method, a system for approximating a curve by using the instantaneous rate of change from a large number of discrete points. That's exactly what we're doing here - we're asking 30 to 60 times a second, "how fast should this be happening" and then moving things along at that speed for a fraction of a second before getting a new reading. However, while the animations work beautifully, implementing them has exposed a poor design choice in separating my Character and Avatar objects, but that fix is underway and pretty straightforward, so it's all good.

And now seems like as good a time as any to start recruiting folks to contribute!Right now I'm interested in getting the art and sound departments staffed up. I'm looking for two (2) people to act as heads in each department. Ideally, these folks have some experience in their field, because they'll be in charge of setting the tone and ensuring the consistence of both the quality and style of assets. The overall audiovisual design (retro, gloomy, futuristic, etc.) is more or less in the hands of the department heads (though we will definitely need to agree on it!). The graphics engine is exclusively based on 2D sprites.

So if you have some experience and want to be a department head, shoot me a private message by Friday, Jan 31 at 5 PM PST telling me which department you're interested in (obviously) and what experience you have in that field. If you want to contribute but don't want to be a department head, just hold on and we'll get to that in about two weeks once we've named some heads, who will be free to field as large a team as they desire. As for additional code contributors, we'll need people to work on networking and AI, but that probably won't be until the game is otherwise feature- and asset-complete.

There probably won't be an update this Monday, what with it already being Thursday and all, so good luck and #BeatRemo.

1 Comments

SummerJammer Update #6: Lights, Camera, Action

Well, maybe not lights, but certainly camera and action.

It's been a good week for SummerJammers. I only put it in two days of work, but I managed to knock out something big each time, and here are the results:

- Camera. The old render system drew things directly to the viewport, which would be a problem if I ever wanted to do things like zoom and pan. The new system is a 2D camera with a 3D position, with the z coordinate (which describes the distance from the things being drawn) used to handle zoom. This means that objects that are closer to the camera (like a popped-up disc) scale up in size so that the scaling doesn't have to be baked into the animations. The camera also, conveniently, automatically handles the letterboxing and related corrections that need to be made. The camera just takes a predefined chunk of "world space," transforms that chunk into "camera space," and then applies the resolution scale matrix to get it to "view space."

-Component framework. I completely removed the whole "trickle down" structure of the components. While it was nice to have a quick way for things to get passed down throughout an item tree, it made it harder to write code for more complex items, which ended up needing their own custom implementations of some of the component features. This eventually led to a lot of cases where there were two different ways to get the same results, which is bad form, so I scrapped the idea of having children managed at the Component level and instead have each game object do its own custom update calls (so instead of checking a generic UpdateableChildren list, a Match will explicitly send calls to its Disc and PlayerAvatars and etc.).

- Hit detection. Done and done. I use axis-aligned bounding boxes, which are rectangular prisms (since I'm using 3D space) with each edge parallel to one of the coordinate axes. Seeing as how the majority of motion in this game is simple translation, this is a perfect fit and the whole thing was crazy easy to do. In the course of about four hours I learned all about hit detection and then designed, implemented, and tested the collision system. It works! As for game-wide hit checking, it's pretty easy since there aren't that many objects that need checking, so I just check the disc against the players, bumpers, and goals and then make sure the players are in their allowed court regions (it's a lot easier to say where an object is allowed to be then where it isn't!). It's probably worth mentioning that XNA has built-in classes for bounding regions but that I am writing my own because I want to learn as much as possible about collision detection.

-Game logic! What I like to call the ons, the methods that tells objects what to do when certain game actions occur. For example, Disc has methods called OnCollideWithPlayerAvatar that resolves a collision and OnThrown that does things like clear the flag saying that it's being held by a player. This is the standard language by which all of the game objects interact with each other, and it's a good practice because it ensures that important attributes of objects aren't changed without permission and without doing all of the things that need to trigger when certain values change.

- Other things. Small things like adding code to relate the world location of an object (which I like to be the center of the object) to the draw location (which is upper-left-corner based) and some stuff that allows for image scaling for non-resolution-related factors, like if the art for a given character is a different size than the character's hitbox.

As of today, there are officially two Giant Bomb Windjammers remakes in the works (the other can be found here). Do I feel bad that somebody got as far in eight hours as I have in.. how many hours ago was November? Not at all! While this is by no means my first time coding, it's definitely my first time doing anything that draws to a screen or has hit detection or is, you know, a game. It's been slow going, but it's just because I've been learning a lot as I go and I don't move on until I fully understand what I'm doing. That is, of course, until I get down the line a bit, realize I didn't know what I was doing and go back and fix things (I'm looking at you GameComponent). The good news is that I'm out of the woods with regards to new stuff. All the rendering, collision, and file structure work is largely in place, which means that from here on out I'm doing stuff I already know how to do, which in turn means faster progress. Unless, of course, I keep falling down into computer science rabbit holes and spend half the day reading about red-black trees and culling methods.

But in a practical sense, this means there are now two projects which will potentially need contributors, so I'm going to put off the call for peeps until at least next week's update. Both projects seem to be in roughly the same place, so the big difference seems to be that this one is using XNA/Monogame and that one is in Unity, and also that I've never done anything like this before (but it's coming along nicely!). I have no interest in merging projects since the whole point of this for me (other than ending up with a bitchin' game) is to learn how to make a game from start to finish, so SummerJammers is here to stay. If you're looking to contribute code, however, definitely give the other project a look, as it's open source and all up on GitHub. Aside from network stuff down the line, I'll probably be handling all of the code myself, but need teams for art and sound asset creation.

So that's it for now. I'm off to clean up some code and add some more input logic. Next week I'll definitely be asking for contributors, so check in if that sounds like fun.

3 Comments

SummerJammers Update #5: Ask Forgiveness, Not Permission

If you're new here, I'm working on a Giant Bomb themed version of the 1994 Neo Geo "classic," Windjammers. It's like pong with a frisbee.

We're back. Here are some screenshots.

Welcome to the world of placeholder art! The big circles are player avatars, the small red circle is the disc, and the little red bar in the upper right corner is a goal. The first shot shows a player holding the disc (I haven't touched any of the position "origin" logic, so the disc goes to the upper left hand corner by default) and the second one shows the disc in motion. For testing purposes, I can control both players with a single X360 controller, with player one moving about on the left stick and player two via the right. Yes, this means that I can play SummerJammers against myself. No, I have not been doing that.

So what's new since last time? On the surface, not much. The throwing is new, and I fixed an issue with resolution scaling (and centered the letterboxing, which is what those blue bars on the top and bottom are). I did a little bit of work on moving some of the hard-coded test code into more generalized implementations; for example, the players now get their control schemes properly constructed instead of being hard coded to respond to particular inputs from my X360 controller. I also finalized how I'm implementing the GameComponent class (not using the XNA one at all).

The rest of my time on SummerJammers - and it honestly wasn't much, what with the holidays and all, most of my work has been in the past 24 hours - was spent thinking about further engine changes and (gasp!) some actual mechanics. Firstly, on the engine front, I'm probably going to redo the render system so that it uses a "viewport" that essentially views a projection of the render surface. The transformation math is really trivial for a physics major like myself (which is good, because this part of XNA's library isn't its most user-friendly bit), and I think it will make it a lot easier to deal with z-axis stuff like disc pop-ups and (another gasp!) jumping, possibly. There are times when I'm still tempted to redo large chunks of the GameComponent framework until I remind myself "it's flexible and modular, you can override methods in your subclasses if you need to" and move on to something else. I've been doing a lot less pre-optimization lately, taking a more "get it up and running in some fashion now, generalize it later" - the "better to ask for forgiveness than for permission" of programming - and it's been working out very well for me. Fortunately, I've done a pretty good job of "black box" programming, which is ensuring that when part of the program needs to talk to another part, it doesn't have to worry about how the sausage actually gets made. Part A will simply ask, "hey, Part B, you got that thing I need?" and Part A does some hidden magic and produces a result. This makes tinkering with the innards of individual parts of the program fun, easy, and less likely to break a lot of other things in the process.

So let's move to the fun part (although, to be honest, all the "thankless" engine work so far has been incredibly rewarding and educational), the actual game mechanics. I haven't implemented anything yet, I've just made some short pro-con lists and thought things over in the shower and over my giant whiteboard (but not both at the same time). Here have been some of my musings so far.

1) Dual stick controls? Moving with the left stick and throwing by flicking the right could allow for more in-air control of the disc, but would also restrict the range of usable controllers and increase reliance on using back triggers on controllers, which isn't always a great idea when you need to be precisely working two analog sticks at the same time.

2) Charge meters? The special moves system in Windjammers has never struck me as particularly elegant, so it was one of the first things I thought about in terms of mechanics. Right now I'm coming down against charge meters, as I don't want the game to devolve into a "play it safe until you can drop a special" fest. Making the specials feel rewarding without having the game be all about them is definitely the biggest design question on my mind right now.

3) Jumping? I'd like to reward players who can take control of the court and push right up to the center, and I think having the ability to jump and spike the disc could be a good way to do this. Think of it like guarding a ball handler in basketball - if they're so quick that you have to stay back from them so you don't get passed, you're unable to pressure them on a shot. Jumping would also make for a great way to punish a misguided lob attempt. Get that outta here!

In other news, I'm cutting the update cycle down to one week from here on out unless I think I''ll be unable to do much work for some reason. The 2-week turnarounds usually end up with me putting in a few days of work, finishing what need finishing, and then taking the rest of the time off, and I'd like to get this train a jammin' if you get my drift.

ALSO, HEY, it's time to seriously talk about staffing up over here. I'm hoping to have the collision detection and viewport rendering all done by next week, which means that I will be more that ready for assets. So here are some things I'm going to need help with:

1) Art and animation assets (all 2D). I can handle the logic, we just need the assets unless you really like my big white circles. Style will largely be left up to the department head(s).

2) Sound and music.

3) Networking (probably not until the game is otherwise feature- and asset- complete)

4) Something else, I'm sure.

I'll keep doing the design, logic, and writing (story mode, baby!). I would like each department to be headed up by one or two people who know what they're doing and would be in charge of whatever people they can scrounge up. Since we can't sell this game (for obvious intellectual property and likeness rights issues) nobody's getting paid behind any of this. Next week's update will hopefully include a formal call for department heads, so start thinking about it. If heading the department isn't your kind of thing, you can still contribute as a team member! What do we think would be the best way to manage all of that? Google doc for sign-ups? Let me know, we have a week to think about it.

So happy 2014 and Jam like nobody's watching. I'mma go add some collision detection. See you next week!

3 Comments

SummerJammers Update #4: The One Where They Finish Up GameComponent

Having been awake for 24 hours, I was slumped over in a chair in a physical therapy office's waiting room while my friend was doing some work to recover from ACL surgery. The previous night, if it could be called that, was supposed to end at a somewhat reasonable 1 AM. I had finished setting up the file and asset structures for SummerJammers and decided to do a quick debug run to make sure that everything was in place and that all of the new code was working as expected. And it was, for the most part, save for a funky little bug where the PlayerAvatar object was receiving Draw calls but not Update calls. I traced the issue to a known issue with how I was implementing SortedSets, namely that a DrawableGameComponent (formerly known as SuperDrawableComponent before I just decided to hide the existing XNA.GameComponent classes) would always try to compare itself to other components using its DrawOrder even when it was supposed to be comparing by UpdateOrder. So I took a few minutes and thought about polymorphism and blah blah blah and decided that it could wait for tomorrow, seeing as how I had an early morning of driving my buddy to PT.

But Blizzard works in mysterious ways, and one email check, one Hearthstone invite, and six hours of digital card-slinging later, I'm there in that waiting room feeling strangely alert despite the protestations of my eyelids. I had forgotten to bring a book to read, so instead I thought about my tumultuous month-long history with XNA's GameComponent class. I had written, deleted, and re-written a lot of code to get the functionality I needed out the GameComponents while still using as much of the existing XNA library as possible, and before the previous night's Hearthstone binge, I had closed up my work with a nagging feeling that I was on the wrong track a bit, that I was going in circles and that my issues with the SortedSet were just symptomatic of a problem that Microsoft had been smart enough to forsee – hence their particular GameComponent implementation and the design of the GameComponentCollection class.

But there, as The Sitting Dead in the waiting room, it hit me. I understood how the XNA GameComponent architecture worked and how it was incompatible with my needs. I understood how a lot of the code I was writing was adding funcionality that already existed in XNA for its GameComponents that wouldn't work for my implementation. After a month of chasing my tail and second-guessing myself about this most fundamental part of the game engine, I understood how my implementation – which greatly streamlines the process for dealing with GameComponent update and draw orders – is in fact a nearly ideal way to get around the many different constraints not just from the XNA library, but from the principles of good object oriented programming. I laughed a bit when I realized that in a month of work I had essentially just re-written a couple of out-of-the-box XNA features, but it was necessary in order to build the engine I wanted. And after all, how much can you really know about something until you take it apart and rebuild it?

So yeah, it's been a good week for SummerJammers. The component classes are complete and locked down, and I replaced the SortedSets with standard Lists and a custom sorting method to fix that issue. In more exciting news, I created all of the code that outlines how assets are loaded from files and used within the game. It's a system that ensures that assets are only loaded once (all praise be to sprite atlases!), can be shared between all game objects, and can be loaded either as-needed or at predefined moments. You have no idea how exciting it is to look at a file structure in code and say “holy shit, these are the sounds and images that are used in the game.” That's not to say it's a hard thing to do. In fact, doing the asset and file structure work has been the easiset part so far. And that was the problem. I had so many possible ways to do the file structure that I ended up writing and re-writing it three or four times trying to make it perfect. I've been bugging my talented and brilliant buddy Adrian for the duration of this project about big-time computer science questions, but I think the biggest help he's been so far has been when he just said “no one file structure implementation will solve every problem, so just pick one that works for you.” If not for that, I'd probably still be looking for a file system unicorn.

On a side note, let me just say that it's been a TON of fun getting an excuse to think more and more and more about the inner workings of computers. Sure, I've been tinkering with computers since I was in elementary school and took classes in computer science digital engineering in college, but it's nice to just have a new excuse every day to jump down another rabbit hole and learn about something in more depth or start making new connections between ideas. For example, writing the asset system got me thinking about the functional difference between the image file on your hard drive and a code object that your game keeps in memory for internal use. It's something I had thought about before, but working on SummerJammers has given me a reason to appreciate it.

So that's that. Basic engine stuff is done. The parent/child system for draw and update calls is working beautifully and is stupid easy to work with. Time to finish up the draw logic so we can start making a proper game, right? So by Monday, January 8, 2014 I want to finish up the code for drawing objects with arbitrary size and rotation and finish the resolution scaling code so that the screen is centered properly. Once that's done, you wont have to read any more of this technical jargon, which will be replaced with talk about doing some honest gameplay design. See you then, Jammerinos.

6 Comments

SummerJammers Update 3: I Came In Like a Wrecking Ball

Party time! Thanksgiving threw me off a bit, hence the extra week between updates, but there's been some craziness happening in the world of SummerJammers. Let's start by seeing how those goals from last time went:

- Fully implement Wall,Disc, and Goal classes

Goal is coming along nicely, including logic to construct goals out of an arbitrary number of GoalSegments for drawing purposes.

- Build a complete test stage with goals, wall, and bleachers

Nope. Turns out there was a lot of stuff that had to get done first, as today's update will make abundantly clear.

- Fully implement methods to convert on-court position to draw position

Done! Every drawable component has a DrawableParent and a RelativeDrawPosition, so it's super easy for a player to get it's on-court position and then add that vector to the court's actual draw position.

- Implement Draw transforms and logic for 1920x1080 and 1280x800 resolutions (more will be added later, I just want to have two different resolutions for testing purposes while I build that framework)

Done, and for any arbitrary resolution! Everything is first drawn to a virtual resolution that I set with two values in code, and then the SpriteBatch just scales the whole thing based on the target "real" resolution. Depending on the target aspect ratio, there will be either vertical or horizontal "letterboxing," but once I'm done with the Draw stuff this will just look like extra crowd around the court (as opposed to a big black bar). The virtual resolution will probably be 2560x1440, meaning that all assets will be designed with that resolution in mind so that only people running 4k screens will have to deal with upscaled textures. There are a few things I haven't been able to test yet, like position scaling, but the basic functionality is there. Also I need to add logic to balance the letterboxing so it doesn't just clump up on the bottom or right of the screen (the top left corner is the default scaling origin). Here's a screenshot showing the scaling effect from a 1920x1080 virtual resolution to a 800x600 target.

The area with the white crosses shows the full 1920x1080 area, and the brown area is a 2000x1000 texture, which explains why it doesn't cover the original 1920x1080 area.

So, What Else Is New?

The past three weeks have seen some pretty radical changes to SummerJammers. Entire chunks of code have been removed or heavily revamped, with the most notable example being the SuperGameComponent and SuperDrawableComponent classes. As I mentioned last time, the SuperGameComponent was my way of enhancing the standard XNA GameComponent class with ways to keep track of "children" that would receive Update calls from their parents, and SuperDrawableComponent added the same type of logic for Draw calls. The problem with my implementation (and I knew it would be a problem eventually) was that SuperDrawableComponent didn't inherit from SuperGameComponent, which is what you should do when you're just expanding an existing class with extra functionality. The reason was that I wanted to inherit some of the event handlers from the XNA.DrawableGameComponent class, which meant I inherited from that instead of SuperGameComponent (and remember, you're not allowed to inherit from two different "branches" of the class tree). However, I realized that the event handlers I was trying to inherit (changes to DrawOrder) were rendered obsolete by the fact that my "children" system uses a SortedSet class that automatically sorts when the "key" (UpdateOrder or DrawOrder) changes. This allowed me to unify my component under a single inheritance column, which is good news.

Of course, now that I've done all of that work, I'm starting to realize that the extra functionality I've built into my SuperComponents could probably just be left to the individual implementing classes, like Player, Character, or Stage. There's a lot of overhead that goes into creating the SuperComponents, and all I really get out of it in return is the ability to say "go Draw your children" instead of "hey, you're a Stage, you specifically have a Court and some Players to draw." This is especially interesting in light of the fact that I removed my ImageComponent class, which was a class that by default would actually draw things to the screen, and moved the literal drawing into the SuperDrawableComponent class (objects that literally draw are tagged with a boolean called "drawsImage"). This got rid of questions like "is a PlayerCharacter a SuperDrawableComponent or an ImageComponent?" and has made the code a lot cleaner and more uniform. But still, it's very possible that, when it comes to my component structure, I may be able to trim some fat.

So aside from the work on the components, I spent some time on the asset management side. I added support for texture atlases, which has dramatically cut down the number of texture loads (which are super slow) and will make it a lot easier to implement animation down the road. I've also started building structures containing things like Courts and Characters - the things you actually see in the game! It was super exciting getting to a point where enough game and draw logic was done that I actually had to start thinking about those things.

But there's still much to do before I start roping in folks to create the assets that will fill up those structures. For starters, there are still a lot Draw issues to manage, such as rotation and relative position for objects built out of chunks, like a Goal built out of GoalSegments. Also, I'd like to play around with using mulitple render targets. This would allow me to draw things that don't change frame-to-frame (like the court and other static images) to an off-screen buffer once and just reuse them instead of redrawing them every frame. It's probably overkill for a game like this, but it's good practice! And don't worry, I'll include logic that only uses extra render targets if your card supports them, so it won't keep you from Jammin' if your hardware doesn't meet the XNA "HiDef" requirements of a DirectX10 card.

So what are the next goals? I have no idea! There's a lot that could get done right now, but it's mostly working with existing features rather than implementing new ones. My instinct is to take another look at the component structure and make a final call on that and then tackle the remaining Draw issues. I'll cut this period to one week, so check back in on December 23, 2013 to see what's new. I'm hopeful that calls for assets will start going out in late January.

5 Comments

SummerJammers Update #2.5: The Human Element

Monday's deadline has come and gone with no update, and there are two reasons for that.

1) Other life stresses. Bills, roommates, existentialism, unemployment and assorted career uncertainty, and a weird combination of choice paralysis and hopelessness. You know, the good stuff. My stress release is games, so I spent a lot of last week with Dark Souls and Rogue Legacy, both of which are great, it turns out!

2) Thanksgiving. Being away from my routines for more than a week (kicking it with the family) knocked me off track. I wrote some pseudo code while I was gone, but when I got back I found it hard to immediately get back into things. Largely because of those aforementioned stresses.

So after a pretty lousy week, I ended up a friend's place playing some Pikmin 3, and being around my friends again helped me get back on the wagon. I've made hella progress since then and I think I should be able to have all the resolution-adjusted draw stuff and the practice court ready to go for next Monday, a week later than planned. As agonizing as last week was for me, I must have been processing some stuff on the back burner because a lot of the scary implementation problems regarding resolution scaling just up and vanished when I got back to work on Monday.

So yeah, proper update on Monday. See you then, and Always Be Jammin'.

Start the Conversation

SummerJammers Update #2: Components All the Way Down

(If you're not sure what subclasses and interfaces are, I've included some helpful definitions at the end of the post)

Welcome back! I've had two weeks to work toward some milestones, so let's start by seeing how that went.

- straight toss in player-determined direction

Incomplete. Disc implementation was pushed back to the next deadline.

- player "dash"

Done!

- basic player/disc hit detection

Incomplete.

- simple "incidence = reflection" disc physics

Designed but not tested since I haven't written any objects that implement the CanDeflectDiscs interface, such as walls.

Best Bug: By accidentally asking for my SceneManager service instead of the SpriteBatch service, I managed to create a fun little Draw loop that went: SceneManager --> Scene --> Player --> SceneManager --> ...

It would be easy to look at the lineup there and say "one and a half out of four is pretty weak," but it's actually been a remarkably productive two weeks. To understand just how much progress has been made, we need to talk a bit about XNA's "component" architecture. There are two component classes defined in XNA, GameComponent and DrawableGameComponent. A GameComponent is essentially just an object that can be "enabled" when it needs to interact with the game logic and "disabled" otherwise (the DrawableGameComponent inherits those capabilities but adds members to determine if it should be drawn or not). The components contain event handlers that get called when an object is enabled/disabled or shown/hidden, but but there's actually not much else to them. The actual Update and Draw methods are left blank, since it's obviously up to each particular component to determine how it interacts with the game and draws itself to the screen. There's nothing saying you have to use XNA's components, but they get the job done and having the event handlers all written is pretty nice, so I've been using them in lieu of writing my own component classes... kind of.

You see, there's a complication. XNA also contains a GameComponentCollection class which can group components to manage relative update and draw orders. So, for example, if I want to ensure that the players get drawn after the court (so that you can actually see them), I could throw the court and both players into a collection with the appropriate DrawOrder values and they will be sorted automatically. This is some pretty sweet functionality, but there's a huge catch. The type of things that are allowed to be stored in these collections are any objects that implement the IGameComponent interface, namely GameComponent, DrawableGameComponent, or any subclasses I write. The collection itself doesn't implement this interface, which means you can't have a GameComponentCollection full of GameComponentCollections. This is too bad because it locks out a really cool recursive implementation where a single Draw or Update call gets sent to a top-level object like a Scene and it trickles down, drawing chunks of objects in the correct order (and each individual object in correct order relative to its chunkmates).

So I toyed with a couple of solutions. My first idea involved subclassing GameComponentCollection to make a new class called SuperComponentCollection. I would make this component implement the IGameComponent interface, thus allowing it to store other collections as elements and give me the recursive functionality I wanted. This was less than ideal for a number of reasons, so I instead decided to write a subclass of the SortedList class that would essentially store and sort chunks of components. It was at this point that I remembered something very important: just because a method is called Draw doesn't mean it has to directly put something on the screen. This lead me to a ridiculously simple solution: just allow each component to keep a list of sub-components. That way, when a component gets a Draw or Update call, it can just pass the call down the line to its children, who will pass it to their children until it finally gets to objects that literally appear on the screen (a compact class I call ImageComponent). So I subclassed the GameComponent and DrawableGameComponent classes into SuperComponent and SuperDrawableComponent and wrote (my first ever!) custom Comparer class that told each object how to sort its children by update and draw order. It works beautifully, with a single top-level Draw call trickling down.

The life of a Scene.Draw() call in my final implementation.Every object is calling its own Draw(), but only the pink ImageComponent objects actually draw to the screen when they do so.

This is big. When I first started with XNA a few weeks ago, it took me a matter of minutes to get something drawn to screen and to move it around with an X360 controller. But that was all hard-coded hack work. Now I'm pretty much in the same place - drawing some dummy art and moving it around with an X360 controller - but it's all going through the proper channels. What's happening on the screen isn't a tech demo, it's the game's actual logic running. In a similar vein, I also built a lot of the IO infrastructure that decouples input commands from the particular device, so while I'm using an X360 controller right now, any device that has a C# library can be supported.

I also feel like I'm "over the hump," so to speak. There's that moment with most computer-science related problems where you can finally make sense of what's happening each step of the way, and I feel like I've reached that point when it comes to the update and draw flow, which is the game in many ways. So it's been a lot of foundation-building lately, but I've got enough pieces in place that I should be able to start putting together a complete practice match without too much fuss. I've got the Stage, Disc, and Player classes in a pretty good place and have started doing some work on mapping on-court position (which is resolution-invariant) to absolute draw position (which is resolution-dependent). So let's go ahead and set the next goal. It'll be modest for a two-week goal, largely because I'm out of town (and away from my desktop) for over a week for Thanksgiving (which is also why there are no screenshots). That means I'll largely be writing code and pseudocode in Notepad until I can get home and add it properly, so I'm largely going to work on things that are self-contained or brand new.

By 5:00 PM PST on Monday, December 9, 2013

- Fully implement Wall, Disc, and Goal classes

- Build a complete test stage with goals, wall, and bleachers

- Fully implement methods to convert on-court position to draw position

- Implement Draw transforms and logic for 1920x1080 and 1280x800 resolutions (more will be added later, I just want to have two different resolutions for testing purposes while I build that framework)

In other news, the community overwhelmingly approved the name SummerJammers, so thanks to everyone who submitted names and voted. Assuming I hit the next milestone, I'd say the call for assets and extra development will go out by the end of the year. In the meantime, can y'all do me a favor and tell me what your native resolution is? I'd like to natively support any widely used resolutions, and I'd like to know what they are before I start doing too much UI work.

Today's Vocabulary:

Subclass. A class which inherits all of the properties and abilities of another class but can add more specific unique characteristics. Poodle is a subclass of Dog- a Poodle can do all the normal Dog things like Bark and Eat, but it can also Strut, which not all Dogs can do. You can subclass a subclass (like Canadian Attack Poodle could subclass Poodle) but you can generally not inherit from two different classes at the same time (like Poodle and Retriever).

Interface: A sort of contract that states that any class which implements the interface is guaranteed to have certain properties and abilities. For example, the IDrawable interface could stipulate that any implementing class must have a DrawOrder value and a Draw() method. However, the exact implementation of methods is left to the implementing class, so you could have a class whose Draw() method does absolutely nothing. In return for implementing an interface, a class can be used any time that interface is asked for, so if a certain bit of code requires an IDrawable object, I can give it anything that implements that interface regardless of what type of object it is. Classes can implement any number of interfaces, in stark contrast to the limit on class inheritances.

10 Comments

SummerJammers Update #1: The Road Ahead

Welcome to Update 1! On the agenda:

1) Design philosophy

2) Name suggestions (Open until 5PM PST on Wednesday, Nov. 13)

3) Status report

4) Looking ahead

For those of you just joining us, last week I decided to get the ball rolling on making a Giant Bomb themed adaptation of WindJammers. The original plan was to have a design document posted today, but I've decided to heed the advice I've received from some GB community members and forego a long preliminary document in favor of more "on-the-fly" iterative design. Since so much of what will make this game is the feel of the action, it doesn't make a lot of sense to try to commit to design choices regarding controls, character differentiation, etc. when a lot of those those aspects will live and die in how well they are executed. However, I have cooked up a design philosophy, a set of goals that all other design choices should serve. They are...

Section 1: Design Philosophy

1) Accessibility - low barrier to entry. New players should be able to quickly feel comfortable using and understanding all gameplay elements, including characters, abilities, controls, and level objects.

2) Transparency. Players should be provided with clear real-time feedback to ensure that they understand how their choices impact their in-game success. Random or "hidden" elements should be minimized or removed entirely, and audio-visual feedback should be clear and immediate.

3) Risk-reward. Players should be encouraged to take chances that can help them seize the initiative in a match. Design should favor aggressive play and calculated risks over passive "safe" play.

When combined, these goals form the driving tenet for the game's design: players should be playing their opponent, not the game. That is to say that players should be spending their time thinking about positioning and head games, not struggling with the control scheme. They should be encouraged to use the full suite of options at their disposal, not just rely on a single move or tactic.

So that's the plan. The trick will be enhancing the core WindJammers experience to create a richer metagame and more varied matches without adding so much that it loses its pick-up-and-play sensibility that makes it a great spectator sport. WindJammers actually has a ton in common with Divekick, as both are stripped down, fast-paced 1-on-1 showdowns, so don't be surprised if I take a few design cues from Iron Galaxy.

Section 2: Name Suggestions

Internally, I'm using the name SummerJammers in honor of the late great Ryan Davis, the eternal King of the Summer Jams, but I think now is the time to open the floor to folks who would like to suggest a name. Just suggest a name in the comments, and if you see a name that you like that hasn't already been seconded by another user, then quote the name in a reply with "seconded." If folks could edit their suggestions when possible to indicate they've been seconded, it will save us duplicate seconds and help keep things orderly. Get suggestions in by Wednesday at 5PM Pacific Standard time and I will run a poll over the weekend to get us a winner.

Section 3: Status Report

I spent the early part of last week trying out various development tools that people suggested, and after a few underwhelming candidates, I fell madly in love with XNA via MonoGame using Samarian Studio as my IDE. For the uninitiated, that means I'm using an open-source version of Microsoft's XNA game tools (which they recently stopped supporting). For the target platforms of PC/Mac/Linux, things should be pretty straightforward, and there's built-in support for mobile platforms as well, though there may be some minor coding and design changes needed (which is something I look forward to outsourcing to you fine folks).

Once I decided on MonoGame, I familiarized myself with XNA's drawing and I/O methods, which were ridiculously easy to get up and running. This is my first time using C#, so I spent a good chunk of time reading up on best practices with regards to naming convention. Most of my coding experience is in Java, C++, and Python, and I was surprised by how little C# resembles the burning hellscape that is C++ despite the similar names. It's a much easier language to use, though I must say I'm not a big fan of not having to explicitly refer to an object member using the "this" keyword" (I've made a habit of always using it, and when I open the doors to community contributions, the style guide will remind you to always use it, as well).

Speaking of community contributions, let's talk about how I'd like all of that to work. As I mentioned when I announced the project, I'll be handling the core of the game since I'm trying to bone up on design and coding skills. Once I have a working prototype of the core gameplay (two things throwing discs at each other with local 2-player action) I'll start asking for folks to volunteer as either contributors or department leads (in areas such as art, sound, music, networking, etc.), and my role will largely shift to a managerial one (though I'll still be tweaking gameplay and working with anyone who wants to help with testing). Folks have been asking about putting the project up on GitHub, essentially making it open source, and while there are no plans to do so in the near future, I'm amenable to doing it down the line once the project has legs to stand on. In managing a project like this, consistency trumps quality, so I don't want to open the doors until there's a strong "voice" established and guidelines are in place to help keep code readable and flexible.

In fact, most of the actual coding so far has been organizational in nature. I've mainly been working on scene management tools with the objective of making everything as modular and independent as possible. I've been making good use of XNA's "services" (which experienced coders will recognize as essentially being global singletons). For the less code-educated, these services provide a way to assign certain types of events to be handled by particular objects. So for example, I've created a class of objects called Scene and an object called a SceneManager to deal with changing, running, or stacking scenes (so, for example, if there's a menu you access by pausing the game, it can just hold the game scene off to the side while you deal with the menu and then bring it back when you're done). The SceneManager handles all scene related events, so I've made the SceneManager class implement an interface called ISceneService, which just means that it's guaranteed to be able to handle any events that need to talk to an ISceneService.

The really cool part, though, is that I can use XNA's service framework to configure things such that if an object ever needs to handle an ISceneService problem (like the player selects an option that closes the current scene), all it has to do is shout "HEY I NEED SOMEONE TO HELP ME WITH THIS ISCENESERVICE PROBLEM" and the SceneManager will roll up and take care of things. The cool part is that it doesn't have to ask for the SceneManager by name - it just shouts that it needs whoever is in charge of scenes and waits for the service to send someone! When it comes to laying the groundwork for a project that will eventually have a lot of people working on it from all over, this is freaking awesome! If I end up needing to change the guts of the SceneManager class - or even replace it entirely with a new class like SceneOverlord - it won't affect anybody else. They just ask for the ISceneService manager and are none the wiser!

Section 4: Looking Ahead

So that's that! Not a lot of game to speak of so far, but that will change by our next milestone, which I'm setting to be two weeks from now.

Update #2 Due at 5 PM PST on Monday, November 25: Create a basic "practice" mode that can be used to test/iterate things like player movement speed, disc speed, controls, and basic physics.

Target features:

- straight toss in player-determined direction

- player "dash"

- basic player/disc hit detection

- simple "incidence = reflection" disc physics

Screenshots will be provided!

That's it for this edition, folks! Remember to get your name suggestions in by Wednesday! And mods, if these updates should go in Off Topic instead of General Discussion, let me know.

9 Comments

The Once (and Future?) Consoles

A new console generation looms, so who's holding the right cards? Or even knows what game they're playing?

As an exclusively PC-based gamer, new generations of gaming consoles have always been life-affirming events. With no brand loyalty or need to justify one console purchase or another, I've always had the luxury of sitting back, grabbing a snack, and watching the internet become fucking awful for a few months as the rabid fanfolk try to convince equally stubborn people that the thing that they bought and enjoy wasn't the right thing and that their joy is just ignorance manifest. And with Sony and Microsoft gearing up for the November launches of the Playstation 4 and Xbox One, respectively, I once again get to enjoy the fireworks (from a safe distance, of course).

Except this time, there's a catch. The last console generation debuted in 2005 with the Xbox 360, making this generation a record-shattering seven-plus years long, and in those years, the gaming industry has gone straight bananas. The name of the game for winning a console war hasn't changed - it's still all about offering something the competitors can't (and that consumers want) - but the old playbooks have been rendered obsolete by massive changes to the industry. As a result, this console generation launch coincides with the most interesting era for gaming in my admittedly short lifetime. Everything from how games are funded and developed to how they are distributed, played, and bought has changed beyond recognition (and seemingly overnight), which means that as devotees sing the praises of their chosen platform, they're shouting over a very interesting conversation, one which is driven by one hell of a question: is this the last true console generation?

Let's answer that question with a question: why the hell do people buy a particular console, anyways? And then let's answer both of those questions (following proper stack ordering, of course).

The Old Gods: Power and Exclusivity

My favorite part of console wars is when folks start tossing around spec sheets. Clock speed, RAM, other fancy shit; if it can be used to show quantitatively show that someone's consumer choices are objectively correct, you can bet that it will spew forth from sycophantic forum-goers when they're not busy putting Yogi Berra to shame with witty terms such as "Gaystation 3," "X-sucks three shitty," or "Nintendo sucksty four." The next generation (which technically includes the already-launched WiiU, but more on that later) has Sony, for the first time since the rivalry started in 2001, fielding a more powerful console than Microsoft. The difference doesn't look to be that big between the PS4 and XBONE, which means that Sony really can't use that small bit of technical superiority as leverage with developers who would be willing to give Sony an exclusive title in exchange for bleeding-edge power. And that's really the thing about console power: unless you're either way ahead or way behind, it's kind of a non-factor. Developers are typically more interested in user install bases than specs, and gamers know that you don't play spec sheets; you play games.

Even growing up console-deprived in the mid 90s (correction, I had an original Game Boy) I knew that what sold a console was its game library. I remember seeing this Sega ad that compared their (in their mind) drag-raceresque Genesis to the broken down jalopy that is the Super Nintendoand laughing every time. Why? Because that jalopy can play fucking Mario. Super Nintendo had the games worth playing, and everyone knew it. When asking for some help deciding between the consoles for her son, a 30-something family friend opened with "there are no games for the Sega," so all I had to do was nod in agreement. Sure, Sega had the horsepower, but they never leveraged it to get an expansive array of exclusive titles that would sell their console. With the 32x add-on hardware for the Genesis, Sega doubled down on the whole "power" angle, but to no avail. Nintendo entered the next generation with unstoppable momentum and a lot of killer franchises while Sega was sent back to the drawing board.

It's worth noting that while surpassing the Joneses doesn't guarantee a win, falling too far behind them in the power struggle isn't recommended. Case in point, the WiiU, which has spent its months-long head start on the PS4 and XBONE becoming the laughingstock of the gaming biz. While a lot of that has to do with some ridiculously ineffective brand messaging (if you thought the WiiU was some sort of add-on for the Wii, you're not alone), the console's lack of power is making a bad situation a lot worse. Even EA, which has never seen a multiplatform release it doesn't like, is having a hard time singing the WiiU's praises due to trouble getting its Frostbite engine (used in the ever-popular Battlefield series, amongst others) to run on the console. Even if folks want to make games for the WiiU, they can't in some cases due to technical limitations, which means that there will be a lot of games that both Sony and Microsoft can use to lure away prospective WiiU buyers. The WiiU can still do other things that the other boxes can't when it comes to motion controls and asymmetric multiplayer via its touchscreen, but unless a lot of developers can find a use for those features, the WiiU won't get enough third-party exclusives to make it competitive with the big dogs.

So if exclusivity is king and power isn't enough to claim the crown in the next generation, what's it going to take? What can Sony and Microsoft do to differentiate between their seemingly equally-matched boxes?

The New Gods: Discs, of All Things

This might sound kind of dumb given that we're talking about boxes that allow people to play video games, but so far the biggest question that's come up with these new consoles is will this thing allow me to play video games? Consumers want assurances that if they pay money for a game then they will be able to play it on their terms whenever they feel so inclined. Again, this might sound like a no-brainer to the uninitiated, but the rise of purely digital distribution and "always online" single-player games has gravely wounded the traditional and straightforward "buy a disc and enjoy" model that has managed to stagger to the finish line of the current console generation. Digital distribution is already a major player on the PC, with Valve's Steam platform leading the charge, but it took a while. A long, long, long while. But has Valve managed to refine Steam from "that thing that downloads Half-Life 2 patches" into something which, while it has its issues (like its Greenlight program for indie titles, for example), has brought unmeasurable value to the PC platform by making it very easy to buy games and play them without draconian rights management systems.

So part of me was a bit surprised to see Microsoft announce a shopping and DRM infrastructure similar to Steam's and get ripped to shreds over it. Sure, Microsoft did a pretty lousy job of highlighting the benefits of the system (or even getting two people within the company to agree on how it all would have worked), but I was personally shocked to see that a system that has proven itself on the PC get such a rough reception on consoles. While it's true that the Microsoft plan was a bit more adamant about maintaining a connection to servers than Steam is, it was a bold and necessary step toward bringing consoles out of the physical era. Some of the features it promised, including a family game-sharing plan and digital buybacks (which have been announced and tentatively announced for Steam, respectively), are going to be mandatory parts of any full solution to the "digital problem," and Microsoft's decision to drop their plan in favor of the traditional disc-centric approach for the XBONE has ensured that the next-gen console war will take place at the kiddie table while the bigger issues of digital distribution and ownership are tackled by PC and (hopefully, because they really need to get with the times) other media such as film and television.

Of course, it's easy to see why gamers would have a knee-jerk reaction in favor of their discs. While the secondary market for games has gotten a bit confusing with DLC, online passes, and registration keys, it's still there and it's still massive. You can also easily borrow discs to play (typically single-player) games in a legal or legal-ish (depending on how you interpret the EULA) way that gets complicated with digital downloads. So there's no doubt that the all-digital future, while it contains many benefits for consumers (which, as Steam shows, can take years to become apparent or welcome), is definitely a sweeter deal for developers and publishers, who can use the internet to sell directly to customers and fight piracy via always-on or "check-in" systems. But hey, physical media got us this far, right? What's the worst that could happen if the next console war is fought with a last-gen mindset?

Less Money Mo' Problems

You really don't want to know.

Making games has gotten ridiculously expensive lately. When Square Enix can sell a trillion or so copies of the critically acclaimed Tomb Raider rebootand not call it a win, it's easy to see that the video game market is not going to survive in its current form. The past year has seen the erosion of gaming's middle class, with sizable (but not behemoth) companies like THQ and Lucasarts being shuttered in the past year. It's no coincidence that the megapublishers like Ubisoft and EA have turned to milking any and all series that can guarantee a profit or artificially enhancing a game's connectivity needs (*cough* SimCity *cough*) to reduce sharing and piracy. But the real winds of change are felt in the form of microtransactions and "freemium" games. If you own a smart phone, then you probably don't need to be told how these things work; you can just look at your purchase history and see that you bought some item unlocks in Plants vs. Zombies 2 or the ability to have multiple games of Letterpress going simultaneously. And while the freemium model is probably here to stay, expensive, powerful, disc-focused consoles aren't the optimal ecosystem for them. Mobile devices have a much larger install base, offer a unique but familiar control scheme, and typically offer enough power for the more casual-friendly fare found in the freemium aisle. Sure, there's nothing stopping freemium games from working on consoles, but they won't do anything to measurably extend the life of the idea of traditional set-top boxes.

Nor, for that matter, will the other response to (and only real silver lining of) the death of mid-range games: indie games. While the next generation will far outdo its predecessor by offering self-publication and knocking down development hurdles (every retail XBONE can be used as a development kit), the fact remains that indies aren't the ones clamoring for new hardware every few years. That's left for the big dogs who have the budgets to max out hardware halfway through a console cycle. So while consoles may finally offer a home that indies find as welcoming as the relatively wild-and-free PC, they're generally more concerned with ease of production and distribution (and patching, as we learned from Fez) than they are with power.

The Singularity Is Near-ish

The indie-friendly atmosphere isn't the only way in which consoles are starting to resemble PCs. With every generation, console system architectures more and more converge with what you'd see on a PC, a fact that becomes obvious as you look at the ever-improving quality of games that are ported to PC from consoles (compare PC versions of Saints Row 2 and 4 if you don't believe me). So while they're perhaps still behind the PC when it comes to digital distribution and hardware modularity, the comparison between consoles and computer is more apples-to-apples than it's ever been. So you'd probably think that this will soon render consoles obsolete, right? I mean, if getting that console experience is as easy as hooking a PC up to a television, then what do they really offer to justify their existence after the next generation?

In a word: simplicity. I absolutely love PCs, but I've spent my entire life figuring out their quirks. I've done things to get games running that would get me arrested in twelve states (including a sublimely archaic ritual to prevent Heroes of Might and Magic 2 from crashing all the time), and I loved all (okay, most) of it. But most folks aren't me. Most folks probably don't want to have to do a driver wipe or edit their registry or fiddle with AUTOEXEC.bat or do any of the things that happen when people release software that's supposed to work with an infinite number of possible hardware configurations (except yours). They want to put a shiny thing in a box and play some Madden, and consoles can make that dream a reality without throwing a hissy hit like a PC. It's a fine line that Steam's newly announced Steam Box tries to ride, but I'm not convinced that PC-style flexibility and console-flavored reliability aren't mutually exclusive (of course, this won't really be an issue if user competency outpaces computer complexity). So I think that after the WiiU, PS4, and XBONE there will be more boxes you place near your TV to play games, and I think that they will come with preset hardware configurations. What remains to be seen, though, is whether or not they will have physical media drives and, more interestingly, whether or not they will simply stream cloud-processed data and images to your screen. Frankly, as long as the game market is strong enough to support innovation, I'll be happy. And I'll probably still be right where I am now: in front of my PC.

*Resposted from my site, www.theschemehatchery.com

8 Comments
  • 18 results
  • 1
  • 2