About Game Development with particular focus on C#, Lua and procedural content generation.
Sunday, December 24, 2006
The moon on a stick
There's a problem though. I split the world into multiple maps and path finding across these maps, probably means changing my path finding code. The multiple maps buisness has always been a headache.
For now I'm happy to get path finding working on a single map. And worry about moving over map boundaries later.
Saturday, December 23, 2006
Old blue cake hat
I'm adding smooth moving between tiles now. Somewhere down the line I'll bolt on my A* library and somewhere after that I'll finish my modest goals for this small project. (You can walk to a chest open it, recieve a message, then the game ends basically) Then I can get back to merging it with my old Einfall code base.
Oh yes I need to get animation in there too. Considering this is about the third time I've written code like this, in this project - I think this time I've gotten it right.
Also I want to clean my coursework up a little and maybe a add a download. It's not bad, apart from the camera being a bit messed up.
Tuesday, December 19, 2006
High Density
It's a little tricky. I want to be able to process / render my various entities. So I should be quickly able to determine what's at a particular x,y tile position and z height.
Any entities on map-1 should be able to be selected as a whole and removed easily. Also entities can be moved from map to map. Yes moving, when moving an entity exists "between tiles", if I want NPC movement to happen at the same time, there could be problems where they manage to land on the same tile. I do want movement to happen at the same time, so this also complicates things, basically an entity can be on one or more tiles. This also works well if I ever wanted to add mulitiled monsters into the game. (Which really I'm suprised we never see in roguelikes)
I've been very good and written tests first. Simplicity is my goal at the moment but not so simple that it's extremely slow.
Wednesday, December 06, 2006
The small grey children, who stand by your bed and watch you while you're sleeping.
This is my *arghh* how does it work code.
#include "stdafx.h"
#include
using namespace std;
int b = 3;
void func(int ** i){
*i = &b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int * p;
func(&p);
std::cout << (*p) << std::endl;
char a;
cin >> a;
return 0;
}
My second sweet snippet is cheap cheap openGL matrices.
This takes in an openGL matrix array, like you'd get from glLoadMatrix, then applies to a vector or vertex.
void TransformVector(float * m, Vector3d &v, Vector3d &d)
{
d.x = (m[0] * v.x) + (m[4] * v.y) + (m[8] * v.z) + m[12];
d.y = (m[1] * v.x) + (m[5] * v.y) + (m[9] * v.z) + m[13];
d.z = (m[2] * v.x) + (m[6] * v.y) + (m[10] * v.z) + m[14];
}
Saturday, December 02, 2006
This buffer is for notes you don't want to save,
I noticed this small function seemed to destroy my frame rate ... but on running it a few times - it bounced back up, maybe the JIT stuff?
Sunday, November 26, 2006
Don't tell me to put my pants back on, they're my pants, I decide when and where ok? ok.
Working on coursework for my Game Programming Masters. In C++. The main thing I've learnt is how to use a profiler correctly, I wrote a particle system from scratch in an afternoon. It makes me wonder if I could oragnise my time this well independently. Currently I'm making render to texture work. It's not hard because there's a library that pretty much handles all the low level stuff for us.
I'm still working on Einfall albeit slower than ever. I think I managed a checkin every two weeks. All my time is spent working on this coursework as the deadline looms closer and closer. I still think it's better to use C# (especially if mono's any good now) for general game development. C++ became a little nicer to program in once I got a memory checker. But there are way way too many "undefined" areas in the language. And stuff in the language that's absolutely pointless - private inheritance?
Anyway enough words - pictures!
Also I'd love a decent unit testing framework. They all tend to suck and require a scripting language - basically because C++ doesn't have any real reflection stuff.
Saturday, November 04, 2006
Ice cubes and the elderly
This is where I am in rewriting the Einfall base. Things are going slowly but they're going :D I feel very strongly that it's important to get as game-like as possible as soon as possible. So I'm working on mouse control, something I don't have in my main Einfall branch. After mouse controls added I intend to make a simple game. Along the lines of a text box saying "Find treasure", there being a treasure chest on screen and when you open it the game finishes. I think if I can do this, a lot of the functionality for Einfalls more complicated features will be cemented.
At some point I'm going to have to revisit and redo my horrid GUI library - it's resource management really sucks.
Currently in einfall something wierd's going on with my camera.
If I have a scene, with the origin 0,0 at the top left hand corner like so:
AB__
____
Where A and B are some tiles. If I changed my camera position by calling. camera.Position.X += 10. I would expect:
B___
____
but I get
_AB_
____
Grah, not sure what's going on. In my code the following happens:
viewMatrix = Matrix.Identity;
viewMatrix.Translate(position);
// ... later on
device.SetTransform(TransformType.View, masterCamera.ViewMatrix);
Which all seems fine to me, but perhaps I'm retarded. I'm willing to work around it at the moment. In the world of C++ and OpenGL I got quake style mouse look going, with help from various internet tutorials and the gamedev irc room. Thought I'm still not perfectly happy with it.
It's been a little too long since I've touched Scheme, so I'll do another problem in that today. Also I've got to get some class diagrams up for my coursework. What else?
Oh on Friday we had a talk on XNA Microsofts new game making stuff. It's like a build system and game library tied into Visual Studio and C#. Looks extremely easy to get a simple game up and running - like mario or arcade clones. Most of the stuff is avaliable free. Oh and it's very very easy to use an Xbox360 controller on your PC - even the analog sticks are easy. Not only that but games developed using XNA will also work on the Xbox360. It's supposed to usher in a new dawn for the indie / bedroom programmer. It all looks very promising. If you want to sell you games - then of course you must give Microsoft some money :) What did you expect?
Some of the XNA stuff reminded me of the Light Weight Java Game Library plus build stuff, Xbox360 support and really cool IDE.
Finally I'm downloading boost for C++ in a last ditch attempt to get some kind of unit testing working for my C++ programs.
Thursday, November 02, 2006
Room!
This is all done in C++ and openGL. It currently supports axis aligned planes, that are subdivided to the correct complexity on start up. There's still a long way to go. Oh the black dot represents where I've put the light.
Also the frame counter can be ignored, as the frames are locked to 1/60th of a second. I need to update the FPS counter to handle this.
Friday, October 27, 2006
The varied mysteries of the inner mouth society revealed at last!
I just added an Fps counter to my coursework, I didn't need this but it's there anyway. I also have a rough plan (half remembered UML ahoy!) - if this plan levels up from "rough" to "okay", I'll be very happy. I'm going to leave it overnight without looking at it and hope it'll have grown by the morning.
Programming C++ after C#, is like programming in broken glass.
Wednesday, October 25, 2006
Burning houses in stinking fog
As I'm still not at home in C++ this took much longer than it should. I had no idea where it wanted the PERL environmental variable defining. (I defined it for the system) but it turned out it wanted it defining in the makefile.
Which ended up looking like this
PERL = c:\Perl\bin\Perl.exe
# Where to look for the tests
TESTS = H:\CW1\Parser\Parser\*.h
# Where the CxxTest distribution is unpacked
CXXTESTDIR = H:\cxxtest
Done a bit of a whirlwind tour through OpenGL and have a massive spec for the game I'm suppose to produce my christmas. A FPS style thingy.
Thursday, October 12, 2006
Beware Of Shadows
How to be a 3D Game Programmer before Christmas*
There are two main areas of self study, C++ and OpenGL. These are extremely abrieviated. Also they are bolstered by lectures and university library which are possibly hard to come by at home :D Some of these steps are things I did but weren't actually required.
OpenGL
*Get a triangle to the screen.
*Experiment with glBegin() glEnd() and their various arguements.
*Experiment with colours and glClearColor
*Rotate the triangle, you're not allowed to use glRotate. Translate it too.
*Spin the triangle according to the amount of time passed since the last frame.
*Draw a circle (use the triangle fan)
*Learn about glPushMatrix and glPushMatrix.
*Create a cube and draw cube function.
*Have a small red cube rotate around a rotating blue cube. (you can use glRotate)
*Investigate culling, turn culling on. Ensure your cube still draws correctly.
*Create a function that draws a cylinder.
*Create perspective matrix. Experiment with the various perspective modes and arrangement.
*Understand what the near plane and far plane are, now give them sensible values.
*Create a light
*Create a number of lights and explore the all the parameters for lights.
*Rotate the lights so that they circle a spinning cube.
*Create a new cube generation function, this function will generate normals, you can also set a subdivision parameter that will set how the sides are divided up. So all sides of the cube might be made up of four planes.
*Explore the various properties of materials.
*Texture a cube.
*Texture a disk.
*Understand how a terrian map works.
*Using vertex arrays and index arrays create a cylinder class.
*Create four seperate windows that show a scene from 4 different views; top, side, perspective, front. You can repeat the rendering code four times.
*Create a program that creates texture and allows you to draw on it so that left mouse button draws blue lines, middle mouse button green lines and right mouse button yellow. Now expand this program into a simple paint program.
*Add a clone brush.
*Don't use a texture instead use glDrawPixels
*Print text to the screen using a simple function.
*Be able to print the text at any x,y,z coord.
*The text should be coloured according to the last glColor call.
*Create a lit scene, with a central large sphere. Give this sphere a yellow material. Now have a sphere orbiting the sphere. Give this sphere a blue material. Now have another sphere orbiting the blue sphere, colour this final one grey. Yes it's suppose to be a model of the solars system - make the rotations correct, so years / days are represented. Add some more planets. Texture all the planets. Be able to rotate the camera around them. Finally create an additional view window so you can observe the planets from a different view (it's okay to redraw the scene to do this)
*Create a plane, use the ARB multitexturing extension, have two textures on the plane. One a base texture, the other on top some parts are see through. Now have both textures rotating in opposite directions. Now create a box above the plane, have each face of the box multitextured and animated. Above the box add a sphere, with a map of the earth, add a rotating cloud layer using multitexturing.
... I'll update this later. I'm still suppose to be working. I just wanted to check out this blogger beta label stuff! :D
C++
*Write a program using the stl with cout and cin that translates celsius to fahrenheit (or vice versa)
*Know boolean stuff, switch statements, if else clauses. All the basic stuff.
*Learn how to use the VS.net debugger, step through, break points, checking values while the programs running etc.
*Now we get a little more tricky. Write a program that will take in 3 colour values RGB then pack these 3 values into a single integer. To make sure you've got it correct, unpack these integers afterwards.
(If you're thinking - that's a bit of leap! The guy who was making the tutorials changed) I interpretted this as the 3 colour values are 0-255.
*Write a program that will search for a word in a file and tell you the line number and word number.
*Write a program that will solve quadratic equations for imaginary numbers. Well this made me wish I'd taken A-level maths :D Make it fast. Make it output the two roots to three decimal places.
*Write an number of functions using passing by reference, value and using pointers.
*Write a program that can parse a text file with brackets and then format the brackets nicely using tabs. Next a few numbers somewhere in the nested brackets. You program should be able to get the highest number and write out is nexting level. Use streams! e.g.
{
{
{
{
2
}
{
}
}
}
{
{
{
20
}
}
}
}
{
10
}
*Do the above program but don't use any looping constructs. (use recursion)
*Requires a decent undergrad degree in computer science, supposedly.
Thursday, October 05, 2006
Suprises
Anyway I have to go now. Blog posts may be down this year :D
Saturday, September 30, 2006
The reasons behind guinea pigs
(define ^
(lambda (x y)
(cond
((zero? y) 1)
(else
(* x (^ x (sub1 y)))))))
Today I'm going to polish off another chapter in the scheme book and hopefully two in the C++ book. Last night I added the FPS counter to the second version of tilemap. I have one or two small todo's today on it too.
On Friday I had an intro lecture to the Computer Game Programming course. There where some interesting figures for where the worlds best selling games are made (this was on slides no source was given)
15% UK
36% Japan
44% USA
therest% other places
I was suprised the UK was so high, and that all the grand theft autos where british made (same for laura croft, broken sword and a host of others I embarrasingly didn't know :) though some I suspected :D ) Interestingly Serious Sam was made in Croatia.
Then we saw the final year projects. They were impressive, one demonstrated fluids in real time, another was soft body modelling.
Soft body modelling is making your normal "hard" polygon model a bit softer and more natural. We can press our skin and it gives a litte, same for clothes, this isn't the case in games where if two models meet they cannot press on each other. Rather we might see some rather ugly polygon clipping problems, or they'd just rebound like they're made from an euclidian solid. The demo showed a 3D worm (from the Worms 3D game by Team 17) and when items interacted with him, his skin would wobble, a cool cartoony effect. The project allowed this kind of soft bodyness to be applied to any model it could load. I think the guy who made it was given a little help from Team 17 but still it was very impressive.
There was another one that animated cloth and another project that added fur dynamically and then rendered it in real time in DirectX. That was good too. The were a host of options for altering the fur parameters, colour, shell number, length etc.
The course is focused extremely hard on the graphics side of game development. I don't believe we'll even briefly cover a definition of a game or what might make one game fun and another crap. That's ok with me though :)
We closed having a look at the Wii and PS3 marketing strategies (I guess) where the PS3 is saying "look we have all this super raw power" - there was a demo of a guy holding two coloured beakers. The Ps3 was hooked up to a camera and it rendered two glasses where the beakers where. He was then able to interact with a bath tub - including pouring water from one beaker to another. The wii was more emphasizing - "our console is going to be fun", it's going to be something you'll play with your friends and many people will enjoy. Then we saw some adverts for the wii.
There's was also a chart showing which companies graduates went to places like Rare, Team17, Lionhead and others.
Looks like it's going to be a lot of hardwork.
EDIT: Did a nice chunk of work on Einfall tonight. Simplified a function or two that was doing too much stuff like:
MasterFunction()
{
MethodB();
}
MethodB()
{
// A load of stuff
MethodA();
// More stuff
}
Converted to
MasterFunction()
{
MethodB();
MethodA();
}
Removed MethodA from MethodB
Something I probably should have seen before. Also extracting some if-boolean statements to seperate functions for clarity. It means it's much easier to read now.
EDIT2: Added the tile part of the map so now I can add some tiles and see if it works - which it pretty much does yay! I set the world origin to the top corner of the window but it seems to be ignoring this for some reason. Otherwise, everything is looking pretty good. Next up is preparing the classes so I can slot them into Einfall without a massive headache :D
Thursday, September 28, 2006
atm confidential dances
Started a new subversion repository where I'm creating a final version of my tight map, which will be fast (like the old version) and handle such things as users logging out and in without crashing (unlike the old version).
EDIT: More accelerated C++, seems tightmap version 1 is quite modular so I won't have to redo any of the code just the windows wrappers stuff (I'll probably tinker anyway :>), I had some confusion resolved.
Tuesday, September 26, 2006
Dank Cat Paw
My C++ is rusty to the point of collapse. So I'm going to work through one or two of the C books I brought along. Then I'll find what are a few good reference books for C++ and order them.
As for my simple tile rendering stuff - it now persists even if you log out and then log back in. And through screen savers and everything else. I want to talk about how to accomplish this but not quite yet :D
I want any articles I write to be in some kind of document source code and then the ones uploaded here are "compiled" to html. So I'm looking into docbook, but it looks very hard to set up. So maybe I'll see what I can do with a few latex plugins.
Sunday, September 24, 2006
In Hull
Today I've added some small bits of code to reset the vertexbuffers when the device is reset in the RenderPrimitives dll. Also polished off another chapter of the little schemer.
Thursday, September 21, 2006
Living in a refurbished slaughter house
Anyway I thought I'd talk a little about DirectX devices and forms. This relates to creating directx fullscreen apps as well.
When you create your device you create a PresentParameters object and this takes in two important variables; the height and width of your display area. If you have a form you might think - oh this is just form1.Width and form1.Height but you'd be wrong! That's the entire height of the form, including the blue bar with the maximize, minimize and close buttons, and the little grey border. If you use these values it will most likely throw some of your calculations off.
One way round this is to put a panel in the form and then use panel1.Height, panel1.Width and this will work fine because the panel has no border stuff. Unfortunately it will fail horribly if you try to do fullscreen. To do fullscreen the component you use must be a form.
So what's the best way to get the width and height? Well it's not to hard-code them, like I seem to have done on my project :D Rather it's to get them from form1.DisplayRectangle. This gives the area you can draw in and doesn't include any of the form fluff, like grey outlines and drop menu strips!
So there you go.
Also looks as if blogger's actually going to show one of my images. This test image just shows how I use firefox and rss. If in firefox you add a bookmark and put it in the "Bookmarks Toolbar Folder", it will appear as a button on a strip just above the window your currently browsing. Then you can press it and it'll take you to the relevant page. Great. If you add a bookmark to an RSS feed in the folder, a button will once again appear on the strip. But this time when you press it, it will form a drop down menu listing all the newest items in that feed (you can do that with this webapge by the way :D You'd get a list of all my latest posts with their rather cryptic titles :) . Even greater. Of course, if you keep doing this, that strip's going to get quite full! So you might want to add a folder within the "Bookmarks Toolbar Folder", this folder will also be represented as a button on the strip.
Click the folder and it will create a drop down of all the links you've put in there. I like to have folder just of RSS feeds. Then I can run my mouse down them and see if there's anything new on the webpages I'm interested in.
If you've read this and you're thinking, "I don't know what RSS feeds are :(", well, well done for reading it all :D RSS feeds are some XML files hosted on the webpage you're interested in and each time the page is updated, the xml's updated too. Then your computer periodically (every few minutes or so) queries this xml file and updates it's local listing of that particular pages updates. So rather than you manually checking for updates the updates are brought to you.
(Well the image seems to work quite nicely. The webpage shown is an online stockmarket electronic broker thing, because recently I've become a little interested in the stockmarket, after reading the, to be honest, rather crappy book, Rich Dad Poor Dad. Expect more images from now on!)
EDIT: I think I've the found artifact problem, it seems to be due to the ratio between directx space and pixel size of the display area and textures.
EDIT: I can't believe I was back again today battling with artifacts when rendering tiles GAH!! Anyway for what's it's worth it's fixed now. I made a new library with fixed spelling called Einfall.RenderPrimitives. Where I made one small change. But I think one of the main sources of artifacts occurs if your form.DisplayRectangle doesn't equal your othographic projection width and length. Currently I'm scrolling smoothly with batched unartifact tiles. So that's nice. I guess the worse thing was this worked fine before on my laptop :O I'm somewhat confident now it will work nicely on all systems. So now all I need do is rewrite my tight map project (which is basically a small tiled engine that uses batching, animation and layers.) and the artifacts should dissapear.
Then once that's working nicely I'll have to merge it into Einfall which I guess will be a never ending serious of headaches. And then, then, I'll have einfall create buildings that actually have walls! Currently the buildings are merely flat outlines.
Final Edit: Quick bit of tinkering and tight map is now compiling as expected.
Wednesday, September 20, 2006
Additional Scheming
I'm not finding the book too hard going and can work out most of the answers to the questions. But I never seem to get the brackets right (as Jani pointed out this is the intially scary thing about lisps) I'm always doing (cons (atom) (atoms)) where it should be (cons atom (atoms)). (>_<) I don't know any of the debugging stuff yet either.
(define spanner
(lambda (lst)
(cond
((null? lst) (quote()))
(else
(cons 'spanner
(spanner (cdr lst)))))))
Here is my amazing second entirely homemade function that takes a list and replaces every atom in it with the word (unitialized variable) "spanner". Yay me.
On an unrelated note
This article on stackless python is quite interesting, the comments are good too.
I've also spent way too much time messing about on a Linux box - it's Ubuntu, easily the most friendly distribution, but I've never ever had an install where I didn't need to compile some C code to get some critical piece of hardware working, if I do ever get it working, that is. It seems unlikely even with the advent of DRM-happy-Vista that Linux is going to widely used on peoples desktops in the near future. I guess if you do happen to have the perfect mix of hardware though Ubuntu is an extremely attractive desktop alternative. Of course there are no games :(
Tuesday, September 19, 2006
Scheme scheme scheme
Anyway behold:
(define test?
(lambda (a)
(cond
((eq? a #t) 'hello)
(else 'goodbye))))
Yesterday I played with the map editor program a bit more. I'm having trouble transforming the device for my various swap chains so that's something I need to play with. (this looks like a reasonable place to start) I also added a moving camera to my tile renderer to make sure there are no artifacts. It works fine. So I documented my simple rendering stuff - the RenderPrimitives library that handles batching. Time to find another suspect for the artifacts.
Monday, September 18, 2006
Removing the close box from a c# form
If you write some code like so:
this.ControlBox = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
Where "this" is some form, you may find yourself with a control lacking a blue strip to move the form around! The solution to this problem is to enter some text in the text field.
this.Text = "My useful form";
this.ControlBox = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
And that seems to be how it's done. Of course there are other ways override the message handler or using PInvoke (yes I tried Google before working this out for myself) but you really don't need to.
Sunday, September 17, 2006
Chasing down bugs.
I just built a very simple program that demonstrates the batcher and I don't lose any tile edges in this case ... so it must be somewhere else. The search continues.
I'm also rather slowly teaching myself Scheme in Emacs because I must have a deep repressed masochism. I'm using the Little Schemer book. So far so good. I'm just running an interpretter through Emacs at the moment. It does syntax highlighting, indentation and bracket matching - everytime I press one bracket, the matching one appears. After reading The Pragmatic Coder, I really felt like I should put in the effort to try and master Emacs. (I still can't imagine it ever matching VS.net productivity but I like the core structure of customisation and extensibility.)
Also I have somewhere to live in Hull, which will be useful as I'm starting University there next week. It use to be a slaughter house, and there are still hooks in a large wooden beam in the downstairs front room! Cosy.
Tuesday, September 12, 2006
Scheme, Petite, Emacs and the error message; spawning child process invalid argument
So I've Gnu Emacs 21.3.1 running on windows and I'm interested in learning scheme. I went into the Control Panel > System > Environmental Variables and edited the PATH variable to include petite. So if I typed petite in a command prompt - up would come the interpretter - great! Or so I thought.
Next I wanted to have it runnable from Emacs, running as a child process so I can compile my code as I type it.
(custom-set-variables '(scheme-program-name "petite"))
Emacs is already preset up for such tinkery so all I need do, is tell it what my scheme program is called. This is where it all went wrong. I could tell emacs to run a shell command, type petite, and it would run it, but tell it to M-x run-scheme, and it failed with the error "spawning child process invalid argument" or a "could not find petite message" depending on if I located gave the full path to petite or just the file name and hoping the windows "path" variable would sort it out.
So various head bangings later and it turns out that emacs doesn't like the quotation marks that I put around the path in the Windows PATH variable. So remember don't to this:
PATH="path1";"path2"
do this
PATH=path1;path2
Monday, September 11, 2006
Ebichu
Using DirectX, C#, Windows Forms, to create a non-flickering interactive form application that also has a render loop for DirectX.
Now there's a smooth, smooth title.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MapEditor
{
[StructLayout(LayoutKind.Sequential)]
public struct Message
{
public IntPtr hWnd;
public Int32 msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
delegate void LoopHandler();
/// <summary>
/// Sets up a render loop so DirectX bits are updated as often as possible.
/// </summary>
class RenderLoop
{
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(
out Message msg,
IntPtr hWnd,
uint messageFilterMin,
uint messageFilterMax,
uint flags);
public event LoopHandler Loop;
private bool AppStillIdle
{
get
{
Message msg;
return !PeekMessage(out msg,
IntPtr.Zero,
0, 0, 0);
}
}
public RenderLoop(LoopHandler loopHandler)
{
Loop += loopHandler;
Application.Idle += new EventHandler(OnApplicationIdle);
}
private void OnApplicationIdle(object sender, EventArgs e)
{
while (AppStillIdle)
{
Loop();
}
}
}
}
Ok, so this is a slightly modified version of my render loop. The thing to notice is there's an event called Loop, this is where you want to attach a function that'll handle your DirectX rendering. Loop's called as often as possible, while the application's free. Yes, I know for a map editor I really should try and save cycles because it should play friendly with other programs but it's far easier doing this way. ( I haven't tested it after making modifications but I'm pretty sure it should work :D)
Anyway, we've got this wonderful looping class let's see how we'd use it in an application.
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form form1 = new Form();
RenderLoop renderLoop = new RenderLoop(delegate()
{
form1.Render();
});
Application.Run(form1);
}
So we create a new form and that form has a render method. This is where DirectX does it's stuff. DirectX might be updating a panel or something, or maybe you want rotating 3D cubes on your buttons - whatever, this is where that code goes.
We hook the form's Render method up the RenderLoop's Loop event. So the game loop now will call form1.Render each iteration. This is often called loose coupling, it's cool because I can use the class RenderLoop again and again in different projects, in different ways.
I hooked the loop to the Render method using an anonymous delegate. If you program C# and don't know what this is - learn it! Right now! Go! Here I use one so I can make use of the form1 variable, instead of having to make it static. I'll finish with an example render loop. *warning this is far more complicated than it has to be because it's ripped straight from my code and it's using swap chains)
internal void Render()
{
if (swapChain.Device == null)
{
return;
}
Device device = swapChain.Device;
device.SetRenderTarget(0, renderTarget);
device.Clear(ClearFlags.Target, Color.Aquamarine, 0.0f, 1);
device.BeginScene();
device.EndScene();
swapChain.Present(this);
}
Wow an actual post with some substance, it's been a while. Using the above code you could have a windows form which is partly directX. For instance a panel might show a £D model and by the panel are a number of buttons that make the model play various animations. This stuff is very useful for writing test programs and editors, or borrowing the Windows GUI if you don't fancy rolling your own.
Happy hacking.
Sunday, September 10, 2006
Harvard concludes - you suck.
But today I've been fooling around with a map editor. (I'm currently not playing with Einfall so much because I need to install a paint program that can handle png alpha channels, this would take all of two minutes, but reading and gardens often seem to get in the way) Yes map editor, a long time ago, some one commented that they were anxiously waiting for another tutorial that would cover map editors. I confess at this point I have no intention of writing a tutorial. My program is very basic at the moment, a MDI parent window. MDI stands for multi-document interface, I think, basically what you'd be using if you used Photoshop - a window for a each picture you opened.
The clever thing is my child windows are Direct X enabled. Using swap chains. I'm thinking about a tile palette but haven't quite decided anything yet, apart from it will be resizable and always arrange the tiles nicely :D
Wednesday, September 06, 2006
maybe you have to be English to know how wounding those eyebrows and coughs can be
Friday, September 01, 2006
The Norske Mustachclub
The situation arises where you might ask the bank for a resource and it doesn't have it . For some reason only one of the banks deals with this situation in a decent manner. It calls an event, where the user of the bank would write a call handling the event and probably loading the missing resource from disk. There's no reason why all the banks shouldn't have this event so I'm in the process of moving it now and fixing things according to the unit tests.
I'm trying to make my more mature code more solid, documented and polished.
Thursday, August 31, 2006
Space Germans!
The html cut and paste plugin is now working so I can put nicely formatted code in the blog again. It wasn't too hard to get Einfall building, which was suprising considering how scattered the source code is. I needed a fresh LuaInterface install, and nUnit and at some point I'd lowercased a full caps namespace so I needed to do a little search and replace but other than that up and running immediately.
Now I just need to dig through my notes and find out what I was up to last. I know I was rewriting how it does the rendering so I guess that's still needs finishing up. Then pushing into the current Einfall build, that I'm some what dreading as it will mean changing the map format.
Getting the new rendering project building and it's blazingly fast on this machine, FPS in the 1000s rather than 100-190 on my portable. Some how some graphical glitch seems to have crept in, but I think I know what it is so I'll fix that soon. I'm going to work through and document it properly. I remember that it was quite well written so I should back up to speed soon.
Monday, August 21, 2006
Irked: Serious Games
So that's good, but what's not good is a growing number of people labelling such games as serious games. This is a bad bad label, if the person who created this label was here now I'd very much like to bop him (or her) on the nose with a rolled-up newspaper and maybe waggle a warning finger at them. Here's the wikipedia definition of "serious games":
Serious games (SGs) are computer and video games that are intended to not only entertain users, but have additional purposes such as education and training. They can be similar to educational games, but are primarily focused on an audience outside of primary or secondary education.
Pah! Psst! Pah!
If you call one group of items serious you are suggesting all other items are some how less serious. Let's take people, if I said "serious people" you might form the following model in your mind.
Serious People: Buisness Men, World leaders, ...
Non-serious People: Comedians, Artists, Bums, Clowns, Mimes...
So imagine if this shadowy education group had targetted music instead of computer games, they would like us to form the following mental model.
Serious Music, music that educates:
Sing 2 School - Multiplication Hip Hop
Alphabet - Music for Clever Kids
...
Non-serious music, music that fails to educate:
Classical, Rock and Roll, Pop, Jazz, Rap, Indie ...
Non-serious music, is that worthless, for kids stuff, that has nothing to redeem it - it merely entertains - it doesn't convey FACTS! Therefore it's not "serious" - it's a waste of time and you should be feeling very guilty about listening to it at all! You grubby hippie frittering your life away by enjoying yourself, I hope this chastizes you sufficently.
The same labels could be applied to books, instead of fiction and non-fiction we could relabel them serious and non-serious (or waste of time, guilty pleasure, whatever label seems to fit best.)
As I hope you can see this way of naming things doesn't help anyone and is a little insulting to anyone not creating media that's not primarily educational. I'd intially distrust anyone "seriously" throwing the term around. Serious is quite subjective, let's keep that way.
Tuesday, August 15, 2006
Burnable Dust
Life update: Teeside cancelled their game programming course, I'll now be going to Hull instead. I'm guessing it was due to lack of interest or they lost a lecturer - I wasn't told anyway :D
I intend to upate this blog with the contents of my lessons. The programming books I was reading are currently being shipped from Japan. I'm mainly catching up on games I missed. Oblivion is fun but buggy - a step down from how stable they got Morrowind. I've got the seasoned schemer and I'm waiting on the little schemer, as I want to learn scheme, all of sudden.
My main project defitently isn't forgotten but I'm doing no programming at the moment, as I build up my development system again.
The main reason I decided to write this post was to highlight a very curious game - Dwarf Fortress.
At the start of the game, a very large, very unique world is generated.
You may then choose from various mountains - here your dwarfs are to create a new settlement.
They can dig into the mountains and creates halls, bedrooms dining areas and the like. They'll need food to get through the winter. Each dwarf has a different skill set but they can ply their hands to anything. The caves might be attacked or flooded so it's important to build doors. You master mind the construction of this new settlement.
The big difference is it's all ASCII! It looks very much like a rogue like, in fact there's also a roguelike in the game, once you fortress is abandoned. It enters the game world as ruins and in the roguelike you can battle the ghosts of the dead dwarfs and loot their treasure.
The interface is daunting but workable once understood (It would benefit greatly from some streamlining). Defintely worth checking out and struggling through the interface problems - theres a massive amount of depth, it's alpha but still very impressive.
Check it out here.
Monday, July 24, 2006
The codes become quite unclean. Here's the most horrible thing in it at the moment:
void OnNodeWantsToChangePosition(INode n, float x, float y)
{
this.RemoveNode((T)n);
n.UnsafeSetPosition(x, y);
this.AddNode((T)n);
}
Not very elegant casts that really shouldn't be required. Moving through a quadtree isn't very efficent, which is cool because they're generally for static stuff (my items). So when to move something in a quad I take it out of the tree, changes it position then replace it in the tree.
Still quite busy - I'll be going to Tokyo on the 31st for five days before returning to Old Bilayati. Upon arriving I guess I'll be quite busy again for a while. And soon I'll start University doing a masters in game programming - I'm considering doing a write up of all lectures here, so that's something to look forward to.
Friday, July 21, 2006
A vibrating blue squirrel
Today I've done a little hacking with the quad tree - well not really, I've created a windows application that makes use of the quad tree library just to make sure it's working as expected - seems ok.
I'm still adding a few notes over here, it's all quite jumbled but could make interesting reading if you have some time.
My goal at the moment is to have the quad tree stuff working solidly. This allows me to get a decent inventory system up and running. It's hard to concentrate as I'm making lots of goodbyes, trashing large amounts of stuff and all that.
Sunday, July 09, 2006
'You ever put a full-length mirror on the floor, and then have a dog stand on it?'
Wednesday, July 05, 2006
A redness sensation
Anyway here's my small description of what and why of the Quadtree.
Let's say you have a map with a few hundred items, candle sticks, dogs, rooms, people.
Let's call in 500.
The naive collision detection goes like so: foreach(item in items) DoWeCollide?
That's 500 comparisons to see if a single object collides, or if your mouse intersects an item. That's a lot. Imagine 50 NPCs are moving thats 50*500 comparisons every frame. A big number.
Oh no, what can we do this is the end of games as we know it!
Yes, it does seem that way ... but wait there's our hero QuadTree!
In a quad tree you split the map up into regions. Cut the map in half vertically and horizontally and you get four equal size regions. Now cut those regions into four, and perhaps once more. So we now have nest regions.
First Cuts
Region1
SubRegion1
SubRegion2
SubRegion3
Subregion4
Region2
...
Region3
...
Region4
...
So we have the above type of regions, notice the hierarchy we've got going on, admire that hierarchy.
Right, now our collision detection is more a conversion like so:
NPC> Hey, First Cuts, do I collide with any of your regions.
First Cuts> Why yes, yes you do, you collide with two of them I'm afraid. Region1 and Region2.
*NPC goes to talk to Region1 and 2
NPC> Hey, Region1 and Region 2 so I collide with any of your subregions.
Region1> You collide with two of mine.
Region2> And two of mine two!
NPC> Okay, time to check if I collide with any objects in those four regions!
"Wait, wait, wait," you might sputter "stop the science train Doctor Scientopolis, what about items bigger than one subregion. What if I have castle that took up half the map?"
Well, Jimmy, the castle would exist at the very bottom of the quadtree - but crucially it would exist in more than one subsubregion. You could write special code, not to attempt an intersect with an object more than once, if efficency is worrying you.
Region1
SubRegion1
-Castle
SubRegion2
-Castle
SubRegion3
-Castle
SubRegion4
-Castle
etc.
So what we saved, let's say you have your quadtree four layers deep (how deep depends on the dimensions of your map and number of your items), then in the minimum case you'll compare each moving object 4, times once per each region. That's a lot better than the 500 we had at the start.
-What about items that span many regions - well they're still added at the lowest subregion - they may be in more than one subregion pool.
In my game I think I want circles, rectangles, points and polygons. It's a nice finite list. I will have an object called intersectCheck which will handle intersect checks between these objects.
Sunday, July 02, 2006
Celestial ninja syndrome
Here's an NPC brain (which could easily be swapped out for a brain that took input from the keyboard or something). It moves one tile down then stops.
public class WanderBrain : IBrain
{
bool tempHaveMoved = false;
#region IBrain Members
public void Process(double elapsedTime, Entity entity, IEntityMap eMap)
{
if (!entity.Mover.Moving && !tempHaveMoved)
{
entity.Mover.Move(Direction.down, eMap);
tempHaveMoved = true;
}
}
#endregion
}
(I'm trying out the component model for my entities, current components that are required are a brain, I already use pretty much the same setup in einfall, and a mover that handles how the entity moves over the tilemap. I haven't put general components in yet.)
So suddenly I'm doing tile based movement where as before I had free wandering :D Still I can have freewandering for the player character and eveyone else locked into the tyranny of tile movement.
Anyway overall much much faster than einfall. Not done quite yet though ... I want to add items that will sit on the tiles. I'll probably also add some simple loading and saving stuff. Oh and I'll make the bottom set of tiles a static vertex buffer with a dirty flag - this should keep things faster!
Friday, June 30, 2006
A five minute dash to a data driven nethack
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?"
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
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.
Listpeople = 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
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
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
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.
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.
Wednesday, June 14, 2006
A young mans primer on C# Game Development
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)
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.