Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Game Design Theory / [STICKY] RPG Creation: A Technical Guide

Author
Message
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 15th Sep 2006 20:17 Edited at: 17th Sep 2006 09:11
Hello and welcome. This is a technical guide on one method of making an RPG. Certainly there are many possible ways to accomplish this, and other points of view and suggestions are welcome. This guide comes from my experience making the RPG demo for the Open MMORPG Project. This guide will specifically focus on code, coding tools, and coding techniques, and is not intended to cover design, artistic techniques, or story writing. This guide is also not intended to assist with team building or team mechanics, though these might be mentioned along the way. For example: I strongly recommend a Game Design Document (GDD) before starting, but I will not be covering how to write one.

I will also be assuming the reader has a fairly advanced understanding of how to program. At the very least, the reader should be able to kick out a 3D pong game in short amount of time. If you have a question or comment about something I have posted, or a suggestion, these are welcome. However, please refrain from asking generic coding related questions in this thread. While I am perfectly willing to help folks out, please remember that there are several boards dedicated to answering coding-related questions.

When done, the idea is that anyone following this guide can make an RPG. It will, of course, be up to you to make it a great one. All the code included with this guide is open source. If you don’t want someone to use your code, please do not post it (post pseudo code instead). Attached media will fall under this same guideline, unless otherwise specified by the owner at the time of posting.

So, onto the first topic: Code Layout and Structure

One of the first items to start an RPG will be the game structure. There will be a lot of source code to include in a game. Also, since most RPG's will have a team working on them, it is important to have identifiable sections that folks can work on. It is also important to have some coding ground rules set before starting. These ground rules should be included in the GDD. Below are a few guidelines I would suggest and will discuss later how to implement.

1) Each source-code file should be self-contained. Each source-code file should contain its own initialization routine and should not rely (as much as possible) on external code. Any code snippets provided for this guide will be self-contained.
Note: This is also necessary for testing purposes. Running a huge code each time to test a single source section to debug it is very time-consuming.
2) The main loop should be as small and readable as possible.
3) Remarks should be plentiful. Even if you are writing your own code, this will save lots of time in the long run. Debugging code will go much faster with remarks.
Note: I would say that for every line of code written, I’ve debugged at least twice as many. So this really is a time-saver.
4) Use functions instead of sub-routines (gosub/return). Then main reason is for stability. A game is likely to have deeply embedded functionality. Failure to return properly from a gosub will cause a memory leak that may not crash the game for a while. Failure to close a function will cause the code not to compile properly, so the error is caught up front, as opposed to during beta testing.
5) Use arrays instead of global variables. Arrays can be declared inside of functions and are global. Global variables need to be declared outside of functions to be global. This also makes it easy to separate and identify ‘global’ variables from local variables.
Example: Dim MyVariable(0)
6) Divide the project into groups and sub-groups. Set up the file structure to easily divide out the groups and help easily identify each group. For example: Game/Source/World/Advanced Terrain/. Game/Source/World/Trees/. And so on.
7) Pay close attention to optimization along the way. There are many tips and tricks to optimizing code and making it run as fast as possible. I recommend researching optimization techniques before writing the first line of code.
8) Use functions to create your own new commands. There are many commands to be created to make life easier. While there are many built-in DBPro commands, there are very few (none actually) specific to writing an RPG. Functions will get the job done.

Generic Code

That’s enough of the guidelines for now. Let’s jump into some code. The first, and probably most useful, source code in any game is the Generic Functions source code. These functions are intended to help with all aspects of our game. As such, they are immune to guideline #1 (above). Instead, these functions should be used as if they were built-in commands by all the other functions. The Generic Functions source code will be an expected attachment to most (if not all) other source codes. Here is our project’s Generic Functions:



While that is a lot of code, there is probably a lot more that can be added. I will leave the generic code for now, with the assumption that everyone can figure it out. Feel free to post questions though.

Advanced Terrain

So, let’s get started on creating our RPG world. One of the first things we need is Terrain. I prefer Advanced Terrain over everything else. Though I have seen some excellent work done with other types of terrain, I feel that AT does the job efficiently while allowing flexibility and retaining good looks.

The first thing we need to create our Advance Terrain is a height-map. A height-map is a grey-scale map (it actually has to be full 32-bit color) where darker shades represent lower terrain and lighter shades represent higher terrain. The size of the height-map will determine the size (or detail level) of the terrain. So a 64x64 height-map will produce a terrain with 64x64 segments. We also need two more image files: A terrain map and a detail map. The terrain map is the map of the entire terrain; dirt-brown roads, grass-green grass, or grey cement. The detail map is a texture that will provide textured detail for your AT. If most of your AT is grass, then you would use a detail image of grass. If most of your AT is dirt, then use an image of dirt.

The next step is to actually make the Advanced Terrain object. Here is a code snippet that I use to create and save an AT object. Since Advanced Terrain objects take a moment to generate it is probably better to create them ahead of time instead of in the game. The objects can be loaded into the game using the Load Terrain command, which will save some time.



If you don’t know how to use Advanced Terrain, I’ve included a help file in the attached rar file.

Okay – I need to wrap this section up now, but before I do, I don’t want to leave you hanging without something to play with. So here is a quick Advanced Terrain loader and controller to move around your terrain. Use the arrow keys to walk around. We will convert that to WASD movement later.




Open MMORPG: It's your game!

Attachments

Login to view attachments
The WhiteDragon
20
Years of Service
User Offline
Joined: 14th Jan 2004
Location: unknown
Posted: 16th Sep 2006 00:10 Edited at: 16th Sep 2006 00:11
Excellent work RiiDii!

Although I knew most of the things you mentioned here, it’s a good reference to have for everyone trying to make a RPG atm or in the future.

I’d also like to stress out the importance of GDD in RPG projects. It’s really the primary thing every person needs to have that wants to start making a RPG. The bigger and better covered GDD will give you more straightforward line of work as you don’t need to start thinking from start for new ideas for a monster or character as you approach to higher levels or stages of the game. That doesn’t mean the GDD “must” be covered in every part of the game (dialogue, items, story, all characters and monsters with their statuses, all items, events etc.), you can make it half-ready and start on the game and finish it up as you progress with your project.

But, there is a reason why GDD “should” be 100% completed before you start on any work (modeling, coding, music making or whatever). If you 1st concentrate on the GDD, the storyline and the game logic itself probably will be better as you’ll work only on GDD and make it best you can. If you mix GDD, coding, modeling etc. all in the same time you’ll end in dead end alley very fast as you’ll run out of original/better/new ideas.

Best is to do it 1 by 1. Make the full GDD 1st (doesn’t matter if it’ll take years, the story and game idea can live forever but 3d models and other game parts get old with time!), them make a good deadline for every part of your project and as last start working part by part on the game starting from main engine and ending with those “nifty” things. As I mentioned above, the story and game idea can’t die or get old as long as it’s original. If you start doing models at the time of just starting the GDD, your models will be maybe way outdated by the time you’ll be ready to finish the project!

"Enjoy the moment... forget the past and the future. Eternity is here..."
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 16th Sep 2006 10:08
Thanks Mr. Dragon. I could not agree more about the importance of the GDD and how it will stay on throughout the game creation. It is meant to be a living document, so it can change as technologies or story ideas change.

Scripting and Parsers
Before I get too much further into other aspects of the game, it is probably a good idea to cover scripting. Scripting allows a lot more flexibility to be incorporated into the game. Scripting also allows non-coders (artists ) to help develop the game as well. If sometime later there is to be a change to some aspect of the game, it can be found much easier to change a script file than to go hunting through over 60,000 lines of code.

To get scripting to work, we have developed some parser code, which disects sentences and stores the resulting "words" in arrays. The basic concept works like this; using the following sentence, "This is a test", the parser will split up the words and store them in an array. So, Dim Word(3): Word(0)="This", Word(1)="is", Word(2)="a", and Word(3)="test".

Instead of spaces, the file parser uses semi-colons as separators. So, the script file looks like this: "This;is;a;test". This way, if we are importing a description, we can include most punctuation. Slayer's sentence parser does pretty much the same job, but is used for internal parsing. Instead of a fixed separator, the function can incorporate a list of separators, such as spaces, commas, periods, and so on. This is valuable for making our spam-box, which does word-wrapping. So the sentences need to be divided out into individual words, and then placed into text areas with word wrapping (which will be covered later).

Here is our parser code:



You may notice that there are two Slayer’s Sentence Parsers in the above code. The first is our generic sentence parser, but the second was developed for a very special reason (and never was replaced by the modified first version). This reason is of particular interest to almost any project. The concept was to use the sentence parser to dissect arguments passed into a function.

The problem with functions in DBPro is they can only accept a set number of arguments. If you set the function up with three arguments, then three arguments is all it will ever accept. It won’t accept two, four, or none; only three. The work-around to this is to pass the arguments to the function as a single string, with the arguments separated by semi-colons. The function the calls the parser, which divides out the arguments, which can be then be used by the function. This allows any number of arguments to be passed to functions. Here is an example of one function that does this:



This is the New_Skills function, which will be covered much later. The first nine arguments are required. After that, any number of strings, integers, or float values can be passed to the function for storage: Very useful.

The parser functions, like the Generic functions, are used by lots of other functions. So this file often needs to be included with other source file tests.

Static Objects (a.k.a. Statics)
Statics are a special type of object designed primarily for detailed background objects, like grass, dirt, sand, flowers, and so on. Statics really help make the terrain look realistic and is a technique used in many other games today (though it is probably called something else). The basic concept is to manage 1000’s of small, low-polygon objects on the terrain to add to the looks of the terrain. Statics are not necessary, and is a step that can be skipped in favor of a higher frame rate. But they look real good and are difficult to pass up.

Statics start with a special copy of the terrain map (from the Advanced Terrain). This map needs to be rotated counter-clockwise 90 degrees and flipped vertically, so it will align properly with the Advanced Terrain (of course, you could do this mathematically in the code, but I got lazy). The image is read into a Memblock and that Memblock is duplicated. The two Memblocks then tell the code which Static Objects to place at what locations on the terrain. This gets pretty complicated, but I think I can explain it.

Memblock 1 (which is a copy of the Statics map) tells the code what type (category) of Static Object is needed (i.e. a grass object, a flower object, a road object, etc.). Each category of Static Objects has about 100 copies of that object to select from. This is where the second Memblock comes in. The second Memblock stores which object was actually used. So, why not just fill the second Memblock and delete the first one? There are not enough Static Objects to go around. For example, if we fill in a small 20x20 area, that is 400 Static Objects. We may only have a 100 of a particular type, and those will get used up fairly quick.

How the code manages this is; if the second Memblock tells the code that a given Static Object needs to be used, and that Static Object is already in use, then the code searches for an unused Static Object of the same type to use in place of the one recommended by the Memblock. In order to search for a new static, the code references the first Memblock for what type of Static Object is needed. I hope that helps explain why there are two Memblocks.

The next thing the code does is check for Static Objects that are beyond the Static Range and remove them from the terrain and placing them in the pool (which is at 0,-10000,0) for future use. The pool is where the code looks for unused Static Objects. Besides a little randomization of size, placement, and rotation, that’s about it. The only remaining technical part to understand is how to angle the Static Object to match the terrain. This is accomplished by taking the location of the object’s x/z coordinates and calculating the ground height. Then the same is done for x+4,z and x,z+4. Then using ATANFULL, the angles are calculated for each rotation, and then the object is rotated accordingly. Here’s the function that handles that:



Feel free to look through the Statics source code attached. But it is not too important to understand how it all works. What you really need to know is how to make a Static Object, texture it, and script it. Just include the source code and call the Initialize_Statics() function at the beginning of your code, and then call the Manage_Statics() function during the main loop. I will cover all this on the next post. In the meantime, attached is the source code for both the Parser and the Statics.

Here is an example of what statics look like. The road, the trees, the grass, and the shadows, were all accomplished using statics.



Open MMORPG: It's your game!

Attachments

Login to view attachments
Slayer93
19
Years of Service
User Offline
Joined: 5th Aug 2004
Location: I wish I knew
Posted: 16th Sep 2006 21:10
Great Job RiiDii Great job and not just because you used my name.

Naruto is the ninja...not really

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 17th Sep 2006 08:52 Edited at: 17th Sep 2006 08:59
Thanks Slayer!

Here's some more information about Statics. Specifically the Static Map.

That static map, as mentioned before, is a rough copy of the terrain map. For example; where there are roads on the Advanced Terrain, there should also be roads on the Statics Map. The colors used on the Statics Map are determined by the Statics script file. Here is our file:



As you can see, the format starts with the file name, then Red, Green, and Blue (I will briefly cover the rest of the items later). These RGB values are the values to paint on the Statics Map in order to have the appropriate static objects appear in that location on the terrain. As you can see, for the Grass Statics, the color RGB(0,255,0) is used. So, everywhere a green pixel on the Static Map is read, the code places a Grass Static Object.

You might be wondering how the pixels are read from the respective memblocks. This was a simple matter of writing a few functions to convert x/y image coordinates to a Memblock position. First, the first 3 DWords (12 bytes) of an image Memblock are the Width, Height, and Color Depth of the image. The next DWord is the x,y = 0,0 location on the image. If an Image is 64x64x32 pixels, the first 64 DWords (after the first 12) in the Memblock is are all the x coordinates along the y=0 row (x,y = 0->63,0). The next 64 DWords are the x coordinates along the y-1 row (x,y = 0->63,1). And so on. Here are the functions used to convert a pixel location into a Memblock location:



The result of the Get_Pixel_Pos() function is the Memblock byte that starts that pixel's DWord. So, to get the color of the pixel at a specific location the code would look like this:
p=Get_Pixel_Pos(x,y,1)
color as DWord
color=Memblock Dword(1,p)

The returned color from Memblock 1 (our Statics Map image) is compared to the loaded Statics database (stored in an array), which returns the type of static that belongs at the location x,y. Assuming no static has been previously assigned to the x,y location (which is stored in Memblock 2), the Unused_Static() function returns a Static Object to use.



The returned value is then stored in Memblock 2 at the location p (which was previously calculated), and the Static Object is placed on the terrain and angled appropriately.

The Statics Map Memblock can also be linked to play sound effects related to the terrain being walked on. For Grass, play a walking in grass sound. For roads, play a walking on rocks sound. For sand, swamp, and so forth, appropriate sound effects can also be played. The speed of the character can also be modified for terrain as well using the Statics Map. As you can see, the Statics Map, while not critical to an RPG, is very difficult to pass up.

The rest of the Statics script helps define some obvious aspects of the Statics, such as size ("add" is how much to randomly add onto the base size), Cull and Fog flags, Grass Flag (which is a flag used to scroll the static texture to simulate wind), and Percentage. The Percentage value is a chance of using any given Static Object type. If the chance fails, the code moves on to the next type and checks that type against a chance value. So it is important to set the last Static Type for a particular RGB value at 100, so a blank terrain space will not show up (unless you want it to).

{I would like to acknowledge Tinkergirl's original work on the Statics Map. She called it something else back when she first introduced the concept, but the basic idea has not really changed very much).

2D Buttons
Any RPG needs 2D buttons. And, while the term "2D Buttons" may seem a bit redundant (as in, are there any other type?), there are 3D buttons, which will be covered later.

The basic concept behind how this project does buttons is by using sprites and sprite collision. Take a small 1x1 pixel sprite, hide it, and position it every cycle with the mouse pointer. Check that sprite for a collision against other sprites, and return the value. This little snippet gives a good idea of this concept.



All that is left to do is check for a mouse button being pressed, and we are in business. The 2D Button code is a bit more complex. Most if it is data management. The buttons can be scripted (ideally they should be). There are also some features that can be applied to buttons, which are normally available for sprites. For example, there is an animated button property, which will switch between two frames on the same image, which indicates the mouse is over that button.

In addition to scripting and features, this button code also retains stored values that can be assigned to buttons. So now two values can be returned from our buttons. The first value is the array position of the button in the database (which is basically the order the button was created in). This value may change if buttons are deleted. The second value is one that is assigned to the button. This value does not change. This can be useful for ensuring that a fixed value is returned despite deleting buttons. Or the return value can be usefull for categorizing buttons. However the assigned value is used, it is a must-have feature.

Here is our 2D Buttons source code:



And here is our Main Menu, which uses the Button functionality above.



You can also download the attached file with source code, media and scripts.


Open MMORPG: It's your game!

Attachments

Login to view attachments
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 17th Sep 2006 20:42
Getting the RPG Started

Let's take what we have gone over so far and apply it to starting an RPG. Here are the first few high-level steps to getting our Main Menu up and running.

Create a new DBPro Project
Set up the file folders in the project folder (unpack the attached rar file for a sample set-up)
Copy in required source files to the project's folders
Place the necessary media file in the project's folders
Create the Initialize Game source file
Create the Main Menu source file
Create two script files

After these 8 steps, and about 10 minutes of coding/scripting, I had the attached functioning Main Menu. It is really that easy. The first 5 steps I think most everyone can figure out for themselves (of course, feel free to ask). So I will explain the last three steps in more detail.

Create the Initialize Game source file
The purpose of the Initialize Game source is to initialize the various group functions, such as the parser or the buttons in this example. If we were to include Dark Physics, for example, we would intialize the physics in the Initialize Game source, but in a function designed specifically for pre-game play.

Create the Main Menu source file
This took about 8 minutes of coding to write. The main purpose of this source file is to load the Main Menu media and capture the program flow in a Do-Loop until the user exits by selecting one of the options. This was accomplished by making the following functions:

Load_Main_Menu()
Main_Menu()
New_Game()
Exit_Game()

Of course, we will be adding on more selection functions (like the New_Game() and Exit_Game() functions) at a later time.

So, how did all this take me only about 15 minutes to create? Well, really, it took a lot longer. I wrote the 2D Button functions and the Parser functions previously. But now everyone can use these functions in any project just as if they were built-in DBPro commands. Let's take a look at some of the functionality used in the attached code.

Parse_File(filename as String,filenum as Integer)
This function reads in a script file and stores the results in a 2D Array: PFile(i,j). Each "i" element represents a line from the script file. Each "j" element represents a "word" from the script file (remember, "words" are separated by semicolons ";", not spaces). The Parse_File() function also sets two Global Variables: parser_max_lines(0) and parser_max_words(0). The variables return the maximimum elements for the PFile() array. So PFile(parser_max_lines(0),parser_max_words(0)) is the last element in the array.

The PFile() array is a string, so all numeric values that are scripted need to be converted by using Val(PFile(i,j)).

The filename is the complete file name and location of the script file. This can be relative or litteral. The file number is the file number that will be used to open the script file. The number must be a file numer that is not in use. The file is closed automatically at the end of the Parse_File() function, so the number is free to use again.

Parse_Buttons(FileName as String,FileNum as Integer)
This function loads in all buttons scripted in a button script file. There are 5 elements read for each button:
1) Image File Location\Name
2) X Position
3) Y Position
4) Stored Value (a.k.a. Return Value)
5) Animation Flag

The buttons are loaded using the script format and placed accordingly. The animation flag will tell the button code to divide the image in half horizontally. The first half of the image will be the "at rest" state, and the second half of the image will be the "active" state. You can see how this animation works when running the attached sample code.
The stored value is any value we choose. Of course, it helps to have a coded reponse to the values that are stored, but it is not necessary. For our Main_Menu() function, the coded values are 1 for a New_Game(), and 99 to Exit_Game(). Any other values will (at this time) do nothing.

return_integer=Get_Button()
The Get_Button() function returns the Stored Value of the button that the mouse pointer is currently over. If the pointer is not over a button, a 0 is returned. Other sprites over or under a button can prevent the correct return value from being returned.


Open MMORPG: It's your game!

Attachments

Login to view attachments
RadiusOFT
18
Years of Service
User Offline
Joined: 14th Jul 2005
Location: Aloha, OR(egon)
Posted: 20th Sep 2006 02:34
I still dont get what scripting is.

Do or do not... there is no try -yoda
cats fit best in a george forman - not yoda
Slayer93
19
Years of Service
User Offline
Joined: 5th Aug 2004
Location: I wish I knew
Posted: 20th Sep 2006 06:53
Good job RiiDii I havent read the whole thing but I will.

Quote: "I still dont get what scripting is."


Scripting is basiclly writing what you want outside the program. Writing something like this


Load object "someobject.x",1
position object 1,100,100,100


is called hard coding. Scripts help out with this by putting it outside the program in a file. This can help if you want to change a little thing in a huge code without recompiling.

Naruto is the ninja...not really

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 20th Sep 2006 11:10
Thanks for the question RadiusOFT.

Think of .ini files as script files. Basically, all a script file is; is a text file with information that is read into the code. The code then does something with that information. The most common example of scripting is used for game settings. When you play a game and set the resolution, shadows on/off, music volume, and so forth; the information is stored in a file. Then, when the game is played next time, the file is read and the settings are set based on the data that was stored.

Scripting can actually go a lot further than just settings. In the case of our RPG, we are using scripting so that each NPC, Zone, Terrain Type, Skill, Quest, Teleporter, Inventory, and so forth can be set using a script file. The file contains information like where to find the media, where to place the object, how to interact with the player, and so much more.

For example: Inventory items have an image (file location/name), item name, weight, value, quality, and a description. When the code reads in the inteventory script, it creates a button (see the 2D Button tutorial above) and puts the data into an inventory array. When the pointer hovers the mouse over the button, the description of the item is displayed. Now, let's say we want to change the description of one of our items. All we have to do is open the Inventory.txt file, find the item from the list, and edit the description. What we don't have to do is search through 60k lines of code to find the description. Here's an example of our Inventory script file (*'s are remark indicators):



Does that help explain it better?


Open MMORPG: It's your game!
RadiusOFT
18
Years of Service
User Offline
Joined: 14th Jul 2005
Location: Aloha, OR(egon)
Posted: 20th Sep 2006 22:44
Yes thanks, but if im correct couldnt you do the same using a User Defined Type?

Do or do not... there is no try -yoda
cats fit best in a george forman - not yoda
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 21st Sep 2006 07:53
Mmm... you are correct. We do use UDT's to store the information from the script files. But we don't want to keep the data in the UDT array:

Let's say for our RPG we want a zone with a beach, some sand, a few palm trees, some grass up the way, and a rocky area. We script all that info into a .txt script file. Now, our next zone is inland a bit and includes a forest, more grassy areas, and a small village. All that is stored in a script file as well. Our next zone is at a slightly higher elevation and includes snow, some grass, dirt, and pine trees. Again, stored in a script file.

If we only use a UDT array, all that data is stored in the game and is using up resources even if our player is not in the zone. By using script files, the old data is dumped and the new data is loaded in for the new zone.

Now let's say we want to add seasons to our RPG. The snowy zone only has snow half the year. We can even use four seperate script files to load the same zone; one for each season.


Open MMORPG: It's your game!
Cash Curtis II
19
Years of Service
User Offline
Joined: 8th Apr 2005
Location: Corpus Christi Texas
Posted: 21st Sep 2006 11:05
I think most importantly - scripting allows you to make changes to the game without recompiling. For a game that is... say... 12000 lines of code, that can greatly speed up development. If you have to recompile every time you increase a monster's health or character's damage, you're going to waste a lot of time. Or, you can simply change the script file and run it again.


Come see the WIP!
x1bwork
18
Years of Service
User Offline
Joined: 9th Nov 2005
Location:
Posted: 21st Sep 2006 15:55 Edited at: 21st Sep 2006 15:57
excellent job riidii. youve encouraged me to get off my fence and back to coding Juxta Tempus. not that im lazy, I just enjoy doing nothing.

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 21st Sep 2006 19:53 Edited at: 21st Sep 2006 19:54
Glad to inspire something other than what I am so good at. But I think it's the 'enjoyment of doing nothing' that makes us smart; we find better, faster, efficienter, and accurater ways of doing things - like inventing new words.

Quote: "I think most importantly - scripting allows you to make changes to the game without recompiling."

Speaking of efficiency: I know this is a big time saver, and yet I keep catching myself recompiling out of habbit.


Open MMORPG: It's your game!
RadiusOFT
18
Years of Service
User Offline
Joined: 14th Jul 2005
Location: Aloha, OR(egon)
Posted: 22nd Sep 2006 02:48
oh btw i think you mentioned somthing about this earlier in the thread but why is it better to use functions instead of GoSubs?
thanks

Do or do not... there is no try -yoda
cats fit best in a george forman - not yoda
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 22nd Sep 2006 04:54
Yes. The first post.
Quote: "4) Use functions instead of sub-routines (gosub/return). Then main reason is for stability. A game is likely to have deeply embedded functionality. Failure to return properly from a gosub will cause a memory leak that may not crash the game for a while. Failure to close a function will cause the code not to compile properly, so the error is caught up front, as opposed to during beta testing."



Open MMORPG: It's your game!
entomophobiac
21
Years of Service
User Offline
Joined: 1st Nov 2002
Location: United States
Posted: 22nd Sep 2006 10:55
The technical part that interests me the most is the multiplayer aspect. I've been fiddling around with various solutions for a client/server system that works as dynamically as possible. (My goal is to have a server that takes care of all the math, from physics to AI.)

But for various reasons I haven't succeeded too well. Not the least being lacking understanding for fundamental multiplayer principles, I guess.
MikeS
Retired Moderator
21
Years of Service
User Offline
Joined: 2nd Dec 2002
Location: United States
Posted: 2nd Oct 2006 01:18
Wow, quite a bit of good information here, nice work Riidii.





A book? I hate book. Book is stupid.
(Formerly Yellow)
Cian Rice
19
Years of Service
User Offline
Joined: 8th Jun 2004
Location:
Posted: 3rd Oct 2006 02:44
Me thinks this deserves a sticky, its a great guide for beginning the programming aspect of an RPG, and we don't have many of those.

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 3rd Oct 2006 09:54
Thanks for the comments.

In case anyone is wondering, I will continue the work on this. Right now I am behind on my schoolwork, and I am so close to graduation. Once that is done, I will write more.


Open MMORPG: It's your game!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 3rd Oct 2006 21:35 Edited at: 3rd Oct 2006 21:41
I found a little extra time, so here is an earlier-than-expected update.

We are going to start looking at our Agent AI. Agents are, for our Open Source RPG, pretty much anything with AI – even minimal AI. Agents would include rabbits, groles, wild garlic, rox lizards, NPC’s, and maybe even doors (still deciding on this one). But before we get into the actual AI, we are going to look at a sort of global-intelligence-system that all our Agents and Player(s) can tap into to get valuable information. This system, for our game, is called the Targeting System, but the concept could be applied to so much more. For example, if you wanted to write a Sim game, this system could be easily modified to allow the agents in the Sim collect/give data from/to other agents (i.e. a merchant giving food to a citizen and taking money from that citizen).

Before I get into the details, I would like to explain why global targeting function were used instead of just variable-types in a UDT array (i.e. Agent(ID).Target, Agent(ID).CombatTarget, and so forth). Two reasons; the first is because not all Agents have all types of targets at all times. The second is that looking up combat information is quicker and easier. Both reasons help save on resources - memory and cycle time (FPS).

For purposes of our RPG, we used three different types of targeting, but they all follow pretty much the same concept. These are; generic Targets (which includes both pre-target and locked-target), Combat Targets, and Aggression Lists. The Target list is pretty straight forward for Agents. If the agent needs to get to another object, that Agent and the target Object are added in a single element to the Target list. Once the Agent arrives at the target object, that element is removed from the stack. For the player, the Target can have two states; unlocked and locked. If the target is unlocked, then the mouse is just passing over the object on the screen. If the player clicks on the object, then the target becomes locked.

Our Combat list stores an object that the Agent has “decided” to fight – the primary target of combat (secondary targets are stored in the Aggression list). There are three ways to remove an element from the combat list; the aggressor dies, the target dies, or the aggressor chooses another primary target. In the last scenario, the combat target is moved to the aggression list and will likely become a combat target again. The combat list also serves a secondary, but valuable, function; it stores combat damage. When an agent attacks a target, if the result a “hit”, the damage is stored in the combat list at the same element the attacker and target are stored. After all combat is resolved, each agent looks through the combat list and pulls their damage from the stack (and resetting the stored damage to zero, of course). If there are multiple attackers, the agent receives multiple sources of damage. The agent receiving damage also copies the source object of the damage and adds that source object as a target object in the aggression list.

The Aggression list stores all the combat targets that the Agent is “remembering” to fight at a later time. We will get into how Agents select targets later, but for now, we will describe this process as a “decision” made be the Agent. When the Agent is in combat with more than one opponent, it can only target/attack a single opponent at a time. All other potential targets (usually because they are attacking the Agent) are stored in the Aggression list. Each target in the Aggression list also has an Aggro score. This higher this score, the more likely it will be the next target. In fact, the target with the largest aggro score an Agent has in the Aggression list will be the next combat target of that agent. The Aggro score is also used when the Agent makes a decision to switch targets.

The code for the player also uses both the Target and Combat lists, but (obviously) not the Aggression list. The damage done to the player is also retrieved from the Combat list.

While this seems to be a complex method of handling targeting and combat (and it is), it really does save on memory and processing time. Instead of each agent searching through the entire list of agents to see which agents are in combat, only the short list of agents that are actually in combat needs to be checked. You also now have a system that can be plugged into any other game you want to make. The damage isn’t set. The rules for deciding aggression are not set. And the system is Object ID based, meaning it uses the object numbers instead of other ID’s, making the system useable by any other system.

Here is a visual layout of the three different arrays and the source code. There is a demo included, which should be removed/remarked out before including the code in any project.






Open MMORPG: It's your game!

Attachments

Login to view attachments
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 18th Oct 2006 21:08
AI Continued...

The next step in the AI routines I will cover is the main AI function, which is a simple loop that executes all the sub-AI functions. Here's the code:



As you can see, the function loops through all the possible agents and runs them through all the possible activities that the agent might do. These sub-functions then make their own determination if the Agent qualifies for the activity within the sub-function. If not, the code exits the function and moves on to the next one. Let's take a look at Move_Agents() as an example.



First, an explanation of what is there: The difference between Move_Agents() and Agent_Move() is simply that Move_Agents() is the decision-making portion, and Agent_move() is the physical movement part. Next, the variables in capital letters are constants that are set to standardized values (it doesn't matter what the values are, just that the code is easier to read with constants). So, if a value is set to AGENT_MOVING, then we can easily read that the agent is moving; as opposed to a value being set to 8. What does that mean?

First, we check to see if the Agent is a valid agent.
If Agent_Not_Valid(i) Then Exitfunction

This is simply a safety check in case the agent is removed or killed or something, before we get to this function.

Next, we validate that the agent is in a state in which it should be moving. This could be idle movement, fighting, or fleeing.
if Agents(i).State = AGENT_MOVING or Agents(i).State = AGENT_FIGHT or Agents(i).State = AGENT_FLEE

The rest of the function simply progresses the movement decision making process. For example, if the agent is fighting or fleeing, it is considered "running" and moves at an increased speed. Then the actual move is made.

I will go into the other functions at a later date, but I want to point out the coding strategy here. AI is not all that complicated. It is simply a matter of breaking down all the little things you want your AI to do into little segments of code, or even sub-segments of code. Ideally, each sub-function should only be about 20 lines or so. This makes it easy to read and easy to debug. As mentioned earlier, functions should be nearly independant when possible. In the case of AI, each function goes into your AI library, and soon you can put together any type of AI you need. Just call a simple master loop, like the one above, and you are done.


Open MMORPG: It's your game!
Bongadoo
17
Years of Service
User Offline
Joined: 4th May 2006
Location:
Posted: 22nd Oct 2006 00:03
Thanks for the time and effort you've put into this post RiiDii, I've found it very useful and informative (especially the Parser code).

I'm currently working on an adaptive caching algorithm for my RPG dynamic loading world, so seeing other world construction methods (especially in depth ones like this) is very useful.

Also I just wanted to say I think the OpenMMO project is fantastic and keep up the good work all involved.
Oneka
20
Years of Service
User Offline
Joined: 24th Apr 2004
Location: Hampton,VA
Posted: 22nd Oct 2006 07:10
Interesting design document, It is funny how my project and yours(the team's) project are so different yet are very similiar in design. Anyway good luck to you all


Making better games everday!
Oh yeah and just so you know its Oh-nek-a not One-ka!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 22nd Oct 2006 11:31
Thanks for the feedback Bongadoo. I would definately like to see that dynamic loading engine. With "pure" DBPro, it can be difficult to do something as resource intensive, like loading, and keep the game going at a reasonable framerate.

Thanks Oneka. And good luck to you as well.

Does anyone have a request for the next section here? If not, I will just keep going with AI for a bit.


Open MMORPG: It's your game!
RadiusOFT
18
Years of Service
User Offline
Joined: 14th Jul 2005
Location: Aloha, OR(egon)
Posted: 22nd Oct 2006 19:06
whats so hard about loading an object? Does it make the game really slow if you use load object command? thanks

Oneka
20
Years of Service
User Offline
Joined: 24th Apr 2004
Location: Hampton,VA
Posted: 22nd Oct 2006 20:58
@RadiusOFT there is nothing hard about loading an object, but if you load an X amount of objects at once it is very noticable and will either lower framerate or cause a pause of the program until it is done loading, anywhere from milliseconds to minutes depending on the amount of data that you are trying to load, so a dynamic loading system would load a set number of items in the background while trying do this and not having to have it too noticable by the player.


Making better games everday!
Oh yeah and just so you know its Oh-nek-a not One-ka!
RadiusOFT
18
Years of Service
User Offline
Joined: 14th Jul 2005
Location: Aloha, OR(egon)
Posted: 24th Oct 2006 05:53 Edited at: 24th Oct 2006 05:57
ahhh. I see. Thanks

Hey if you have time could you mabey talk about techniques to speed up a games fps? that would be great, thanks.

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 27th Oct 2006 02:01
Sorry, it took me a while to find it, but here is an excelent resource for how to speed up game fps.
http://forum.thegamecreators.com/?m=forum_view&t=88661&b=1

One of the most important things I can suggest to do is to create yourself a little timer program that simply checks the timer at the start of a test and then again at the end of a test. Then run two tests side-by-side (like 100,000 times each) and see which is the faster method. The timer measures in miliseconds, but the clockspeed on your CPU is in nanoseconds, so you need to run calculations several thousand times to notice any differences in processing time.


Open MMORPG: It's your game!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 7th Nov 2006 09:45
3D Buttons:

One important aspect of an RPG game is the ability to interact with the world; whether that is the envioronment or an Agent(AI entities such as critters or NPC's). When you want to open a door, clicking on it is pretty standard. When you want to talk to an NPC, clicking on them is also the norm. What 3D buttons allow us to do is code the clickability of 3D objects similar to the way 2D buttons are clickable.

The first thing needed when "inventing" 3D Buttons (also called Object Buttons), was to determine what would happen. Similar to 2D buttons, I wanted the object to be able to return a given value. That value could be used by the code to decide how to handle the button-click. A second factor was how to limit how many 3D Buttons would be checked at any given moment. If the zone has a lot of objects, a lot of button checking could impact game speed. So, it is a good idea to restrict object checking by distance. If an object is too far away, the object is ignored. Otherwise, the object can be checked for clicking.

Another factor I considered to be usefull was to store the last button clicked. This way, if the player clicks on a 3D object, and then does releases the mouse button, the last object clicked can easily be recovered. Certianly, the coder can easily keep track of all the same information externally of these functions, but then again - anything else could be handled externally as well. So it was coded into the function set and if it is needed, it is already coded - ready to go. No external storage need; nice and convenient.

Also for convenience, there is a timestamp recorded when a 3D Button is clicked. This way, if for any reason, the time since the object was clicked is needed, it is easily retrieved. 3D buttons can also be named. Storing and retreiving text can slow down a game, so this needed to be optional. Not onlly is naming a 3D button optional, but the array that stores the names is seperate from the main 3D Button array. This helps keep resources to a minimum and keep FPS moving right along. Take a look at how the arrays are set up:



As you can see, each button has an Index, Object ID, a Return Value, Range (clickable distance), Name, Time (stamp), Active (flag), and Click (type). The click type indicates which mouse-click stores the mouse button state (i.e. Left-Click, Right-Click, etc.) at the time the 3D Button was activated.

There is also an entire suite of functions that can be used to return all the stored usefull information. But for the most part, only the following three functions will be used regularly:

Initialize_Object_Buttons()
Make_Object_Button(ObjectID as Word,ReturnVal as Integer, Range as Float, Name as String)
Active_Object_Button()

Rumage through this code to see how the buttons were made, or you can simply use this code as inteded as a library of functions to import into any project. There is also a demo showing how 3D buttons work. Move around with the arrow keys, and left/right click on the boxes.




Open MMORPG: It's your game!
wildbill
18
Years of Service
User Offline
Joined: 14th Apr 2006
Location:
Posted: 7th Nov 2006 22:18
Actually using the range check function for button clicks is way to simple. It has prevented brain meltdown for me and is much appreciated.
Siolis
17
Years of Service
User Offline
Joined: 19th May 2006
Location:
Posted: 7th Nov 2006 23:10
Shouldnt this be in a different forum as i keep clicking on it to read theory and keep reading code.

Doh!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 8th Nov 2006 08:51
Quote: "Actually using the range check function for button clicks is way to simple. It has prevented brain meltdown for me and is much appreciated."

Quite welcome - glad I could help.

@Solis:
Maybe. It is still theory. Just because I provide code to support my theories, doesn't mean there are not discussions to be had on how best to accomplish something. For example; there was a nice discussion on using scripts vs. UDT's up there. So far though, it seems folks just appreciate the ideas and the code I am posting. Anyone wants to add to what I have put out there is more than welcome.

I will agree that this could go, perhaps, in the code snippets section, but then someone could easily say "shouldn't this go somewhere else, like in Game Design Theory?" Seems to me that 'complaining' about getting code with the theory is like complaining about getting hot fudge on your sundae (unless you don't like hot fudge on your sundaes... but that would be your problem, not really anyone elses then).

Anyway, kidding aside, thanks for the perspective. I will certainly try to add in more "theory", but not less code: I personally think it adds value.


Open MMORPG: It's your game!
The crazy
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Behind you
Posted: 8th Nov 2006 15:57
Yeah, chill out siolis. It's great that he's doing this. I, however cannot eat fudge But that doesn't mean I can't appreciate this code.

Siolis
17
Years of Service
User Offline
Joined: 19th May 2006
Location:
Posted: 8th Nov 2006 21:05
Firstly, nothing irritates me more than people purposely misinterpreting what I post with the intention of frying* me and normally i would swear at you but I’m going for a business like persona here so i wont, but i will correct you, now let me make this perfectly clear:

I am not angry, annoyed, pissed off, irritated or in need of chilling out for i am perfectly cool and was making an observation.

I have not read this thread and did not say I did. My words were:

“Shouldn’t this be in a different forum as i keep clicking on it to read theory and keep reading code.”

Which doesn’t indicate my exact actions except that I haven’t been reading it because it doesn’t seem of interest to me.

I was also not criticizing the quality of it, i simply said i saw code as i scanned and didn’t bother to read it as it doesn’t seem to cover RPG subjects such as Inventory, Character Status, Plot Lines or anything else i relate with RPG design. Looking now, i can see the subjects you have covered are; Scripting and Parsers, 2D Buttons, Static Objects and how to set up an RPG project in DarkBASIC Pro, none of which are related to theory and all of which relate to either generic coding and/or DarkBASIC Pro.

Now I wont be reading this thread again, so don’t bother replying as I wont be lowering myself to you people and if you plan on calling me touchy or anything else, here or anywhere else, I’ve seen you specific posters doing it to other people and I’ve called you on it, you keep trying it on with me and ill report you, with examples, to the mods.

(Frying is what I call a group of posters trying to discredit the intelligence and standing of another poster by either flaming baiting or making comments such as “Chill out” when people are not actually annoyed at anyone but merely making a reasonable comment.)

And just as a last word, now ive read it, I now still hold my opinion that it should be moved, the topics are mostly code based and you keep referencing DBP.

Siolis

PS: Just to avoid any confusion; my mood as of this post and second is as follows:

I am slightly annoyed about your attempt at frying, I do think this post belongs in the DBP forum, I will, in a few seconds, forget about this post and be entirely happy about everything in my world again, mmk.

Doh!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 9th Nov 2006 10:20 Edited at: 9th Nov 2006 10:22
Siolis, I am really having a difficult time understanding your frustration.

1) How can you "not read this thread" but "keep reading code"?
You say you didn't say you read this thread by quoting a line talking about how you say are reading this thread.
Quote: "I have not read this thread and did not say I did. My words were:

“Shouldn’t this be in a different forum as i keep clicking on it to read theory and keep reading code.”"


Maybe you can understand my confusion.

2) You may have made only an observation, but it does have the overtone of a complaint. I agree: "This shouldn't be here" is absolutely an observation, but one that is typically only observed or stated if there is a complaint. Otherwise, why bother? Would you not agree? And you have the right to complain. And, while you don't need to, I suppose you even have the right to complain when people point out that you are complaining. But at some point, you are just complaining to complain.

3) I fairly put the words "A Technical Guide" into the thread title, warning about all the (boring) technical information within. The very first post also went into more detail about how this is a technical guide. Only halfway through the first paragrah (not much reading needed at all), I wrote;
Quote: "This guide will specifically focus on code, coding tools, and coding techniques, and is not intended to cover design, artistic techniques, or story writing."


I appologize if any of this confused you. It was never my intention to trick anyone into coming into this thread.

Siolis, I simply responded to your original observation - noting it AND appreciating your feedback (true, after a bit of fun - but that's all it was - I even said so).

Now, would you do me a huge favor and edit out your comments, in your previous posts? I will do the same (including this post) if you do. Maybe The Crazy can do the same. I would very much appreciate it.


Open MMORPG: It's your game!
The crazy
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Behind you
Posted: 9th Nov 2006 15:56
Quote: "Now I wont be reading this thread again, so don’t bother replying as I wont be lowering myself to you people and if you plan on calling me touchy or anything else"


Definitely touchy... seriously, if you didn't need to chill out before, you do now

Quote: "Maybe The Crazy can do the same"


Oh yeah totally dude. But he said he isn't coming back so we'll see...

But back on topic. RiiDii thanks a lot man. That button code really helped me out.

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 9th Nov 2006 21:40
Quote: "That button code really helped me out. "

Glad to help.


Open MMORPG: It's your game!
Daris Xiao or Benjy Wright
20
Years of Service
User Offline
Joined: 13th Dec 2003
Location: Face first in a bowl of soup.
Posted: 11th Nov 2006 20:40
@RiiDii : Dude this is amazing stuff, And I believe this is the perfect forum for it. I've been following for a while, and your thread here and the posts on it have really helped me out. Just if you didn't know, I'm the guy developing the engine for the Redwall Game, and I never understood memblocks until now. I'm building my own approach based of my new found knowledge aquired mostly from your tutorial here, so keep up the excellent work!

Daris Xiao - Phonetic: Daris Shiao. aka: Benjy Wright.
2.4Ghz Pentium 4 (800FSB!!!) - 1024mb RAM - ATI Radeon 9800 Pro 256mb Video
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 11th Nov 2006 22:29
@Daris Xiao or Benjy Wright: Thanks for the comments - and glad to have helped!


Open MMORPG: It's your game!
indi
21
Years of Service
User Offline
Joined: 26th Aug 2002
Location: Earth, Brisbane, Australia
Posted: 8th Dec 2006 08:24
i think this has become worthy of a sticky.
slaps some glue around.

RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 8th Dec 2006 19:30
I am no longer a sticky virgin . Wait, that doesn't sound quite right. Anyway, I am working right now on revising the OMMORPG Project with a significant change combining Agents, Geometry, and Skills using the Infinite State Engine. Once I have the code down, I will return here to post the source and how it benefited the overall engine.

Sneak Peak (thoery for now):
The Infinite State Engine allows us to create and track any "AI" state needed. The I.S.E. allows the definition of any state one can think of - hence the name, not an infinite number of states. Each state is assigned to an object or just an ID (no object required). Internal coded states have a negative ID value assigned for the state value. Scripted state values are assigned positive numbers. Ideally, this will allow either auto-assigned code-generated values or script-assigned values.

Geometry is being classified as an Agent that simply doesn't do anything. This makes it easy to combine Agents and Geometry as well as reducing the code. Skills are basically states that Agents (or the player) are in at any given time. For example, when casting a spell, the player is in a "spell casting" state for a short period of time. The completion of that state triggers a unique event (if the spell casting is successful). For most spells, the event will be to create an Agent - an AI that will complete the requested task. For example: A Fire-Spear spell will create a little flame-elemntal critter that heads directly towards the target and attacks the target for x damage. Once damage is dealt, the Agent is "deleted". A healing spell works the same way, but will deal negative damage. A tracking skill or spell will create a slow moving wisp that will head towards the target creature type being sought.

With a little creativity, and hiding the background works going on (ignore that man behind the curtain), Agents will be quite effective at simulating almost any skill or spell effect. This is how skills will be combined with Agents to, again, simplify the code. As a side effect, Agents will have far more potential capabilities.


Open MMORPG: It's your game!
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 4th Feb 2007 03:49
I still plan on posting more updates here, just have been very busy with various other tasks as of late. The Open MMORPG project has started the next phase of development; a full RPG. The one thing I think that was missing was a complete GDD that we stuck to "religiously". To start off the full RPG phase, we are putting a lot of effort into the GDD.

Our GDD will consist of two sections. The first section will be a "goal" section, which basically describes what the player will see and how the player will interact with the game, the UI, and so forth. The second section of the GDD will be the code section. As the "lead programmer", it will be my job to divide up the code into itsy bitsy teensy weensy tiny small bitty little... ummm... functions of code. The more detailed I can accomplish this, the easier it will be to code the entire project.

Each Source Code page will be a "category" of code to accomplish a generic task, like buttons, or menus, or maybe managing terrain and the skysphere(s). Each source code page will then be broken down into component tasks, which will be broken down further into primary functionality and support functionality. Primary functions are "application functions" that are intended for use elsewhere in the code. Support functions are functions that are only intended to support the primary functions, and should not be called from anywhere else in the code.

With the project sliced up into small components, we can then focus on sections at a time, and complete these sections in a relatively short period of time: I figure each source code page should take 1 to 2 weeks to complete, and maybe another 2 weeks to fine tune, debug, and tweak to perfection. With this plan, progress can readily be seen as well as felt. A sense of accomplishment will go a long way to keeping a project on track.


Open MMORPG: It's your game!
zircher
21
Years of Service
User Offline
Joined: 27th Dec 2002
Location: Oklahoma
Posted: 4th Mar 2007 20:05
Any chance of us seeing more code in the future. I'm interested in seeing how you implement the agents.
--
TAZ

"My goal is to replace my soul with coffee and become immortal." -- Wally
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 7th Apr 2007 18:47
There is certainly a desire to continue, but my time is being pulled in too many directions in the real-world. So it may be a little while before I can put anything together.

My apologies.


Open MMORPG: It's your game!
zircher
21
Years of Service
User Offline
Joined: 27th Dec 2002
Location: Oklahoma
Posted: 9th Apr 2007 17:22
Fair enough, I'm on a slow development track myself as I work on a pen and paper gaming project before getting back into DBP coding again. I look forward to the time you can continue this thread.
--
TAZ

When you feel like absolutely no one is watching you, that's probably a ninja. - Ask A Ninja
RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 10th Apr 2007 01:08
I am working on a core engine at this time, which will likely change a lot of my previous suggestions. I am not going to announce what the engine does at this time, but it is changing the way I have previously coded games - for the better, of course. Keep an eye out in either the Announcements or the WIP boards.


Open MMORPG: It's your game!

Login to post a reply

Server time is: 2024-04-28 11:55:06
Your offset time is: 2024-04-28 11:55:06