plik


ÿþUsing design patterns in game engines By Rasmus Christian Kaae kaae@daimi.au.dk Student of computer science and programmer at TietoEnator Consulting A/S August 2001 All rights reserved USING DESIGN PATTERNS IN GAME ENGINES.....................................................................1 1.0 INTRODUCTION............................................................................................................................2 2.0 MODEL-VIEW-CONTROL FOR THE ENGINE CORE ..........................................................................3 2.1 Model......................................................................................................................................3 2.2 View........................................................................................................................................3 2.3 Control....................................................................................................................................3 2.4 Example code .........................................................................................................................4 2.4.1 Comments on the code.........................................................................................................6 2.5 A graphical representation.....................................................................................................7 3.0 LAYER PATTERN FOR A 3D-ENGINE .............................................................................................8 3.1 Top layer.................................................................................................................................8 3.2 Second layer ...........................................................................................................................8 3.3 Third and lower layers ...........................................................................................................8 3.4 Example code .........................................................................................................................9 3.5 A graphical representation...................................................................................................11 4.0 CLOSING....................................................................................................................................12 1.0 Introduction Design patterns are well known patterns that may help the programmer in the initial phase of a programming project. They can be used as a guideline on how to fragment and divide the functions of a program into smaller fragments. In this article I will discuss my point of view on how to structure a game engine, using available design patterns. My knowledge mainly comes from personal experiences and from my study at the computer science department of Aarhus University. There are many different design patterns and they all have different purposes and useability, I have choosen to center the game engine around a model-view-control structure with an underlying layer- structure. The layer structure is used in the 3D-engine core. It is adviseable that you are familiar with polymorphism in C++. 2.0 Model-view-control for the engine core The core of the engine should be able to handle all tasks that are involved in a game. This means handling input from the user, handling possible input from other users (network games), handling the game events and of course handling the audio and visual output. For this I will use a derivate of the model-view-control design pattern. This pattern divides the engine into three vital parts. Model-view-control is particular useful for GUI-programs since it provides a certain degree of modularity which makes it possible to port a given implementation to other graphical-output devices. For example, a given game engine may be implemented to create a running DirectX program using the latest DirectX SDK and the wish is now to port this to OpenGL. Since all the code regarding the dialog between the game engine and DirectX is to be kept in the view classes, this makes the porting easier - whilst only the view classes should be altered. More information on the model-view-control architecture can be found at http://ootips.org/mvc- pattern.html and http://compsci.about.com/cs/mvcpattern/index.htm 2.1 Model The model part of the structure will contain all game structures. For example the 3D-engine structures will be kept in this class, also the behaviour patterns, which holds information on what to do on a given user input, is stored in this part. The model part has no relation to the view and control part of the structure. This means that the model part can be used individual in another environment. 2.2 View The view part contains everything that involves output to the user; in this case audio and visual communication. For example, this is the place to implement OpenGL and DirectX drivers. The view part of the structure is related to the model part. This means that the view part is able to communicate the current state of the model to the user. 2.3 Control The control part is the most essential part of the structure. When initialized it allocates an instance of the view and the model classes and awaits user input. The user input is then parsed on to the model part, where the input is processed, and shortly after the view is asked to project the current state of the model. 2.4 Example code The following example code is in pseudo-C++, which means that it will not compile. /* InputBlock contains the current input from the user */ class InputBlock { // todo : add interesting variables and functions that displays the user input }; /* The model of the game */ class Model { public: Engine3D *m_engine; Sound *m_sound; Model(); UpdateControl(InputBlock *input) { // todo : react on the current input } }; /* ViewVisual is an interface class to be implemented for visual drivers */ class ViewVisual { public: ViewVisual() { } // pure virtual function that handles the changes in the current model virtual void Update(Model *model)=0; } /* ViewVisualOpenGL an implementation of the ViewVisual interface */ class ViewVisualOpenGL { public: ViewVisualOpenGL() { // todo : init code } // display the current state of the model void Update(Model *model) { // todo : paint the model->m_engine } }; /* ViewAudio is an interface class to be implemented for audio drivers */ class ViewAudio { public: ViewAudio() { // todo: init code } // pure virtual function that handles the changes in the current model virtual void Update(Model *model)=0; }; /* ViewAudioDirectSound an implementation of ViewAudio which will play sound via DirectSound */ class ViewAudioDirectSound { public: ViewAudioDirectSound() { // todo : init code } void Update(Model *model) { // todo : play the current sound from model->m_sound } }; /* View is the class that connects the visual and the audio drivers */ class View { protected: ViewVisual *m_visual; ViewAudio *m_audio; public: View(Model *model, ViewVisual *visual, ViewAudio *audio) { m_model=model; m_visual=visual; m_audio=audio; } void Update() { m_visual->Update(m_model); m_audio->Update(m_model); } }; /* Control is the class that handles input from the user and starts the output */ class Control { enum { ESCAPE_IS_PRESSED, USER_INPUT }; private: View *m_view; Model *m_model; public: Control() { m_model = new Model(); m_view = new View(m_model, new ViewVisualOpenGL(), new ViewAudioDirectSound()); } ~Control() { delete m_model; delete m_view; } InputBlock Input(int which) { switch (which) { case USER_EXIT : if (escape_is_pressed) return new InputBlock(ESCAPE_IS_PRESSED); break; case USER_INPUT : if (user_has_made_an_input) return new InputBlock(the_new_input_info); break; } } void Run() { while (!Input(USER_EXIT)) { if (Input(USER_INPUT)) m_model->UpdateControl(Input(USER_INPUT)); m_view->Update(); } } }; /* The main function which allocates our structure and starts it */ void Main(int argc, char **argv) { Control *control = new Control(); control->Run(); delete control; } 2.4.1 Comments on the code The above code will initially allocate a controller. This controller then allocates an OpenGL output device, a DirectSound output device, and a model. After this allocation the main program calls the Run() function of the controller. This function puts itself in a position where it loops until the user presses the exit-button. Until the user exits the program will update the model and view according to the given input. If an input is given, then this input is parsed on to the model and processed. When the input (or the lack of input) is processed the controller asks the view to do an update. Upon exit the code will clean up nicely. 2.5 A graphical representation CONTROL MODEL VIEW The above figure represents the communication in our current model-view-control structure. Control communicates messages to both model and view, whereas view retrieves data from the model. These relations should be changed to fit the exact needs of the individual implementation. I like to use the above as it gives me sufficient independency between each of the classes. However it might be a good idea to add a communication line from model and view to the controller, in order to allow these to inform about sudden errors! 3.0 Layer pattern for a 3D-engine The initial goal of using layer pattern for organizing the 3D-engine core, is to make the accessing code as easy as possible. As an example it should be possible to say scene->m_activeCamera- >LookAt(pos, target) and the whole scene will adapt to this. Also 3D-model loading should be kept in "hidden" layers, so everything will be handled at a higher level (thus the rendering will be carried out by the view-part of our engine-core). The whole engine will be divided into at least 3 layers, where each layer will extend to get more and more low level with the actual math. 3.1 Top layer The top layer gives a basic interface of which the programmer can change and update the current status of the scene. This upper layer communicates the input to the lower levels of this structure, for example, when a player moves to a new location the top layer will make sure that the given player- object will get a new translation point, so on the next repaint the player will be rendered at the correct position. The same thing goes for lights and cameras (in first-person-shooters the camera equals the players point of view). 3.2 Second layer The second layer is more in-depth and contains full classes and interface classes for further extension, for example multiple types of light-sources (spot-light, omni-light, point-light, etc). 3.3 Third and lower layers These layers contain the actual implementation of for example, light, hiearchy-objects etc. 3.4 Example code To explain the (vague) definition of a layered 3D-engine I will here give some sample code. /* second layer component - light, contains the interface for the different light-source types to implement */ class Light { public: enum { OMNI }; int m_light_type; virtual void* GetData()=0; }; /* third layer component - lightomni - this is a direct implementation of light */ class LightOmni : public Light { public: LightOmniData *m_light_omni_data; LightOmni() { m_light_type=OMNI; } void *GetData() { return m_light_omni_data; } }; /* second layer component - object, contains the interface for the objects to implement */ class Object { public: Vector *m_vertices; Face *m_faces; // sets the current translation point for the given object virtual void SetTranslation(Vector &v)=0; // fills the pointers with sufficient data virtual void GetObjectData(Vector *out_vertices, Face *out_faces, int *out_num_faces)=0; }; /* third layer component objecthierachy - this is a direct implementation of object */ class ObjectHierachy : public Object { public: ObjectHiearchy *m_child; Vector m_translation; // sets the current translation point void SetTranslation(Vector v) { translation=v; } // fills the pointers with sufficient data void GetObjectData(Vector *out_vertices, Face *out_faces, int *out_num_faces) { ObjectHiearchy *o = this; while (o->child!=NULL) { // add data from "o" to out_vertices, out_faces and // out_num_faces } } }; /* contains the upper level of the layered structure note: it is adviceable to use linkedlists instead of static arrays in scene-classes, but since this is just for example purposes I will not describe that here. */ class Scene { public: Camera *m_currentCamera; Camera **m_cameras; Light **m_lights; Object **m_objects; }; 3.5 A graphical representation Top layer SCENE Second OBJECTS LIGHT CAMERA layer Third layer HIEARCHY OTHER SPOT OTHER The above illustration shows the class-relations between the layers. When using the above design you are allowed to abstract away from all the pedantic details about each and every object-type, and may write generic code that works on all of the implementations of the Object class (and Light and Camera). 4.0 Closing This article was written since I felt the need for it - I have been looking for such an article for sometime (with no luck). It should be regarded as a suggestion on how to implement a game engine (read: this might not be the perfect solution). During my experience as a programmer I have found the use of design patterns very good, since it allows you to lean back and use trusted structures, instead of reinventing the wheel. Chapter 3.0 and 4.0 might be subject to discussions since there are many individual elements to be considered. For the 3D-engine the implementation may differ from one 3D-editor to another. Have fun with the programming, Rasmus Christian Kaae

Wyszukiwarka

Podobne podstrony:
in game advertising
IEEE Finding Patterns in Three Dimensional Graphs Algorithms and Applications to Scientific Data M
(eBook PDF GUI) Design Patterns as Tools for User Interface Design
Learning Python Design Patterns Gennadiy Zlobin signed
(Oracle) J2EE Design Patterns
Using Linguistic Annotations in Statistical MAchine Translation of Film Subtitles
design patternJEB9B64
NUMERICAL METHODS IN CIVIL ENGINEERING
Using the EEPROM memory in AVR GCC
Patterns of damage in genomic DNA sequences from a Neandertal
In A?ze The Game
Design and performance optimization of GPU 3 Stirling engines
How to Debate Leftists and Win In Their Own Game Travis L Hughes
Turbulent heat transfer enhancement in a triangular duct using delta winglet vortex generators
Enhanced light trapping in solar cells using snow globe coating
Design Guide 17 High Strength Bolts A Primer for Structural Engineers

więcej podobnych podstron