Sunday, October 28, 2007

WikiForAll - a wiki devoted to comedy

Yes, that's right, a new wiki enters the world...

http://www.wikiforall.net/

If you're in need of some humour, this wiki is the place for you.

Sunday, October 14, 2007

On Dvorak Layout and Game Design

After a mate suggested I try out Dvorak because, I quote, "your fingers fly, man!", I figured I had nothing to lose and setup the Windows language bar to let me switch input modes from the standard US keyboard to US-Dvorak keyboard layouts. Needless to say, the switch has not been seamless. It is so much more difficult to learn a new layout when I've been typing on the standard US layout for such a long time (it may also have something to do with the lack of proper labels on my US-style keyboard). Even having an image in front of me of the layout doesn't help much.

And, to make it worse, I keep hitting the key combination to o,cyjd mre.o (switch modes) accidentally. One day when I get really bored I'll just open up Notepad and type "The quick brown fox jumps over the lazy dog" over and over until I can get it nice and fast. But who has time to spare, in this fast-paced world?

Me, obviously. After all, I have taken on a project at school to write a multi-player RPG for my class to play when assessment finishes. As of the time of writing, it currently supports scrolling the map when the local player moves too close to the edge, drawing other players (although I have not yet plugged in the networking code to update these other players), an inventory manager (though no pickups yet or anything like that), and am in the progress of implementing a statistics manager (experience points and such).

When complete, I hope to do a test run with the class and if successful recruit some of the more artistic members to draw the tiles for the game (as it is a 2D, top-down, tile based game). After creating some nicer tiles, I can then proceed to optimize the code like crazy, making it run really quickly locally so that network latency is not as much of a problem as it could be in a 3D game where the local version must update the frame and wait for input from the network.

I actually have had an ingenious inspiration relating to NPCs in the game as well. Instead of having them built into the game, which increases code bloat and makes life harder, NPCs will be programmed as clients to the server, meaning that an NPC is nothing more than a basic program with AI logic in it to respond to game events, that connects to a specific server as if it was a human player. This method allows the NPCs to be easily customized on the fly, and makes testing the program much easier (once the server is started, it doesn't need to be quit again just to fix an AI bug).

The only thing I can't figure out is what to call the game. If you like, you can post tile ideas as a comment to this post. Who knows, maybe your suggestion will become the name of the game!

Saturday, September 29, 2007

On Game Development

Due to my recent lack of success in game development (a 3D FPS is quite a challenge at times - more on this later), I've decided to go back to the first game I wrote - a simple "Pong" clone with a couple more features and a nasty AI.

My 3D FPS works nicely, it loads levels and you can move around in them, but I never got collision detection setup in the engine, or any guns or any FPS-related stuff. I was mainly concentrating on getting a scripting engine setup for it, and after I got boost::python to work in the engine I realized most parts of the engine needed to be rewritten anyway because they were slow and causing massive code bloat.

My old Pong game works nicely as well. You can load it up, select the difficulty level from the (extremely) rudimentary menu, and the AI can get tough. Unfortunately it was plagued by my lack of knowledge of the DirectX APIs and hence code is scattered everywhere in an attempt to make a working game.

The new one will use a simple structure to do its work - not one massive procedure called every time the screen needs to be rendered. With a separate procedure for AI, physics, and drawing, the internal code base becomes much simpler and easier to work with. Monolithic functions (ie, those with > 100 lines of code) will be split into multiple (smaller) procedures.

And, possibly one of the most important things, the menu will be separated from the main game loop.

I don't know what I was thinking when I wrote the first revision of Pong, but for some weird reason I decided it'd be a good idea to put the menu code into a conditional block:
if( inMenu )
{
// do menu stuff
}
else
{
// do game stuff
}

The initialization for the menu was a bunch of hacks to get a bunch of strings into an array - now I know better methods for doing this. Often the menu strings would mingle with each other and end up becoming quite confusing.

The new game will hopefully fix all these bugs in the initial code base and utilize the full power of DirectX 8 (instead of DirectX 1 which I was using before). The final planned feature is something that all my friends suggested after playing the first version - "Add networking". It should be fun to write a basic protocol that updates paddle and ball position for a single client. Or even to have a fancy "spectator" view and a "tournament" mode for those who wish to have a LAN party with a bunch of mates.

It shouldn't take too long (hopefully no more than a month) and I'll post a link to the final binary when I'm done.

Friday, September 28, 2007

Gaming: Pick up and Play or The Epic?

Has anyone noticed a trend lately in game development?

We have near-realism in our graphics (see some screen shots of F.E.A.R or Half-Life - they look incredible), with advanced sound systems that allows us to hear something "behind" us, and artificial intelligence that makes your enemies seem that much more real. Games almost make us feel like we are playing a movie.

Who cares?

Why is it that a simple game, with terrible graphics yet a fun concept, can leave the player entertained for hours?

Yet, after viewing screenshots and attempting to play a game called "Ragdoll Smasher" (see here), I realized that this guy had figured it out. The graphics are simple (at best) and sometimes a bit jerky, and there's no story, but you can sit there for hours throwing bodies around trying to knock over the obstacles.

Another simple yet fun game is "Thermonuclear War" (see here) - basically, you have a bunch of nukes and blackness in which to nuke. Take out all your enemy's cities, you win. It's written using the Windows console, so it's not gorgeous, but interesting nonetheless.

Small and simple games like these can become quite addictive, because you don't need to spend a long time at the computer to be engaged in the gameplay. They're literally pick up and play games. For a casual gamer, such games as Ragdoll Smasher (for the violent types) and Thermonuclear War (for the control freaks) can often be a quick boredom buster.

I don't want to discount the success of Half-Life (or other similarly successful games). They are excellent games and a lot of hard work has been put into them. But if I just want to play for a half an hour, I won't be satisfied with my progress in Half-Life as compared to a win in Thermonuclear War.

Monday, June 11, 2007

Direct3D Mistakes

My stupid pyramid shape was rendering wrong, and I was getting somewhat confused at this until I actually asked some people over at GameDev.net and got some help. Nothing they did helped, so I looked through my code. After some searching, I found I was disabling depth buffering! Enabling it was a quick fix to my problem.

Read your code often!

Sunday, June 10, 2007

Frustrating Forum Users

This really frustrates me: http://www.developerfusion.co.uk/forums/thread/153675/#153675

The person asks for some help to learn the language and instead gets given hundreds of lines of code, which is poorly commented and in no way helps him.

To make it worse, it's an assignment this guy is doing, and to get given code like that can get him in trouble for cheating on his assignment. I just don't think it's fair on him for such a person as "Mohammad Rastkar" to give him all that code, and not give him any real understanding of what it does, and why it does it.

Rant finished.

Friday, June 08, 2007

My OS and 3D Graphics (not related)

I was talking to a fellow devver on AIM this morning, and he asked to see my OS GUI, which of course I agreed to. I'm going to post it here so I can look back in a year's time and see how far I've come (click to see it in full size, it's 800x600):



The cursor you can see is the one in my OS, and the wallpaper is that of a fave band of mine. So far so good, I'm going to rewrite my window manager because at the moment it crashes. Once done, I can post the image of windows in my OS here.

Anyway, other than that, I've been toying with Direct3D, which I was talking about a couple of months ago. After giving up I've decided it's time to try again, and I've succeeded! I can create (and, most importantly, modify) a spinning pyramid! I'm really pleased, and I'm about to texture it, which will make me even more pleased.

In other news, I'm planning on porting Descent 1 to my OS, and once complete it will be the first 'official' game for my OS.

And now, I must go because I need sleep.

Monday, June 04, 2007

Compilers and Such

Since the last time I posted, a lot has happened in my development life.

At the moment, I have 3 main projects which I am working on:
  • My hobby operating system (Mattise - http://mattise.sf.net/)
  • The TI-Basic compiler, for Texas Instruments graphics calculators (http://tibasic.sf.net/)
  • Neural Network System ('learning' AI)
Add in exams and school, and I'm pretty busy! So I decided to save myself a lot of time, and wrote a simple linked list class, that I'm going to post here.

//--------------- CLinkedList: Linked lists for any type ---------------//
// Copyright 2007 _____________
// Created 29-5-07
// License: GPL

//--------------- Includes ---------------//
#include
#include

//--------------- Class Definition ---------------//

/**
The CLinkedList class basically is a shell around a certain data
type. It allows linked lists to be created for any data type,
hence saving coding time.
**/

// main class
template<> class CLinkedList
{
public:

// initializes the list
CLinkedList();

// destroys all data in the list
~CLinkedList();

// dumps the list
void Dump();

// clears the list
void Clear();

// inserts data at the given offset, shifting everything else
int Insert( _T, int );

// pushes data onto the end of the list
int Push( _T );

// pops data off the end of the list
_T Pop();

// gets data from the list
_T Get( int );

// deletes an item
void Delete( int );

private:

// the list type
struct myType
{
_T data;
struct myType* next;
struct myType* prev;
};

// the start of the list
struct myType start;
};

template<> CLinkedList<_t>::CLinkedList()
{
// set the next and prev fields of start to null
start.next = start.prev = (struct myType*) NULL;
}

template<> CLinkedList<_t>::~CLinkedList()
{
// clear the list, free the memory
Clear();
}

template<> void CLinkedList<_t>::Dump()
{
// iterate through the list, displaying information about each item

// running pointer
struct myType* curr = start.next;

// running accumulator
unsigned int i = 0;

// delete each item
while( curr != (struct myType*) NULL )
{
// print it
cout << "LIST[" <<>data <<>

// get the next pointer
curr = curr->next;
}
}

template<> int CLinkedList<_t>::Push( _T d )
{
// find the end of the list, then append the data

// running pointers
struct myType* prev, *curr = &start;

// wait until curr is null
while( curr != (struct myType*) NULL )
{
// save the current pointer
prev = curr;

// load the next one
curr = curr->next;
}

// check that the one we want to add to isn't null
if( prev == (struct myType*) NULL )
{
// fail!
return -1;
}

// safe, so append - we need to make a structure first
struct myType* m = (struct myType*) malloc( sizeof( struct myType ) );
m->prev = prev;
m->next = (struct myType*) NULL;
m->data = d;

// fill it in
prev->next = m;

// success!
return 0;
}

template<> _T CLinkedList<_t>::Pop()
{
// find the end of the list, and remove it after saving its data

// running pointers
struct myType* prev, *curr = &start;

// wait until curr is null
while( curr != (struct myType*) NULL )
{
// save the current pointer
prev = curr;

// load the next one
curr = curr->next;
}

// check that prev isn't null
if( prev == (struct myType*) NULL )
{
// return start's data
return start.data;
}

// prev holds the data we want
_T ret = prev->data;

// now unlink prev (the previous one's next is NULL)
prev->prev->next = (struct myType*) NULL;

// and free the pointer
free( prev );

// return the data
return ret;
}

template<> _T CLinkedList<_t>::Get( int offset )
{
// loop through the list until we hit either NULL or the offset

// offset into the list
int o = 0;

// running pointer
struct myType* curr = start.next;

// keep on going
while( o++ != offset && curr != (struct myType*) NULL )
curr = curr->next;

// we've hit the offset or NULL
if( curr == (struct myType*) NULL )
return start.data;

// return the data
return curr->data;
}

template<> void CLinkedList<_t>::Delete( int offset )
{
// loop through the list until we hit either NULL or the offset
// then unlink it

// offset into the list
int o = 0;

// running pointer
struct myType* curr = start.next;

// keep on going
while( o++ != offset && curr != (struct myType*) NULL )
curr = curr->next;

// we've hit the offset or NULL
if( curr == (struct myType*) NULL )
return;

// unlink the item
curr->prev->next = curr->next;

// free the memory
free( curr );
}

template<> int CLinkedList<_t>::Insert( _T d, int offset )
{
// loop through the list until we hit either NULL or the offset
// then append data to it

// offset into the list
int o = 0;

// running pointer
struct myType* curr = start.next;

// keep on going
while( o++ != offset && curr != (struct myType*) NULL )
curr = curr->next;

// we've hit the offset or NULL
if( curr == (struct myType*) NULL )
return -1;

// create a new item
struct myType* m = (struct myType*) malloc( sizeof( struct myType ) );
m->data = d;
m->next = curr->next;
m->prev = curr;

// link it into the list
curr->next = m;

// success!
return 0;
}

template<> void CLinkedList<_t>::Clear()
{
// iterate through the list, freeing memory as we go

// running pointers - never start at 'start' because it isn't heap allocated
struct myType* savnext, *curr = start.next;

// delete each item
while( curr != (struct myType*) NULL )
{
// save this one's next
savnext = curr->next;

// delete this one
free( curr );

// get the next pointer
curr = savnext;
}

// and make sure start is setup properly
start.next = (struct myType*) NULL;
start.prev = (struct myType*) NULL;
}

It's extremely simple to use:
CLinkedList ll;
ll.Push( 5 );
ll.Push( 6 );
ll.Push( 7 );
ll.Delete( 1 );

You might say, 'what about std::vector?' The above class is more portable, and works without modification in my own OS.

I'm gearing up to post a multitasking tutorial someday, so keep your eyes peeled!

Bye for now, not forever!

Monday, April 09, 2007

Operating System Development...

It's been a while since I've posted here... Been too busy working on my newest project: Mattise, my hobby operating system. You can see a couple of screenshots and download it at http://www.sourceforge.net/projects/mattise. Many thanks to all the people over at OSDev.org for helping me with all the problems I had with it.

The other project I'm embarking on alongside my operating system is a physics class which can be inherited by other classes. For instance, the physics class is called 'PhysicsObject'. If a user wanted a box, he creates a class called 'PhysicsBox' that is derived from 'PhysicsObject'. At the moment it is extremely experimental but covers velocity changes and acceleration.

If I get around to it I may post some little tutorials on operating system development here. Keep your eyes peeled.