Friday, March 30, 2012

New Post, new strategy

Hello everyone,

I'm going to be trying a new strategy to the blog, it will mean my posts are more frequent, but possibly that makes them less interesting.  Aside from my "usual content" I will be posting "engine maintenance" content, just a log, essentially, detailing the changes made to Princess throughout the course of a day.  This is mostly to help me (how selfish of me) keep track of everything that I've done, to what file and why, because future Kevin is going to want to know what in the world past Kevin was thinking, guaranteed.

So what have I done today?  I've tightened up Kinect a little bit.

"But Kevin," you ask, "You've been saying that for months! How much tightening can possibly be left?!"

Let's just say I'm the personal trainer of a morbidly overweight technology.  There's a whole lot more tightening that can be going on here!

But I did do work, so to speak.  I've kind-of-sort-of-maybe finally adopted a new method of looking at my hand "point cloud" that seems to work well enough for my needs.  Taking (slight) inspiration from calculus, I changed my method of storing my cloud points as elements of the X-axis (each x-axis spot has a small list of Y-axis positions)

From there its quite simple, I split the cloud into bottom-max values and top-max values (Y-axis) I check for valleys and peaks (derivatives, anyone?) and If I get a certain amount of peaks and valleys in my point cloud I assume this is "fingers" and then  my problem is solved.

What if the person has the hand to the side?  And their fingers didn't point up or down?  I also check the number of points on the given Y axis, any more than four (at least one gap) then I, again, declare the hand to be "open"

Again, are there are ways to do this better, but I want it done FAST, so if I can hit all of this in just one or two passes, I am a happy man, and I can devote my time elsewhere to gameplay programming.  Had a friend of mine, Ozzy, test the game rather unplanned, which confirmed to me that: The hand opening/closing is "good enough"

It needs more work, but it's good where it is at.  Will I work on it more? You bet, I'm a perfectionist when it comes to, well, random things, but this Kinect is one of the areas I always feel I need to improve at.  And so I shall, but it's now officially on the back burner of the project.

Ozzy also showed me a degenerate strategy I'll have to talk with Brian about.  One of the coolest parts of our game is the "smashing" feature, it's simple, but fun, if you have guys in your hand and then bring your hands together, they get crushed and blood spews everywhere, it's an insta-kill.  However, it's also entirely possible to pick guys up and clap your hands together rapidly, just hovering guys above the ground and as such simply kill attackers left and right without rhyme or reason.

So that must be remedied, but overall we need to reign in the number of our attackers.  Too many guys on the screen doesn't make for what feels like good gameplay, just really hectic arm-waving.  Brian and I talked it over, we're going to try to lower the enemy count but raise the health and see if that helps maintain the difficulty but makes the game more about having fun smacking guys around a lot.

I'm also thinking about bringing back the "close hand to grab" functionality, at least temporarily to see if, now that Kinect is a little bit nicer, it brought anything to the gameplay.

I also implemented a quick pausing system that pauses the game if you are "interrupted" or step out of frame it pauses the game and allows you to step back in, quit or resume the game.  It's not perfect, for some reason the draw order for the pause is out of whack, but it works and it's something that I had been meaning to do for a while.

The next few things I want to nail down is a more efficient system for the numbers popping up every time you hit enemies, it really can slow the game down for a bit if there are a lot of enemies on screen, and.. dang it, I just forgot.  Well, I'm sure it will come to me in time.

I actually have a lot left to do.

- Background displays village and enemies leaving village (think the "what's coming next" indicator in Tetris)

- Kinect Wide-gestures (earthquakes, etc)

- Finish up scoring sytstem/hit tracking/combo recognition (base system is in place, I want the visualization to be there)

- Tweak Kinect every so slightly if time permits.

- Add catapult men.  (Sssh! it's a secret!)

- Add more sounds and some music

- Many more things I am forgetting right now.

That doesn't seem like a lot, even to me, but I know things will be much harder than they seem, and I am missing a number of different tasks.

We also need some awesome intro cutscenes or something similar.  We are re-working elements of the story to be a little more cohesive with what we've got.  We shall see how that goes, we have to be very careful now, the difference between an okay game, a good game, and a great game is how it all comes together.  We've got the art, we've got the design, I'm holding the program together with staples and superglue, it's good.  We need it to be great.

Okay, that was my Coach-Carter moment.

Elsewhere in the world I finished my Delaunay Triangulator by complete accident.  Well, not entirely, I scrapped all of my old code that I had because it was just not working and I couldn't figure out why.  I re-did the code in a much cleaner and simpler fashion... and it still didn't work.

Then I changed the order of the vertex creation in new triangles and... lo and behold it worked.  A seemingly random and insignificant matter as the specified order of vertices in a new triangle makes or breaks the algorithm... yet I followed it to the T, and there was no mention of vertex-dependent order?  Did I still do something wrong?  I have no idea, but boy am I glad there are only 3 verts in a triangle or I would have never figured it out by moving random stuff around.  Which is how I come to a find many a solution in my code.  It means I'm always 98% right and 2% wrong... but being 2% wrong still means you are wrong in programming and logic... and math.  Most especially math.

Can't be wrong, must improve.

Must maths, must programs, must logics, must succeeds.

Wednesday, March 28, 2012

Slowly but Surely.

Had a talk with Brian Schrank today, our adviser/professor for the capstone project.  He thinks the game is coming along nicely and is shaping up well, which is a huge relief, but it's more than clear we aren't out of the woods yet, a lot of work, and I mean a whole lot of work remains on this project.

Also, zombie yoga needs the Kinect working at 100% levels by... April 15th.  Oh snap.

So what did I get done today? Practically nothing, I'm still working on my triangulator that I mentioned last (or the one before last) post, and after having a day off of it it's ridiculous to go back and have such a clear head of where everything was going wrong... which hopefully will happen with Zombie Yoga's pose recognition system too, but that's aside from the point.  I simply got too far into the system and made some dumb mistakes with inter-class relations.  Now it is very, very, very close to working.  The only issue now is I have too many triangles on the inside of my objects, as opposed to having only 2 triangles in a box I have 4, they simply create too many triangles and let the others overlap.  This is cause for minor concern, as I don't really know why this is happening (duh) but also minor celebration (yay!) in that I got the Delaunay triangulation technique to mostly work.

The other thing I did was go ahead and build a system for combos in our game.  This leads into one of the points Brian (Schrank) mentioned today, that while our game is coming along great, some of the cohesiveness is missing.  We have a game where you play as an angel, defending Eden, but with an arcade-y feel with points and numbers popping up everywhere and cartoony graphics.  Each element is great on its own, the arcade feel is fantastic and was met by players with good responses, the carnoony art that Justin has been working on is simply amazing, and the story is one that has a lot of potential.  But we have to cut back and reign it all back in, possibly major changes are coming in the future of this project, not necessarily in gameplay, but perhaps in presentation, we shall see.

Anyway, the combo system is a fairly flexible system, C# for some unholy reason decided it didn't really "like" binary search trees and doesn't include them as a base systems class which strikes me as rather odd.  Regardless, I had to set up what would be a "quick search" system (ended up being a dictionary of lists...!) that could take the first "hit type" that a creep has received, find the appropriate list of possible combos, and iterate through that list until a match is found and a combo is registered.  The combo is found, the appropriate message is displayed, point's added, and a counter keeps track of the times each combo is used/found/registered, etc.  It's pretty standard stuff, however we can get a lot of creeps on screen, and searching through a list  which has a list of conditions each combo must fulfill can eat up more time than I'd like, so the combo system has a cap.  Think of it like your computer trying to send packets.  There's a queued buffer of packets waiting to go out, if your packet encounters a full buffer of packets then, well, it get's dropped. (Yay multiplayer game development explaining the different joys of packet loss!)

My system is not quite so elegant (if you can call fumbling a packet elegant) it simply has a set number of times per second that the CheckForMatchingCombo() call can actually be utilized.  If it has already reached it's max for that second, no more "expensive" calls iterating through the dictionary and lists will be made.

That kind of stuff is busy work.  My system works, I have no doubt there are more elegant and efficient solutions, but mine is robust, it allows for lots of experimentation with different combos and more importantly it works, which is all that I need for it right now.

Tomorrow beings the long process of beginning to wrestle with the kinect again.

We who are about to die, salute you.

-Kev

Monday, March 26, 2012

Spring

It has Sprung.  Too quickly, if you ask me.

Well what have I done?  Not much, admittedly, for my spring break my dear cousin came out to visit me in Chicago, and we had a great time doing all the things tourists do.

Up to and including getting really tired the last day and spending it watching movies and TV, haha.

In all seriousness, it was great to have her here, and as much as I enjoyed the break, it's time to get back to business.  Or "srs bsns" as it has come to be known in our capstone group.  I have to get back to working out, and to all of the things I have to do this quarter, which includes...

Calculus II (After a year off...!)
Multiplayer Game Development (Looking forward to this one!)
Capstone II (Duh)
Real Time Graphics (Please be good, please be good...)

And..
Working as a lab mod
Training for the next Judo tournament
Grading for Charley (My awesome faculty adviser at DePaul)
Zombie Yoga (...so much to do... so little time)

Not to mention the things I want to do, like learning how to do some sweet aerial kicks and tricks to impress at the dojo at home (as well as get me in better shape doing something fun as opposed to lifting which I find very hard to do without someone to do it with)

But, what have I done in terms of PROGRAMMING over the break?

I've been fiddling with creating a generic volume class for princess to be used in mo' advanced versions of our current collision system (which needs to be re-hauled... when I have the time)

It's a relatively simple system, it just takes a series of 2d vertices specified in a counter-clockwise order that is closed by connected the last vertex to the first vertex.  There are edges between each of these vertices that check against other edges for collisions and etc.

That, my friends, is the drop-dead easy part.
A vertex class? Piece of cake.  Edge class? I could do that in my sleep.  Connecting them together? Pah! No problem.

So... then WHY am I still stuck on this?  Well that's something I've been asking myself.  You see, I'm trying to make the whole process as simple and efficient as possible, but at the same time I want this as robust as possible.

If I just want to check edge to edge collision, my system can stop where it's at, however, if I want to check if, say, certain points are contained in my newly created volume that beings to give me problems.  If this volume that you've specified is convex, meaning that there are no interior angles in yo' shapes, then all I have to do is check to see if a point is to the left of each edge in the lot, and TA-DA! If it is, then the point resides inside the volume.
Pictures always help me

...however, if my shape is non-convex, then this to-the-left-of-each-vertex thing kindof falls apart.  (also, the more complex these shapes get, the more processing has to be done for each interior check, which is also a general case, but if there was a simpler way....)

So what to do?  Well, its elementary really.

In theory.  In practice, not so much.  The solution is to divide up the interior of the bounding volume into triangles, then loop through each triangle when looking for a point lying on the interior of a shape, and do some quick and cheap eliminations of unlikely triangles (point not within min/max bounds of a given triangle) before doing the messy stuff (checking the relative space to an edge).

Again, that's not my problem, my problem is HOW to break up the interior into triangles?  Well, I kicked around a lot of my own idea for a while.  That should be read: I do what I always do when I get stumped, snack profusely while staring blankly at my computer letting my mind alternate between creative thinking and flavor comprehension.

Regardless, I was getting nowhere, this is not a simple as I first thought, so I decided to see if the internet knew anything, and lo and behold I found this, or a good explanation about Delaunay Triangulation, which does more or less what I want to do, it takes a list of vertices, and creates a convex hull out of all of them.  The article I linked is the only article I think is worth reading.  I found a dozen more before (with source code) and they made no sense to me until I saw the picture-illustration of the algorithm at work in that article.  That's when it all made sense to me.

That being said, I'm still having problems.  One is conceptual, and one is my implementation.  The implementation problem arises when I try to remove triangles as denoted in the algorithm.  For some reason my algorithm is very trigger happy and removes too many triangles, leaving me with a sadly half-complete volume-mesh, which makes a very unhappy Kev.

The conceptual problem is that Delaunay's method creates a convex hull, even when  I don't necessarily want a convex hull.  So I have to go back through once good ol' Delaunay has done his thing and then remove any edges that connect vertices that shouldn't be connected.  Imagine two vertices as Romeo and Juliette, which would make me Poison.  Or Death.  Though I think them both dying was supposed to be, as well as tragic, somewhat reassuring because "they died together" or "died for each other" or whatnot.

It's been a while since I read that play for English in high school, don't judge me.  Getting back on track, this is achieved relatively simply if messily by comparing the angle between the two "true" outside edges of each vertex, if the angle from the first to the second (thinking clockwise here) is greater than or equal to 180 degrees or Pi/2 then it's a lovely convex point and we don't have anything to worry about, however, if the point is less than 180 degrees and we have a third edge between the two vertices at either end of the vertex in question, that edge must be removed to maintain our desired non-convex result.

But I haven't even gotten to that part yet because of my trigger happy triangle-removal portion of my code.
This is depressing, this algorithm shouldn't have taken more than a day to implement.

This quarter is going to kill me.
It's 0200. I can't maths, I can't draws, I can't programs. Therefore, I blogs. I should probably sleeps, though.
-Kev

Saturday, March 17, 2012

Dreams, Aspriations, and the Sweat of my Brow

Looking down from my precarious perch on my chair, it's evident I could probably use some more sweat of my brow and lose a couple extra pounds.

Regardless, I haven't updated this thing in a very long time.  That's in my coming "new quarter" resolutions. I'm doing a lot, and I want some place where I can, at least personally, see the progress that I am making.  Speaking of progress, an update on Capstone!
Screenshot of our current build
It's looking really good, especially considering where we came from.

Kinect is at almost 100% functionality, a few tweaks remain to be implemented before I'm completely happy with the result, but for now all of our base functionality is in. (Throwing, smashing, swiping and hitting)

The next steps would be to implement a combo system, and special moves such as the earthquake and tornado, the team also discussed some interesting ideas as to changing our background to be more interesting/interactive, I will keep you all posted on that.

Unfortunately (for some...?) I won't be nearly as content-heavy with my descriptions of what has been done, honestly the game has come a long, long way from where it started, and since my last update there is simply too much to cover.  I will say, however, that my current method of determining Kinect hands open/closed is about as straight up as a hack as it is going to get.  I'm currently using what I assume to be a "point cloud" system, which simply generates the points around a given model, image, or in this case "body part"

I have no problem in isolating the hands from the rest of the body, that's the easy part.  The tough part is quickly and cheaply reading all of this constantly updating data and determining: Hey, this is an open hand, this is a closed hand.  I also have to do all of this processing alongside whatever my game is trying to run.  Simply put, this isn't a very fun problem.

The Kinect, as I have previously mentioned, is event-based, or rather that is how we choose to use the Kinect.  As many headaches as this can create, it eventually saves on processing because we are only doing these operations when the Kinect is good and ready, and we don't have to keep asking it "Hey, are you ready yet?" Over and over.

Anyway, every time the Kinect shoots me a depth image I go into the quasi-lengthy process of running through segments of the depth map, checking for the relative depth locations from the hands.  This is opposed to my original system, where I built and entire group of "depth objects" based on the Kinect's depth image and then manually determine which segments are hands, feet, etc... Every. Single. Frame.

Good lord, what was I thinking?  While the Kinect's skeleton may not be entirely accurate, it has it's own processor and using the data it gives me is certainly much more efficient than trying to build my own skeleton, and while I may have been proud of my skeleton for being "mo' accurate" it didn't have any efficient means of determining joints and the like, and in the end it just wasn't practical.

Luckily I'm still using a little bit of that logic to get the hand point cloud I'm working with.  I don't know if it's really a point cloud or not, because at this point I'm simply tracking the max hand width/height and the number of points per line.

Points per line?  Yes, well, this is a cheap way of checking and seeing if "Hey, this line has 4 points" which registers as having a "gap"  If enough of these gaps are registered then the hands are considered to be "open"

Of course, that's not the extent of it, especially because the Kinect won't see fingers as being spread apart unless you really make an effort to spread 'em good and wide.  I do some checking with the depth values and if a depth drops a certain per-defined amount, then another point is added, this time classified as an "inside point"  These factor into the points-per-line which means if fingers are curled inwards, even though the outline may look like a closed fist, the inner finger-outlines are still (somewhat) registered.  However this only works on a horizontal axis, the lines read from left to right like a line of text, going vertically through the depth pixels add more passes and can be bad for the cache, not that what I'm doing is terribly cache-efficient in the first place, though.

The issue here is that the Kinect's depth values degrade over distance from the Kinect.
What?
Well, the distance from the tip of my index finger to my palm if I'm pointing at the Kinect is read differently if I'm standing right in front of the Kinect compared to me being 10 feet away from the machine.  My finger is not physically shrinking or growing with the depth (duh) but the Kinect's perspective is saying so, at least on the depth map.  I haven't found a precise and simple way to convert from depth-map values to physical values such as meters.  Granted, there are equations that MSDN provides to do the conversion, but I have not had good results from using those functions.  In other words, the problem persists after the conversions, possibly because I'm looking for very small distances and the equation is a distance approximation.
(The Kinect works in meters for skeleton frames)

Well, it's 2:30 and I have Judo tomorrow, so I should get some rest so I can get my butt whupped (...into shape?!)

But yes, the original meaning of the post?  I'm applying for internships and jobs, which is a nerve-racking and anxious project for someone who is not entirely confident in themselves.  It's the same story as asking a girl out for a date, or coffee or whatever you kids do these days.  It requires confidence and assertiveness.  Insecure and unassertive people know this, but there are severe mental blocks when it comes to changing their personalities, even if temporarily, to just drop the insecure and unassertive parts of themselves off at daycare and go have fun with the adults.  So I feel as if I am lying when trying to make myself appear hire-able material.  I'm not unintelligent, I'm not a sloth, when I work, I work hard, I give it my best efforts and I always strive to improve, but I know I'm not the best at anything, and that knowledge in itself has hindered me far more times than I care to count.  Just because I'm not the best doesn't mean I'm not good, but try telling that to my psyche.  I am, everyday, but it's an uphill battle.  I'll get there someday.  In the meantime I feel very awkward crafting a Resume and cover letter to make me stand out as "The best"

I feel as if job-hunting is a competition, and I don't enjoy competition, I am much more comfortable being friends with all, not trying to beat somebody out for something.

Okay, but for srs now, bedtime.

Have a good night (morning?) everybody,

-Kev

Stress test.  Yes, we have elephants.
Oh yeah, doodles.  Early morning roommate ambush!

Wednesday, March 7, 2012

Close Enough

Hey everyone (or rather, hey whichever single person decided to read this)

Despite my silence, I've been up to a lot.  Finals are in full swing after this week, I've got a few final projects to finish up, Zombie Yoga is unofficially at GDC and Capstone is... kind-of-sort-of coming along.  I just have one last Kinect tweak before I have it where I want it to be.  It's been like that all quarter, though, it's very discouraging.

One of those days...
I'm not in the mood necessarily for a full update, but a low-down wouldn't hurt.

In the past quarter, I have:

Modified Princess to be based on matrix-transformations for rotation, scale, translation, etc, the usual stuff, it was a long time coming since I first learned about the matrix representations of position and related information, but it made it into the engine.  We've re-worked the system slightly to better deal with destruction/creation (hint: in a managed language, try not to leave too much stuff for the garbage collector, be smart or the collector could cause your program to chug.  We weren't being smart before)

Finite state machines have been implemented, up next would be goal-oriented behavior and fuzzy logic, this is all straight-out-of-the-book stuff from the Game AI class I am taking.  Which, by the way, is a complete flop of a class.  I have never been so uninspired and frustrated by a class.  This is what happens when you take a curious mind and shove it in a class with a time limit, all of the interesting parts of the class are not covered because we "lack the time" and the only assignments we give are maddeningly frustrating because ALL of the base code has already been given, no fundamental understanding of the underlying processes are truly necessary or even gained because half the time I'm wrestling with finicky compiler errors from not having the correct includes, or perhaps because I'm busy trying to re-write all of classes I'm supposed to be deriving from because I want just a tiny bit of the base changed, and the hierarchy of classes is all too reliant on each other down the line to permit simply inheriting into a different class.
End rant about that, however.

Game Jam took place.. wow, almost two months ago!  Going in with friends made all the difference, and while I'm still not completely happy with the product of our game jam, we actually got a small game finished, and had we not had late night version control issues I'm confident our game would have been as polished as any of our competitors.  Regardless, it was a lot of fun making a game with guys that I respect and who's skills continue to impress me and make me strive to better myself.
GO TEAM JAM!

By now I've totally lost my train of thought, so goodnight, and goodluck with whatever challenges may be facing you, as I turn back to face the challenges of uncooperative code, lethargy, and the infamous Microsoft Kinect.  Away!




-Kev