In every project, there's always some part that are just not that exciting. Some people like to get it done first to keep the icing for the end. Me, I say "do it when it's needed whatever it's fun or not". Well, I just "finished" the login/create account/forgot password system...
I've done more "login interface" than I can count. Each time I tell myself "Great, I'll use this in every other projects". Unfortunately, this is rarely the case. There's always some different twists, different needs and while you could probably come with some generic module to start, sometimes it's just easier to start from scratch. Some might say it's my design skills that are just terrible but if I take a look back at what I've been working on, I don't feel ashamed.
So the work on the interface is started and it's probably be as much job as doing the server side. That's ok, I'm gonna learn a lot. That will be the first time I'll use that much things like Script.aculo.us and Prototype and it will be just exciting to see what will become the "final product" evolving.
Friday, October 19, 2007
When to do the boring stuff
Sunday, October 14, 2007
A taste of what I have in mind for the interface
I'm at that point where I have most of the basic systems done and I need a more robust interface to test them all (my prototype is real dirty).
I'll start work on the interface and I need to figure some basic things as what will be the dimension. I'll be using the graphics found on Lost Garden and sprites generated from the Charas Project for the characters and NPCs. It's already in my plans to allow players to build their own sprites so they don't end up looking all the same. All they'll have to do is to upload the sprite and wait for approbation before setting it up to their character.
The chat and skills zones doesn't look really good but I'm hoping to find someone later to refine those parts unless I'm able to make something good out of it.
After reading this post from Elder Game, I'm now seriously thinking of adding some kind of on-screen map.
So here it is (click to zoom)
Wednesday, October 10, 2007
Range attacks in
The range attack is really just an upgrade of the melee attack. Since the "range check" was already in, the only new mechanism needed was something to check line of sight. Again, there was plenty of resources on the web to understand how to accomplish this.
To determine if a target is in the line of sight, I used Bresenham's line algorithm. All I really wanted to achieve is to make sure there is no obstacles between the attacker and its target.
There's many explanation of this algorithm but what was most helpful for me was this article on Code Project. My function receives coordinates of the attacker and the target as well as an array for "collision coordinates" which are coordinates of props with an elevation higher than 0 (characters are always on elevation 0 while buildings, trees and such have an elevation of 1.). So instead of drawing a pixel, there is a check against the array (which is in fact a generic dictionary). If the current calculated coordinate is found in the array, the function simply returns false, meaning you "can't see" your target. The checks are made at the same time as the line is "drawn" so it doesn't have to calculate it all if a collision is found before it reach the target.
To test this I only needed to create a new prop type (crossbow) part of the range weapon family and create a skill called "Basic range attack" part of the family "Range attack". Just like melee attack, when the skill is used, we make sure the weapon type currently equipped match the skill type. Everything else is just the same code used for melee attack.
This took about 3 hours to code and get it running which is great. Being able to "finish" a system in little time really does help for motivation.
The more it goes, the more I only see some tweaking tasks on my to-do list which mean that after I'm done with the crafting mechanic, I'll probably start to work on the interface. We're getting there and I can't wait to invite some people to help me test this.
Saturday, October 6, 2007
Demo 3 : It's alive! Basic NPC AI, A* pathfinding
When I wanted to add some basic AI to NPCs, I add no idea how to start. Hopefully, many people before me had already think of it all.
I first started to elaborate the controller class that would become the "brain" of each NPC. I knew I needed some kind of loop and a way to decide what action a NPC is to perform. From there, I built a really basic action called "random move" which really only do what it is named after, move randomly without any purpose. That was a start.
What if I attack this NPC? I want him to follow me and attack if he's range. But how does he get around those buildings? Didn't took long before I concluded I was lacking some basic knowledge on the subject. I then asked Uncle Google.
I found many resource and was lucky enough to find some code in C# to help me understand. Here's some link:
http://www.codeproject.com/cs/algorithms/PathFinderLibrary.asp
http://www.codeproject.com/cs/algorithms/PathFinder.asp
http://www.gamedev.net/reference/articles/article2003.asp
I'm using a very basic A* algorithm that should be good enough for what I want to achieve which is allowing a NPC to follow a target around buildings and other objects. With the tutorials I read, it was easy enough to come to a result. In fact, the hardest part was to remove diagonal movement that for some reason, I've been unable to remove the way it should have been done. Having spent enough time already on this, I simply removed the diagonal coordinates from the coordinates available (instead of raising the cost for diagonal like it should have worked). It shouldn't bring any problem. Anyway, all the pathfinding code is isolated so it's really just a matter of recompiling a DLL if I want to improve it one day.
I'm quite happy with the final result but I feel I'll have to revisit this, performance wise. For now, each "non-static" NPC is running it's AI in it's own thread. When the server starts, each AI is started separately and is independent. In the long run, if I end up with lot of NPCs, I think this might cause some problems.
I don't quite know what is the usual way to deal with this but another way to do this would be to have 1 thread per zone. Each zone is responsible for the NPCs in it and the thread is looping through all NPC. Do NPC 1 action, do NPC 2 action, .... , returns to NPC 1...
Again, the code would have to be optimized to make sure a NPC isn't waiting for another one. The advantage of having each NPC in it's own thread is that it's easy to set cool down time for each action and making sure it is exactly as expected. The commoner in the demo have a cool down time of 1.5 seconds between each moves and attacks. So what's happening is that I let the NPC do whatever action he is currently doing than set the thread to sleep for X seconds, which is the cool down time of the action that have been performed, then function calls back itself to check for next action.
So here's the link to the demo:
Demo 3
Thursday, October 4, 2007
More Metaplace stuff
Each time I read about Metaplace, it sounds quite like I could have used it for my project. Of course, I guess it would take away some of the fun of starting something from scratch but it would surely remove some of the pain too.
I haven't bumped into anything terribly difficult yet but I can see that a long beta will be needed as there's a lot of possible scenarios. The current basic AI system I'm building might be a system that will require more time than expected. That's why I'll keep it basic to make sure I don't create a monster getting out of control. A demo for the AI should be available soon.