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

About this blog

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

Entries in this blog

 

The Return of the Giant Mummy: Revenge of the Unde

I write this while my gf is sleeping. There is something I still don't understand concerning my relation with computers. I mean, she's a girl, so she is probably more interesting than my notebook. But I continue to speak to my notebook (you know, the one with a sux0rz kebord).

Lack of updates
I told you, I was ill. I can't sort ideas when I'm ill. So I didn't write anything here during that time. But now, I'm fine.

I just remember that you don't bother with this kind of information.

A poor graphic driver in a poor graphic engine
This is probably the central part of the graphic engine. On Jan-26 we saw that our graphic engine tells the graphic elements to draw themselves. To be able to do this, they need to use a graphic device driver (let's call him the graphic driver) which is able to handle low level resources.

Now, who does instanciate the graphic driver? As I see it there is two possibilities.

First, as it name implies, the driver can be viewed as a system resource. Therefore, it should be created by the system framework (just as the display and the input objects). This sound rather logical but if we dig further then the problems are coming. For example, the driver will probably need to expose some resource creation methods - and these resources looks like graphic objects. Therefore the graphic driver should know what is a graphic object - and therefore it should know some part of the graphic engine. Which is plain stupid since it adds a circular reference in our design.

The second solution avoid this problem: the graphic driver, although it seems to be a system object, is considered as a graphic engine entity. The graphic engine is responsible for its creation. The problem we now have is that the graphic engine now relies on a system object. But is this really a problem? Let's see the biggest impact of this solution: it makes the graphic engine dependant on the platform, which is not what we want. We are lukcy, because this dependance can be avoided using a clever directory structure (a la Loki). But this is an implementation trick and we should not speak about these now.

Inside or outside?
Each possible design seems to be the complete contrary of the other. Actually they are, because they are using a diferent paradigm. One tells the graphic engine: "hey, you should use this driver", while the other tells "the graphic engine is using this driver".

Our main issue is that it seems that none of the proposed solution is acceptable.

Well, this is not really true.

Let's consider our first solution. I told you that the graphic driver resources are graphic objects. Indeed they are: it sound weird to not consider a texture (for example) as a graphic object. But we can view the problem using another point of view: "I am the graphic driver, I'm a system object, so why don't you consider the resource I create as system objects?". After all, this is equally true. For example, a DX texture holds a reference to the underlying IDirect3DTexture9 object, which may be considered as a system object if we consider IDirect3DDevice9 as a system object too. Using this point of view we don't need the dependencie over the graphic engine anymore - basically: we solve our problem.

Now, let's have a look to the second solution. The engine creates the driver - and therefore the code of the driver is inside the engine itself. This does not allow us to transparently plug another driver - because only one driver is known. Is i a problem? To answer the question, let's ask another one: why do we want to plug another driver into the system?

I am hearing your answers: "because maybe there is a more efficient driver". Then we should use it and discard the first one. "But maybe it would be good to support multiple platform". You mean: at the same time? No matter what your answer is, you'll be able to find arguments who defeat the purpose of supporting multiple drivers at a design level. Of course, when it comes to implementation, maybe we'll create more than one driver. But the key word in the later sentence is implementation. And the answer to this problem had been written some paragraphs ago: Loki does it, so why don't we use a clever directory structure? A single compilation flag will enable us to produce a program which will use one of the 88 driver we wrote. We can even create a driver which is in fact a driver loader - which will load a particular driver at run time.

So both are good
Yes (well, as of today, it seems that both solutions are acceptable. Remember a design is an itrative process. Maybe we'll ffind another problem concerning one of these solutions).

You may ask: "why do you say that? Now we don't know which model to choose!".

There is one important thing about design that I didn't said already. There is more than one correct design. This sound obvious but is often forgotten. When we design, we often try to do our best. Sometimes, we have to choose between two or more solutions. When one is obviously better, hen we have to choose it. But when they are equally good (or, since it may happen sometimes) equally bad, where is the problem then?

Rule of thumb: don't create problem where there is no problem :)

And the winner is...
I won't tell you who wins :) Since you already knows that the two solution are correct, the one I pick is only a matter of taste - and I must encourage you to develop your own taste ;)

Anyway the result is there: now, we have a graphic object to manage. Wether it has been created by the engine or given by the system is not really our problem, since it does not change the representation.


class AbstractGraphicElement
{
public:
virtual draw(GraphicDriver gdrv);
};

class GraphicEngine
{
GraphicDriver gdrv;
public:
init();
uninit();
draw(AbstractGraphicElement gel) { gel.draw(gdrv) }
};


Next point?
Now it begins to be easier. We know the fundamental objects and how they interact. Now we probably have to think about the details...

We have still another big point to consider: my explaination off the game MVC was rather short. We need to complete it in order to have a decent view of what is the system, the game, tthe ame engine and so on.

Anyway, good night, and I hate Hulk.

Emmanuel Deloget

Emmanuel Deloget

 

Warning: you just got a brain cancer.

About init() and uninit()
First, I feel I have to justify the name. As TANSTAAFL pointed out in a previous post, init() and uninit() are really poor names. As a programmer, I perfer create() and destroy() to them. Anyway, I'll stick with these names until we hit the implementation for two reasons:
although they are poor and not very descriptive, their meaning is clear enough to fulfill our needs for the time being.
I have to bear the burden of my previous mistakes... :)

What do these function do? The second one is easy : uninit() will do the exact contrary of init(). Now we cannot define init() as a function that does the exact contrary of uninit() anymore so we'll have to find a better answer.

What does it need to do? It has to make sure that the graphic subsystem is correctly initialized. If it is not, then it must return an error. It must also ensure that we are now able to draw what we want to draw - this phase is a special part of the setup phase: you initialize the underlying rendering state machine to satisfy the needs of the application when it is able to accept your orders.

Here comes the problem: how to initialize a graphic subsystem (probably using a known API) in the first place? I'm not speaking of DX or OpenGL init here. I speak of what they need. In extenso: who is responsble for creating the window?

Our problem is that the window may also be used by other subsystems because of its proeminence in the windowing system design. You may think that I speak about Windows here - and you are wrong. Any windowing system I used (I used quite a few, from Win32 to TVision (yeah! remember da ol'time), from GTK+ to plain XLib) are using more or less the same contests: the input is tied to a particular window. Therefore we not only need the window to deal with the rendering but we may also need it to read the user input. Because of this reason, we are not able to create the window during the graphic engine initialisation.

It means something important: we need to build our graphic engine on top of another software component: the system component, which will enable us to perform all the tasks we need to perform - ranging from reading user input to render the view on the user screen.

We are still lucky - because we don't need a full abstraction of the system application model. We only need a simple way to deal with these things - using the Win32 system, we'll only have to write a bunch of thin classes. The only thing we'll have to worry about: we need a level of abstraction which is good enough to be able to manage systems which do not have any kind of window management.

We'll speak about this is a subsequent entry.

Headache
I'm ill. Cold. See you next time? I promise I'll do my best to give you more information :)

Emmanuel Deloget

Emmanuel Deloget

 

Arf !

It seems that to enter the top 50 rated posters of gamedev, you'll have to be at least... Some kind of 1337 I suppose.

Proof:





Nothing more to say.

Edit: clicky for full size.

Emmanuel Deloget

Emmanuel Deloget

 

Agathe, daughter of Mr Dapawa.

News again

No news. Since you don't read them, why should I write news?

design.continue()
Our last analysis lead us to this potential solution:

class GraphicEngine
{
public:
init();
uninit();
draw(GraphicElement gel);
};

The internal implementation of the draw() function is not known yet. In fact, we
have two possibilities to implement this method.

the draw() method init the internal state of the graphic engine with the
GraphicElement data and launch a rendering operation.
the draw() method calls a virtual gel.draw() method which performs the real rendering.

The first solution gives the full drawing control to the graphic engine. The application only have to set up a somewhat small parameter set. The engine is free to ignore the bits he don't want to consider. This is an easy solution, but it has some major drawbacks:

since the game do not know what are the data which are used by the engine, it must fill all the GraphicElement members.
To add more effect or feature, we have to add more GraphicElement members and more code in the graphic engine - for instance, at least one rendering path might be added. The complexity of the rendering engine will grow exponentially, which is never a good thing in a softare designer point of view.

The second solution clearly beats the first one in the sense that the game application don't need to init everything - only the needed features. Moreover, the complexity of the graphic engine do not change when we add features or effects. On the other hand, it requires that we have an interface to setup the engine and launch the rendering. This is the way graphic API works. Both OpenGL and DirectX let you choose the way you want to perform the operations. The benefits are far more interesting than this potential drawback.

We therefore choose the second solution:

class AbstractGraphicElement
{
public:
virtual draw();
};

class GraphicEngine
{
public:
init();
uninit();
draw(AbstractGraphicElement gel) { gel.draw() }
};

Finished?
Of course not! This was the easy part. We'll continue next time - we have now a rather large subject to deal with: the graphic engine needs to provide an interface to the graphic driver.

So, we continue
Yes.
But not today.

Why?
Because.

You blunt
...



Emmanuel Deloget

Emmanuel Deloget

 

Wow. An alien.

News 'n stuff
Customizing this journal is not so complex after all. It may be dangerous but not complex (I hope noone will try to misuse this great opportunity).

I added some links in a column on the right. I'm happy.


O_o
._.
;_;


My html skills are teh sux0rz. Like my notebook kebord.

Anyway, let's continue my "design course" (can I call this a course? I think it is obvious that my goal is not to design my 2D engine but to show how I design it, and why I design it this way).

Three components and one "little" deflection
I'm not sure deflection is the right word to use. Damn, I'm still unable to write correct english sentences (yeah, I know, I'm teh sux0rz too).

Last night I started to speak about design patterns. I made it clear that a game is made with data, algorithm, and a representation of these. Datas and algorithms can be abstracted as the model, and their representation is of course the view. We need the last one to complete the holy trinity: the controler. This is not difficult to locate it: the game input system is a very good candidate - and for now we'll stick with that.

You got it: this is one of the most famous mecanism: the model-view-controler, or MVC for those who are intimate with him. The MVC is well-known for its ability to be mapped to useful design patterns. Maybe we'll be able to study this in details in a subsequent journal entry (read: certainly not today, and maybe never. I'm dumbass ;)).

For those who don't know how the MVC works, let's define it using simple words. To a view is attached a controler. The controler is responsible for handling (for example) user input. In response to these inputs it modifies the model. In response to this modification, the model updates the attached views. You can learn more about MVC in [1].

MVC implies that the view knows how to represent the data. Since we are developping our graphic engine as a "component-on-the-shelf" (COTS, see [2]) we don't want the engine to know the model. Remember, We have discussed this issue in a previous journal entry. When we consider both predicates (the view knows the model and the graphic engine does not knows the model) we clearly see that the view component of the MVC must be split into two different components: the first one is the graphic engine itself. The second one is some kind of glue which will be able to transform a model into its representation.

The glue object interface may use the observer design pattern. In this pattern, the subject (the model in the MVC) sends an update() message to all its observers when it is modified. Let's do this more clearly using a pseudo C++ language:


class Controler
{
World w;
modifyWorld() { w.update(); }
public:
onUserInput() { modifyWorld(); }
};

class World
{
View v;
updateView() { v.draw(this); }
public:
update() { updateView(); }
};

class View
{
set gels;
GraphicEngine ge;

drawElement(GraphicElement gel)
{
ge.draw(gel);
}

public:
draw(World w)
{
updateGraphicElements(w);
for_each_element(gels, drawElement);
}
};


This pseudo codes shows how we can create a game which is independant from the view. If we want to modify the view (maybe adding a third dimension) then we only have to modify the view. This is of course not simple - it may need a lot of work. But it is far better than modifying the whole game!

What else?
I believe I have to speak about the GraphicEngine itself again... Yeah. I may do that...

References!
[1] Glenn E. Krasner and Stephen T. Pope. A cookbook for using the model-view controller user interface paradigm in Smalltalk-80. Journal of Object-Oriented Programming, 1(3):26-49, August/September 1988.
Some info can be found on wikipedia
[2] COTS are discussed at cmu.edu - they appear to name them "commercial-on-the-shelf" because of the nature of teh components themselves. For our purpose, what we want to create is really a COTS-like, not a real commercial component, hence my initial pick: "component-on-the-shef".

PS: it seems I can't remember how to create an anchor in da html. Let's do that next time...

Emmanuel Deloget

Emmanuel Deloget

 

The Good, the Bad, and the Design

News
I know you don't care but I received my copy of Dave Eberly's 3D Game Engine Architecture. I'll have a look to his new code.

I use a notebook to type this. The kebord of this notebook is really teh sux0rZZ.

What did we say?
Gosh. Even if I agree with you about the weird LIFO journal structure - it do not fit my current needs and in fact I find it pretty good - I suspect you are able to scroll down and read what I said yesterday. To simplify: the preliminary design I did two days ago has a some important issues that we need to correct.

So : how to resolve this issue?
Our main problem arise because we don't have clearly stated our goals. Remember we are designing a 2D graphic engine. We want to be able to reuse this engine later, maybe in another completely different project. Another thing we want to do is to abstract the rendering code from the game code.

The last sentence is very important. It makes us ask ourselves what is the game code? This is a question we didn't consider yet. Hey! What did I say? There are questions we forgot? Oh! Wait wait wait...

Lets me rephrase the whole thing. We tried to design a graphic engine, we did something which is obvioulsy not correct and we just saw that we forgot at least one question?

Speed vs accuracy
This is always the biggest problem with design. It leads to the failure of small and big projects. As developpers, we want to rapidly code something. We do some design, then we code, and we experience some major problem wit our code. Wee have to do "clever" things to correct the problem - and of course we soon forget the exact meaning of this completely crazy piece of code. We, as coders, often fail because we tried to do things too fast.

So, what do we have to do then?
Let's restart with what is perhaps the most important thing is a software design: the specifications. OMG you'll say! Yes, we forgot them! Yes, we forgot them. Writing the specification or such a large project would take a long time, so we'll only stick with the simple lines : as a component, we want our 2D graphic engine to be open to reusability and therefore should not be tied to a particular game type. It have to be able to draw whatever we want to draw using a simple interface. Of course, it should be fast - while this is a part of the specs, we won't emphasize this point.

You might say that we didn't say anything yet that we haven't previoulsy said. This is not totally true. At a first glance we said that we wanted to create a 2D graphic engine. The we added the draw methods. The particular organisation of these two methods gave us some kind of headache - they were obviously not correct since we wanted to do a graphic engine and not the graphic engine of a particular game.

Let's speak about something else
In order to ease our design we have to think about what we want to do. We want to do a game which uses the graphic engine. This single sentence implies that the game and the graphic engine are two separate things. I previously asked the question "what is the game code?", we did not answer it yet. The game code is a collection of data and algorithm which are used to play the game. They are not related to the rendering code - which is performed by the graphic engine.

On one side, the game code, on the other side, the graphic engine. Or, to be clearer: on one side the game model, on the other side the game view.

Sounds like we should be able to use some design pattern at the higher design level.

Probably. And...?
Nothing else. See you next time? We'll probably speak about the same thing.

Emmanuel Deloget

Emmanuel Deloget

 

Design II : Attack of the GraphicEngine

Abstract of the previous shows
In the previous installment of my ongoing journal activity, I decided to speak about UML design. I now see that my wording is obscure and contains a lot of (sometimes kebod related) english errors. My bad. Nevertheless I decided to continue to speak about this subject - I find it interesting. Since noone really read this journal (thanks Mushu for the info), I bet it will not hurt your brains.

Good design, bad design
The preliminary design I got yesterday is a bit small. Some pseudo-C++ gives us:1


class GraphicEngine
{
public:
init();
uninit();
draw(World world);
draw(NonStaticObject object);
};


It raises an interesting question: who performs the drawing? Should we say that the GraphicEngine draws the World object or should we say that the World should draw itself using the GraphicEngine? The answer is not very simple.

First, let's consider a simple design issue: what if I decide to modify the graphic engine? I may decide to finally go the 3D way. I probably won't want to rebuild all the game code because of this modification- even it if is a large modification. Or I may decide to adapt the drawing to the device capabilities (a mobile phone is more restricted than a PC). Using this wording it seems that I should let my GraphicEngine draw the world. It means that my GraphicEngine will have to know how a World object is built. Here comes the problem...

OTOH the GraphicEngine is a base component that should not be aware of what the game really is. If I decide to modify my underlying World representation later - because of some important design issue - I will need to modify the GraphicEngine as well - even if the rendering itself do not change. Moreover, if I decide to add a new object type that have to be drawn then I'll have to modify the GraphicEngine as well.

Conclusion: there is something missing. We have to forget our preliminrary design and we need to find better answers to the questions I asked yesterday: who will use the graphic engine, and what will the actor do with it?

To be continued... :)

Emmanuel Deloget

Emmanuel Deloget

 

OK, let's begin serious things...

About my projects
I currently have tons of different projects in mind - at least 4 of them are related to game development. I already spoke about the Designer Wiki System (oh! DWS looks like a cool name...) in one or two threads so I won't speak a bout it here unless I make some major improvement to the PHP code. 2 out of the 3 other projects are still in the "early development stages" (usually you use this expression when you haven't done anything yet).

The last one is a 2D RPG (2D top view), and I'm currently designing the graphic engine. I won't speak about the game itself, and I won't speak about the gameplay - which is rather basic. I target both PC and mobile phone (I'd like to program a nokia - this may modify the gameplay because of the limitation of cell phones). You might think that I should use java to do it. I won't (I never used java. I bet a game should not be the first thing to do with a language that you don't master).

Anyway, I was speaking about the graphic engine design. Why should I begin with it? There are tons of other components in a game - sounds, gamerules, input and son on - and the graphic part is just one of them.

The point is that once the graphics are set up, I can show the game to others, and maybe I'll be able to hire artists to deal with sound and sprites. I'm not able to do my own sprites and I really need (well: I'll really need) an artist to help me. This will be easier when I'll get something to give him ideas about the game itself. Until then, I'll use free tiles/sprites which can be found all over the net.

About design
If we do some short UML design sequence, we have to ask ourselves the question: who is going to use the software we are currently doing? In my own case, this is simple: the game will do. Not me, not the user, only the game. When it comes to library design, this is the only answer you'll be able to do. Since human beeing are not able to read binary code and execute it in their mind, only a program can use a library (a package if we use UML terminology). That's really cool.

The difficulties begins when we ask the second question: what will the actor do with your software? In UML terminology, you deal with use case scenarii. This is typically the negliged design part, but I believe it is the more important. How can you design a library interface if you don't know what your library will have to do? This is not possible. Moreover, I'll bet you'll experience some really difficult design issue even if you barely know what should be the goal of your program.

When I say "my graphic lib will be able to display a 2D world and the player and 2D object sprite and monsters and cool graphical effects" then I said nothing interesting. The real "use case scenario" question is a bit more complex.

So, what are the use case scenarii? Let's examine some (like in: not all) of them:


the game needs to init and uninit the graphic library. This one was an easy one. It simply says that I'll have at least two entry points in my package: init() and uninit().
the game needs to display the static world. Wow. The big one. What does mean "displaying static the world?". Static is easy: this part of the world only deals with things that don't move. We'll have to admit that we still don't have a clue of what a world is. What this issue tells us is that a world is not really a graphical object - it is more a game object - and therefore is not a part of our library. We don't care about its internal representation for now - this may evolve during the design process.We have now another entry point: draw(worldtype world);
the game will need to display non static objects. Since static means 'which do not change during the game', we can understand that non static means 'which can be modified during the game'. A player's avatar is a non static game object. A door is also a non static object. There are tons of non static object in the game world, and this use case deals with their display. Again, we add one entry point to our package: draw(nonstaticobjecttype object).


Of course, there are numerous other "use cases". I'll probably give you all of them in a subsequent journal entry. In this (rather short) design, I can only display my world and display a player.

Before we'll stop considering the different use cases, we'll have to ask ourselve another important question: 'did I forget anything important?'. Of course we did. We forgot to ask ourselves numerous questions which are related to the design of our graphic library: who is responsible for doing the collision detection? If we need a per-pixel collision detection then the only subsystem who is able to do it is the graphic engine. If we only need a simple collision detection then we'll may be able to perform it outside of our package - this should be better.

What next?
The next point will be simple: we'll begin to design the different class we need, and - of course - we'll have to update our preliminary design. We'll need to have a look to the inside of a graphic system.

And?
Nothing else.

Emmanuel Deloget

Emmanuel Deloget

 

As always, I'm late

It seems that every other GDnet+ user already began their journal. I don't. Well, I didn't, until now.

Here are the reasons why I finally decided to begin one:

1) I want to give informations to newbies. I often saw recurring questions on the programming forums and I beleive these recurring questions should be answered in a sticky thread. This is not really feasible. Anyway, I'd like to centralize these recurring questions and answers in a non official FAQ.

2) there is no such thing as point 2.

3) I want to speak of my projects. To give informations about my code. To share my coding experience with gd.net users. Gamedev is really a great place, with tons of great individuals. Because I really like this place, I want to give a contribution to all the gamedev users.

4) I want to the master of the world.

Of course, I don't encourage anyone to read this devlog. I hope to fill it with interesting stuff/ideas/infos, and I hope I'll be able to update it on a regular basis. But if I spend too much time playing with it, I won't be able to master this world.

Mastering the world needs some time, you know...

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!