Tuesday, June 21, 2011

One small leap for Kevin, one giant leap for...?

A late night update!  Which means what?
Well it means I was too darn something-or-other to update this afternoon.  I have successfully finished the last touches on my Camera object!
I'm so hood.  Good, I mean good.  Please don't shoot me.
Now the camera object, bear in mind, is not a new concept in games and different versions of 2D cameras have been created probably thousands of times by programmers far more adept than I am, and they probably did it in half the time, if not a quarter of it.  However I stubbornly refused to turn to the internet (safe for Microsoft's reference pages, which just tells me what a particular method does, since XNA itself has very little in-dev-kit documentation) for any of my solutions which means a few things:

a) I figured this stuff out on my own, using brains and trial-and-error.  Okay, so mostly I used trial-and-error, sue me.
b) I probably did it in all the wrong, wrong ways that better coders would cry to witness.

Or shoot me with a missile, as I devour a sub.  You know, whichever is easier at the given moment.
But I got it done, and hopefully I learned much in the process.  I'm still not entirely sure of what I've done or how I accomplished it, but it works and tomorrow I'll go back over everything to see just how I got all this crazy stuff to work, and try to streamline the process or make it more efficient.
BAHAHA.  Who am I kidding, efficiency just isn't my thing.
WHAT IS THAT? IS THAT EFFICIENCY? OH GOSH KILL IT NOW!
If remember, or care enough to skim through my previous post, the last problem I was having was with image rotation and having a nice clean rectangular cut off of the image rotation so I could have a 2D camera with any given bounds on my screen.  My problem came in when XNA drew a segment of an image based on a rectangle and THEN rotated it, which means I couldn't just cut off an image at a certain point to match up with the edges of my camera because after the edge was determined, then the image would be rotated, ruining that perfect edge that I had before.

My solution?  (warning: this is a pretty crazy solution).
If the rotation wasn't 0 (normal image) then my program gets color information (pixel-by-pixel RGBA information, Red-Green-Blue and Alpha bits of info, respectively) from the specific frame of the image I wanted to draw, and then using a transform matrix (remember matrices? yeah those things come in handy apparently!  Luckily XNA does most of the work for me) that is formed using the rotation amount that we are looking for in the image and creates x and y "steps"
Pic Unrelated

I myself am kind of fuzzy on how all this functions, but I'll describe it in the best way I can.  I create a new blank image of the appropriate size, and then the "step" x and y from the first image, a pixel-by-pixel break down of the colors are transformed on top of this new blank images, and the step x and y are used to go through the rows of the rotated image pixel -by-pixel and row-by-row.

Now I have to do this because even with this new fancy transform my old image is still a rotated rectangle with pointy edges where there should be nice vertical and horizontal lines.  So over the new blank image I extract the color points from the old rotated image (only my new blank image is nice and square)

This works fantastically except for one thing: the step x and y are integer values, or whole numbers.  Numbers such as 1, 2, 3, 4, 1712, and 813,145,845,993,2452 (though that would be too much information to hold as an integer value in C#, that could also exceed a long int too, but I'm too lazy to check.  I believe it does, but don't quote me) which means when I rotate the points using a transform matrix well at certain angles I get blank spots, or pixels that are skipped over simply because of the lack of precision when being forced to stick with whole-number values.  From my knowledge there is no way around this, you can't  have .5 of a pixel, that's not possible, but as I stated that means I have blank pixels in my new rotated image.

To solve that I simply used a handy-dandy color interpolation function, using the color values of the two pixels to the left and right of the blank pixel to form a new color in-between the old.  It works well enough, and since these rotation functions are only called when at the edge of the screen (where a part of the sprite is "off-screen") it should not be enough to be noticeable or to detract from the atheistic of the game.

And with that, I have a complete camera class that can display the game world from any position, with any zoom factor, and that can take up any rectangular space on the screen without having images "spill over" it's bounds.

The game that I'm working on with David now doesn't need half, or really any, of that functionality, but David will be happy to know the Camera class can now handle his awesome menu idea.

Rock on,

"But not too hard" - Clergy
- Kev

No comments:

Post a Comment