Sunday, September 30, 2012

Performance

Performance is an interesting problem to solve, and one I am none too experienced with. While playing our game I've noticed a considerable hiccup, mostly when many projectiles on the screen. As a good guess, I commented the logic pertaining to projectiles, ran, and to my surprise the performance glitch still existed.

Stumped, I turned to the internet for assistance. Turns out, there's a reasonably good piece of software called SlimTune that came to my rescue. It is technically a beta, but it is open source and easy to use once you decode some of the results on your own. Not all the visual data has come to being useful just yet.

So what was the problem you ask? Well, I navigated the labyrinth of function calls and to my surprise, the problem was not what I expected.



The method call to the enemy draw was causing the problem. Not because of the textures or any complex logic, but because I was drawing a primitive rectangle around the enemy health bar to give it some emphasis. This was the lazy route and would've been solved when we used an actual image for the health bar, but it just goes to show that as useful as primitives can be, they can cause quite the backup.

Saturday, September 29, 2012

We Still Exist

Hello everyone. I know we have not posted in a while. As I had eluded to, our activity will not be as frequent. Tonight, since I had some time, I decided to make a few changes to the game. Very small changes, and I will also post a video of the game since I never did that with the playable version. This post will start off technical, for those interested, and end with the playable video.

I made a couple performance changes. Nothing that would effect anything too much, and I imagine there are countless other areas that this could be applied. I wanted to point out some subtleties in the .NET language that can, without being aware of how things work underneath, cause some unintended loss of precious CPU cycles when running constantly for every game update. During event driven applications these generally don't matter much, but in the game world we have many complex computations where the CPU cycles are better spent.

The first one was the inventory. Previously, we did the logical idea in the loop by adding an if condition, and if the current inventory selection is the equipped selection, draw the selector icon behind the item image. You can see this in the video as we select items. However, we call this method on every update, and an if condition can do nefarious things to a CPU pipeline. That is, modern CPU's use a pipeline to optimize instruction execution per clock cycle. With a branch, the CPU doesn't know which instruction to execute until the branch is evaluated. I won't bore with the more technical details of instruction execution, but the inventory had a notable branch that wasn't required. Even though it wouldn't cause any serious penalties, this statement is only true once in the entire loop. This makes branch prediction somewhat useful, but the guess can be avoided entirely by doing the calculation ahead of time based on the selected index.

The next one was in the camera. We use a special algorithm for locking the map in place to the player isn't distracted by the nothingness in behind all the image drawing. That algorithm is responsible for moving the map when the player is in a specific boundary, but when the player moves to a corner, the map stops moving to a minimum of 0, 0, and a point based on the map width and height. This method made use of the player position, width, height, and its translation from the attack image (A translation of -64, -64). Originally, we used the properties in player to get the position and sprite width and height every time it was needed in the calculation. Because is is a property, this is creating a function call for every player.Position and player.CurrentSprite, and player.CurrentTranslation. That's a total of 6 function calls!

A function call requires for memory to be allocated on the stack (a memory data structure that is used as a pointer for the current executing method), all data on the CPU registers to be temporarily stored and new data allocated for the function call, and then deallocated off the stack with the return value. This is a lot of extra work, called a context switch (particularly brutal in database applications), that can be avoided. So, what I did was create local Vector2 variables for each of these, and used that. At the expense of a small amount of memory, we've reduced half the function calls. Using the X and Y values of a Vector2 is a value shift, because these are public variables rather than properties, and this invokes no additional functions.

The last one, and this currently only effects loading of the maps, is one of my previous changes to the AI component. I had mentioned that I used reflection to solve the problem of AI Components being referenced by all enemies. This was a solution, but as I looked back wasn't the ideal solution. Reflection is a lovely tool and makes most scripting needs not needed in the C# language due to its versatility. However, it can be slower and produce overhead, although not enough to be a major performance drain, is typically slower than direct access. There was another reason, once I thought of a different solution, I felt that it was a more reliable approach and fit into the AI Component paradigm in a way that I was comfortable with. Reflection added unnecessary logic to the create method which had made me a sad panda. So, in the end I added a clone method to the AI component, and I allow each individual component to clone itself and its required properties, rather than looping through all of them with reflection when they might not even need it (Looping includes branching). We add a function call, but the amount removed from using reflection and the cost of indirect access should be better since the components can have various functionality. This would also allow enemy spawns to be more efficient, should we ever include them.

I apologize to those who aren't here for the technical dribble, but this is part of our passion, and I know many struggle as I did. It took many years of dedication to have the understanding that I do, and I would probably still be considered an amateur. A happy one, though! Some people would roll around naked in money, but me? Ones and zeros, baby.

Well, now that you have a mental image that is none too exciting, I present to you the video!


As you can see, we have a playable dungeon with a "boss" at the end. The boss being a clone of the light bug but with a blood red glow, if you will. This is what I presented on the Friday before last. Enjoy!

Saturday, September 22, 2012

Success(Cont. By John), My Drive, and The Future!

YAY! finally me and Jared have built something Playable and moderately worth showing. Its been a long week and a half of working an average of like 13 hours a day but I feel like it turned out well!

If you want to see Jared's Post is 'should' be below, this one hahaha

Me and Jared have been trying to make ANYTHING for a long time now, this proves not only to others but to ourselves that we can do something, get something done, and to me that means a lot. My dreams are slowly but surely coming true, and I plan to continue forward in this direction. I'm really happy with how it turned out, but with anything, There's so many things I would have done different had we more time. But overall its good for a first run.

More insight into my personal drive for the project, and the future of this project and others after the Jump

Friday, September 21, 2012

Success!

I'd like to formally announce that John and I have met our goal of a playable game! I brought it into my office today, tried to look fancy with my xbox controller, and played our lack of content game! There were a couple performance hiccups, but I didn't care. It was the first time I was able to show something I've helped build with true pride, knowing that my code is running well, and that my dreams are coming closer to fruition. My audience was a great group of people that I have come to love and respect over time, and I'm glad that they were able to share in that experience.

All good things must come to an end though. It is a harsh reality that this project will take someday. As I said in my previous entry, we would like to complete it, but it will take time to build everything else, mainly the content of the game. That's what is so beautiful about this game. We built the entire framework such that the content of the game will simply be using what we built. We squashed bugs here and there (and I am sure there are many more), and stuck to it and came through.

The game itself is not impressive by any means. You have one dungeon, some enemies, a random brute light bug enemy at the end and some switches. We wanted to build more, and change the keyboard input (I'd do it now, but i'm above the neck in homework which I am currently procrastinating on, plus I am lazy), but we have a build that we can give to people should they want to try it. Others may get over it within minutes, but for me, and I would say for John as well, that the ingenuity that we displayed in building the game will be with us for the rest of our lives as we continue to drive towards our intellectual passions.

Some may not completely understand why we did this. I'd like to try to explain that in a way that makes sense to me. Why would I spend my vacation, and for 12-15 hours every single night work on this game? My vacation was literally nothing but working on this game. John and I have been asked this question, and I'm going to explain why the best I can.

I personally have many reasons other than passion, including personal ones. However, when I was younger, games were how I passed time. Games involved me in a world that I could make sense of, and allowed me to be the person I am today. There is so much to some games that not everyone realizes. There are entire universes to explore. You solve problems and witness passionate stories from minds that worked tirelessly to bring hours of entertainment (For the record, this is why people who pirate games piss me off to no end). Not all games are simply about getting to the next level. This is what I love about games. They gave me something to look forward to in the future, and I want to do the same for others. Knowing that I could inspire someone to be passionate about something, games or otherwise, is an ultimate goal of mine, much like those who wrote games for me gave me my passions. It's a tough road, but eventually, you, me, and anyone else can achieve something if they try hard enough. That was the ultimate goal of this week. To show that we could, and that we did.

Finally, we started this blog to show the immense progress that can be made by two passionate people. If you compare the videos from before to how the game shaped up - you can't even tell that they're the same thing! As I had mentioned to others, knowing that this is our lovechild, that we built it from scratch using nothing but our own knowledge (and XNA, of course), is a tremendously good feeling. We know the code inside and out, and from when it was nothing but a little visual studio project! They grow up so fast!

Anyway, I hope we have helped inspire some people to pursue their passions, whether it is in games, computer science, or otherwise. Beginning, and working on something that you're passionate about, and then completing it is a feeling that words can't express. I'm so glad that I did this, even if it took my entire vacation. It was one of the first times that I was able to show people something I created, even if it wasn't perfect, that I was incredibly proud of. John did a wonderful job on maps and graphics, and we came together on everything.

I believe my rant is over now, and for those who are simply waiting for the game, the link is below:

http://www.thelunchboxlegion.net/AP/ArmorPotions.zip

The not as intuitive keyboard controls are:
W - Move up
A - Move Left
S - Move Down
D - Move Right
Space Bar - Swing sword (It will swing in the direction of the player)
Mouse Click - Fire selected projectile (From the lower left corner)
Arrow keys left and right will switch the selected item

Note: You need the XNA 4.0 redistributables to play this game! The easiest way is likely to go straight to the source:  http://www.microsoft.com/en-us/download/details.aspx?id=20914 

If anyone has any questions, suggestions, anything at all please reach out to us. We would especially like to hear if anyone has actually been affected by our work :)

Until next time!

Deadline

On the final stretch, we came across many things that we'd like to do. Although I'm highly satisfied by what we've managed to do in such a short time, it is unfortunate that we are unable to complete everything. For the presentation tomorrow, the graphics will be unfinished, but most of the functionality will be present. I'll share a couple problems that we had before going there, however.

Floating point numbers are an interesting beast in the world of computer science. The arithmetic can easily become unaligned when done many times. Our health bar is a clock in the game, and I had gotten it working.  Then, I decided I wanted to animate the clock strokes because it looks much better than a simple jump to where your health currently is. So on the first check in of the code (lines 84 and 90), we had to make a check to see if the current angle was greater than 0. What happened was, as shield and health were depleted, the angle was a little off to the right, rather than at a perfect 0 degrees.

Then we had a new problem. Healing did not animate. What's worse, it didn't even move back up! So we had to add additional checks to get this to work correctly. This all worked perfectly fine before animation, but because we were doing it one degree at a time (1 / 2 * PI), precision was eventually lost. Now, we have a perfectly functional health clock. 

Tonight, I was adding the enemy loader to the game. This way, on loading of the map it will maintain and update the list of enemies for the current dungeon. We had really only tested with one enemy, and other enemies used different components. When loading many of the same enemy, the reference to the AI component was the same to all components. This caused bizarre behavior with the enemies, they quite literally moon walked off the map. Although humorous, with time dwindling it was more on the frustrating side. In the end, I had to create another new instance on load the enemy, and set its properties through reflection. The reward is present though, as our game is looking more and more like, well, an actual game. Some graphics will not be complete, but this is as good as any. It will be a short presentation if anything as there is no real content at the moment. I can, however, show the functionality.

Some may also notice that I added a feed of all of our code commits. For anyone interested in the code (Be wary, it's certainly not perfect), that is your stop.

We'll be building a map to contain more environmental functionality tomorrow since we're very tired after the past week.

Since I'm excited regardless, here are a couple more pictures of our progress!



Thank you to everyone that supported us! We'll likely continue working on this for a little bit longer as we still have functionality to complete, but time is much more precious now that I will be back to work and classes. I will continue to post about various other things, including ideas for the game. I welcome anyone to give us suggestions, and to directly communicate with us about our game.

Until next time!

Tuesday, September 18, 2012

Map Collision and its Intricacies

I began working on map collision yesterday and made some measurable progress. I made additional progress today, and John made a new map to play around in. We realized two things. The maps we had worked with were all originally square. Thus, when we went with a map that was not square, we realized that our map was being drawn incorrectly! That is, the width of the map was being drawn as the height of the map. This resulted in a change in the calculation in drawing the map. Easy enough. Then, we had another problem. The collision deals with the x and y axis individually. When we held down the left direction, the collision would be fine, but when you pressed down as well as left, it would put you through the wall like the below picture. Eventually, you could wiggle your way outside of the map.


I figured that this would be a complex calculation in the collision logic that didn't allow for the corner tile to be checked against collision. I didn't think that was logical, but I went with it. Turns out, the problem was simple.

The collision result was being overwritten when there was more than one tile being checked. With my supreme knowledge (lol) of Boolean logic, I added a bit-wise OR operation to the collision for each check. Now it returns true for each axis if there ever was a collision, and false otherwise. So to clarify, what was happening was in the first iterations of the loop, there was a collision, but in later iterations there was no collision, which overwrote the fact that there was a collision with a previous tile. This solved the problem with the way our collision logic currently works.

You'll also notice that there is a little white box. That is its collision box. That means that we do not collide with its upper body when it comes to walking. In the words of John, our  perspective is all kinds of messed up. But we'll let that go for now. An example is below:



We are in crunch time with getting the remainder of the functionality working. We still need combat, and we're going to be shrinking the tiles. We'll be working hard before any further updates. Until then!

Monday, September 17, 2012

The Calm

After 50 to 60 hours of relentless hacking at our creation, we've decided to take tonight and tomorrow as a time of rest. We still have much to do, but we are not concerned with being able to get it done by our deadline, even if they are complicated tasks. All the pieces are beginning to flow together. We integrated John's camera with my entity and item code, equipment was tested and works, AI area of effect attacks and states as well as being able to change complete behavior with the change of a single text file. Our design likely has flaws, but we are very happy with what we've done, and I'd hate to sell either of us short. John has done a tremendous job with the maps and the graphics. We are really pulling together to accomplish what we set out to do, and I'm very excited that we've made it this far.

The below video will show this. John posted some concept stuff in the last post, and you'll see it in action here. The first video I posted was mostly temp graphics that I had laying around. I am pleased at the style we're giving the game.


The first thing I should warn about is that we have not implemented collision yet. That is one of the tasks for the remainder of the week. However, this should be enough to show our massive progress since we started. We're currently hovering around 2,000 lines of code. In retrospect, that is not a lot, but it's always a fun metric to look at if nothing else. The light bug AI uses a generic "Area of Effect" module that will charge and attack when the player is near, and move randomly otherwise. I can change this behavior as well as its properties painlessly. Further, I can add this AI to another enemy and change the image, the delay of the charge and the lifetime of the effect without touching code at all. This shows how the AI comes together, and with its versatility, John's map system can easily be integrated.

You'll also note that the player no longer "moves", but everything around it moves. This is the integrated camera system, and what you see in many 2D games but may not always realize it. While the player still moves internally, the drawing centers everything around the player creating an effect of the player moving, while keeping the player centered. The player has a couple inventory items that can be cycled, and are shown in the video as linear, area of effect, and cone projectiles respectively. A cone is a linear projectile, but it fires at a spread of 45 degrees to create a "flame thrower" effect.

I've thought a lot about what keeps me going, and I honestly  believe that because I've been so busy between work and classes these days that it makes me appreciate the time I have to accomplish something. Before when I was discouraged, I would quit. Now, I keep going. It truly is the best way, especially when what you are doing is difficult. This game will not be perfect, but we've learned so much about the environment we're building in.

Our tasks for the remainder of the week currently include:
  • Map and Enemy collision
  • Linking map switches (i.e. door switches) to doors, so when activating them they correspond to the correct door
  • Designing at least one dungeon to be playable
  • Combat
  • A couple tile textures that need to be implemented such as deep water and lava
  • The GUI for inventory and perhaps a couple of other screens

Most of these are simply extensions of what we have already written, with the most difficult being map related items. Tomorrow will be a slow day, but some progress should still be made.

I'm amazed we've gotten this far and are on track for our deadline. One success after many failures is a great feeling, and even better than I can say that I've completed the challenge imposed on myself for my director. With our track to success has come dedication to our passions. 

For now, we have some limited functionality that is useful to a player. Next time though, we should have a fully playable demo!

Until then!