Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 21 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
21
Dung lượng
144,55 KB
Nội dung
private: float m_fMinSpeed; float m_fMaxSpeed; }; // class HasSpin { public: HasSpin(); HasSpin( float fMin, float fMax ); float GetSpin() const; void SetSpinRange( float fMin, float fMax ); private: float m_fMinSpin; float m_fMaxSpin; }; // class HasDirection { public: HasDirection(); HasDirection( const MATHS::Vector3 & vDir, float fPerturbation=0.0f ); void SetDirection( const MATHS::Vector3 & vDir ); // Set the direction vector. void SetPerturbation( float fPerturbation ); // Sets the amount of randomness in the direction. MATHS::Vector3 GetVelocityVector( float fSpeed ) const; private: MATHS::Vector3 m_vDirection; float m_fPerturbation; }; /*******************************************************/ Object-oriented game development406 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 406 class Emitter { public: /* * Constants/typedefs/enums. */ /* * Lifecycle. */ Emitter( const MATHS::Vector3 & vPosition ); /* * Polymorphism. */ /* * API. */ const MATHS::Vector3 & GetPosition() const; void SetPosition( const MATHS::Vector3 & vPos ); // Set/get the point of emission. protected: /* * Helpers. */ private: /* * Data. */ MATHS::Vector3 m_vPosition; }; // end class // class EmitterDirectional : public Emitter , public HasSpeed , public HasDirection { Case study: Cordite 407 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 407 public: /* * Constants/typedefs/enums. */ /* * Lifecycle. */ EmitterDirectional( const MATHS::Vector3 & vPos, const MATHS::Vector3 & vDir, float fMinSpeed, float fMaxSpeed, float fPerturbation = 0.0f ); /* * Polymorphism. */ /* * API. */ MATHS::Vector3 GetParticleVelocity() const; // Gets a velocity based on the direction, // speed and perturbation settings. protected: /* * Helpers. */ private: /* * Data. */ float m_fPerturbation; }; // end class } There are no virtual function calls required here, so it’s all nice and quick. Notice that there is no ‘create particle’ call in the Emitter. The function of this object is to calculate initial values, and it does this by having ranges between Object-oriented game development408 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 408 which random values can be picked (if we want a single value, then we make a range of size zero). Within game code, a subclass of Emitter needs to support a non-virtual member function InitialiseParticle, where the particle type is also defined in the game code. This then uses the base emitter to calculate values to set up the particle: void MyEmitter::InitialiseParticle( MyParticle * p ) { p->SetLife( GetLifeSpan() ); p->SetVelocity( GetParticleVelocity() ); } The class that creates and manages particles is the ParticleSystem, which is a templated object based on three parameters: ● The Particle, which you provide and which should support the non- virtual methods void Update( Time aDeltaT ); bool IsActive() const; void Render( Renderer * pRenderer ) const; IsActive() should return false if the particle has expired. ● The Emitter subclass, supporting InitialiseParticle() as described above. ● The renderer you’re using as an argument to the particle Render() method. Putting these all together looks like a bit like this: namespace PRTCL { template<class Particle,class Emitter,class Renderer> class ParticleSystem { public: /* * Constants/typedefs/enums. */ /* * Lifecycle. */ ParticleSystem( Emitter * pEmitter, int iMaxParticles ); Case study: Cordite 409 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 409 virtual ~ParticleSystem(); /* * Polymorphism. */ // Update active particles by the elapsed time. virtual void Update( float fDeltaT ); // Removes all active particles, sets the age to 0. virtual void Initialise(); // Renders all the (active) particles. virtual void Render( Renderer * pRenderer ) const; /* * API. */ // Generates a number of particles. The maximum set // in the constructor cannot be exceeded (it will // silently fail if so). The return value is the // actual number generated. int Spawn( int iRequestedParticles ); int GetActiveParticleCount() const; float GetAge() const; Emitter * GetEmitter(); const Emitter * GetEmitter() const; protected: /* * Helpers. */ inline void elapseTime( float fDeltaT ) { m_fAge += fDeltaT; } void freeActiveParticle( iterator itParticle ); private: /* * Data. */ tParticleList m_ActiveParticles; Object-oriented game development410 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 410 tParticlePool m_ParticlePool; Emitter * m_pEmitter; int m_iMaxParticles; float m_fAge; }; } Yes, the particle system is free to have virtual functions. Any instance of a system is only updated once per game loop (or perhaps less), so a single poly- morphic call will be dwarfed by the actual update of the contents. We can then use the API and the protected helpers to fine-tune our subclassed particle system. For instance, a particle system that continuously chucks out particles (e.g. smoke) may look like this: template<class Particle, class Emitter, class Renderer> class ParticleSystemContinuous : public PRTCL::ParticleSystem<Particle,Emitter,Renderer> { public: /* * Constants/typedefs/enums. */ /* * Lifecycle. */ ParticleSystemContinuous( Emitter * pEmitter, int iMaxParticles, float fGenRate ); /* * Polymorphism. */ void Update( float fDeltaT ); /* * API. */ // Sets and gets the maximum number of particles // that can be produced. You can’t set more than // the maximum passed in the constructor. void SetCapacity( int iCapacity ); int GetCapacity() const; Case study: Cordite 411 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 411 // Sets the rate at which particles are replenished. void SetGenerationRate( float fRate ); protected: /* * Helpers. */ void maintainParticleDensity( float fDeltaT ); private: /* * Data. */ float m_fGenerationRate; int m_iCapacity; }; 11.1.8 And so on Within Cordite, there are many more components that make up the complete game. For example, a path controller that intelligently rescales Avatar walk cycle animations depending on the route direction and speed, a camera con- troller, or a console that allows inspection and modification of internal game state. The large majority are reusable without change; of the remainder, only one or two are so specific to this game that they are not worth recycling. With good design and careful implementation, video games can – contrary to the received mythology – be created from small, reusable building blocks, which can be extended through the familiar mechanism of polymorphism. Figure 11.16 summarises the components we have discussed. We’ve split the components into three – somewhat arbitrary – levels: core, which are components that are generic and/or exist in their own right or are used in another game; intermediate, which are components written especially for Cordite but that are otherwise generic; and game, which are (somewhat loosely) classes that specialise classes in the other levels and generally glue the required behaviours together but are generally not reusable. In this example game, given the (fairly arbitrary but not unrepresentative) components we have selected for discussion, 13 of 17 components are reusable. That’s nearly 77% of the components. Although it would be a big (and mistaken) assumption to make that all the components are the same size in terms of lines of code or number of bytes of object code, it is hard not to reach the conclusion that by writing games using component technologies, the overwhelming majority of component code is reusable and about half of that may exist already. Tell that to your producer! Object-oriented game development412 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 412 Case study: Cordite 413 SOS Intermediate MAP EVTSCR GRID PRTCL CNUT REND DMGD EVT STRM CTRL SCENE COLL CorditeSOS FX CorditeCTRL CorditeObject Core Game Figure 11.16 Overview of the Cordite components that we’ve discussed. 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 413 11.2 Summary ● Much of a game’s architecture can be put together with a set of existing, reusable components. ● The components provide a framework from which specific behaviours are imple- mented and utilised via the mechanism of inheritance. ● The bits that cannot be put together in this way can still be written as compo- nents with the possibility of reuse in other games or applications. ● The notion that you can’t do reuse in games is therefore utterly refuted. It is the author’s fond wish that this is the straw that breaks the Hacker’s Charter’s back. However, this does not mean that gamedevelopment will become easy, or a cyni- cal, churn-’em-out process that recycles dated technology. Far from it. The intention is to stop bogging our development down with rewriting, re-debugging and retesting the ‘simple’ stuff, and to focus instead on utilising the increasing amounts of CPU power and RAM to push the boundaries of what we believe is possible. After all, isn’t that why we’re in the games business in the first place? Object-oriented game development414 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 414 T he conventions used follow the policy discussed briefly in Chapter 3. More standards are adopted than are required by the policy, which is intended to be a useful minimum rather than a definitive maximum: Variable scope is indicated by a single-letter prefix followed by an underscore: g_ means a variable is global. s_ means a variable is static – visible only in the declaring module. c_ means a variable is a static class member. m_ means a variable belongs to a class instance. A modified Hungarian notation indicates the type of variable: p means a pointer. i means an integer (compiler native size). u means an unsigned integer (compiler native size). c means a character (eight-bit signed). str means a nul-terminated string (or string class type). v means a vector. m means a matrix. a means an instance or reference. f means a single-precision floating-point value. b means a Boolean value. Publicly accessible functions and methods start with an upper-case letter. Private functions and methods begin with a lower-case letter. In both cases, names are composed of word fragments with no separators, each fragment starting with a capital letter. So if we see the variable m_pResourceManager, we know we’re dealing with a class member that points at a resource manager type. If we see iNumSprites, we are looking at a local integer counter for our sprites. Preprocessor macros are in upper case with word fragments separated by under- scores for clarity, e.g. MAX_SPRITE_NAME. Namespaces are given names with a single short (no more than five characters) word fragment in upper case, e.g. namespace REND { /*…*/ }. Appendix: coding conventions used in this book 415 8986 OOGD_Z01.QXD 1/12/03 3:03 pm Page 415 [...]... loops 231 foreign language support 180 fragmentation 201–3, 268, 282–4, 291–2 frameworks 35 FSVR component 192, 195 function call overhead 54–5 fundamental singletons 81 game objects (GOBs) see objects GameCubeTM 2 games software development, distinctiveness of 15–21 Gamma, E 76 Gang of Four book 76–7 garbage-disposal systems 200, 309 generic systems 250–1, 257 8986 OOGD_Z04.QXD 1/12/03 3:02 pm Page... 221–4 console games 284 const-correct code 66 constraints 214 container components 152–8, 288 control methodology 16–17, 20, 401–4 conversion between computer systems 7 copy-and-paste 35–6 copy-on-write (COW) 292 Cordite (case study) 387–413 core features of games 19, 355–6 core technology 374 cost of developing games 14 creative designers 383–4 cross-platform development see multiplatform development. .. non-player character (NPC) control 135–7, 280 notation in software engineering 69–72 null objects 272 null version of software 358, 362 object factory 89–95, 320–1, 325–6 object instances 143–5 object orientation, characteristics of 52–6, 69, 226, 252, 269, 385 object streams 391–3 objects in case study 398–401 classes of 269 definition of properties 275 management of 281 open-ended design 18–19 optimal version... www.gotw.ca/ Sweng-gamedev is a group talking C++, software engineering and project management for games, among other things Subscribe at www.midnightryder.com/ If you’re writing compilers, a scripting system or other language-related systems, and you’re fine with using STL in a game, then ANTLR surpasses yacc and lex See www.antlr.org/ For lots of info about how to write physics for games, Chris Hecker’s... Programmers, Chichester, UK: Wiley Bourg, D (2001) Physics for Game Developers, Sebastapol, CA: O’Reilly Brown, W., Malveau, R., McCormick, H., Mowbray, T (1998) Antipatterns, New York: Wiley Eberly, D (2000) 3D Game Engine Design, San Francisco: Morgan Kaufman Gamma, E., Helm, R., Johnson, R., Vlissides, J (1994) Design Patterns – Elements of Reusable Object- Oriented Structure, Reading, MA: Addison-Wesley Johnstone,... relationship 71, 268, 276–7 hashing systems 157–8, 292–3 Havok 207 header files 41–3, 50, 242–3, 246, 268, 296 heuristic content of games 19 hidden functionality 354 hierarchies of objects collapsed 267–9 shallow 269–70, 281 vertical 270–4 Higinbotham, William 4 history of games 4–8 horizontal reuse of software 34, 37 ID values 300–1, 321–3 incremental delivery 352–5 inertia tensors 211–15 inheritance... development culture of development 367 damage tags 312–23 databases 291 decompression of data 202 dependencies in code 38–41, 132, 136–41, 181, 326 cyclical 185–6 elimination of 41–3 illogicality in 148 localisation of 44–5 reduction of 148 dereferencing 304 design of software 72–6 commercially-available tools for 69 embedded in development 382 design teams 379–84 designers of games 329, 367–8, 383... 45–50 reverse-engineering 69 reviews of development work 31–3 rewriting of software 357, 361, 366 risk management 366, 379–82 robustness of games 16 run-time-type information 57 Russell, Steve 4 Russian doll pattern 111–15 SCENE component 182–3 scheduling 351–5, 365–6 scripting 279, 329–32, 395–8 language issues 347–8 layered systems 340 servers 221, 224–5 simuloid games 18 Sinclair Research 6–7 Singhal,... 1/12/03 3:02 pm Page 421 Index Abrash, M 17 abstraction 52, 371 accountability 353 actor objects 273 Adobe Photoshop 370, 378 allocation of storage 283–301 animators 378–9 antir 348 application components 150–2, 259–65 architecture specialists 370–1 articulation 341 artificial intelligence (AI) 135–6, 372 artistic content of games 20, 375–9 ASCII text 178–80, 330 assembly language 7, 52 asset-generation packages... Programming Language, 3rd edition, Reading, MA: Addison-Wesley Watt, A., Policarpo, F (2000) 3D Games: Real-Time Rendering and Software Technology, Harlow, UK: Addison-Wesley 417 8986 OOGD_Z02.QXD 1/12/03 3:03 pm Page 418 8986 OOGD_Z03.QXD 1/12/03 3:03 pm Page 419 Web resources No collection of Web resources for game developers would be complete without Gamasutra: lots and lots of really useful source code, . component 192, 195 function call overhead 54–5 fundamental singletons 81 game objects (GOBs) see objects GameCube TM 2 games software development, distinctiveness of 15–21 Gamma, E. 76 Gang of Four. what we believe is possible. After all, isn’t that why we’re in the games business in the first place? Object- oriented game development4 14 8986 OOGD_C11.QXD 1/12/03 3:01 pm Page 414 T he conventions. 387–413 core features of games 19, 355–6 core technology 374 cost of developing games 14 creative designers 383–4 cross-platform development see multiplatform development culture of development 367 damage