Jump to content
  • Advertisement
  • entries
    109
  • comments
    175
  • views
    117891

About this blog

This journal is approved by the Get A Life Commitee. I swear.

Entries in this blog

 

News from the world outside

Yeah, there's a world outside gamedev.net, and most of the time we call it "the real world".

The work on the future "standard 3D game math library" (no name yet, but that's not very important for the moment; its current codename is math3d, thanks to Jon Watte) is going well. Lots of questions, lots of interresting proposals and points of view on the dedicated wiki. Very interresting.

About the PS3/X360 war, let's say something fun: the ability to plug an external player in the X360 is clean, because if Sony get the HD market, MS will be able to release a blu-ray player for the X360. I just wanted to make sure that everybody was aware of this. I continue with Toshiba, who just released the first HD-DVD player. Its price: something along the line of 500$ (according to the article), to be compared to the price of a blu-ray player (1000$). I guess that an external player for the X360 would cost less (MS plans for 250$).

Toshiba also released the first HD-DVD labtop. Sony just released the first blu-ray labtop. Price: 3000$ and more. Of course, at this price, you get the best of the best. Hell, no: Toshiba's HD is only a 100GB at 5400 rpm. Stupid.

Now that war in Iraq is officially "finished", the HD war begins. I believe this one will be rather funny to watch.

Emmanuel Deloget

Emmanuel Deloget

 

OMG ! No updates!

That's true, no update. Even worse, the last update I made told you that I planned to release the RPG console game and some goodies during April - I was not able to do so, mostly because my life is accelerating and my spare time is now very short. As a consequence, my post rate slightly decreased during the last weeks.

Needless to say, I apologize for everything.

Anayway, I don't forget it - I just postpone the release date because I have tons of things to do (yes, Maz, I'm working) and not enough time to do it.

Some good news about me: I'm going to find enough money to buy a flat or a small house - I'm going to own my nest! Of course, I need to be careful about this (loads of money, everything is coming from the bank).

I would also speak of a great idea: the creation of a C++ standard math library for game development. A great discussion occured in the past few days on sweng-gamedev.

How many of you would be interrested in a standard math library for game development?

Emmanuel Deloget

Emmanuel Deloget

 

I just can't believe it !

In the November thread I created some weeks ago, I was mocking Sony because of their "when it's done" syndrom, in reference to our beloved Duke Nukem Forever vaporware -

Well, according to this DNF is supposed to hit the shelves before the end of the year.

Will the PS3 be released before or after DNF?

Emmanuel Deloget

Emmanuel Deloget

 

I have no time to add a title here

Just notices something weird while surfing the new Pipo DeClown journal: it is not possible to rate a journal owner from the journal itself. You have to use his/her profile. I find it annoying.

Emmanuel Deloget

Emmanuel Deloget

 

Wot ? I am Living ? Strange...

Apologies...
As you might have seen; I was quiet these last days. This is because I had some bad news (nothing awful... just a set of bad news). It killed my mind and I had to face a lot of migraines. This is not dangerous fro my life, so don't cry.

The problem is more that I was barely unable to think during these last days, so I didn't do my homework - to be fair, my day work also suffered from the situation.

Helas, no homework == no text RPG update. That's the sad thing. I need to hurry up.

Some work to do
Fortunately, I know where I want to go (that's something cool, since I don't have any functional specifications for the product).

There is two steps in this project: the first step is to design a correct (but not excellent) solution. As I already said in a previous post, the solution can be improved using other technologies - EDI and other already pointed scripted languages. The second step is to create an application that will use this design. In order to be a usefull tool, the application needs to be somewhat complex. Obviously, this is the case: I have to make a text based RPG, and these beasts are never simple.

I have some good news for you: the second step is nearly completed. Hopefully, I'll be able to give you a full text game in a few days.

But remember that this is not my goal. The real goal of the project is to give you some hints about how to design an application, not to deliver you a game. It means that I have something more important to deliver - and that's still a big ToDo.

Roadmap
finish the game code, with full comments: deadline on April the 16th
finish the BIIIIIIIIIIP: deadline on April the 30th
Then, you'll just have to send me some money (to my paypal account)
I may have some cool stuff for you during the few comming days.

Next project
I am already working on my next project, as some already knows. And this is super mega secret (well, not much. You might be able to find some clues about what I'm doing right now on these boards), so I won't talk about it, even if you try to torture me.

Emmanuel Deloget

Emmanuel Deloget

 

Beginning game programming

Disclaimer: this is full of typos and grammar errors. I don't have much time to correct these right now, so I guess I'm going to correct them later...

OK, you decided to pick up game programming (and maybe MMO programming), and you want an advice about what language / API / tools you should use. As always, the thread starts with a "is Blah Blah Diese Plus Plus language good enough for game programming ?" or "Can I redo Oblivion with Bum Bum API ?" and usually ends in a language or API war, with zaelots of both camps coming with nebulous and misleading arguments (such as "langage Yuk is widely used in the industry, so it's the best one one one lol", with an obligatory "you must give a try to Lisp/Haskell/brainf**k, it rocks!").

Don't let the others tell you what you want to learn.

There are a lot of programming languages, some of them are widely known and rather hard to understand, while some others are easier to pich up but less known. My goal is not to list them - just have a look to the gdnet forums, you'll hear about most of them in less than a day (C++, C#, python, C, (Lisp, Haskell, Brainf**k), some Basic flavor, and so on; oh, I forgot Java, and the classic HAV1).

In this post my goal is to help you to choose a language - and to put some rationale behind the choice. Then, i'll try to give some advices about API that you might use.

Choosing a language
This is tricky. If you never programmed anything, then it will be The Hard Part. Why? Because hey, you probably don't have a clue about how a program works! If you ask the question here, you'll get answere ranging from "learn C++" to "learn C++" (with "teh Fruny exception" - he'll say "learn Python", or something like that). These are, IMHO, bad advices, because these languages are way too complex for a beginner. C++ requires years to be mastered, uses concepts that are hard to grab (for example, pointers), and both C++ and python are using a programming paradigm2 which looks simple (object-oriented often look simple) but which is, in fact very difficult to understand.

I believe you should learn a interpreted procedural language.

Why ?

First, by using an procedural language you'll be able to spot the flow of your program - meaning that the language will allow you to think your program as a list of actions that will be executed one after one. It is easier to get a mental representation of such kind of behavior.

Second, using an interpreted language will allow you to debug your code easily - because you'll be able to modify/run your program more easily than a compiled program. You'll be able to progress by trial and error - trial and error is a good progression method, especially if it is backed by a good book.

Of course, you need a decent IDE3 - something that will allow you to think to your program and not to the magic that happens behind the scene. While none is simple enough to be understood in a couple if minutes by a newcomer, you'll be able to find some of them that are easier to manage.

The first tool I'd advocate is MS QBasic. Yes. It is old (it came with MS DOS 5.0), works in console mode, and looks odd. But BASIC flavors are easy to understand, and this one is a good one. The problem is that it is not distributed by MS anymore. Powerload may still have it, but the legality of this page is questionable.

Another (far less questionable) solution is to use lua. Lua is a cross plateform interpreter, so you'll be able to use it on yout *nix box (young padawan). You'll be able to find an IDE for Windows (and even a compiler - thus, when you'll be more confident with your skills, you'll be able to release softwares! [smile])

Finally, python can be used as a procedural language, despite the fact that it is an object oriented programming language. You can use the interactive interpreter rather easily, but it will still be less convenient than a full blown IDE.

If you don't find the IDE that suits your need, you are still able to use a text editor (for example, PSPad) and integrate the interpreter you want with this editor (will not be easy, but it can be done).

Now, you are ready to learn how to program.

I want to maek a leet game!
Now, you need to learn an API. But which one will you choose? There are just too many of them! Oh, wait, there is only 2 main API (OpenGL and DirectX), maybe 3 if you count the Win32 GDI, so the choice is not that difficult, right?

The short answer is no. In fact, you have more than 2 choices: you have plenty of them, because what you want to do is to use a graphic engine, not to use a graphic API.

If you are still in the learning process, trying to build your own engine is rather pointless. Of course, you may be able to do it, but it is a huge task and while you do it, you don't do your game! Moreover, I bet that you won't be able to finish your engine - because your design is bad, because coding it is boring, and so on. There are tons of reasons to not finish a graphic engine.

BTW, I often see the utterly pointless discussion entitled "should I use DX or OpenGL?". The answer is: use whatever you want - it is up to you to pick up what you think is better. The worst answer I ever heard (and I continue to ear it very often) is "use both; put the renderer in a DLL and load it at runtime". This is pure nonsense. Unless you are able to prove me that there is an absolute need for this, don't do this (and yes: only one renderer will work at a given time).

On the contrary, if you use a pre-made engine, you'll be able to do your game directly. It means that you'll be able to concentrate on the game design and on the gameplay, which is a rather good thing [smile].

Now, what engine should you use? Well, it depends on your knowledge and on your experience. A 3D engine requires some linear algebra knowledge. A 2D engine is far simpler, but is more limited (of course). Anyway, since you are supposed to be a beginner, I suggest that you stick to a 2D graphic engine for an important reason: 3D games tends to be bigger than 2D games in terms of content - which means that they are also bigger in terms of code to manage this content.

Conclusion
The most important thing to remember is to keep it simple (but not stupid). A simple language in a simple IDE, simple tools and simple libraries. Once you'll master these, you'll be able to puch forward and to learn new things - learning a new language is far easier if you already know one, despite what everybody will tell you, because you acquired the basic knowledge of what a program is and how it works.

The other important thing to remember is to be patient - John Carmack himself had to learn before he was able to do these highly technical games.

The last thing to remember is that the others advices won't replace experience. They can help, of course, and it is still a good idea to ask for advices.

I hope I was able to help you :)



(1) HAV is the acronym of "HTML And Variables". This is a Hockey MMORPG programming language, and most of us (including programming beasts like Fruny or Washu) are still unable to use it correctly, so I suggest you to forget this at this stage.

(2) Most languages comes with a programming paradigm - for example, C#, C++ or Java are supposed to be used as object-oriented programming languages, Lisp is a functional language and C is a procedural language. Anyway, the programming paradigm is rarely enforced by the language itself (you can do procedural programming with C# or object-oriented programming with C).

(3) Integrated Development Environment. An IDE typically let you type code in an editor and integrates the tools that will allow you to run and debug this code.

Emmanuel Deloget

Emmanuel Deloget

 

Clarifications and random thoughts

Notes about what I do
I have to explain some things about the text RPG thingy I'm doing right now. First, this is an exercise in software design, not a exercise in game programming. It means that the real goal of this stuff is to show how to decide what solution to use, not to show that I always use the best available solution. While I'm trying to develop a semi-realistic solution (the games rules are rather complex: some of the rules are actually inspired by the D20 system (skills, for instance)), it is obvious that this solution can't be used in a production evironment.

Of course, the right way to go should be to incorporate a scripting system into the game rule engine. This way, the engine will be very open.

I won't do this, for at least 3 reasons:
adding a scripting system only increase the number of solutions that might be choosen to answer a particular problem. It don't change how we need to think in order to answer this problem.
a scripting system may add some unneeded complexity into the game engine (object and function binding?)
in the end, I'll have to write scripting code, which is rather similar to non-scripting code. For teaching purpose, I'm going to stick to C++ :)
This is why i'm going to hardcode nearly everything. It means that each time you'll want to add a room to the game, or a new creature/npc, a new object then you'll have to build the game again.

Fortunately, I'm not (totally) dumb. Adding a scripting system (and changing some design solutions I took) will be the next step of this teaching session - once we'll have a working version of our text-based game :)

I still have a lot of ideas ;)

Rooms and Doors
Now, a (very) small update about the project itself: since we are going to handle rooms, I finally added the Sector classe: which represent a "room". I used this name because I'd wanted to add more than just rooms to the game: forests and their glades are pretty good setups too :) Sectors handle pairs of Path+Sector (using std::pair) to link themselves to some other sectors (the Path object can be NULL - they represent the condition to go from one sector to another one, and having no path does mean havin no restincting condition). For example, a Path can implement a secret door, a locked door - or a speaking door, if you really want to ;)

This is subject to change. I originally did this because I didn't want to introduce yet another cyclic dependency between Path and Room. using std::pair I break the dependency between Path and Sector (the dependency between Sector and Path still exists) and I allow myself to reuse a Path that don't have any intrisic data in another room. One of the consequence of this is that I am not able to say from which room the player comes - meaning that I can't create one-way doors using this system.

Another solution would be to reintroduce the cyclic dependency (the path knows to which sectors it belongs). I loose the possibility to reuse a path that don't have intrisic data (because now, all pathes have these intrisic datas) but I gain some other possibilities.

Another possibility is to introduce a base class for Sector. Sector inherit BaseSector, Path knows BaseSector, and Sector knows Path. The solution might be good, but it introduces a fake class (BaseSector) whose role is to be known by another class (Path). This design is rather artificial :/

Some pretty useless thoughts
A nation at war releases a lot of war-related games. Strangely enough, these games are supposed to be fun to play. I still don't see what makes war so fun.
I should stop irc. It eats too much time, and is not really good for productivity.
working with a terrible headache is really difficult
as I stated on irc yesterday evening, I'd like to work for a game company in UK - as a consultant. If you believe someone can be interested, please, drop me a word :)
See ya laters, dudz!!!11twelve

Emmanuel Deloget

Emmanuel Deloget

 

More fun with weapons and armors

The update is going to be short - I don't have much to say :)

Yesterday I added some basic races to the game system; I decided to give some equipement to these races, so I created a bunch of class to inherit InventoryObjectWeapon and InventoryObjectArmor.

The new weapons are: WeaponDagger, WeaponWoodStaff, WeaponShortSword, WeaponLongSword, WeaponWarAxe, WeaponWarHammer and WeaponSpear.

The new armors are: ArmorHelmet, ArmorTorso, ArmorArm, ArmorLeg and ArmorShield.

As you can see, nothing really - except that I only needed less than one hour to add these. This is not really a great achievement since there isn't a lot of code to write.

More interesting, I also added WeaponEnchanted and ArmorEnchanted.

I was facing a small problem: how to say that a weapon is enchanted? After all, if I add one weapon type to the game, I may have to write the same code to handle the enchanted version of the weapon. The other solution is to add an "enchanted" property to the weapon. But then what if I want to create ethereal weapons? Or fire-based weapons? Adding yet another property to the base weapon class is really not a ggood option.

Fortunately, design patters are going to help again - in particular the decorator design pattern.

WeaponEnchanted is a decorator. It modify the behavior of any other kind of weapon, allowing me to create a new kind of weapon on the fly (the same goes fro the ArmorEnchanted class). If I want to add another property to the weapon, I'll simply add another decorator to the class framework and that's it: instant enchanted ethereal weapon :)

See you later ;)

Emmanuel Deloget

Emmanuel Deloget

 

A bunch of creatures...

Yes, I know, I tend to multiupdate my journal these days.

First, thanks everyone for your support about this tiny RPG system project. I really hope you like it (after all, that's why I discuss this in my journal) and I hope you'll like the ending part much more - you know, the parts where I'm going to explain everything in details :)

I added a bunch of creature classes - it took me 30 minutes to do so (you can't believe how easy it is now [smile]).

CreatureRaceHuman: trivial - the typical human; good at everything (read: it has a bonus for each skill)
CreatureRaceDwarf: the dwarf (resistant).
CreatureRaceElven: the elven race (wise).
CreatureRaceZombi: people who look like Evolutional
CreatureRaceVampire: er.. vampires. You don't want to fight them right now.
CreatureRaceSkeletton: a skeletton warrior. It is pretty easy to defeat
CreatureRaceGiantRat: a giant rat
CreatureRaceGiantSpider: a giant spider (ouch)
CreatureRaceBrownBear: a bear that can really hurt you
CreatureRaceOrc: our beloved orc
These creature races inherit the existing CreatureRaceBase class, which holds the natural weapon as a InventoryObjectWeapon (all the creatures, even humans, have a natural weapon). This weapon is, in fact a NaturalWeapon instance which implements natural weapons using a template - enabling me to create different type of natural weapon without having to create a new class each time (the only thing that is different bewteen two natural weapon is their names and max damages).

As for now, the world namespace look like this:

[clicky for full resolution]



See you later!

Emmanuel Deloget

Emmanuel Deloget

 

Pink Martini On Tour

This is a very short entry about something that is not game coding related - but it's still damn cool.

I saw Pink Martini (official web) yesterday evening in Aix en Provence and it was really great. The show lasted only 1h30 but they sang their major titles (including their own version of Michael Kamen's Brazil) plus a new one - which was doubleplus good.

Emmanuel Deloget

Emmanuel Deloget

 

Let's do something else, now!

In the quest for our perfect RPG rule system, we are at a point where we can see it in action. It is now time to calm down, to let ideas come in again, and to do something else - we know that we'll have to come back later, since not everything had been implemented (magic? creature states?).

So far, here is what we've done:

[clicky for full resolution]



Now, let's implement the game itself (after all, that what we really want [smile]).

The game have to implement all the races, objects, creature behaviors and possible actions that will be used. I will limit myself to a bunch of creature races (human, orcs, elves and some other kind of monsters) and a small number of objects. Anyway, the framework is easily extended by new classes.

The classes I've already done are:
CreatureActionFactory: factory of creature action; we'll change this factory to handle the creation of actions (thus, we'll be able to handle the input/output system in the actions themselves, without modifying the game code itself)
CreatureBehaviorBase: inherit CreatureBehavior to embed an action factory
CreatureBehaviorPool: a pool of CreatureBahaviorBase
CreatureRacePool: a pool of CreatureRace
CreatureRaceBase: the base class of all our creatures; it implements the populateSkillList() method - hence, all our creatures will have the same skill list
CreatureRaceHuman: the first creature race - the human race:)

See ya later, dudz!

Emmanuel Deloget

Emmanuel Deloget

 

By the way...

This is a sequence diagram representing the main internal loop of the fight manager. I was unable to represent it correctly (how do I do these damn object creation and destruction?). Of course, this may be the UML 2.0 way of representing things - I'm not sure, but since I'm mainly stuck with UML 1.4 I can't really say that they do it wrong.


clicky to view a larger version



Emmanuel Deloget

Emmanuel Deloget

 

We create worlds ! Well, at least, we try...

Hey! I had some feedback about my singleton entry - not as much as I was expecting, but I still had some feedback :) Thanks a lot!

I finally decided how I'll present the results of my little "how to maek a 1337 RPG system" study. I'll write a very very long article about to explain the choices I made - how I made them and why they are good choices. After all, this is a software design course, not a programming course [smile].

Now, fight !
That's what I'm doing. I'm fighting against myself (and Ogre3D, but that's another project - let's forget this for the moment).

My main problem is about the fight manager - you remember, the FightManager class that implements a fight. It is rather tricky to implement it because I decided to implement a generic rule library that should not assume how it will be used. Of course, I must make some implementation choices that have an impact on the library interface but I can't enforce a particular game play choice. For instance, typical text games are often turn-based (at least during the fight management) while 3D games are often real-time.

This enourmous difference, of course, have a great impact on how things should be designed.

For example, in a 3D RPG, the player won't wait his turn in order to kick this horrible creature with his blade - the user will simply move the mouse and wait for the resultion of the action. It means that I have to provide a way to intriduce the user input into what's typically a loop (something like a "do { } while (somebody is still alive)").

Another example is how to deal with the output: in a text-based game, I'll write everything on the screen; in a 2D RPG, I'll se the actions of the NPCs - I'll see their weapon move and so on. As a consequence, I can't hardcode the result of an action - and, again, I have to tell the main engine what the results of the actions are.

Finally, the end condition of a specific fight may change. For example, the player's enemy might surrender, or the player may flee. I can't hardcode this too.

Design patterns to the rescue!
Again, design patters come to our rescue.

The first problem can be solved using an abstract factory. This abstract factory is influenced by the user input - for example, the factory can ask to the user what he wants to do and he will create the corresponding action.

This action is a strategy. Its role is to implement the algorithm that will impact the attacking creatature and the defending one. It will also be responsible for the UI reporting (display the action results).

The end condition problem is also correclty handled by using a strategy that will be responsible for the evaluation of the current fight state and that will tell us if we need to stop the fight.

Progress
I only added 2 classes to the project today:
Damage: this class handle the damage along with their type (fire, ice, poison, weapon, and so on).
Condition: this abstract class handles a condition - it defines a isTrue() virtual method.
It's cool, isn't it? [smile]

Update
I'm still playing with StarUML. There is two other small problems with the reverse engineering tool:
It adds the return type "void" to your model when your methods don't return anything (just because the method prototype is "void something()")
the associations are not good: they should be either compositions or aggregations, not just simple associations. Plus, the software can't handle the standard libary correctly (it should add the correct association type and change the multiplicity accordingly; instead of this, it just generates a std::vector variable in the class).
Plus, the interface to add a class then a method then some parameters is rather unproductive.

Emmanuel Deloget

Emmanuel Deloget

 

Text RPG update (post n100 in this journal!!11one)

Nothing much interesting. I was testing StarUML - the open source UML modeler - at work, so I decided to create a class diagram of the RPG rule system (read: what I've implemented so far).

Click on the image for full resolution.



The StarUML C++ reverse engineering tool is one of the best I ever used. The class diagram is rather easy to construct - but the window organisation of StarUML needs a big screen (this is not really a problem since you have a big screen, isn't it?).

I have to test the C++ code generation to see whether it can be used in a production environment.

Anyway, it's an impressive product!

Emmanuel Deloget

Emmanuel Deloget

 

Notes about singletons in C++

Wot! Did I stop to work on my text RPG? Que nenni. This is an article I prepared last year, when I was young and self confident about my own knowledge. Anyway I thought you could find this interesting (and don't forget to discuss about this in the comments. I tend to believe that I don't get anough comments - I'm pretty sure that it is because you find me boring and dull and stupid and... yes, I'm kidding).

Before reading anything else, you have to read another journal - [Washu]'s one. Last year, he wrote a 3 part entry about singletonisis, a (helas) common programmer illness. For information, references as added to my Small reference collection at the top of my journal.

As it seems very simple, the singleton pattern is a very popular pattern. Unfortunately, it is not simple, and the consequence of this is that most users don't use it correctly. The goal of this journal entry is to spot a number of common mistakes in singleton implementations and to correct them while explaining the pro and the cons of the pattern itself.

But since I target a midbie audience (those who have a decent knowledge of C++ but don't consider themselves as gurus), I believe I have to say something about the pattern itself: what exactly is a singleton?

The definition
To quote the [GoF], the intent of the singleton pattern is to "Ensure a class only has one instance, and provide a global point of access to it".

The first point is "ensure a class only has one instance", and the key word in this point is not "single" but "ensure". The first goal of a singleton is not to declare an instance of a class - a global variable would act the same - but to ensure that you won't be able to create more than one instance. This is quite different.

The second point is probably even more important: "provide a global point of access to it". Again, the key word is not "global" here, but "point of access". What does this mean? Simply that any access to the singleton is controlled, which in turn means that I can do whatever I want to protect the accesses to my singleton object. This is rather important, probably more important than the first point.

Are you sure you carefully read the definition above? If you still think that a singleton is no more than a convoluted global variable, please, return to the previous paragraph and reread it until you fully understand it. This is really important, because the rest is only an implementation problem.

Studying common implementations
I did a fast survey on how you, gdnet users, implemented your singleton. There are some good ones, some less good ones, and some bad ones. First, let's see the bad ones.

Construction and destruction, the basics
The following (slightly modified) code has been borrowed from an gdnet thread
template ISingleton : public BaseClass
{
static BaseClass *mInstance;
public:
ISingleton() { ... }
virtual ~ISingleton() { ... }

static BaseClass* instance() { ... }
};

There are at least 2 major errors in this design, so let's spot them.

First, nothing forbids me to do :
MyBaseClass myVariable;
And one of the singleton intent is completely defeated by this single line. I get the same result if I write
ISingleton myVariable;
What is the problem here? The answer is simple: public constructor. When I have a public constructor in class A, nothing can forbid me to create any number of instances of A.

Next point: what will happen if I write
delete ISingleton::instance();
The code compiles just fine, bu of course any subsequent use of the singleton will crash the program. Again, this is due to another public member: the destructor, this time.

Construction and destruction, a no-no
I only saw this code once on gdnet, and I can't remember where I found it. The only thing I remember is a great black hole and then nothing. I believed I was in Hell.
Let's see the Horror in action (I heavily modified the code so that the OP will not be able to recognize it - I don't want him to kill me).
class Singleton
{
static Singleton * mInstance;
public:
Singleton() { mInstance = new Singleton(); }
~Singleton() { delete mInstance; }
static Singleton *instance() { return mInstance; }
};
Do you understand me? Here, I have the same problem as before, and even worse, because I modify the singleton when I instantiate it. But the worse is probably the recursive call in the constructor.
How do this singleton works? It doesn't work at all, and I suspect the OP to have written this on the board without testing. Let's examine how it should work then.
When I call Singleton::instance(), I get the static member mInstance, which is not initialised yet, because no instance of Singleton has been created. So let's create one:
Singleton singleton;
Yeah. Now, the instance is created and it creates the mInstance. And this instance creation is cool, because it creates a third instance. And then a fourth, and so on. Double yeah, this code is recursive and never-ending.
Let's correct the problem by adding guards then:
class Singleton
{
static Singleton * mInstance;
public:
Singleton() { if (!mInstance) mInstance = new Singleton(); }
~Singleton() { delete mInstance; }
static Singleton *instance() { return mInstance; }
}
Ok, we get rid of the recursivity. We still have a problem: to create the singleton instance, we need to instantiate the singleton. Sounds quite illogical since we want to have only once instance at at time. It is even worse: the destructor deletes my instance, so if I want this instance to last until the program death, I have to set up a global variable. You said it: OMG!

What is the problem here? Again, it is a constructor/destructor problem. None of them should play a role in the static instance creation, because it leads to at least one level of recursivity, meaning that I'll need to create an instance of a singleton to init my singleton's instance - and I'll have two singletons then.

Singleton, the Ogre 3D approach
One thing that bugs me with this otherwise wonderfull 3d engine is the singleton management. To create the Ogre::Root object, you must instantiate it using the new operator. Once you've done this, you are able to use it as a singleton.

// init
m_pOgreRoot = new Ogre::Root(szPlugins, szConfig, szLog);
// this call will crash if the Root object hasn't been created yet
Ogre::Root::getSingleton().doSomething();
// at the end of the software wa are allowed to delete the ogre singleton!
delete m_pOgreRoot;
IMHO, a better approch would have been to do an initialization function
// init
Ogre::Root::getSingleton().init(... param list...);
// this call won't crash, but doSomething() can throw an exception if
// something should have been initialized before
Ogre::Root::getSingleton().doSomething();
// to explicitely destroy the singleton, I need another method
// -- this is rather bad, since it may be called at any time and might
// -- do rather bad things in the end
Ogre::Root::destroySingleton();
This allow the singleton to be always valid - which is, I think, far better and less error prone.

A better approach
Let's write the code
class Singleton
{
static Singleton *mInstance;
Singleton() { }
~Singleton() { }
public:
static Singleton *instance() { ... }
};
What is the problem of such code? It seems good enough.
Well, not exactly. I can still play with it:
Singleton mySingleton(*Singleton::instance());
What did I do here? I created a copy of my singleton. What will the compiler say? Nothing. If you don't provide a copy constructor, it will provide a default one for you. Quite cool, isn't it?
Again, I have two instances of my singleton, which is obviously not a good thing.

The beginning of a solution
The last piece of code was rather good, expect for the copy constructor problem, but this problem is easily solved by adding a non-default private copy constructor:
class Singleton
{
static Singleton *mInstance;
Singleton() { }
Singleton(const Singleton& s) { }
Singleton& operator=(const Singleton& s) { return *this; }
~Singleton() { }
public:
static Singleton *instance()
{
if (!mInstance)
{
mInstance = new Singleton();
}
return mInstance;
}
};
Let's try to summarize the strength of this implementation:

we cannot create an instance of the singleton using the default constructor, because it is private.
we cannot create a copy of a singleton instance
we cannot destroy the singleton out of he singleton class because its destructor is also private
since we defined the copy constructor, we also define the operator=() - this is commonly refered as a good practice

The first two points make it clear than I cannot create more than one instance of my singleton object - thus the 'single instance' intent is really enforced. The third point avoids me to accidentally destroy my singleton instance - which is rather cool.

There is still at least one problem in this simple implementation: I have no way to control the lifetime of my singleton, mostly because I don't know when I should destroy it (moreover, I forbid myself to destroy it from the outside of the class, so I just can't delete it when I decide I'll no longer use it).

On singleton lifetime, the first approach
A common mistake I often saw of these boards is to use the following:
class Singleton
{
static Singleton mInstance;
Singleton() { }
Singleton(const Singleton& s) { }
~Singleton() { }
public:
static Singleton *instance()
{
return &mInstance;
}
};
It seems to resolve the life time problem - the singleton will de destroyed at the end of the program.
Actually, this solution is worse than the previous code, because you can't know if the singleton is created if you try to use it before main() is called (for example, in the constructor of another singleton). Singleton::instance() can return a pointer to invalid memory, and your program will crash.

On singleton lifetime, Meyers' approach
Another solution is to use what is called Meyers singleton - first expressed in [SM-2] IIRC (the third edition of [SM-1] also uses it).
class Singleton
{
Singleton() { }
Singleton(const Singleton& s) { }
~Singleton() { }
public:
static Singleton *instance()
{
static Singleton theInstance;
return &theInstance;
}
};
This code ensure that the singleton will be created when it is needed (because the C++ standard tell us that a static variable in a function is created the first time you enter in the function. Since it is a static instance, and not an allocated one, it will be destroyed at the end of the program. It seems good now - we have our final candidate!

Well, not exactly. There is still an embarrassing problem here, because of the order of destruction of static instances. The standard says they are destroyed in the inverse order of their creation - it means that if a static instance of A uses my singleton in its constructor, then my singleton will be destroyed before my instance of A. What if A destructor tries to use the singleton? Again, I'll crash my program.

The real solution is...
...nothing. There is no real solution to this problem. Meyers singleton is quite good, but has still some drawbacks. It can be extended - because it is rather easy to know if the instance of your singleton is still valid or not (monitor your singleton destructor) but once you detect it, it becomes tricky. If the singleton holds some important resources, they are probably destroyed too, and maybe you don't have any way to recreate them. If it is not the case, you can try to recreate the singleton - it is possible, using placement new.

Templated singletons
A templated singleton has to obey to every rule I described in the comments above, and these rules also apply to the client class (the template parameter). Moreover, the client class have to declare the singleton template class as friend because there is no other way to gain access to the constructor of the client class. Some of you might object that it is possible to set the constructors and destructors as protected (and since our singleton template class inherit the base class, it automatically gains access to the methods he needs). While this is a possible solution, it is not technically viable: what does forbid me to inherit a dumb class from the base class in order to bypass the singleton limitations?

There is at least one more problem with templated singleton:

the client class construction is limited to a very simple construction - either the default one or a particular one that have to be the same or each declared singleton.
to avoid this problem, you have to declare a construction policy - but then is creates another problem: there is no other way to declare the creation policy but to declare it as a template parameter, because feeding the instance() method with a function pointer is not an acceptable solution. Since it is a template parameter, it means that the singleton type you declare is dependant upon this policy, i.e. if you change the policy, you change the singleton type. Unfortunately, static members are common to every instances of a particular class. In our case, it means that we can create two singleton ot type MyType by changing the creation policy. This is weird.

[AA-1] gives an in-depth explaination of a templated singleton class that can be extended using policies - I suggest you to read it if you plan to implement this.

Using the singleton pattern
As you already know, this pattern should not be used instead of a global variable - mostly because you should not have any global variable. Again, the [GoF] tells us what is the applicability of the singleton pattern:

I think I have to put the emphasis on the second part of the first point: and it must be accessible to clients from a well-known access point. Using the singleton pattern just because you believe that only one instance of a particular object is needed is called lazyness (the first symptom of singletonisis). But if you need to control the access of this object then yes (for example, only calls from a particular thread can succeed), you just found a good singleton candidate.
You found it by yourself, singleton are rare, very rare. Fortunately, it is still possible to find good examples: a multi-threaded pool-based memory manager might be one of them (the fact that you are working in a multi-threaded environment force you to protect the memory manager access). [AA-1] cites some other possible uses of the singleton pattern, but some of these are questionable IMHO.

Avoiding the singleton pattern
As you might see from this entry, it is rather hard to implement a correct singleton. It is even harder to know when to use it. As a consequence, it should be nice to avoid it whenever possible. Of course, the singleton offers nice opportunities, and its rather cool to announce in a meeting "let's use the singleton pattern" (I did it several time just to see my coworkers' faces). But let's face it: it is difficult to use. How to avoid using it then? [Washu] gives a very good answer to this question: refactor!

Conclusion
There are still numerous issues with the singleton pattern that hasn't been addressed here. For example, is you singleton thread safe or do you need to protect its use? This question and similar ones are not the purpose of this journal entry. Moreover, there are some more complete resources about singletons - the best one I ever read is in [AA-1] - I suggest you to read it if you want to learn more about singleton and a lot of other subjects. In particular, [AA-1] address the problem of Meyer's singleton destruction in an elegant way, using the so-called phoenix singleton. It also deals with a lot of other implementation issues.

I tried to give you some solution to create a correct singleton. But correct is by no mean a synonym for perfect, and you can sill abuse the C++ syntax to do bad things with singleton.

Thou are warned :)

Emmanuel Deloget

Emmanuel Deloget

 

I continue...

Let's add another 2 hours on the project - two hours and not much code, because I was unable to correctly think.

The new classes in the project are:
FightModifier: this class contains informations about the fight modifiers (selected weapon, attack, defense) of a creature. It contains only temporary datas, since they can be invalidated at any moment. As a consequence, FightModifier is populated only when the creature attacks or defends itself.
FightModifierPopulator: well, I already told you that I found a job for the InventoryVisitor class, and here it is. FightModifierPopulator inherits InventoryVisitor and implements two visit() method: one for the InventoryObjectWeapon and another one for the InventoryObjectArmor. The informations it gets is then used to populate the creature's FightModifier instance.
CreatureHolder: remember the CreatureGroup class? It was handling a group of creature. Now, it handles a group of CreatureHolder, an object that bind a creature to a creature behavior. The CreatureGroup class doesn't change much (the interface now use CreatureHolder instead of Creature, but that's not really a big problem).
CreatureBehavior: this abstract class implements the behavior of a creature - ie its intelligence. It is a pure IA based stuff, but it is still very important. For instance, I can't fight if I don't know how the AI-controlled creature will act during the fight - maybe they'll attack, maybe they'll launch a spell or drink a potion, I don't know. Giving this kind of information is the role of the CreatureBehavior class.
CreatureAction: CreatureAction instances are strategies that implemente the creatures actions - fight, drink potion, and so on. The implementation of these action is application defined (and probably depends on the game core)

Only a couple a classes, as you see. I've been slow for a stupid reason: I wasn't able to think to put the CreatureBehavior instance outside the Creature class. The problem is that the CreatureBehavior manage actions, and those actions needs to know the Creature class - the implied circular dependency was rather stupid, and I wanted to get rid of it before coding. And then I went in my kitchen and got a drink (fresh water). The light came: the creature doesn't care about its behavior. As a consequence, I can remove the CreatureBehavior from my Creature class and tada, the circular dependency disapear.

And I was very slow at figuring this. My bad.

So far, I've implemented 33 classes, spaning over 51 files representing 51,3 KB and containing 1433 lines of code. That's pretty... weak. Yesterday, I had to deal with a file written by a contractor some yaers ago, and the constructor of the class was 1950 lines long - insane programmers, who open files, show message boxes, asserts everywhere in a constructor but never throw any exception.

Anyway, I have to goto bed now. I'm tired :)

Emmanuel Deloget

Emmanuel Deloget

 

Text RPG rul3z teh big one one one

So far, I've worked about 5/6 hours on the project. The classes I've added today are the following:

ActionTest: this abstract class is used to test if a a particular creature successfully act or not. Here, we make use of the strategy pattern: the algorithm to know wether an action is successful or not is defined by the concrete action. I'va added these needed action tests:

ActionTestSkill will make a skill roll
ActionTestBody will roll an aptitude (body1)
ActionTestMind will roll an aptitude (mind1)
InventoryObjectEquipable: all the equipable objects of the inventory inherits from this base class. It inherits from InventoryObject and is still an abstract class. By the way, I also defined some other inventory object classes:

InventoryObjectMoney which inherit InventoryObject holds a money count.
InventoryObjectWeapon: you guessed it
InventoryObjectArmor: you guessed it too (you are rather clever [smile])
I still need to define some other inventory object types, but these are the most important for the combat system.
OppositionTest I've done the action test, and I also did the oppossition test management - where two creatures confront eeach other. Again, the class is abstract - the plan is to apply the strategy pattern here. So far, I've done some useful derived classes:

OppositionTestSkill: do you want to bargain with an NPC merchant?
OppositeTestBody: arm wresting anyone?
OppositeTestMind: will you resists to the fear aura of this powerfull living dead?
last (currently made) but not least: OppositeTestFight: this one is the base of the fighting system. It does special rolls, modified by the creatures equiped armor and weapons. The combat is mainly resolved using this specilized opposite test.

Speaking of the combat, it may be time to do it now, what do you think?

As for now, the fighting system is pretty evolved. Considering the amount of work I have to do, I wonder if I'm going to be able to get it right the first time.
create the fighting creature list. The player can have allies, and he may fight more than one creature at a time.
sort the creature list (this is an optionnal step, but it can be funny to do some kind of initiative check before the fight)
begin the fight round
for each creature which is not the player
choose action (based on the inventory and on the creature behavior
if action == fight, choose an opponent
resolve action for the player, we have to ask what he wants to do and process his action too
if any creature is dead, remove it from the fighters lists - if the killer is the player, he wins some experience points
repeat until the player or all its ennemies are dead
As you can see, there are some hard parts to implement: how the AI controlled creatures will choose what they want to do or their opponent, how to do the action resolution (if it is a fight, nothing to say; but what about launching a spell, drinking a healing potion or equiping another weapon?)

When I began to think about this project, I thought about implementing a very simple game system (without skills, without those pesky action and opposition tests, and most notably with a very limited fight system - 1 vs 1). I must admit that it was pretty poor, so I've decided to make a correct oen (not very complex but still: it might offer some great gameplay opportunities). Because of this, I decided to cut the most complex feature; the user undo - it is really complex (saving the whole game state?!?!) and doesn't bring anything to the game.

As you can see, I made some cool progress, but I have to handle one of the the hardest part right now. Of course, there is another one comming: the magic system.

I guess I'll have some good time (and comments are welcome, as allways) [smile]


1: hu hu hu. You want to know the games rules, don't you ? [smile]

Emmanuel Deloget

Emmanuel Deloget

 

Again, a small update

I'm going to do a lot of small updates every time I need it (to speak about the progress I make everyday). I hadn't much time to work on the source code today, so I only did one important class: the CreatureGroup - believe it or not, it handles a group of creature. The class is meant to be used in teh combat system, but since it has a visit() method it can be used for various purpose.

There are a few things I'd want to say about this class. First, it is heavily commented - very heavily. For example, this is the code of the visit() method:

// visit all the creatures; this is again a use of the
// visitor pattern, but this one is slightly different since
// there is only one creature type (ie we don't have any
// difference between a human player and a dragon NPC).
bool CreatureGroup::visit(CreatureVisitor& visitor)
{
for (size_t i=0; iif (!visitor.visit(mCreatures)) {
return false;
}
}
return true;
}
As you can see, while I just taled about the visit() method and despite the name of the CreatureVisitor class, I make clear that I don't apply the real visitor pattern here - mostly because I don't really need it (and remember that I target simplicity).

Second, in this class I decided to introduce the notion of functor and template method. For example, the creatures in the CreatureGroup can be ordered - I provided a sort() method that takes a ORDERER template paramater:

// order creatures depending on a parameter functor
// ORDERER must overload operator(); you can pass
// one of the ordering functor defined before
template class ORDERER> void sort(ORDERER orderer)
{
// since it is a template function, I have to define it as an
// inline function
std::sort(mCreatures.begin(), mCreatures.end(), orderer);
}

The notion of template is loosely introduced (I should rewrite the comments) and the notion of functor is explained in detail in the header file.

I'd also like to talk about the visitor pattern. Yesterday (I believe it was yesterday), I told you that the visitor pattern breaks the OCP rather violently. It also introduces another problem in terms of OO design: a cyclic dependency.

The visitor have to know the concrete class it must visit, and the concrete class have to know the visitor. This is what I'd call tight coupling.

It seems that the visitor patter, while solving a very difficult problem, exhibits some specific difficulties itself.

This is the primary reason why I implemented a pseudo-visitor in the CreatureGroup class (the other was: I don't really need a full blown visitor).

Next to do: the combat system and the action resolution system. The combat system is pretty evolved. I must handle the player and the AI controlled creatures (both the friendish ones and the other ones). I must let the player decide what he is going to do (rather simple: attack, defend, launch a spell, use an object or flee) and I must choose the actions of the different AI-controlled creatures (their behavior is given by the creature race or by a specific behavior object, I don't know yet) I must also decide who gains the initiative and who attack who. Then I must process everything, roll the attacks, compute the damages and so on (I found a job for the InventoryVisitor: find what is the current creature weapons and armors).

Of course, the combat system itself is very simple (I throw a dice to attack, you throw a dice to defend, if mine is greater than yours then I hit you); there are some little quirks but most of them are already implemented.

Now that I explain it, it seems rather complex [smile]

See you later, dudz !

Emmanuel Deloget

Emmanuel Deloget

 

Small update about the text RPG project state

This is a small update. I hadn't much time to work on the Text RPG project (mostly because I had a lot of stuff to do this week-end), but I have still done something.

To those who are reading this to learn something, I must say that I'm going rather quick here, withour explainations - they will come later, be patient :)

So far, I've created the following classes:

Attribute: handle the creature attributes.
Skill: handle the creature skills. The creatures skills reference an attribute.
Inventory: the creature inventory. It contanis a list of...
InventoryObject: guess what ? Yes, it is. The creature inventory is full of InventoryObject. This is the base class of all the other objects (weapons, armors, keys, money, and so on)
InventoryVisitor: this is an application of the visitor pattern.
CreatureRace: abstract class that gives informations about the creature race (its capabilities, its sub-type, the standard skill and attributes values, the racial skill and attributes modifiers, and so on). It is easy to inherit (a lot of small functions to write) so creating new races is really fun :)
and of course Creature: this is the creature holder class. Any character or monster in the game is a Creature instance (the difference comes from the race and the class [not implemented yet]).
some small utility classes: Dice is a template class that emulates a dice and Dicebag is only used to shuffle the dices (ie seed the randomizer [smile]).


There is something bad with the visitor pattern. It somewhat breaks the open-closed principle (see [RM-1]) because if I add a new InventoryObject type, I need to add a new method in the InventoryVisitor class. Oh, wait. I just had a look to my GoF and found that this is point 3 of the consequences section for the visitor pattern:



I choose the exception rather than the rule and my visitor class is not abstract (the methods does nothing). This is not a problem for me, because in the game system most visitors will only overload one of the base class method (a key is not a weapon, and you can't use your helmet as a spell). But still, I'll have to modify the base visitor class each time I'll want to add a new object type.

As you see, there is not a lot of code (roughly 18 kB, and there is a lot of comments). Nevertheless the game system code is nearly complete (I have a bunch of InventoryObject inherited classes to write, some InventoryVisitor, as well as the action and combat resolution).

If everything goes well, I'll have some time to work on this subject before the end of the week :)

See you later, dudz !

Emmanuel Deloget

Emmanuel Deloget

 

What a good idea...

I've just got an idea, something not very complex (it may need nearly one or two days of work). I noticed that there are a lot of questions on the beginner's forum where new users claim that they want to make text-based games - RGP style, full with rooms, actions, monsters and so on.

So, why not doing one ? After all, it is not very complex, and is a good design excercise (especially if you want to make it in order to teach something to C++ newcomers).

So let's see what are our needs

room display - display informations about the room; the information may change, based on past user actions (for example, a monster can be killed)
user input should be carefully handled - I don't want the user to type things that will crash the game, and I want the system to be fairly simple (the action set is fixed by room)
the game model should not be dependant on the console to work (hey, I have preached the MVC in games paradigm for at least one year, and I would make a game that ignore it?).
room description should be read from a file (the main question is: do I need one file or one file by room ?)
there is some kind of RPG combat that will need some kind of RPG rules. It is not a real problem, it is just... complex :) Anyway, I prepared a complete article about developing a RPG system (actually, it was about using design principles and design patterns, the RPG system was only to make the article game-oriented; unfortunately, I never finished it [sad]) , so I know the problem rather well.
there should be some particuler actions - jump over a pit, for example, may require a special test.
there should be monsters, treasures, hidden treasures and secret rooms. Ah ah ah ah! And maybe a beautiful princess. Unfortunately, it can't be naked - for obvious reasons.
no need for scripting - I'd want to keep everything simple; as a consequence, the game logic will be entirelly hard coded.
the user shall be able to load and save his progression.
the user may undo one operation. Ok, I understand that it is rather powerfull, but when you are killed because of a poisonous trap in the very last room, it can be... well, you know.
last but not least I should earn at least 20.000.000 bucks with this game. Or I may distribute it for free, with the source code. I don't know...


Of course, there are a lot of other needs (I guess I'd speak about them in subsequent journal entries).

Be prepared to suffer some boring entries about software design again :)

Emmanuel Deloget

Emmanuel Deloget

 

"Somewhat type-safe " enums in C++

I don't know why I want to write this down, since it is a not-that-good solution to a known problem. Anyway, let's begin.

As you all know, C++ enumerations are not type safe. Let's have a look to a simple example:

enum Values
{
value0, value1, value2, value3, value4
};

Values myValue;

// .. later in the code ...
myValue = 100;

your compiler may issue a warning, but this code is still legal from a C++ standard point of view. The problem is that 100 is not a value of the enumeration.

As a consequence, I can't be sure that when I'll use myEnum its value will be one of the values I added to the enumeration - and guess what - this is a Bad Thing.

The solution I use is pretty simple: I encapsulate the enumeration in a class:

class Values
{
public:
enum Enum { value0, value1, value2, value3, value4 };
private:
Enum mInternal;
public:
Values() : mInternal(value0) { }
Values(const Enum& v) : mInternal(v) { }
Values(const Values& v) : mInternal(v.mInternal) { }
Values& operator=(const Values& v) { mInternal = v.mInternal; return *this; }
bool operator==(const Values& v) { return mInternal == v.mInternal; }
bool operator!=(const Values& v) { return mInternal != v.mInternal; }
Enum get() const { return mInternal; }
};

Now, I can write this code

Values v1(1); // -- ERROR !
Values v2(Values::value0); // valid
Values v3;
Values v4;
v3 = 1; // -- ERROR
v4 = Values::value0; // valid
if (v1 == 1) { } // -- ERROR
if (v2 == Values::value1) { } // valid

Of course, I am still able to setup a Values with an int - since there is no automatic cast, I will need an explicit cast

v1 = (Values::Enum)(1); // valid

The get() method is provided because there is no automatic conversion from the class to int - such conversion would break the == and != operators (because the compiler would try to convert my Values to an int when I write "v1 == 1"). Nevertheless, it can be useful to get the real enum value - for example:

switch (v1) // -- ERROR
{
// ...
}

switch (v1.get()) // valid
{
// ...
}


Cons
... Not much? Oh: you have to write the class. It takes more time than just writing the enum :)

Pros
A lot:
type-safetty (even if it is not total) is better than no type safety
this type-safety is hidden, since most of the usage of the variable won't change
since everything is inlined, the use of this class costs nothing
the explicit cast (to throw an int into the value) is more readable and less error prone than an implicit cast
writing Values::value0 is more readable than value0 alone
I can enrich the class to do a lot of things.


There are probably a lot of other advantages to this method - that's why I use it :)

Emmanuel Deloget

Emmanuel Deloget

 

Helping beginners is so kweeeeeel !

Hey ! First update in many weeks !

I just want to say that Lazy Foo's SDL tutorials are really good for beginners. They are very simple, short, progressive, and they work. Kudos to Lazy Foo for these.

It even made me change my sig. I guess that every week or so, I'll put a new web site that target beginners as a link in my sig .

Software Design
It seems that this is what I mostly do these day on these boards. Really, I like it. Actually, I like object oriented software design (this is an evolution: I used to love coding but and I continue to to love it, but software design is so great that I tend to prefer design to code).

The last one was about the design of a game state manager (here) and I believe there's some good ideas in this design.

I won't speak of the subject itself (you are probably clever enough to be able to click on the link above) but the way of thinking that is behind.

First, I tend to encourage closed design. This is the reason why I did the GameStateManager this way: it is generic and don't have to be modified to adapt ato a new situation. The Game object itself may also be generic if we feed it with an abstract factory that will be responsible for creating the different game states. Again, this is a closed design (you don't have to modify the game object in order to modify the behavior of the game). The only things that will need some modifications are the game states and the game state abstract factory. Both inherit existing classes (GameStateFactory and GameState). I don't need to modify these, since I can extend them using inheritance.

2nd point: I tend to encourage the use of design patterns. Inheritance is a key feature for some design patterns - for example, our GameState class is a policy (a multi-policy in fact). The behavior of the object do not depends upon its base interface.

Conclusion: this is an exemple of using the open-closed principle (as well as an exemple of how abstract factories and the policy pattern can be useful).

This conclusion is also true when I reread my answer to Nitage's question. Again, the main goal is to provide solution that won't need to modify anything (adding a new tool don't change the Terrain class) but that will still let the programmer whatever he wants. This time, I achieved the goal by using the policy pattern (for tools) and the (powerfull) iterator paradigm. Moreover, we also dissociated the tool class from the terrain class (the tool class and the terrain class both depends upon the iterator class, which is an abstraction that can be rather... abstract).

Really, I like software design.

Of course, I have to take care of one important thing: it seems that I'm getting prouder and prouder... Oh, well, I guess that someone will remind me what "humble" means [smile]

Emmanuel Deloget

Emmanuel Deloget

 

Tidbits

Nothing really fancy to say, so let's try to enhance our culture...

Christmas is comming, so I allowed me to give some presents to myself (good boy, isn't he?).

Vitalic's Ok Cowboy: this is a really good piece of techno, whith very big titles (Poney Part 1, No Fun or the slower Trahison)
I decided to give a try to Francois Ozon, a French movie maker. I went to the theater and saw Le Temps qui Reste, the story of a man who knows he's going to die from a cancer.
I bought some books by Isaac Asimov and Roger Zelazny, because I love reading them ;)
I also bought some comics and mangas: the 5 first tomes of Hisashi Sakaguchi's Ikkyu, Tessa, Agent Intergalactique [FR], t11 to 13 of Samura's Blade of the Immortal (L'Habitant de l'Infini is the French title)

I also bought some other CD (Paris Combo live, Gotan Project's Inspiracion Espiracion, and Pink Martini's Hang On Little Tomato).

Now, I really need some money.

Emmanuel Deloget

Emmanuel Deloget

 

Yeah !

I'm happy.

My gdnet+ membership had been renewed for another year. I'll still be there and there until (at least) dec 2006. Prepare for another year of

(not funny) humor
(not very accurate) technical rambling
(not very accurate) C++
newbies bashers bashing
falling in love with caitlin each time she posts a new photo
(dull) posts
(irrelevant) PMs
bad English and French words


Maybe I'll have time to

learn C#
learn how to program
learn why I want to program
learn C++ (would help)
learn more English and French words
get rich
rul3 teh wArld!!!111


I also have tons of projets, maybe I'll try to get some help from you in a near futur [smile]

Emmanuel Deloget

Emmanuel Deloget

 

Insignificant journal entry

I've been busy these days, and my forum activity dropped down. Nevertheless, I managed to get 1 post per rating point, as seen here:



The cool thing about this is that there is no interest at all in this post. Crazy, isn't it?

Emmanuel Deloget

Emmanuel Deloget

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!