Thursday, March 24, 2005

A week off!

I've got a week off work!
I don't know if this will mean more will get done or less! But it will probably mean no updates for a week.

Wednesday, March 23, 2005

The Weekend!!

This week I've played about with smaller programs, played some games (which a rarity for me, living in Japan working off a laptop. But I must reccomend Seven Days A Skeptic created in Adventure Game Studio, all free, all very nice). Incredibly professional work for an Indie. It gets to me too - because I really want to make games. All this wonderfully complicated programming I'm doing is currently far far removed from actually making a game! So I'm going to download Adventure Game Studio and have a play with it this weekend :)

Also I'm finally going to fix my resolution problem - because it's hard and after I've done I'll be able to move on to more fun pastures.

Thursday, March 17, 2005

Rendering DirectX as part of a Window, using a Panel placed in the Form

Sometimes we don't want DirectX to render to the entire window. We'd rather have it render to a smaller subsection of the window and then we can use the form and prebuilt controls to interact with it.

This is especially true for map editors. Usually you will want to leverage the power of a rapid development app like C# to create an easy to use, flashy map editor.

It's actually really really easy to create a map editor style interface. Or to put it another way to render to a panel of your form.

Let's Start A New Project



As nearly always I'm using C#. I create a new project and choose a new Windows Application. First stop is the form designer.



Select panel from the tool bar and then draw this onto your form. Easy! This is where we will be displaying our DirectX scene.

Giving the form a standard game loop



Forms as I'm sure we all know are event based. We want some more control. So we change the code and introduce a function that will be called each frame.


static void Main()
{

Form1 form = new Form1();

form.Show();

while (form.Created)
{
form.Process(device);

//Let the OS handle what it needs to
Application.DoEvents();
}
}


That's how the game loop works. All our stuff goes in Process. Before we look into process though, I've added some code to the Form1 constructor. This code sets up the DirectX device! Let's take a quick look.


public Form1()
{
InitializeComponent();
InitializeGraphics(); //Sets DX up for the panel
}


Okay so we make a call to InitializeGraphics(). We have a global in our class called device.

 public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
static public Device device;


We set this device up in InitializeGraphics(). It's very straight forward and minimalist. Infact similar to how we set up directX for the entire window, before now. This time though we pass in the panel rather then the entire form.


public void InitializeGraphics()
{
try
{
// Now let's setup our D3D stuff
PresentParameters presentParams =
new PresentParameters();
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.Windowed = true;

device = new Device(0,
DeviceType.Hardware,
panel1,
CreateFlags.MixedVertexProcessing,
presentParams);
device.DeviceReset += new System.EventHandler(this.OnResetDevice);
}
catch (DirectXException e)
{

MessageBox.Show(null, "Error intializing graphics: "
+ e.Message, "Error");
Close();
}
}


All pretty standard. Now let's write our process code so we can actually prove this works. We'll just clear the DirectX background and then present the results.


private void Process(Device device)
{
device.Clear(ClearFlags.Target,
System.Drawing.Color.Magenta,
1.0f,
0);
device.Present();
}





There we go beautiful. (Why can I never get the boxes to align nicely in the center - bah!)

Wednesday, March 16, 2005

Managing a Computer Game Project Alone (because you have no friends)

Once again I'm dying of a cold. This is what you get for working at a school. Each snot-weasel full to the brim with disease ready to infect you. So I'm in no real mode to think in a logical manner and continue programming. So I thought I'd look into project management.

The Old Way





(The blurriness is me moving about when I'm taking a picture with a camera phone)

This is how my project is currently planned. Scavanged pieces of A4 are plastered to the wall. The crude scribbles decorating their faces tell me in which general direction I'm heading. I guess this is some how better than absolutely no plan at all.

Actually I develop my game in stages. I guess stages can be thought of as milestones but I only deal with one milestone at once. Currently I'm in the early part of stage II. Each stage is complete once a number of goals have been achieved - scrolling maps with loading, saving and npcs for example.

Also I have a half done design document in a word file. That while very good is very very incomplete. There are also about eleventy-billion .txt files scattered around my computer with notes and ideas. To make things extra confusing I have a custom made database program that has some stuff in it too. So in a word I'm disorganized.

Well that was the old strategy. I looked about to decide whether I could come up something a bit more flexible and shiny.

Better Project Management



As far as I'm concerned there are two facets to my project - the design (free form creative) and the actually programming of it (locked down logical). I want to be able to control the effort I expend on each.

Design Document - something like a wiki with lots of meta data that allows me to tie in all my flights of fancy with the actually basic ideas of my game design.

Programming and time management - sometime like a to-do list but with knobs on.

Running a webserver with bells and whistles



Most of the software to fufill my above two specifications is made to run on the internet and to be used through a browser. This is something I was willing to bend on. I'm programming in C# with DirectX so I'm on a windows box. To use wonderful internet apps I need things like a webserver, php, mySQL. All three just scream hassle. Luckily though - we have the French!

Yes French people have made a wonderful little program called EasyPHP that will install Apache, PHP and mySQL. With this base setup a number of web-programs can be loaded on top with which we can work our magic. It's very easy to use, infact all I did was click on the installer and it worked.

I only use this for local access. I'm sure if you wanted to publish to the big mean world of the internet you might want to brush up on security and all that unpleasent jazz.

Programming and Time Management



I recommend dotProject.



It takes a little work to get set up but it is some incredible and free management software.

Once you have it up and running you should break your entire project into basic chunks. From start to end. You can call these thing milestones. Then you can have each chunk be a parent to smaller tasks. And do this again and again and again until you have a big list of managable tasks.

(If your able to do this you are a better man than me, or woman - though I'm not a very good women to begin with, for one I don't have any breasts :( )

Each task can have a dependancy list. For example make the NPCs dance the macarana cannot be done until model loading code is written. So the NPCs dancing is dependant on some of IO routines.

I'm sure a lot of this comes in most useful for big teams. But I'm a lone developer my project is my own!

Each task you add can be given notes and an extimate for completion!

This is rather wonderful because it will give you the amount of man hours needed to complete the project. This way you can check how probable it is that you'll die or not before it's due. Also as you tick off you tasks a bar will advance and tell you how close you are.

There's also stuff for managing how much money your spending and interactions with various companies. As I'm working on a budget of £0 I use all this information for my own amusement. That's the basic of dotProject it does cool things with bug tracking too and is really up to a professional standard.

Design Document and Creativity



It's often the case that when I'm working on one part of my project I'll get an idea about something later on. Currently one of two things happen -

  • It's written in a text document, piece of paper, note book, some childs homework - and almost immediately lost.

  • I drop whatever I'm currently programming and go to work on my wonderful new idea.



Well rather than have this happen I'd like to add the idea to my design document. But a design document is a big linear thing that's not necessarily easy to change. A more networky webby thing is much better. This way you can link you idea to the various points in the project that it would effect.

So at first I thought Wiki! Like wikipedia I can go to whatever page and add a new link to my new idea. So I installed QwikiWiki. It was nice but didn't suit my needs. It had lots of unpleasent bold black errors I couldn't figure out how to add a page from it's web interface. It was also very basic I desired something with a little more structure.

Then I read this and thought - oh that looks good. And so it was. It allows me to easily stratify my design document and makes it far easier to grow. This is easier to get working than dotProject. But it requires more customization to get it from a blog with bells and whistles program - to a loose cool design document with bells and whistles program.

Free Image Hosting at www.ImageShack.us

It allows catergories and keywords and subcaterogries and all that nice stuff. So that's what I've been adding a few of my scattered enteries into of late.

Sunday, March 13, 2005

Continent Generation and Detection for Computer Generated Worlds

Recently[1,2,3] I've been experimenting with algorithms to create random landmasses. Once I'm given this random land I want to run some functions on it that will give me extra data.

I want to know:

  • How many landmasses are there (those areas of land bordered by sea)?

  • Which tiles make up these landmasses?



World Generation Output


X = Earth
O = Water

OOOOOXXXOOOO
XXXOOOOXOOOO
OOXXXOOOOOOO
OOOOOOXXXOOO
OOOOOOXXXOOO
OOOOOOXXXOOO


In the above I would say there are 2 landmasses. Because the landmass at the bottom and top wraps around (I don't want my world to be flat, if not round I want it to be at least donut shaped). I had some trouble imagining an algorithm that would go through this and give me a Continent Array, each array entry containing a reference to those tiles in each continent. So for the above the output would be.


ContinentArray.Count = 1

ContinentArray[0] = [0,1],[1,1],[2,1][2,2][3,2][4,2]
ContinentArray[1] = lots of tiles


This is the kind of problem that must be handled by Adobe Photoshop when you use the magic wand tool. Anyway the solution I came up with was to use a recursive algorithm. It's probably a reinvention but I called it the "Explorer Algorithm".

The Explorer Algorithm

I'll write this in some C# flavoured psuedo code.


Explore(ref array AContinent, int x, int y)
{
if(map[x,y] == Water)
return;

//It's an earth tile in our continent so let's add it
AContinent.Add(map[x,y]);

// now we set it to water so we don't add it again
map[x,y] <- Water;
//Explore surrounding tiles
Explore(AContinent, x, North(y));
Explore(AContinent, x, South(y));
Explore(AContinent, East(x), y);
Explore(AContinent, West(x), y);

//Also explore diagonal tiles - depends on
//what you define landmass as I guess

Explore(AContinent, West(x), North(y));
Explore(AContinent, West(y), South(y));
Explore(AContinent, East(x), North(y));
Explore(AContinent, East(x), South(y));

//*

}


* I think I might be able to return the tile to Earth here without problem but I haven't checked so I don't know.

The minor problem with this is that it sets your continents to water. But you merely iterate through your new continent array and set all the tiles back to Earth and eveything it fine.

So to use the explorer algorithm you would do the following:


forall the tile [x,y] in map
{
Array c = new Array;
Explore[c, x,y]

if(c != null)
BigContinentList.Add(c)
}


Then you would take every continent in the big continent list and iterate through it's tiles setting them to Earth.



So I expanded my earlier program and it now can count the continents and allow me to cycle through the highlighting each one. As you can see the 10th continent is currently highlighted.

This Weekend's Code

Well I did the above. Then I fixed up my game code so it doesn't crash and does streaming a lot more efficently. Then I made the fullscreen switch work pleasently. When switching from fullscreen to a window the window looks nice and actually has it's frame and all the window stuff one would expect. Then I kind of ran out of steam but what I should have done was if the resolution is higher then show more of the map but that's a lot of work! In fact I've been avoiding it but it's something I need to get done so I can get on with the GUI.

Thursday, March 10, 2005

Last night was my Japanese lesson so I didn't do anything.

Today my brain is trying to work out this continent detection algorimth. I keep getting lost in phrases like "an arrays of an array of an array" because it's the only way I can think to shuffle things around competently.
Well I've got it working in continent generation working in one dimension with border wrapping. At least it looks that way and I've every basic case that all other cases can be made out of. I've had three goes at getting this working but this current tool seems quite good.

Maybe it's slow it's quite hard to tell. The next step is constructing continents from runs! I'll probably need a run datatype to achieve this.

Wednesday, March 09, 2005

Yesterday the internet died but it's back again today. I did a little work last night on trying to detect continents that the map generates ... but it doesn't give the correct answer and it's gridingly slow.

Problem

The Continents are too "splodgy" (it's important to give formal defintions :D)
The sea is too empty - boring to explore!

Possible Solutions

1. Alter border check

Instead of throwing dirt out to the 8 square border around a grid point, now and again throw the dirt randomly further. Therefore generating mini-islands.

2. Temporal Seeding

The intial seeding is given a third dimension time. If you put a seed in towards the start it grows to full continent size. If you put it in grownAmount-1, it's going to be a small island. So if you increase the number of seeds and space them over time, then there'll be more diversity.

3. Limit Seeds Proximity

Do a check the prevent the seeds being seeded within a certain distance from each other. Though this won't really create many islands.

4. Recursive Application

Grab areas of empty ocean and apply a short run with fewer seeds to that subsection of the map.

I Chose Solution Number 1



Why? Because it's the easiest to implement.

To the top of GetRandomOffset I addec the following.


int odd = random.Next(0,50);
if(odd == 1)
return random.Next(0,100);


So when grabbing a random border there's no a 1 in 50 chance that you'll be given a random number 0-99. So this means the border can throw out random islands.

I ran this and it caused far too much "decay-iness" (back to those formal terms. There weren't enough whole continents, and hardly and continent seperation.

So I changes 50 to 100 but the problem remained.

Well I thought - this isn't good! What's the problem?

And the problem was that these seeds where being put down too early. Therefore I was getting large continents rather than the small islands I was after! So what's the solution to this?

Well I only allowed the borders to go crazy after half the map was generated - that way the seeds are never going to grow into massive continents instead they'll stay as exciting islands - which is what we all want.

So I had an extra argument passed into GetRandomOffset saying how far we were through the growth. Once we were over half way through I'll allowed the borders to now and again be thrown out in a random way.

Disadvantages

Are minor and would not effect my final game. The previous system we did not have to known the Growths half way point - therefore we didn't need to have a pre-ordained growth amount. We could grow a bit, have look, if it needs a bit more growing we could grow it more.

We cannot do that with this system (we kind of can but the results are bad) because we need to know the full growth rate ahead of time. At the half-way point through the growth we can start seeding the islands.

Continent Detection

After generating the world I'd actually like to identify the independant land masse. My current algorimth is broken but it's what I'm thinking about currently.

Final Notes

I also modified the code so that it allows "wrapping". That is a continent will not be confined to the edge of the map. It's spread will merely wrap around to the other side.

I also generalized the code in such a way that it would be easily portable to my game. (Though it does look a little arkward for just fooling around with a bitmap.)

After continents are put down I may added some rivers.

Also coast. I'd imagine an actual coast "cell" would be 75% land.
Once again, last night I did nothing! Well actually I surprisingly went to International Laddies Day but that's an aside.

So today I once again have some free time so I added a little more to the world generator - namely I made it a Threaded Application. In C# this is painfully simple. The last time I did threads was in C on Linux and I remember it being unpleasent.

This was a snap and it's safe too. It's impossible to have threads accessing any resources at the same time. So now you press the "Grow" button and it grows in real time!

(I also noted a small bug where I was allowing coordinates to equal 100! Oops should be 99, should really be bitmap.length-1 but what are you going to do.)

So that's something that's keeping me occupied today. Really the method of generation needs changing too.

Extremely Quick Guide to how I added Threading

First you need the resources:

using System.Threading;


Then I wanted to have a thread object in my class. I wasn't very original in it's naming.


Thread thread;


Then everytime I press "Grow" I need to make a new thread and start it. I also need to turn off the input buttons to prevent any resouce conflicts. (Probably anyway :D I mean some how the bitmap is being published to the screen every cycle and yet also updated by the thread - I assume this is automagically taken care of by C# some how :D)


private void button1_Click(object sender, System.EventArgs e)
{
//Grow the map
thread = new Thread(new ThreadStart(this.GrowMap));
thread.Name = "Map Growing Thread";
thread.Start();
}


This say's when you press the Grow button then start the thread up.


private void GrowMap()
{
DisableControls();
int growthAmount = (int)numericUpDown2.Value;
listBox1.Items.Add("Growing for "
+ growthAmount + " iterations.");

for(int i = 0; i < growthAmount; i++)
{

Grow(bitmap);
pictureBox1.Refresh();
Thread.Sleep(1);
}

pictureBox1.Refresh();
EnableControls();
}


Disable the controls merely set the Enabled bools to button1 and button2 to false. Enable controls set's them back to true. I don't want to be messy with the same resources my therad is messing with.

I tell the picture box to update. After I've finished a round of growing it. Then I pass control back to the form. Then the form grabs publishes the new results to the screen. Therefore there's no conflict of interest between the thread and the main loop - yay!

So anyway no you press Grow and it looks like a living organism it's cool.



I also changed the background colour to a less eye arresting blue.

Tuesday, March 08, 2005

Last night I did no work on the game at all. Infact I mostly sat in bed watching old Xfiles episodes I'd found in one of the cupboards. American and Canadian adverts are the worse adverts in the world. Really, they really suck. It makes you worry who they think the target audience is.

Anyway today I was thinking about world creation which is kind of around the corner. Basically content generation and all that good stuff. I've never worked with bitmaps or done any non-directX graphical stuff in C# but assumed it wouldn't be to hard. I was right! It's the easiest thing ever.

Drag a few bits and pieces over to the form and then add a little code.




Currently I'm going for the simplest world generation algorimth I could think of. The world is divided into a grid. At the start it's all sea. You begin by "seeding" the world. This means that a number of "seeds" are put at random grid positions. All a seed does is turn the grid point from blue for sea to brown for earth.


for(i <- 0 to maxSeedNo) { map[random, random].gridColour <- earthColour; }


Of course, the above psuedo code isn't anything like my code but I'm sure you get the idea. (For a start the random numbers should be some how bounded by the number of grid points in your map).

This is all I've done so far but it's only taken a few seconds. I didn't even have to look anything up I could just fiddle with VS.net GUI! Of course I choose the most garishly bright colours I could to dazzle the senses and woo the mind.

The next stage is to grow the seeds. The way I'm currently thinking of doing this is to iterate through the map. All seeded areas throw out another seed around their border. If it lands upon an already seeded grid point then nothing happens (I was thinking of it making that grid point grow higher but I want simple first). If it lands on the sea well then thats another seeded area and it turns to earth.

So what would that look like?
Well it would look like this:




Not too bad for a first go!

The main problems - maps are quiet found and pretty round.

Possibly solution during Growth iterations throw a few seeds into the sea.

The Code

Well let's have a look a some of the main algorimths in C# this time :D


private void Seed(Bitmap b, int seedNum)
{
for(int i = 0; i < seedNum; i++)
{
b.SetPixel(random.Next(100),
random.Next(100),
System.Drawing.Color.Brown);
}
}


So that's throws seedNum amount of seeds on to our map. In C# that argument to the random function is the maximum number it must under. So putting in 100 rather than 99 is fine.

The only other interesting function is grow. And as you might imagine this is called a growth number of times.


private void Grow(Bitmap b)
{
for(int i = 0; i < b.Width; i++)
for(int j = 0; j < b.Height; j++)
{
if(b.GetPixel(i,j).Name == "ffa52929")
{
try
{

int x = GetRandomOffset(i);
if(x > 99) x = 99;
if(x < 0) x = 0;

int y = GetRandomOffset(j);
if(y > 99) y = 99;
if(y < 0) y = 0;

b.SetPixel(x,
y,
Color.Brown);
}
catch(Exception e)
{
Console.WriteLine("Something odd" +
" has happened!");
}
}
}
}


Quiet a straight forward function the only two things of note are: b.GetPixel(i,j).Name == "ffa52929" which means "under the particular pixel encoding we are using is this colour brown?". The other thing is getting the border offset GetRandomOffset(i) - in which direction is the next seed going to be laid down?

I put this in a seperate function because random only returns non-negative numbers! I needed to change that and didn't want to do it in the middle of the code and mess things up.


public int GetRandomOffset(int i)
{
int r = random.Next(0,3);

switch(r)
{
case 0:
return i;
case 1:
return i - 1;
case 2:
return i + 1;
}
return i;
}


And they're all the main functions everything else is just prettiness to go around it. One last note is that if you set the growth to 1 and keep pressing the grow button then you can see the world forming before your eyes.

The only useability problem at the moment is that it blocks while its working. If it was coded using a timer or something then we could put up a progress bar maybe in the future. That's the most basic land generation function ever though, enjoy.

Easy to Port

To generalise this code and make it easier to port over to my main game code I'd probably use an interface. The functions will then use the interfaces methods and therefore be very spiffy and wouldn't need to be changed again. Basically it would probably be:


namespace MyGame.WorldGeneration
{

public enum LandTypes {Earth, Sea};

interface GeneratableTerrain
{
void SetState(LandTypes landtype);
}

}


That would probably do the trick quiet nicely, though I wish I could think of a better name from my interface there.

Monday, March 07, 2005

Works been reasonably light today so I've done a little code rearranging. What's really needed the is total crash proofness which really can't be achieved yet :(
I wrote a suprising amount of code this weekend but didn't actually get very far. I ran in to a problem with streaming in maps over a few game frames.

Basically the problem is: What should we do until the map is streamed in?

It was problem I had known about but forgotten. Anyway instead of sitting back and coming up with something elegant, I thought: just wait I can hack this together!

So I closed my eyes and bashed away at the keyboard and after a few false starts I had skeleton maps in place. They took all the information a normal map needs and stored it. Then when the normal map was read in from the disk it could update itself from the skeleton.

I think it's a bit messy the way I've done it but the general idea is okay.

Then I needed some code that handled the problem of shutting down while a map is being streamed to the disk or from the disk. That wasn't too hard. I just put some code in the closing event and then had it pass the message down to my other game objects. The load queue gets cleared and the save queue is run until it's empty -> Saving everything to the disk.

And finally I've been using Sunbird for project management. Yes I know it's totally inappropiate but all the other stuff seems to require a web server and I have problems getting PHP and IIS to play together nicely. Also sunbirds in very early development and it has bugs and it's slow as dead, rotting, buried horse. But that's all an aside basically I've add a daily task to doing a piece of sprite art. (Though for some reason it doesn't seem to appear everyday - bah). So this weekend I drew two frames of a eyeball monster and a sword. The sword is possibly too shiny, the eyeball monster is okay I think it's something that it's quite hard to do wrong.

Thursday, March 03, 2005

Letsee I'm dying from a cold and cannot really think clearly - therefore I should be getting rest and not attempting to soldier on with my project. But crazy is as crazy does. It still seems I have no classes to teach at school either so I'm may as well use my time somewhat productivley. I don't really want to be seen collapsed unconscious on the desk. It mars the somewhat professional image I try to get across.

So I've pulled across the files from my streaming loader and strapped them.
There's a wierd bug that only comes up now and again when I try and cross map boundaries but I have no idea how to reproduce it.

Wednesday, March 02, 2005

Despite my fierce cold, I did a little programming last night and yesterday. Resulting in map streaming saving and loading being completed and bug free. The code will become cleaner once I have a new version of the map to load as well. Until that time though I will consider it done.

The next step is to intergrate it. I may do that today.
Then after than I'll add extremely basic gui - probably some kind of console.

Tuesday, March 01, 2005

I think I have flu. Luckily all classes are not on due to exams Therefore I was able to do some work on the game today. Save streaming could potentially work. It needs testing.