Friday, June 30, 2006

A five minute dash to a data driven nethack

So I've been poking my new fast rendering code a bit.
It's currently fine for tiles and layers, the various layers and tiles can manipulated by Lua, FPS is pretty good.

But this new rendering method isn't going to work with the current code base - so I need to rewrite how entities (creatures) are handled. That's what I'm doing now, it's getting there though I think afterwards it will need some "sleekening".

Hopefully they'll be walking around by the end of this weekend.

It's sooo humid here at the moment :P





And now for a random text file from my desktop beating out some of the issues I was having.


Recently I've been playing with Lua again, I'm still working on getting my map rendering stuff very solid before I plug it into EINFALL. I want to get it in there and not have to mess with it again :D

Anyway my Lua problem goes something like this-

=Lua Question=

Let's say I have a Class Person, then I have several instances p1, p2, p3

Person has a moveto(x,y) command

I want a script inside each person that uses the moveto command local to the particular instance of the class - what's the best way to do this?

(What do I mean local to a particular instance of the class? Well let's say I have a script and it's shared by p1, p2 and p3. When "moveto" is called in the script it should move the object that called it)

=Answer=

The one way that springs to mind right now is to pull the class object (p1 p2, or p3) into the Lua script so it knows what is currently calling it.

Therefore we can create a Lua global:

_FocusedPerson = ?;

and create the moveto(x,y) command in lua

moveto(x,y)
_FocusedPerson.MoveTo(x,y); -- move to here is called a C# function in Person
end

Then in the C# person class have.


class Person
{
public void ExecuteScript(Lua lua)
{
lua[_FocusedPerson] = this;
lua.DoString(script);
}

public void MoveTo(x, y)
{
...
}
}


=Alternative Answer=
Handle the specific object instances seperately in Lua. (not something I'm going to be doing)

=Thoughts about Entities on Tile Maps=

Where do we put them?

I think this is the big question. Where do we put the entities?

1. Game.AllTheEntities[0] = Bob?
2. Game.Map[0].MapEntities[0] = Bob?
3. Game.Map[0].Tiles[0,0].Entity = Bob?

These are the three main places that jump out at me. Game in my opinion is too high level and too messy.

1 - It's harder to not process and not render the entites you don't need to.
2 - I think I'm choosing something like this.
3 - I can't do multi-tile characters!

I think it depends on what your programming.
(Note I've currently decided to do option 1 :0, TileMap's getting to croweded and "coupled")

=Entity Movement=

Entites should stand on grass, covered with flowers. But they should stand behind leafy foliage.

Tricksy. Let's say

[0,0]grass = layer 0
[0,0]flowers = layer 1
[0,1]leaf foilage = layer 1

If we walked from 0,0 to 0,1 we can't leave the entity on the same layer or we'll be standing on top of the leafy foilage - that wouldn't look nice!

Oh dear we can't do the simple solution - an entity can't be merely assigned a layer and then left to get on with it. Everytime the player moves from tile to tile - he needs to be inserted into the scenery according to a heurisitic.

All layers need an extra value that I'm going to call hangRank, the hangingRank determines whether a tile should hang over the player.

A tree trunks hang rank would be 0, as would grass and all that.
The leafy foliage hangrank would be 1.

Each time the player moves we check the currect tiles hangRank and make sure it matches with the next movements hangRank. We can then render by hangrank not by layer. Yay.

So I'm going to have entites and then make hangRank stuff works correctly.

=A little later=

Wait that's far far to complicated.

Instead I'll keep the current layer system but every say 10 layers I'll call that a "hard layer" one that players might stand on, object might sit on.

Then the main render loop will look a little like:


for(int i = 0; i < layerMax; i++)
{
int hardLayer = 0;

foreach(Texture t in LayerTextures)
{
RenderLayer(i, t);
}

if(layer == (hardLayer * hardLayerSize) - 1)
{
foreach(Texture t in entityTextures)
{
RenderEntities(i, t);
}

hardLayer++;
}
}


=Z-fighting=

Now for a vaguely unrelated topic (this isn't Z-fighting in the floating point 3D graphics problem sense)

Let's say we have a building, let's say a tree grows behind the building. The tree's leafy layers should be shoved behind the building.


TTT
+---T-+
| | Not this
| |
+-----+

TTT
+-----+
| | But this
| |
+-----+



Yes, I know, I'm probably not going to have growing trees, but I do intend to have building construction - I know biting off, chewing more than, and all that. Anyway here's the solution as I see it.

I want a third type of tile, or possible addition to the normal tile, IConstruction, which means it's grouped with other tiles.

The Y-Line of the wall / buidling is the highest (nearest bottom of the screen) tiles Y position. The trees Y line is the same.

So the trees Y-Line is going to be the bottom of the trunk, let's say the tree's trunk is at 3,3. Then the house back wall's lowest line is 3,4, the trunk and all other parts of the tree must make sure their layers are lower than the wall.


..and that's the end of one of my note files.

Monday, June 26, 2006

"Does dying bother you?", he flipped the page, "Well then what do you intend to do about it?"

Today I updated the second Lua tutorial to work with the latest version of LuaInterface - just enough people where becoming confused to spur me into action. Unfortunately the nice highlighting has gone but this time there's source code and indentation.

I'e been playing more with my "TightMap". I "upgraded" it's message system (no doubt making it far far slower :D) so it currently looks a little like this.

I can do things with it that are probably all together too clever such as:


void OnClickVerify(object sender, EventArgs e)
{

form.SendGameStateMessage(new VerifyMap(delegate(string answer)
{
statsForm.VerifyState = answer;
}));
}


Then I added Lua to the map. Then I added Lua messages to the message system. Then I added a Lua tab to my Map Stats form - so you can write chunks of code to modify the map and then send the code and watch the map change in real time. That's a bit groovy. Of course the only lua function in there at the moment is one the kills the map (correctly deferencing all it's textures I might add). I'm sure I'll add a few more tomorrow - modifying map tiles and layers.

And that's it. Started reading Ender's Game again at school, so the author's a fascist mormom homophobe he still writes a very good book.

More Scripting in Lua

In the first LUA tutorial - we looked at how to call C# functions from LUA. All well and good ... but what about using classes? That's kinda of important isn't it! You want to interact with your NPC classes and all that kind of cool stuff. This is what we'll be covering here.

Let There Be Classes!



I assume you can set up a LUA enabled C# project - we're going to do another nice console window one.

First thing to note:

Classes, enumerations, structs, what have you, . . . are all "CTS types".

Q: "What does CTS stand for?"
A: "Shutup"

Right, so how do we use these CTS types inside LUA. How how how?

Well there are two important functions that we must use.

1. luanet.load_assembly
2. luanet.import_type

While you're commiting those to memory - let's start creating a demo, framework, example whatever! Let's make one. So we make a new console application.

When I type you . . . type. Just like that



Using the previous tutorial we created a LUA enabled C# program. You should end up with the following and should be able to compile it without errors (if you fail in this hang your head in shame and go read the first tutorial again)


using System;
using System.Collections.Generic;
using LuaInterface;

namespace LuaScriptingAdvanced
{
class Room
{
Lua lua = new Lua();

public Lua Lua
{
get { return lua; }
}

public Room()
{
}

static void Main(string[] args)
{
Room partyRoom = new Room();

}
}

}


Now we're going to add a class, a marvel of object orientated design and programming.


class Person
{
public string Description = "";
}


Amazing! Well let's say we want a few of these people in a room. We need the generic collections namespace. Luckily it's already at the top of the room class.


using System.Collections.Generic;


The class "Room" is where we'll be having the party so we need to add some code there. We'll have a list of people in the room (enjoying the party) and we'll have a function look, that will tells us what's going on.


class Room
{
// Our revellers.
List people = new List();

public void Look()
{
foreach (Person p in people)
{
Console.WriteLine(p.Description);
}
}


We need one last function then we can start our LUA stuff. Can you guess what function? No? Well it's an AddPersonToParty function, doesn't exactly roll off the tongue but it will do.


public void AddPersonToParty(Person p)
{
people.Add(p);
}


Making Use of Lua



Let's stick to tried and true ground first and register the above function. Well kind of tried and true - it has a type in it, Person, that's not basic to LUA! But if you're not afraid, I'm not afraid, let's continue! We're going to jazz up the room constructor like so.


public Room()
{
lua.RegisterFunction("JoinParty", this,
GetType().GetMethod("AddPersonToParty"));
}


Hmm sweet jazzy jazz. Here we register the room's function that will let us add people to the party from a Lua script (The room also contains a Lua reference). Imagine if we created more than one room object! We would have problems, we'd always register over the last join party function! Luckily we only ever want one room, so this is okay.

Also we're going to expand the main function so it actually does something.


static void Main(string[] args)
{
Room partyRoom = new Room();

partyRoom.Lua.DoFile("scripts/party.txt");
partyRoom.Look();

Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}


Obviously the DoFile line of code jumps out. Scripts directory? "party.txt"? What's all this? You might wonder.

For now it's just filler in your bin directory create a directory called scripts. In the scripts directory create blank text file called "party.txt". Okay now you're all caught up.

So we call our [tag]script[/tag] and then call the room's look function - this will scope out the people at the party for us. Of course there are no people at the moment. Guess what the script might do! Now to write that script.

Coding in Lua



Ready? Okay go to the bin directory where the executable is being generated. You know where you dumped all those Lua dll files? Yeah? Good. Go there. Now you should have already created a text file named "party.txt". Open it and prepare to type!


--Grab the class info

luanet.load_assembly("LuaScriptingAdvanced");

Person = luanet.import_type("LuaScriptingAdvanced.Person");

--Steve
steve = Person();
steve.Description = "There's Steve drinking something brown and frothy from a shoe.\r\n";
JoinParty(steve);


For now Steve is a one man party. Okay now run the executable and try not to look alarmed. We should get the output:


There's Steve drinking something brown and frothy from a shoe

Press any key to exit.


And there you go. Remember what CTS stands for and you'll be fine! Now you can add classes to your Lua files - and you now what classes mean - prizes!

Let's Do Functions



We have to make use of the Lua libraries to do this. We're going to use the base library. Let's go back to our person class and add a few bits.


class Person
{
public string Description = "";
public string Name = "";

public void GiveName(string name)
{
Name = name;
}
}


Wow, talk about your contrived examples :D. Now let's check out that look function, in the room class.


public void Look()
{
foreach (Person p in people)
{
Console.WriteLine(p.Name + ": " + p.Description);
}
}


Let's alter the part of script dealing with Steve to include this new ground breaking function.


--Steve
steve = Person();
steve.Description = "There's Steve drinking something brown and frothy from a shoe.\r\n";
steve:GiveName("Steve");
JoinParty(steve);


Notice the little colon rather than a peroid. Be careful about that otherwise it will trip you up. Okay that should be enough to keep you going.

If you're going to use ints or numbers as function arguments remember all Lua's numbers are doubles therefore they need to be converted. This is done automatically yah! But in order to do it automatically you must include the math library. Using this: room.Lua.OpenMathLib(); will sort you out.

Next time I might do delegates, of course consider the amount of time that seems to pass between tutorials before you go betting your deadline on me. You may also be wondering about inheritence and all that ... the answer is yes you can but it's not something I think I'm going to need at the moment so I'm leaving it alone.

Source Code



Source Code

Sunday, June 25, 2006

Soap and Sand

Hmmm goals didn't really get completed, well the ones associated with einfall anyway.

I've finished my basic map engine (engines overselling it but I can't think of a better word). It has batching, layers, layers with alpha channels for fringing, animation, different texture orientations, texture management and all that good stuff.

I want to add loading and saving, in a basic manner and there's one or two things that can be done cleaner - though it's very clean as it stands. I'm quite happy with it.

Here's a screen shot earlier from today.



It has a debug tile image I was using to check the tiles could be rotated okay. There's a info window that confirms that texture managements actually working, and some basic querying of the map.

I may make a second version that accepts Lua commands to modify the map but after that I'd be getting far too distracted :D And it's high-time to work the code back into my main project.

On I need to decide if I'll store entities on the map, on in the world and if they'll be linked to tiles or not.

Also randomly here are some links about data driven design: http://groups.google.com/group/rec.games.roguelike.development/msg/b21039bdc091a4fc?dmode=source

Friday, June 23, 2006

Incan Chatterbots with roses

Brief Thoughts On A Object System For An RPG

In RPGs you generally want lots of objects, that can be used in a number of ways.
I think a good object interface would be:

interface IItem
{
void Render();
void Process();
void HandleMessage(IMessage m);
}

By default messages are ignored. But you could send messages like "Hear footsteps", "It's nighttime", "You've been stepped on.", "You've been moved by the wind", "You can hear talking" ...

I've mentioned message systems before in regards to implementing them in C#.

Today was quite productive really, I finished off the texture manager. Source code's avaliable here - I think it's overkill for anyone who isn't juggling multiple game maps on the screen at once. Have a look through, feel free to tellme how stupid I am :D It's fairly well commented and there's a windows application that demonstrates the idea quite well.

Next I switched back to the batching stuff I was doing. I added some code to my quad class and now it's texture setting stuff allows you to flip the texture on the horizontal, vertical or both axes. This is something that was noticably missing in the main project.

Weekend goals:
Simple Quad Tree Prototype (for einfall)
Houses (einfall)

Fuzzy Vague Goals
Tight map class (batching knowledge)
Hack tight map class into einfall.

One thought I was having is that classes like map, tile, sprite can get quite massive - you've got IO, GameStuff, Resources and Rendering. It's nearly impossible not to avoid having these things in your class to some extent - or at least they're prescene effects the design. (You could have IO entirely external but your class would have to be quite open).

I thought maybe something like:

Tile
{
RenderInfo renderInfo; // vertices, colours, highlights, position
GameStuff gameStuff; // blocking, objects / monsters, triggers
IO io; // save load the tile
LayerInfo layerInfo; // tiles stacked on top of this one.
}


But it's messy and it makes really long code lines. Instead I think I'm just going to resign myself to the fact some classes are fatter than others and split the code into logical chunks using partial classes.

If you don't know what partial classes are you may not have played with c# recently - basically it allows you to split a class over a number of code files.

Thursday, June 22, 2006

Novemberist

It seems today's, a day for old thoughts and memories - they keep bubbling up unbidden. One thought that worries me more than it probably should is about the follow scenario. Most of the worlds population's dead, modern life has been totally wiped out, we have nothing but a vast natural planet. How well would I do in restoring modern technology?

I suspect not very far at all, maybe I could build a house, a water wheel - though it would probably be a poorly crafted water hexagon. But what about computers, gene therapy, material for clothes, engines, aeroplanes, space travel, dynamos these things would be lost. Perhaps with a lot of help I could manage a crude steam engine.

Maybe this would be good for a game but I cannot imagine how you'd program it so it was real and pleasant to play. (I can imagine a number of cheap ways to do it but they miss the point - of having the worlds technology level rely on your knowledge)

Personal Hell's



Recently I've been working on a texture management system. Why would I need a system to manage textures? Surely it's all quite straight forward, make an enemy load his texture, slap it on, when the enemy dies, unload the texture - easy.

Putting it like that it does sound easy but I have a rule.

1. I only wanted to load a given texture into memory once.

Okay fair enough makes sense. Create a database where the textures are loaded. Each time some object wants a texure either increase the reference count in the database or if it's not in the database - load it. Simple.

And that is pretty simple and it's what's currently in my main project. The only problem I have with it - is it becomes very vast very quickly. There are 100's of references and I have no idea if they're being deferenced properly. Worse than that when I know somethings gone wrong - I have no idea how to track the problem down efficently.

Enter the thing I'm working on now. I keep getting the feeling I'm making something overly complex and it's probably not worth it. Though this does nothing to stop me.

My game worlds are divided into chunks, each chunk manages it's own textures. Textures are modified at run-time, chunks are often swapped in and out of memory. Of course I still stick to my rule 1 - I don't want to load a texture more than once.

Therefore I still have a global texture repository but instead of reference counting every texture instance it references how many chunks use it. This has a few follows ons -

Error checking becomes a little easier:
- there should never be more references to a texture than there are chunks loaded
- it's not too hard to verify that the reference data about the chunks local data is correct.

In theory, sounds quite good - in programming terms - I think my code could be easier to follow.

Tuesday, June 20, 2006

Everybody loves Anonymous Delegates


public override int AddResource(T resource, string externalKey)
{
int internalKey = base.AddResource(resource, externalKey);

// When a resource is added it's reference is auto set one

resource.ReferencesAreZero += delegate(object sender, EventArgs eventArgs)
{
RemoveResource(internalKey);
};

return internalKey;
}

Monday, June 19, 2006

Philosophy has all the best beards.

Well the batch program now does layers, in possibly the most inefficent way ever.

Layers are a little problematic, it's all to do with pesky Z-ordering and how players can place themselves between different layers. Maybe I need to have pipeline or batch manager like Z uses in his code.

Ah, also the layer I choose to add was an alpha-blended fringe layer. The graphics I made is grass fading raggedly into transparency. Then I put this as a layer of top of a stone tile and it blends to make a transition between grass and stone. The nice thing is that this tile covers all grass transitions.

(You can generalize this so that with one texture you can represent all transitions. This is known as texture splatting. )

Then again, it might be inefficent but it's not slow, so maybe it's all fine :D The codes become a little messy and I think the benchmark program itself has grow quite large. It's time to break down my last iteration into well thought out namespaces, add unit tests, generalize some of the functions and stuff. At the end I hope to have tight little modular package that's very fast.

Also the Game Programming For Monkeys Tutorials don't even mention this speed problem, so maybe I need an add on chapter at the end.

Also I really, really want to complete something vaguely game like. I've completed plenty of apps and small libraries but I have nothing game like that I've completed at all ... well at least not recently.

Saturday, June 17, 2006

A bout of a case of springtime giddiness.

Recently I've been writing a benchmaker for batching. I've got a map up with animation using batching - that's working quite well. Before putting it into my main project though, I want to get layers, items and moving entities in there. Yes practically a whole new game base :D But I need to make sure everything works correctly before I can start adding it into the main project.

Wednesday, June 14, 2006

A young mans primer on C# Game Development

I've become totally distracted by batching at the moment. Mainly because I think it will kill my tearing problem in EINFALL and this would make me happy.

I still don't understand the very very root cause of the problem so I've asked on the gpwiki forums.

I've also been writing a program that has many different methods of rendering a tile map, and seeing which ones best. I still haven't done one that actually batches yet but I've still managed to get double the frame rate by using a dirty flag and cutting out a per frame SetStreamSource call :D

I think I finally understand how to approach a nice batching algorithm, I just wish there was a little more code around. I'm not quite sure what flags to set and things to get optimal results.

Also I want a greasemonkey script called "GrammarNazi", it would search each page for such things as "could care less" and would correct them to "couldn't care less", the same for "addicting" and other bits and pieces. It would making browsing the web more pleasant.

I'm also thinking a little about a story generator, I've not written anything down but I do have few ideas in my head. I mean like a written story nothing to do with a game.

Monday, June 12, 2006

>A tightly packaged bundle of analogies. Pick up? (Y/N)

So I've offically selected Teeside as my Uni next year for a computer games programming masters.

Today I worked on a C# DirectX Form that's a basic tile engine. With only a DirectX enabled form (clearing a panel to a blue colour) I get around 60fps - though there do seem to be sudden dips now and again, not sure why...

I create a "naive tile render" which fills the panel up with around 750 tiles. Each tile renders itself, setting the stream, transforming the world, setting the texture and drawing it's own quad. It's still runs at 60fps.


public class Map
{
public void Render(Device device)
{
foreach(Tile t in tiles) t.Render(device);
}
}


Okay so I make it render the same thing 3 times each frame so around 2250 tiles, not unthinkable in a game with many different layers items and npcs. Frame rate goes down to about 15fps. So now I've got the base mark. I'll try to improve it by playing with batching. Also I'm running on a portable so speeds are never going to be blistering :D

That actually took nearly all my free time at school, I'm embarrased to say, I was having trouble getting the entire texture to render on the tile ... but then I realized I was putting it on upside down :D

The program also shows the "working memory" though I'm not quite sure what this specifically is. (I found this in System.Environment.WorkingMemory or something, I haven't looked it up yet.)

I also finished reading about Ultima Onlines resource system plans:
Part1
Part2
Part3

I found it interesting as I use to play UO. No recent mmorpgs interests me at all, they are just cooperative, single player style, games in a vast chat room. In UO the game and game goals were more emergent from interaction with the players, especially pre-trammel. One thing unique to UO in my eye was the stories it generated, players told each other story after story of happenings on messages boards, they made websites telling stories of things that happened to them. The modern morpgs are more "I did pre-set quest X", "We attacked guild Y, as per usual". They're more streamlined, plasticy.

Sunday, June 11, 2006

Found conflicts between different versions of the same dependent assembly.

Why does this happen? Well it's the mess that comes with managed DirectX version 2.0, something I believe that's still in beta ... anyway it's quite quite different.

Now if you're making a nice new DirectX project, as I'm inclined to do now and again, you add your directx references as per normal. Now, if you're anythingl like me there are a host of DirectX versions to choose from that you've installed over the last few years. Maybe you use the same heurisitic as I do - and choose the one with the biggest version number - well if you choose 2.0, this is a potentially a mistake. Fair enough. The problem is when you try and replace it with an earlier version you might get the error:

Found conflicts between different versions of the same dependent assembly.

Pah. You click okay or whatever - auto resolve it please - but it's stil fails when you try and run the game. Grahhh what's happening?

Well go into the solution explorer and double click on app.config, and remove anythings that mentions DirectX 2.0

And then everything should work. Yay!

The whole reason I wanted a nice new directX project was because I wanted to do some benchmarks for different Tile Rendering methods I've been chatting to z over email about this. I'd always heard of batching but it sounded scary and hard and therefore I never ever looked any closer. But then these emails made it clearer what the problem was, though I still need to read about it :D It's all to do, I think, with the time it takes to send things to the GPU vs the time it takes to do things on CPU. Z's written something about on his blog. So thanks for that, now that I'm able to use DirectX again I'll start my own benchmarks soon.

Still not too programming going on - it's very humid here at the moment, all I want to do is sleep :D

EDIT: a secret for your enjoyment, I'm currently maintaining two technical blogs but one lives only on my local machine. I think next year I'll have some kind of server access to I'll switch then making the local blog public, it's rather better and has quite a bit of content I've not put here because I don't like messy around getting uploads working :D

Tuesday, June 06, 2006

The first stand

No code this weekend! No code this morning. It's like a pattern.

There was a little code at school where I'm making a prototype Final Fantasy Battle type game in Java using the Golden T Game Engine or something (obviously the name needs changing as I can't remember it) with scripts in Python. That didn't last too long because I got distracted by reading about the Ebola virus (and the others in the charming Filoviridae family) - another reason never ever to go anywhere near central Africa.

EINFALL needs changing so the map generator takes advantage of layers - this shouldn't take long to do, maybe tomorrow morning.

If you been checking my del.icio.us bookmarks you might notice I've been looking at the gamedev four elements contest.

The four elements are: Europe, Eblem, Emotion, Economics. This actually gave me an interesting game idea but it's not strongly tied to any of the particular elements. I even worked up a set of small mile stones.

Speaking of mile stones there's an open source project management program that caught my eye yesterday (a little like Microsoft Project.) Here it is, OpenWork bench, looks interesting.

But I don't know if I'm going to work on it or not. I'll have to have finished EINFALL stage three first and my Java+Jython battler.