Friday, May 27, 2011

I scroll, you scroll, we all scroll . . .


Making the tiles scroll was actually a bit easier than I thought it was going to be, and I feel like I leveled up a bit because this was the first Skeleton Wizard problem I tackled by just rolling up my sleeves and jumping in there, rather than comparing my code to another game that was already doing what I wanted.

I used to be terrified of the word algorithm. To me it evoked graduate-level math teachers scrawling impenetrable glyphs across lecture-hall sized chalkboards. After a few weeks of programming tutorials and books, I finally had a perceptual breakthrough: an algorithm  is simply your plan for solving a particular programming problem. When I thought I was just trudging angrily between my cubicle and the cafeteria, muttering to myself about why the damn tiles won't line up properly, and scaring small children . . what a was actually doing was developing algorithms!

So for the tile and background scrolling behaviors I devised a system that I figure is probably at least as old as Mario, and may not be optimal but it works: The player is always in one of three "zones", or vertical sections of the screen. If the player is in the center section, the wizard moves freely. When the player enters one of the left or right side sections, the wizard stops moving and the tiles move instead. Many tweaks were required to get the behaviors I wanted, but after another few days of lunch-break muttering I found the proper code to make the player interact with the environment in a way that feels pleasing.

If I didn't know any better I'd think this was starting to look like a game . . . is it time to add bad guys already?

Thursday, May 19, 2011

A Real Background and a Real Bug


Well, it's still dopey programmer art but at least I'm not looking at a flat grey-blue wash. I made this thing 4000 pixels long so once I have the scrolling code the art will be ready to go. Unfortunately, I ran into a kind of technical snag that I haven't encountered before: XNA is telling me that it's having assembly problems, and that some of my stuff was originally built with a different version of XNA than other stuff. It offers to fix it for me by altering an "app.config" file, but if I take it up on the offer the game throws an exception while loading the wizard's texture and won't start.

This is frankly the kind of baffling, scary, dot-net hokery pokery bullshit that I hoped to avoid. It really is true that if you are even dabbling in game development you'll eventually have to figure out just about everything related to your tools, but I dread trawling through msdn pages trying to parse out the nature of a Visual Studio compiler error. One minute you're sailing along making wizards jump over pine trees, and the next you're elbows deep in the dirt. So it goes.

I have been shuffling the build between work and home computers using ftp, could there be a difference between the two versions of Visual C# 2008 I have installed on each machine? If there was such a significant difference, why would it suddenly rear its head? I tried removing my most recent class, which controls the background, to no avail.

Here we have, for the first time, an entirely persuasive argument for version control, even at the toddler-dev level. Since I'm absolutely certain that this bug was not always there, when I get home tonight I can just step back through my version tree until I find a build that doesn't have the bug, then look at the changelog and I should have my answer. Easy, right? Like so many other things, before I try it, it couldn't look easier. . .

 EDIT: I had a bit more downtime this afternoon and did some search engine sleuthing . . . I still don't know exactly what the hell happened here, but it turns out if I go to Project > Upgrade it rebuilds the solution and the error goes away. Best guess: When I was creating the background class, I fat-fingered it and created an XNA 3.0 class instead of a 3.1, because 3.0 is still an option in the menu and it's conceivable I could have done that. Why just deleting that class didn't fix the problem I don't know, it must have done something to the compiler that could only be resolved with an "upgrade". Windows! Yeah!

Monday, May 16, 2011

I have levels!


The tile engine infrastructure is starting to pay off. After working out the animation bug (I was totally right about it), I whipped up some programmer art and implemented the idea of Collidability - different kinds of tiles will react differently to player collisions. You can hop directly up through a bridge and then land on it, but a block will stop you.

Things I'm looking forward to (the bullets are back baby):
  • Bullets (not the list kind, the shooty kind)
  • Enemies
  • A background
  • Scrolling - I want each level to be the same height as the screen but much longer.
  • More Hud stuff, level indicator, points
  • Some stuff to collect for points
  • A GUI level editor (no clue where to even start with that)

Sunday, May 15, 2011

A Disturbing Development


Here I was all proud of myself for doing a thing or two . . and I'm going to try to get through this update without a bulleted list, so here are the things I did: 'shopped up a doors.png with some doors and got the game to display them, created a placeholder title screen and at least the concept of a game over screen - it's currently blank but it happens in the right place! Still having a problem where SW will lose two lives at a time, haven't bothered to go looking for it yet but boy the kids would riot over a bug like that in my day, all those quarters lost . . gotta solve that one quickly.

SW also has a new jump animation, which is just two frames dependent on facing, and a four-frame falling animation that I actually feel kind of cool about. I set the animation to start when the player's falling speed was over a certain limit, and clamped the animation into two sets of two frames that the game flips between dependent on player facing. So in most cases when the player is falling he shows just a single posture, arms straight out, but if he falls far enough to where his speed breaks that limit, the animation kicks in and he starts waving his arms in panic. In the future I want to dial in the values around this to where you only start waving your arms around the fall height where you're starting to get injured . . . maybe. . . still not entirely sure I want to implement fall injury, but if I do I certainly want to use animations in this way to telegraph potentially bad falls to the player with a margin of error wide enough where the player can adjust, maybe be able to take a single bad fall so the controls aren't unforgiving . .

That's all great, but why does the Skulled One  have octopus arms? I'm not 100% sure, and it's late enough to where I'm in no shape to deal with the problem tonight, so I'm just going to be Armchair Developer and spin some theories here with my pipe and slippers, which is of course way more fun that actually getting in there with a mental machete and hacking your way through the code.

The Load Content function grabs a bunch of textures of the player, which get turned into animated sprites, and then in the Player.Draw function I go through a bunch of ifs and elses to figure out which way the player is facing, if the player is jumping or falling, etc, and then based on that the game grabs whichever animated sprite corresponds to that behavior and throws it on the screen.

My water cooler quarterback guess is that I put two if statements in a row when I should have put an if and an else statement. So the game says "Oh, you're facing right? here, have this sprite. Oh, you're jumping? Here, have this sprite too." I haven't properly separated these questions to produce the correct results.

I hope to the Gods of Programming it's something that easy.

Wednesday, May 11, 2011

That Grim Specter


Skeleton Wizard can never really die of course, but since this is a classic platformer, I have given our hero a number of lives, which can be taken away if he does something foolish like falling off the bottom of the map. At present nothing happens when you hit zero, so I'll need to do a state / screen framework to allow for a "GAME OVER" situation, which means I need a title screen, plus I'm getting tired of looking at that blue background, and the Wiz could use some jumping and falling animations . . . sounds like an art push lies in my near future.  

Monday, May 9, 2011

It was a TYPO


I had a modulo sign where I should have had a division sign, but it's an instructive moment for two reasons (I enjoy bulleted lists, does that make me evil?):
  • The reason I allowed such an elementary typo was that since I'm uncomfortable around unfamiliar or poorly-understood math (like our friend the modulus operator), my eyes will kind of glaze over and I'll just type in the code without paying too much attention. By contrast I never would have made that kind of mistake when, say, addressing a function with a bunch of parameters, I'd be on my toes syntax-wise. It's just another delightful little example of my math-related neuroses. 
  • The only way I found the end of this tangle of Xmas lights was by applying the same logic I used on the collision problem: I need information about the source rectangle for the block on screen, and I need to be able to change that information. Since I can see several different blocks onscreen, it's unavoidable to realize I must already have the information I'm looking for, since I'm clearly using it to draw blocks. The bug hunt then becomes a relatively simple matter of finding the variable holding your info (in this case it belonged to a method within an instance of a burly Dictionary data structure, which I still don't quite get).

Fun With Tiles and Blocks


Well it didn't take too long to get utterly lost again.  Rather than follow the plan and do some game state stuff, I decided block prettification was suddenly priority one. Since my blocks (arranged in a 5x5 square on my .png) all looked the same, I made the happy assumption that my game was just doing what I expected it to be doing behind the scenes, presenting a nicely random array of blocks that all just happened to be identical in appearance. Once I started adding some details, it became apparent that the game was only ever painting a small subset of the available tiles to the screen. With some detective work, I determined that I was getting five tiles in a diagonal row from the top left of the image to the bottom right. Here's an image of the .png, with a number layer overlaying it. The yellow circles indicate which of the tiles are actually being drawn to the screen:


Now if you look closely at the top screenshot, you can see I'm outputting an additional small number at the upper left of each block. This number represents the "tile sheet index", it is randomly bouncing around between one and twenty-five, just like it's supposed to. That's the number that I thought was telling the game which tile to draw, but obviously I was wrong about that.

This is the kind of fiendish mathematical bullshit that serves as a small barrier to entry for the novice game programmer. If you're just grabbing code you don't understand and plugging it in, when it stops working how can you fix it? You don't know how it's doing what it's doing. I really do want to get this fixed but I may have to shelve it in favor of some problems I know I can actually solve quickly.  

Sunday, May 8, 2011

YEAH BABY



My hour of darkness and tribulation came to an end this morning, as I finally got all my tiles detecting the player. I started from the premise that since I was already drawing individual tiles to the screen, somewhere in my game I was already detecting and making use of information about the size and position of each tile. Since my Intersects() function takes two Rectangle objects, I knew I needed to get a rectangle for each tile with this info in it. I added a blank Rectangle object called "boundbox" to the definiton of the Tile constructor, so now every time a tile was brought into being it was given a blank rectangle. Then I went into the loop where it loops through every potential tile placement on the screen and determines whether there is a visible tile there, according to the Dictionary object that reads that info from the level.txt file. In that little chunk of code inside the loop where, for each individual tile, the game assigns it a position and a texture, I just added an instruction for the game to fill up that particular tile's  "boundbox" with the relevant information before moving on to the next tile. Pass each tile's rectangle and the player's rectangle into the Intersects method every time we cal Update, and pow, suddenly we're in business.

Even in this trivial piece of code(against which I banged my head for the better part of two weeks) there are already things I see as being wrong that will have to be fixed. Let's make a bullet list:
  • The first obvious blunder I found testing it is that my method for extricating the player from a block he has sunk into is not very elegant. Basically if he's coming from underneath (player.IsJumping) I increase his Y value until he's out of it, and if he's approaching from the top (player.IsFalling), I drop his Y value until he's standing on the block. Looks great in most cases, but if you time your jump right and hit a mid-air block from the side, you get a popping effect as the player is suddenly repositioned above or below the block. The refactor is to do it the way it's done in the XNA example platformer, which I still haven't wrapped my head around, it somehow gives you the depth and direction of a collision between rectangles, so you can just push the player back in whichever direction he entered, however far you need.
  • There are a lot of places where, inside a loop, I'm calling some property of the Tile class or doing some fugly piece of math, many many times a second. Instead I should give the method some member variables that create all the necessary values before running the loop, and then just plug those unchanged values in rather than flipping them around at high speed. This is the kind of thing the Big Orange Book is teaching me about performance!
OK maybe two bullets is enough there, I could go a while listing the problems with what we already have, including the jump itself, which has no power curve and isn't timed in the way the walk is, which will probably cost me down the line. But today is not a day for worry and pessimism! Today I have swung the silver sword of the game programmer, and lopped off one of the hydra's heads. Surely this hydra isn't going to grow a bunch more heads overnight, right?

Next steps: Doors and Death
 

Saturday, May 7, 2011

Yea as I walk through the valley of the shadow of derp . . .

The internet is littered with dead blogs. I myself have made a few, perhaps you have too. When you start learning a new subject, your enthusiasm lights you on fire, and you feel the need to share your progress with the world, to share your joy at grasping new concepts, finding new paths, inspiring yourself!


And well you should. However, I think it's also important to document your down days and moments of despair, because everyone who works creatively has them. After all, what is the value of the creative artist if he/she is not a person who can walk up to an unfamiliar problem and immediately start coming up with, if not solutions, then at least ways to approach the problem that transform it from a mysterious bogeyman into a an abstract problem that can be approached, reasoned with, maybe bargained with . . .


You may have gathered from this, or from the lack of screenshot this week, that my "Skeleton Wizard" platformer has run into difficulties. Well, it's true, and if this blog is good for anything it should be good for exposing the weaknesses that cause bright-eyed indie game devs to plow straight into the earth at hundreds of miles per hour.


Now, this problem is probably trivial to most anyone who would be going through the back issues of some self-taught nerd's gamedev blog, but try to imagine instead that you are facing a problem that would stump you. And if there is no such problem, please close the tab and go f . . . ind something else to do.


Wizard walks and jumps on blocks. Kindergarten shit.


First time out, I got a class Block, which when called into being as a live instance is going to have some set attributes regarding its size and texture/appearance. Note that calling Block does not give the block a position, it just means that the game, at runtime, is going to create and gather a bunch of these objects that are examples of the for "Block" which is going to have some characteristics common to the Block class. My Game1 class has an array of these guys called blocks[], with its array length set to a static variable called iMaxBlocks, which is set to, whatever, 10 in this example. iMaxBlocks being what we'd call a "static member" of the class Block, a variable attached to that class that won't change and that will be the same for any instance of that class we decide to conjure up.


I apologize if this is so basic as to be worthless; there are probably lots of blogs by real, competent programmers that you could read. This blog is by a dude who had to re-take high school geometry, and the hope is that my hapless machete swipes through the field of game development may point the way for interactive media professionals even stupider than myself.


But I digress . . . The problem with blocks[x] is that I haven't given my Block class the same kind of drawing and placement "infrastructure" that Tile has . . Tile being based on a tutorial for tile maps allowing the designer to create levels using a text file with comma delineated lines keyed to cell contents, like a line with a small platform might read


'.''.''.''.''P''P''P''.''.''.'


or the like, which is basically a crude level design tool, and thus immediately attractive, but I am quickly faced by what must be a fundamental problem: how do I integrate the data structures I am using to draw these maps with the data structures I am using to check player collision with blocks - they are different and something has to give.


More on  this when I figure it out . . but if this post has a point, it's this: the "hardness" of "unsolvability" or "fuckthisishardness" of a given problem is not an inherent function of the problem. To a chicken, starting an automobile is an "unsolvable" level problem, while for a human it is trivial. If, when facing a problem that does not have an obvious point of entry, you cast yourself as the chicken in the chicken vs. car keys scenario, then of course you will not succeed. Find a framework, or a window, or a perspective, or a viewpoint on the problem that casts it into a place where you can work with it, like you would cast a (float) into an (int) if you had to.


OK maybe I've made my point.

Monday, May 2, 2011

Version Control


When I started my game programmer journey, I was aware of version control as one of many, many subjects I was going to need to devote a lot of study and practice time to. Within a week or two version control had elbowed its way to the front of my "to learn" queue, saying "uh, you want to just play around in your codebase and try random things? Without ME? Have fun reconstructing your project from scratch every time you make a horrible mistake . . that is, every time you fire up your IDE, haw haw"
To my credit I was not ignorant of version control systems. I had used Perforce in a few different studio situations, and felt pretty comfortable pulling files, making branches and then re-integrating them, keeping various versions with different purposes up to date with one another, I felt pretty good about my version control cred.

All that #swag crashed and burned the day I tried git. 
Undaunted, I grabbed svn and TortoiseSVN

OK, I'm still apparently dumb as hell. 

Thankfully, there's Bazaar, which I was able to download and configure. Maybe once I've had a few weeks with it I can upgrade to one of the more powerful version control apps . . . 

So I'm an idiot, so what, Bazaar is awesome, haters gon' hate.

Sunday, May 1, 2011

One Step Forward . . .


My second screenshot looks even uglier than my first, but it's actually a  leap beyond! That gold blob is the player, who can be controlled with the arrow keys and can jump with the spacebar. The player can interact with each of the tiles, and I can change the outline of the level by editing a text file. The jumping and collision are still a little rough, but I think this is a much better development "platform" than my previous version. Still don't know exactly how it's doing some of this stuff, but I imagine I'll find out in the process of fixing the basic movement mechanics.
 

Dead Tree Addict






The laundromat I go to most Sundays is a few blocks from a huge secondhand bookstore with an exhaustive tech section, and I have a weakness for acquiring these things . . why not? At $10 - $15 a pop used they are a great value, and to me there's nothing more inspiring than a heavy Tome of Knowledge that offers the promise of answers to any question you have . . . once you know enough to learn what questions to ask!

A big secondary project to the platformer I'm tooling around with is to forge through all the example code in the XNA book, entering it myself by hand. I've already managed to get a triangle onscreen which the book assures me is in 3D, although at this point I'll have to take its word for it. This book jumps into the deep end fast, and if I hadn't started with a bunch of the more hand-holding internet tutorials I would probably be lost already, or at least more lost.

The C# book is interesting, it starts out with a broad overview of game programming concepts, then gets really crunchy into using DirectX for graphics. The book pre-dates XNA and covers a lot of stuff that it looks like you don't really have to do anymore, but I think it will be a good resource for looking "under the hood" at how XNA is handling graphics.

The third book is sky-high abstraction, covering even subjects like how to decide who to hire for your game development team, how to run postmortems, all kinds of good stuff. This one I'll probably read straight through kind of slowly over the course of several weeks.

 

 

First Screenshot


This is my last working build of Skeleton Wizard, a platformer with a vague "Black Sabbath meets Mario" design philosophy. As you can see I wrote a bunch of variable values to the screen with a spritefont in a "Debugger" class . . probably a dumb way to do it but it allowed me to look at some info fast . . .

I say last working build because I'm currently going back over it and building the display and collision code from scratch. The pictured version treats blocks as objects in an array, and I just draw them and do collision on them using a for loop. This works fine for a line of ten or twelve blocks, but gets unwieldy when trying to do whole levels. I dug into the issue and found a bunch of  "tile engine" type tutorials, some of which I'm still investigating.

There's a row of about ten tiles the player is standing on, those are created with my old 1D array method and they have collision. There's even a nice little thing where if you approach jumping from underneath, your eventual position is determined partly by your jump speed . . one of those things where I was like "OK I don't quite understand why this works but it seems to make a difference". . . All the other tiles visible onscreen were generated by the method found in the tutorials and examples, where you have an external text file containing the level "map" that gets read in, etc. These tiles do not currently have collision, which is why I am starting over! Should have done it the right way the first time. . .