Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 60 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
60
Dung lượng
775,09 KB
Nội dung
int main(int argc, char argv[]) { LPDWORD threadid = NULL; HANDLE thread1 = NULL; PMYPARAM param = NULL; param = (PMYPARAM) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MyParam) ); param->value1 = 9; param->value2 = 800; //create thread in suspended state thread1 = CreateThread(NULL,0,&threadFunction1,param,CREATE_SUSPENDED, threadid); if (!thread1) { cout ( "Error creating thread\n"; return 1; } cout ( "thread created: " ( &threadid ( endl; //launch thread ResumeThread(thread1); WaitForSingleObject(thread1, 500); CloseHandle(thread1); HeapFree(GetProcessHeap(), 0, param); cout ( "done\n"; system("pause"); return 0; } The output of this program looks like this: thread created: 0012FE8C thread function running parameter: 9,800 thread function end done 100 Chapter 5 n Working with Windows Threads Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Although we aren’t doing anything magnificent like solving the largest prime number known to mankind or testing out threaded engine code on an 80-core experimental computer, this chapter does do one thing well—we learned how to create a thread function for Windows threads with support for parameters. Now, you may take any of the previous examples and adapt them to Windows threads fairly easily. Programming Windows threads is a relatively straightforward process since the functions covered in this chapter are part of the Windows SDK and already available in Visual Cþþ by default. Making use of the Windows threads is not a problem, but we have not covered any of the advanced topics like mutex locking to protect data, as the concept is the same here as it is with POSIX and Boost threads. Summary That wraps up Part I and our tour of the four key multi-threading libraries: Boost threads, OpenMP, POSIX threads, and finally, Windows threads. I think it’s time to get started working on some very serious game engine code! Summary 101 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com This page intentionally left blank Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Creating an Engine for SMP Experimentation The second part of this book is dedicated to the development of a game engine. The engine will feature 3D shader-based rendering, 2D sprite animation, static meshes, hierarchical meshes, mesh rendering, shader-based dynamic lighting, entity management, picking (selecting an object in the scene), and collision detection. We will build each component of the engine one at a time while learning about these advanced topics in Direct3D. n Chapter 6: Engine Startup n Chapter 7: Vectors and Matrices n Chapter 8: Rendering the Scene n Chapter 9: Mesh Loading and Rendering n Chapter 10: Advanced Lighting Effects n Chapter 11: Wrapping the Sky in a Box n Chapter 12: Environmental Concerns: Recycling Terrain Polygons n Chapter 13: Skeletal Mesh Animation part II 103 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com n Chapter 14: Sprite Animation and Rasterization n Chapter 15: Rendering to a Texture n Chapter 16: Entity Management n Chapter 17: Picking and Collision Detection 104 Part II n Creating an Engine for SMP Experimentation Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Engine Startup Building a game engine from scratch is a lofty goal with the potential to be a great learning experience. Like restoring a car from the frame and body work to the engine and interior, which lends insights into how the car will drive beyond the “road feel” in the steering wheel, designing a game engine from WinMain to the entity manager to the animated hierarchical mesh renderer lends the programmer a unique insight into how his or her games work at a deeply intimate level. Since the engine will be in development for many chapters, we will take the simpler approach by just adding engine source files into each chapter demo individually and forego the process of creating the engine library project (static or DLL) until the last chapter. Having devel oped all of the demos with a separation of the game engine and gameplay code in separate but dependent projects, I can vouch for the positive advantages to using a single project approach to the demos for the time being. For one thing, the engine will be in a state of flux as it is developed over the coming chapters, so at no point will the engine be “finished” until we have covered every topic and built every Cþþ class needed. In the final chapter, we’ll have a final engine project available for further use. This chapter covers the following topics: n Why build an engine yourself? n Creating the engine project n Engine core system chapter 6 105 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com n Engine rendering system n Engine support system n Verifying framerates with FRAPS Why Build an Engine Yourself? What is the purpose or advantage of a game engine, as opposed to, say, just writing all the code for a game as needed? Why invest all the time in creating a game engine when you could spend that time just writing the game? That is essentially the question we ’ll try to answer in the pages of this book, beginning in this first chapter in which we’ll be building the c ore code and classes for a new engine. The simple answer is: You don’t need an engine to write a game. But that is a loaded answer because it implies that either 1) The game is very simple, or 2) You already have a lot of code from past projects. The first implication is that you can just write a simple game with DirectX or OpenGL code. The second assumes that you have some code already available, perhaps in a game library— filled with functions you’ve written and reused. A game library saves a lot of time. For instance, it’s a given that you will load bitmap files for use in 2D artwork or 3D textures, and once you’ve written such a function, you do not want to have to touch it again, because it serves a good purpose. Anytime you have to open up a function and modify it, that’s a good sign that it was poorly written in the first place (unless changes were made to underlying functions in an SDK beyond one’s control—or perhaps you have gained new knowledge and want to improve your functions). Advice It is helpful to decide whether one is interested primarily in engine or gameplay programming, in order to devote effort into either direction (but not often both). An engine programmer focuses primarily on rendering and optimizations, while a gameplay programmer focuses on artificial intelligence, scripting, event/animation syn chronization, user input, and fulfilling design goals. Valid Arguments in Favor In my opinion, there are three key reasons why a game engine will help a game development project: teamwork, development tools, and logistics. Let’s examine each issue. 106 Chapter 6 n Engine Startup Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com n Teamwork is much easier when the programmers in a team use a game engine rather than writing their own core game code, because the engine code facilitates standardization across the project. While each programmer has his or her own preferences about how timing should be handled, or how rendering should be done, a game engine with a single high-speed game loop forces everyone on the team to work with the features of the engine. And what of features that are lacking? Usually, one or two team members will be the “engine gurus” who maintain the engine based on the team’s needs. n Development tools include the compiler(s) used to build the game code, asset converters and exporters, asset and game level editors, and packaging tools. These types of tools are essential in any game project, and not practical without the use of a game engine. Although many programmers are adept at writing standard Cþþ code that will build on multiple platforms and compilers, game code usually does not fall into that realm due to its unique requirements (namely, rendering). Cross-compiler sup- port is the ability to compile your game with two or more compilers, rather than just your favorite (such as Visual Cþþ). Supporting multiple render targets (such as Direct3D and OpenGL) is a larger-scale endeavor that is not recommended unless there is a significant market for Mac and Linux systems. Direct3D is the primary renderer used by most game studios today for the Windows platform. Advice Writing code that builds on compilers from more than one vendor teaches you to write good, standards-compliant code, without ties to a specific platform. n Logistics in a large game project can be a nightmare without some coordinated way to organize the entities, processes, and beha viors in your game. Logistics is the problem of organizing and supporting a large system, and is often used to describe military operations (for example, the logistics of war—equipping, supplying, and supporting troops). The logis- tics of a game involves managing the characters, vehicles, crafts, enemies, projectiles, and scenery—in other words, the “stuff” in a game. Without a system in place to assist with organizing all of these things, the game’s source code and assets can become an unmanageable mess. Why Build an Engine Yourself? 107 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Let’s summarize all of these points in a simple sentence: A game engine (and all that comes with it) makes it easier to manage the development process of a game project. Contrast that with the problems associated with creating a game from scratch using your favorite APIs, such as Direct3D or OpenGL for graphics, DirectInput or SDL for user input, a networking library such as RakNet, an audio library such as FMOD, and so forth. The logistics of keeping up with the latest updates to all of these libraries alone can be a challenge for an engine programmer. But by wrapping all of these libraries and all of your own custom game code into a g ame engine, you eliminate the headache of maintaining all of those libraries (including their initialization and shutdown) in each game. The best analogy I can come up with is this: “Rolling your own” game code for each game project is like fabricating your own bricks, forging your own nails, and cutting down your own trees in order to build a single house. Why would you do that? But perhaps the most significant benefit to wrapping an SDK (such as DirectX) into your own game engine classes is to provide a buffer around unpredictable revisions. Whenever a change occurs in a library (such as Direct3D) that you regularly use in your games, you can accommodate those changes in your engine classes without having to revise any actual gameplay code in the process. Valid Arguments Against There are many game engines available that a developer can freely (or affordably, at least) put to good use for a game, rather than re-inventing the wheel, so to speak. These engines usually support multiple renderers (OpenGL, Direct3D 9, Direct3D 10, etc.). Examples include: n Irrlicht—“Free Open Source 3D Engine” (http://irrlicht.sourceforge.net) n OGRE—“Open Source 3D Graphics Engine” (http://www.ogre3d.org) n Torque by Garage Games (http://www.torquepowered.com) Any of these three engines would be a good choice for any aspiring indie game studio, so why would someone want to try to create their own engine and try to compete with these well-rounded, feature rich, strongly supported engines with large communities of users? Touché. It’s about the learning experience, not about trying t o compete with others and outdo them in a foolhardy attempt to gain market share with a new engine. That’s 108 Chapter 6 n Engine Startup Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com not the purpose of building your own engine at all! It’saboutthejourney,the experience gained, the new skills developed, and improving your marketability. Advice Building your own game engine is like a car enthusiast building or restoring his own hot rod show car. There is some kinship with professionals like Chip Foose and Jack Roush, but a great chasm of experience and expertise separates a hobbyist from the pros. Do not try to compete. Rather, learn new skills, do your best, and try to enjoy the learning experience! Creating the Engine Project We are going to create the core game engine project in this chapter and then expand it over the next dozen or so chapters to include all of the features we need to build advanced demos, simulations, and games—with the goal of later improving the engine with the threading techniques covered in Part I. Threading will not be weaved into the fabric of the engine from the start—our first goal is to build a stable engine and make it as efficient as possible before implementing any thread code. The starting point i s the core engine developed in this chapter, which will include WinMain, D irect3D initialization, D3DXSprite initialization, basic game events, timing, and, of course, a game loop. The great thing about doing all of this right now at the beginning is that we will not have to duplicate any of this code in future chapters—it will already be embedded in the game engine. The engine project will remain a standard Win32 executable project, as opposed to a combination library/executable pair, for the sake of simplicity—I w ant to make the material easy for the reader to get into without logistical issues like solution/ project files getting in the way early on. But, all of the source files will easily build inside a Win32 library project just as well (static or DLL, it doesn’t matter). Advice Most of the source code printed in the book is free of comments to save space (since much of the code is explained in the text), but the comments are in the source code files in the chapter resource files (www.jharbour.com/forum or www.courseptr.com/downloads). Let’s get started creating the engine project so that we’ll have a foundation with which to discuss the future design of a multi-threaded engine. The Engine class is embedded in a namespace called Octane. This namespace will contain all engine classes, so there will not be any conflicts with other libraries you may Creating the Engine Project 109 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... color depth D3DDISPLAYMODE dm; p_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm); //set configuration options for Direct3D D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = (!fullscreen); d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.EnableAutoDepthStencil = 1; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; d3dpp.PresentationInterval... //namespace //define the global engine object (visible everywhere!) //extern Octane: :Engine* g _engine; extern std::auto_ptr g _engine; Following is the Engine. cpp class implementation, with all of the engine initialization, updating, and rendering code #include "stdafx.h" #include "Engine. h" using namespace std; namespace Octane { Engine: :Engine( ) { p_apptitle = "Octane Engine" ; p_screenwidth... Direct3D device (hardware T&L) p_d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, p_windowHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &p_device); //if hardware T&L failed, try software if (p_device == NULL) { debug ( "Hardware vertex option failed! Trying software ." ( endl; p_d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, p_windowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,... "Engine init succeeded" ( endl; return 1; } /** Resets 3D transforms by setting the identity matrix **/ void Engine: :setIdentity() { D3DXMATRIX identity; D3DXMatrixIdentity(&identity); g _engine- >getDevice()->SetTransform(D3DTS_WORLD, &identity); } /** Resets sprite transforms by setting the identity matrix **/ void Engine: :setSpriteIdentity() { D3DXMATRIX identity; D3DXMatrixIdentity(&identity); g _engine- >getSpriteObj()->SetTransform(&identity);... comment(lib,"winmm.lib") #pragma comment(lib,"user32.lib") #pragma comment(lib,"gdi32.lib") #define VERSION_MAJOR 1 #define VERSION_MINOR 0 #define REVISION 0 //end-user functions extern bool game_ preload(); extern bool game_ init(HWND hwnd); extern void game_ update( float deltaTime ); extern void game_ render3d(); extern void game_ render2d(); extern void game_ event(Octane::IEvent* e); extern void game_ end(); LRESULT CALLBACK... d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.BackBufferFormat = dm.Format; d3dpp.BackBufferCount = 1; d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.hDeviceWindow = p_windowHandle; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; 124 Simpo 6 n Engine Startup Chapter PDF Merge and Split Unregistered Version - http://www.simpopdf.com debug ( "Creating Direct3D device" ( endl;... following functions, which are declared as extern in Engine. h Since they are extern, they must be implemented somewhere in the game project (usually that will be the main source code file, main.cpp): bool bool void void void void void game_ preload(); game_ init(HWND hwnd); game_ update( float deltaTime ); game_ render3d(); game_ render2d(); game_ event(IEvent* e); game_ end(); You are welcome to rename them to... Creating the Engine Project 1 23 //was there an error creating the window? if (!hWnd) { debug ( "Error creating program window" ( endl; return 0; } //display the window ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //save window handle in engine g _engine- >setWindowHandle(hWnd); debug ( "Creating Direct3D object" ( endl; //initialize Direct3D p_d3d = Direct3DCreate9(D3D_SDK_VERSION); if (p_d3d == NULL)... p_windowHandle = 0; } Engine: : ~Engine( ) { delete p_input; if (p_device) p_device->Release(); if (p_d3d) p_d3d->Release(); } std::string Engine: :getVersionText() { std::ostringstream s; s ( "Octane Engine v" ( p_versionMajor ( "." ( p_versionMinor ( "." ( p_revision; return s.str(); } void Engine: :Message(std::string message, std::string title) { MessageBox(0, message.c_str(), title.c_str(), 0); } void Engine: :setScreen(int... ) { g _engine- >setCommandLineParams( lpCmdLine ); Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Creating the Engine Project 1 13 debug ( "Params: " ( g _engine- >getCommandLineParams() ( std::endl; } //let main program set screen dimensions debug ( "Calling game_ preload" ( endl; if ( !game_ preload()) { debug ( "Error in game_ preload" ( endl; return 0; } //initialize the engine . Source 3D Engine (http://irrlicht.sourceforge.net) n OGRE—“Open Source 3D Graphics Engine (http://www.ogre3d.org) n Torque by Garage Games (http://www.torquepowered.com) Any of these three engines. engine object (visible everywhere!) //extern Octane: :Engine* g _engine; extern std::auto_ptr<Octane: :Engine& gt; g _engine; Following is the Engine. cpp class implementation, with all of the engine initialization,. game_ init(HWND hwnd); extern void game_ update( float deltaTime ); extern void game_ render3d(); extern void game_ render2d(); extern void game_ event(Octane::IEvent* e); extern void game_ end(); LRESULT CALLBACK