Giáo trình Beginning DirectX9: Phần 2

83 75 0
Giáo trình Beginning DirectX9: Phần 2

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Giáo trình Beginning DirectX9 phần 2 cung cấp cho người học các kiến thức: Chia nhỏ đối tượng, sử dụng hiệu ứng, hiệu ứng âm thanh, xây dựng dự án mẫu, bài tập thực hành,... Hi vọng đây sẽ là một tài liệu hữu ích dành cho các bạn sinh viên đang theo học môn dùng làm tài liệu học tập và nghiên cứu. Mời các bạn cùng tham khảo chi tiết nội dung tài liệu.

Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN CHƯƠNG CHIA NHỎ VÀ LÀM MỊN CÁC ĐỐI TƯỢNG B ạn học cách làm để tạo object 3D code biểu diễn lên hình Có lẽ bạn nghĩ q trình thật nhàm chán chưa có cách để tạo tất object code Bạn nghĩ Hiện 3D nhập cuôc Nó mơ tả thứ game bạn giống với thực thể Những mơ hìnhcó thể thể vật thể đặc điểm xung quanh bạn chính Với đặc điểm bạn đưa mơ hình vào game, bạn biểu diễn với đối tượng Mesh dịch chuyển điều khiển chúng Đây phần mà bạn học chương này: ƒ Direct3D điều khiển mesh ? ƒ Cần để hợp lý hóa model 3D? ƒ Định dạng file X gì? ƒ Làm để tạo lưu giữ mesh? ƒ Làm để load model 3D vào game? Xây dựng giới 3D Mơ hình 3D giúp chúng bạn thể giới ảo mà bạn muốn tạo Những mơ hình bổ xung gamer đối thủ gamer môi trường Những mô hình lấy từ đâu? Nếu bạn có package thiết kế 3D giống Max Maya, bạn có cơng cụ cần thiết để tạo thứ cho game bạn cần Nếu chương trình bạn khơng có bạn dùng package khác MilkShape 3D, làm việc tốt Sau tạo model, bạn đưa chúng vào định dạng file 3D có Nhưng bạn cần biết làm để load file định dạng 3D vào game Mục đích sách giúp bạn làm việc với định dạng file mà Microsoft tạo Chú ý: Bạn tìm MilkShape 3D trang http://www.swissquake.ch/chumbalumsoft/index.html 96 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Mesh gì? Code bạn điều khiển mơ hình 3D load vào game xem Mesh Một Mesh code container mà chứa thứ liên quan đến đối tượng 3D Nó bào gồm vectơ, tọa độ texture liệu khác Bằng cách sử dụng liệu có mesh object bạn biểu diễn mơ hình 3D lên hình Chú ý: Thư viện tổng hợp D3DX chứa tất thứ mà bạn cần để sử dụng mesh Direct3D Direct3D định nghĩa Mesh nào? Hầu hết mesh Direct3D dựa ID3DXBaseMesh interface Interface cung cấp kho dự trữ dành cho model bạn, giúp methods có hiệu lực để tăng tốc độ truy cập tới liệu mesh Ví dụ method GetVertexBuffer ln sẵn có ID3DXBaseMesh interface để giúp bạn truy cập trực tiếp tới vectơ buffer đối tượng mesh Dưới số kiểu Mesh khác nhau: ƒ ID3DXMesh – Đây dạng mesh interface chuẩn mà bạn sử dụng ƒ ID3DXPMesh – Interface cho phép bạn sử dụng mesh tiến hành ƒ ID3DXSPMesh – interface điều khiển đơn giản hóa mesh object ƒ ID3DXPatchMesh - Interface cung cấp Patch mesh theo chức Mỗi kiểu mesh lưu giữ tất vectơ model vectơ buffer cung cấp cho bạn thông tin vể model, ví dụ số phần tử số vectơ Tạo Mesh Bước sử dụng mesh game khởi tạo mesh object Mesh object kho dự trữ, cất giữ tất thông tin cần thiết dùn để mô tả model bạn Direct3D Sau bạn tạo mesh, bạn dễ dàng copy tất thông tin mà model bạn cần Hai hàm Direct3D dùng để tạo mesh: D3DXCreaetMesh D3DXCreateMeshFVF Vì hàm tạo mesh cách khác nhau, làm rõ hai hàm D3DXCreateMesh Giao diện ID3DXMesh giao diện đơn giản mesh interface, dễ dàng tổ chức thực cách nhanh chóng Trong phần này, bạn học cách làm để tạo mesh ID3DXMesh interface hàm D3DXCreateMesh D3DXCreateMesh( DWORD NumFaces, DWORD NumVertices, DWORD Options, CONST LPD3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pDevice, LPD3DXMESH *ppMesh ); 97 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Hàm D3DcreateMesh có tham số: ƒ NumFaces Số phần tử mà mesh chứa ƒ NumVertices Số vectơ mà mesh chứa ƒ Options Giá trị từ bảng liệt kê D3DXMESH ƒ pDeclaration Ma trận thuộc đối tượng D3DVERTEXELEMENT9 Những object mô tả FVF cho mesh ƒ pDevice Một Direct3D device hợp lệ ƒ ppMesh Con trỏ trỏ tới đối tượng ID3DMesh hợp lệ Đoạn code sau cách làm để tạo đối tượng mesh mà chứa đầy đủ vectơ, dùng để tạo khối lập phương HRESULT hr; // biến giữ mesh tạo LPD3DXMESH boxMesh; // ma trận D3DVERTEXELEMENT9 D3DVERTEXELEMENT9 Declaration [MAX_FVF_DECL_SIZE]; // tạo khai báo cần thiết cho hàm D3DXCreateMesh D3DXDeclaratorFromFVF (D3DFVF_CUSTOMVERTEX, Declaration); hr= D3DXCreateMesh(12, //số phần tử mesh 8, //số vectơ D3DXMESH_MANAGED, //sử dụng nhớ cần thiết cho mesh Declaration, //ma trận kiểu đối tượng D3DVERTEXELEMENT9 pd3dDevice, //the Direct3D device &boxMesh); //biến giữ mesh //kiểm tra giá trị trả để chắn bạn cómột đối tượng mesh hợp lệ if FAILD (hr) Return false; Như bạn thấy, đoạn code tạo mesh chứa 12 phần tử vectơ tất chúng đưa vào biến boxMesh Biến thứ ba D3DXMESH_MANAGED thông báo Direct3D cần sử dụng nhớ cần thiết cho vectơ index buffer để tạo mesh Bạn nên ý hàm D3DXDeclaratorFromFVF phải gọi trước hàm D3DXCreateMesh D3DXDeclaratorFromFVF tạo đối tượng cần thiết D3DVERTEXELEMENT9 cho tham số thứ cách sử dụng Flexible Vertex Format (định dạng véctơ linh hoạt) mà model bạn sử dụng Khi bạn sử dụng hàm D3DXDeclaratorFromFVF, bạn không cần thiết phải tạo đối tượng D3DVERTEXELEMENT9 D3DXCreatMeshFVF Hàm D3DXCreateMeshFVF không giống với D3DcreateMesh điểm dựa vào kiến tạo mesh Định Dạng Véctơ Linh Hoạt (Flexible Vertex Format) thay dùng Declarator Mesh object giống với mesh object tạo hàm D3DXCreateMesh phần trước Hàm D3DXCreatMeshFVF định nghĩa sau: HRESULT D3DXCreateMeshFVF( DWORD Numface, DWORD NumVertices, DWORD Options, DWORD FVF, 98 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN LPDIRECT3DDEVICE9 pDevice, LPD3DXMESH *ppMesh ); Hàm D3DXCreatMeshFVF cần tham số: ƒ Numface - số phần tử mà mesh có ƒ NumVertices – số véctơ mà mà mesh có ƒ Options – giá trị từ bảng liệt kê D3DXMESH ƒ FVF – Flexible Vertex Format véctơ ƒ pDevice – Direct3D device hợp lệ ƒ ppMesh – trỏ trỏ tới đối tượng ID3DXMESH Dưới chương trình mẫu gọi hàm D3DXCreateMeshFVF //biến giữ giá trị trả HRESULT hr; //biến giữ mesh đựơc tạo LPD3DXMESH boxMesh; //tạo mesh cách gọi gàm D3DXCreateMeshFVF hr= D3DXCreateMeshFVF (12, 8, D3DFVF_MANAGED, D3DFVF_CUSTOMVERTEX, pd3dDevice, &boxMesh); //kiểm tra giá trị trả có hợp lệ không if FAILED (hr) return false; //Numfaces // NumVertices // Options // FVF // pDevice // ppMesh Một lần bạn tạo mesh cách sử dụng nhớ quản lý cho véctơ, index buffer việc định giá trị D3DXMESH_MANAGED Khi việc gọi hàm kết thúc, biến boxMessh giữ đối tượng mesh hợp lệ Hàm D3DXCreateMeshFVF hàm dễ sủ dụng hai hàm tạo mesh Filling the Mesh Bạn tạo mesh object, bạn cần bổ xung thêm liệu để mô tả model mà bạn muốn thể Ở đây, bạn có kho rỗng với kích thước thích hợp để chứa liệu cần thiết cho việc tạo khối lập phương Để xác định khối lập phương, trước tiên bạn cần lock véctơ buffer lại bổ xung vào véctơ mà khối lập phương cần Tiếp theo bạn cần lock index buffer copy toàn index vào Hàm SetupMesh giúp bạn bước hồn thành mesh với thơng tin cần thiết để tạo khối lập phương /************************************************************************************** * SetupMesh * Set up the vertex buffer and index buffer of a mesh **************************************************************************************/ HRESULT SetupMesh() { HRESULT hr; //biến giữ giá trị trả /////////////////////////////////////////////////////////////////////////////// //các véctơ vertex buffer CUSTOMVERTEX g_Vertices[ ]={ 99 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN // X Y Z {-1.0f, -1.0f, -1.0f, D3DCOLOR_ARGB(0,255,0,0)}, //0 {-1.0f, 1.0f, -1.0f, D3DCOLOR_ARGB(0,0,0,255)}, { 1.0f, 1.0f, -1.0f, D3DCOLOR_ARGB(0,0,255,0)}, //2 { 1.0f, -1.0f, -1.0f, D3DCOLOR_ARGB(0,0,0,255)}, //3 {-1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0,255,0)}, //4 { 1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0,0,255)}, //5 { 1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB(0,0,255,0)}, //6 {-1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB(0,0,0,255)} //1 //7 }; //Copy véctơ vào vertex buffer VOID* pVertices; // lock vertex buffer hr = boxMesh->LockVertexBuffer(D3DLOCK_DISCARD, (void**)&pVertices); //kiểm tra lại để chắn vertex buffer lock if FAILED (hr) return hr; ///////////////////////////////////////////////////////////////////////////////// //index buffer data //index buffer xác định phần tử khối lập phương, //hai phần tử mặt cube WORD IndexData[ ] = { 0,1,2, //0 2,3,0, //1 4,5,6, //2 6,7,4, //3 0,3,5, //4 5,4,0 //5 3,2,6, //6 6,5,3, //7 2,1,7, //8 7,6,2, //9 1,0,4, //10 4,7,1, //11 } //copy véctơ vào buffer memcpy(pVertices, g_Vertices, sizeof(g_Vertices) ); //mở khóa véctơ buffer boxMesh->UnlockVertexBuffer(); //chuẩn bị copy index vào index buffer VOID* IndexPtr; //khóa index buffer hr-boxMesh->LockIndexBufffer( 0, &IndexPtr); //kiểm tra xem index buffer khóa chưa if FAILED (hr) return hr; //copy index vào buffer memcpy(IndexPtr, IndexData, sizeof( IndexData)*sizeof(WORD)); //mở khóa buffer boxMesh->UnlockIndexBuffer(); return S_OK; } Điều mà hàm SetupMesh làm tạo ma trận g_Vertices Ma trận chứa véctơ véctơ màu mà bạn cần để xác định khối lập phương Tiếp đó, vectơ buffer bị locked thấy ví dụ Việc gọi hàm memcpy để copy tất véctơ vào vertex buffer sau thực unlock buffer 100 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Tiếp theo bạn cần điền vào index buffer Giống vectơ buffer, bạn phải lock trước liệu copy vào Các index mà index buffer sử dụng xác định ma trận IndexData Chú ý ma trận IndexData có kiểu WORD, điều có nghĩa chúng value 16-bit Sau bạn có giá trị xác định, bạn lock index buffer copy vào index việc gọi hàm memcpy unlock index buffer Chú ý: Cả vectơ index buffer cần thiết để tạo đối tượng mesh hợp lệ Hiển thị Mesh Bạn tạo mesh đưa liệu vào đó, bạn sẵn sàng đưa hình Hàm drawMesh việc biểu diễn mesh cần Hàm làm khối lập phương quay hình /*************************************************************************** *void drawMesh (LPD3DXMESH mesh, D3DMATERIAL9 material) * Draws the mesh ****************************************************************************/ void drawMesh (LPD3DXMESH mesh, D3DMATERIAL9 *marterial) { //quay mesh D3DXMATRIX matRot; D3DXMATRIX matView; D3DXMATRIX matWorld; //tạo ma ma trận quay D3DXMatrixMultiply(&matWorld, &matRot, &matView); //lấy biến đổi vào kết ma trận matWorld pd3dDecice ->SetTransform( D3DTS_WORLDM, &matWorld); //đưa giữ liệu vào sử dụng pd3dDevice->SetMaterial(material); //vẽ mesh mesh->DrawSubset(0); } Phần hàm drawMesh quay dịch chuyển khối lập phương hình Sau giữ liệu mà khối lập phương sử dụng nạp vào qua việc gọi SetMaterial Phần quan trọng hàm drawMesh gọi DrawSubset Hàm DrawSubset thông báo Direct3D phần mesh bạn muốn thị lên hình Vì mesh mà bạn tạo phần trước chứa nhóm đơn thuần, giá trị truyền cho DrawSubset Trên hình 7.1 kết mesh đựợc hiển thị hình Bạn tìm thấy đầy đủ source code chapter7\example1 đia CD-ROM 101 Dịch TransTeam diễn đàn Gamedev.VN Beginning DirectX9 Hình 7.1 hình ảnh mesh cube hình Chú ý: Mesh chứa nhiều nhóm đặc tính khác Những nhóm khác lưu giữ tập hợp tất phần tử dùng để mô tả phân chia mesh Ví dụ bạn có vùng mesh mà cần texture khác nhau, vùng đặt vào nhóm đặc tính riêng rẽ Bằng cách này, bạn điều chỉnh lại texture giữ liệu mà Dicrect3D sử dụng trước kết xuất nhóm Tối ưu hóa Mesh Khi mesh tạo, khơng có định dạng tốt ưu để Direct3D vẽ Ví dụ mesh bạn phải chứa véctơ bị lặp lại sử dụng cho nhiều phần tử, véctơ phần tử khơng nằm thứ tự có hiệu Khi tối ưu hóa mesh cách sử dụng “véctơ dùng chung” cho phép véctơ phần tử xếp lại, bạn tăng trình thực kết xuất mesh Thư viện tổng hợp D3DX cung cấp hàm để tối ưu mesh: Optimize OptimizeInplace Mỗi hàm thực công việc với key khác Optimize tạo output mesh, ngược lại OptimizeInplace làm thay đổi input mesh Tôi giải thich cụ thể hai hàm sử dụng với mesh Hàm Optimize định nghĩa nhu sau, lấy input mesh, tối ưu khởi tạo output mesh HRESULT Optimize( DWORD Flags, CONST DWORD *pAdjacencyIn, DWORD *pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVerTexRemap, LPD3DXMESH *ppOptMesh ); Hàm Optimize có tham số: ƒ Flags – dấu hiệu dạng tối ưu cho việc thi hành Bạn càn tìm flag cho tham số bảng liệt kê D3DXMESHOPT 102 Dịch TransTeam diễn đàn Gamedev.VN Beginning DirectX9 ƒ pAdjacencyIn – trỏ trỏ tới ma trận lưu liệu liền kề cho input mesh ƒ pAdjacencyOut – trỏ trỏ tới ma trận lưu giữ liệu liền kề cho output mesh đựơc tối ưu ƒ pFaceRemap – trỏ trỏ tới buffer lưu index cho output mesh ƒ ppVertexRemap – địa gửi đến trỏ giao diện ID3DXBuffer dành cho output mesh ƒ ppOptmesh – giao diện ID3DXMesh lưu giữ output mesh tạo Hàm OptimizeInplace làm thay đổi input mesh, xác định sau: HRESULT Optimize( DWORD Flags, CONST DWORD *pAdjacencyIn, DWORD *pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVerTexRemap, ); Hàm OptimizeInplace có tham số: ƒ Flags – dấu hiệu dạng tối ưu để thi hành Bạn tìm thấy dấu hiệu cho tham số bảng liệt kê D3DXMESHOPT ƒ pAdjacencyIn – trỏ trỏ tới ma trận lưu giữ liệu liền kề cho mesh ƒ pAdjacencyOut – trỏ trỏ tới buffer lưu giữ dũ liệu liền kề cho mesh tối ưu Nếu bạn không muốn tập trung liệu liền kề, bạn chuyển giá trị NULL cho tham số ƒ pFaceRemap – trỏ trỏ tới buffer lưu giũ index dũ liệu phần tử Nếu bạn không muốn chọn thơng tin bạn gán NULL cho tham số ƒ ppVerTexRemap – trỏ trỏ tới giao diện ID3DXBuffer dùng để lưu giũ index véctơ Bảng 7.1 Các tham số Flags Giá trị Mô tả D3DXMESHOPT_COMPACT Sắp xếp lại bề phần tử để bỏ véctơ phần tử không sử dụng D3DXMESHOPT_ATTRSORT Sắp xếp lại bề phần tử để giảm số trạng thái giũ liệu thay đổi D3DXMESHOPT_VERTEXCACH Sắp xếp lại bề phần tử để giúp đưa hình vẽ D3DXMESHOPT_STRIPREORDER Sắp xếp bề phần tử để phóng to chiều dài hình tam giác gần kề D3DXMESHOPT_IGNOREVERTS Chỉ giúp bề phần tử đựợc tối ưu, véctơ khơng D3DXMESHOPT_DONOTSPLIT Ngăn ngừa cắt nhỏ cảu véctơ chia sẻ nhóm D3DXMESHOPT_DIVICEINDEPENDENT Giúp véctơ cất giữ kích thước vào tập hợp mà kích thước làm việc tốt phần cứng đựoc thừa kế 103 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Getting the Mesh Details Trong suốt q trình tối ưu hóa mesh, bạn tò mò muốn biết details mesh mà bạn làm việc có Ví dụ bạn phải tự hỏi có vécto bề phần tử mà mesh chứa trước tối ưu hóa Giao diện ID3DXMesh cung cấp hàm có ích cho mục đích này: ƒ GetNumVertices – Trả số véctơ có mesh ƒ GetNumfaces – Trả số phần tử có mesh Đoạn chưong trình sau mẫu mà cách làm để sử dụng hàm biểu diễn cửa sổ MessageBox chứa số phần tử số véctơ //biểu diễn số véctơ số phần tử vào mesh std::string numVertices; sprintf ( (char*) numVertices.c_str (), “message”, MB_OK); //biểu diễn số phần tử mesh std::string numFaces; sprintf ( (char*) numFaces.c_str(), “numFaces = %d”, pMeshSysMem->GetNumFaces()); MessageBox (NULL, numFaces.c_str (), “mesage”, MB_OK); Biến pMeshSysMem phải chứa mesh hợp lệ trước GetNumVertices GetNumFaces gọi The Attribute Table Trong suốt q trình tối ưu mesh, bạn có tùy chọn khởi tạo bảng đặc tính Bảng bao gồm thông tin đặc điểm buffer mesh Attribute buffer chứa đặc điểm véctơ mesh Như nói trước, mesh chứa nhiều nhóm đặc tính Mỗi nhóm chứa danh sách véctơ mà thực chức nhóm Khi sử dụng nhiều nhóm đặc tính bạn chia cắt cách có lựa chọn mesh thành phần riêng rẽ Ví dụ mesh xe chia thành nhóm chứa thân xe nhóm khác chứa bánh xe Nếu nhóm chứa thân xe đánh dấu nhóm nhóm chứa bánh xe nhóm bạn sử dụng cách gọi hàm để gọi hàm DrawSubset để vẽ toàn xe cafMesh->DrawSubset(0); cafMesh->DrawSubset(1); // vẽ thân // vẽ bánh xe Vì nhóm cần liệu khác nhau, việc gọi hàm SetMaterial phải đựơc gọi trước hàm DrawSubset Để phân biệt nhóm riêng rẽ mesh, bạn cần tạo bảng đặc tính Bạn tạo bảng đặc tính cách gọi hai hàm tối ưu Khi bạn gọi hàm tối ưu xắp xếp lại bề phần tử bảng đặc tính khởi tạo lại Theo mặc định mesh cần nhiều loại vật liệu, tập hợp khởi tạo cho nhóm Trong trường hợp khối lập phương bạn tạo ví dụ trước chứa loại vật liệu Hàm OptimizeMesh sau đưa khối lập phương chứa biến boxMesh chia thành nhóm nhỏ riêng Một nửa khối lập phương biểu diễn phần vật liệu, phần thứ biểu diễn phần vật liệu khác 104 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN /********************************************************************* *OptimizeMesh *************************************************************************/ void OptimizeMesh (void) { //gọi hàm OptimizeInplace để khỏ tạo bảng đặc tính boxMesh-> OptimizeInplace(D3DXMESHOPT_ATTRSORT, 0, NULL, NULL, NULL); DWORD numAttr; D3DXATTRIBUTERANGE *attribTable = D3DXATTRIBUTERANGE [2]; // lấy số vật thể bảng boxMesh->GetAttributeTable(attributeTable, &numAttr); //chuyền đặc tính cho nhóm thứ attributeTable[0].AttriId = 0; attributeTable[0].FaceStart = 0; attributeTable[0].FaceCount = 6; attributeTable[0].VertexStart = 0; attributeTable[0] VertexCount = 8; //chuyển đặc tính cho nhóm thứ attributeTable[1] AttriId = 1; attributeTable[1].FaceStart = 6; attributeTable[1].FaceCount = 6; attributeTable[1].VertexStart = 0; attributeTable[1] VertexCount = 8; // viết bảng đặc tính lên mesh boxMesh->SetAttributeTable(attributeTable, 2); } Đoạn chương trình gọi hàm OptimizeInplace mesh khối lập phương chưa biến boxMesh Vì tơi sử dụng OptimizeInplace, nên tiếp tục sử dụng mesh khối lập phương ngun Sau tơi tạo nhóm đặc tính riêng rẽ nên tơi xây dựng ma trận có hai phần từ kiểu D3DXATTRIBUTERANGE D3DXATTRIBUTERANGE *attribTable = D3DXATTRIBUTERANGE [2]; Mỗi phần tử cấu trúc D3DXATTRIBUTERANGE chứa thông tin mà Direct3D cần để xác định bảng đặc tính Cấu trúc D3DXATTRIBUTERANGE đây: Typedef struct_ D3DXATTRIBUTERANGE { DWORD AttribId; DWORD FaceStart; DWORD FaceCount; DWORD VertexStart; DWORD VertexCount } D3DXATTRIBUTERANGE; Cấu trúc D3DXATTRIBUTERANGE có biến: ƒ AttribId – số nhóm hành ƒ FaceStart –chỉ số phần tử nhóm ƒ FaceCount – số phần tử có nhóm ƒ VertexStart – số véctớ nhóm ƒ VertexCount – số véctơ mà nhóm chứa 105 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN định Nếu máy bạn có nhiều cạc, bạn phải liệt kê chúng tìm mà chương trình bạn cần Bạn tạo thiết bị DS cách sử dụng hàm DirectSoundCreate8, định nghĩa sau: HRESULT WINAPI DirectSoundCreate8( LPCGUID lpcGuidDevice, LPDIRECTSOUND8 * ppDS8, LPUNKNOWN pUnkOuter ); Hàm cần ba tham số: lpcGuidDevice Nó miêu tả thiết bị âm sử dụng Tham số DSDEVID_DefaultPlayback NULL Dùng NULL bạn muốn dùng thiết bị âm mặc định ppDS8 Địa biến lưu thiết bị DS tạo pUnkOuter Giao tiếp IUnknown đối tượng điều khiển Giá trị nên để NULL Một lệnh gọi chuẩn gọi hàm DirectSoundCreate8 sử dụng thiết bị âm mặc định có dạng sau: // biến giữ giá trị trả lại HRESULT hr; // biến lưu giữ thiết bị DS LPDIRECTSOUND8 m_pDS; // Thử tạo thiết bị DS hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ; // Kiểm tra giá trị trả lại để chắn có thiết bị tạo if FAILED ( hr ) return false; Nếu đoạn code ko thể tạo thiết bị DS đúng, hàm trả lại FALSE Liệt kê thiết bị âm Thỉnh thoảng, bạn muốn liệt kê thiết bị âm hệ thống Nếu, ví dụ như, thiết bị âm mặc định ko có đủ tất hàm mà game cần bạn tìm thiết bị khác hệ thống bạn Nếu bạn ko muốn dùng thiết bị mặc định, bạn phải liệt kê thiết bị có sẵn trước gọi hàm DirectSoundCreate8 Khi qúa trình liệt kê hoàn thành, bạn cần GUID cho thiết bị, mà bạn truyền cho hàm DirectSoundCreate8 thay NULL Quá trình liệt kê quản lý qua hàm DirectSoundEnumerate Như thành phần DX, liệt kê thiết bị cần hàm callback Hàm DirectSoundEnumerate gọi hàm callback thiết bị âm phát Trong hàm callback, bạn xác định khả thiết bị chọn xem có muốn dùng ko Hàm DirectSoungEnumerate định nghĩa sau: 164 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN HRESULT WINAPI DirectSoundEnumerate( LPDSENUMCALLBACK lpDSEnumCallback, LPVOID lpContext ); Hàm DirectSoundEnumerate cần tham số: lDSEnumCallback Địa hàm callback lContext Bất liệu bạn muốn truyền cho hàm callback Đoạn code sau cho ví dụ gọi hàm DirectSoundEnumerate: // Biến lưu đoạn code trả HRESULT hr; // Gọi hàm DirectSoundEnumerate hr = DirectSoundEnumerate( (LPDSENUMCALLBACK)DSoundEnumCallback, 0); // Kiểm tra đoạn code trả để chắc hàm gọi thành công if FAILED ( hr) return false; Hàm DirectSoundEnumerate callback Hàm callback cung cấp cho DirectSoundEnumerate gọi trình liệt kê tìm thấy thiết bị Nếu nhiều thiết bị cài đặt hệ thống, hàm callback gọi lần cho Nhiệm vụ hàm callback cho code hội để tạo thiết bị DS dùng để thu thập thơng tin thiết bị Nếu bãn tìm kiếm thiết bị âm có khả bắt âm chẳng hạn, bạn kiểm tra khả thiết bị truyền cho hàm callback để xem có khả ko? Hàm DirectSoundEnumerate cần hàm callback định dạng DSEnumCallback BOOL CALLBACK DSEnumCallback( LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext ); Bạn phải khai báo hàm callback theo cách say Hàm callback cần tham số: lpGuid Địa GUID định nghĩa thiết bị âm Nếu giá trị NULL, thiết bị liệt kê thiết bị lpcstrDescription Một biến NULL-terminated string cung cấp dòng text miêu tả thiết bị 165 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN lpcstrModule Một biến NULL-terminated string cung cấp tên module driver DS cho thiểt bị lpContext Dữ liệu thêm vào truyền cho hàm callback thông qua biến lpContext DirectSoundEnumerate Hàm DSEnumarate trả lại giá trị boolean Nếu giá trị TRUE, hàm DirectSoundEnumerate tiếp tục liệt kê thiết bị thêm vào Nếu giá trị trả lại FALSE, trình liệt kê kết thúc Chú ý: Thiết bị thường liệt kê hai lần, với giá trị NULL truền cho tham số lpGuid lần hai GUID Ví dụ hàm callback say tạo hộp thoại hiển thị tên thiết bị âm driver /****************************************************************************** * DirectSoundEnumerate callback function ******************************************************************************/ BOOL CALLBACK DSCallback( GUID* pGUID, LPSTR strDesc, LPSTR strDrvName, VOID* pContext ) { // Biến tạm thời lưu thông tin thiết bị string tempString; // Xây dựng biến String thông tin cung cấp hàm callback tempString = “Device name = “; tempString += strDesc; tempString += “\nDriver name = “; tempString += strDrvName; // Hiển thị kết hộp thoại MessageBox (NULL, tempString.c_str(), “message”, MB_OK ); // Tiếp tục liệt kê thiết bị khác, trả lại TRUE return true; } Một biến string tạm thời tạo để lưu thông tin Hàm trả giá trị TRUE, nên liệt kê tất thiết bị âm hệ thống Tồn ví dụ nằm thư mục chapter10\example1 đĩa CD Hình 10.1 kết quả: Thiết lập mức độ hợp tác 166 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Bởi DS cho bạn quyền truy cập tới thiết bị phần cứng, nên có cần xác định mức độ hợp tác Tương tự DirectInput, DS thử nhận quyền truy cập bình thường tới thiết bị Với DirectInput, bạn nhận quyền truy cập dành riêng tới thiết bị, giới hạn quyền dùng ứng dụng bạn Với DS, bạn ko thể nhận quyền truy cập dành riêng với thiệt bị âm thanh, bạn thiết lập mức độ ưu tiên cao cho ứng dụng bạn hệ điều hành dùng thiết bị âm Tất nhiên, bạn ko thể giành quyền giành riêng với cạc âm thanh, nên ứng dụng khác(cả hệ điều hành) gây âm chúng Có ba mức độ hợp tác mà DS thiết lập được: DSSCL_NORMAL Mức độ hoạt động tốt với ứng dụng khác cho phép kiện khác xảy Bởi ứng dụng bạn phải chia sẻ thiết bị, nên bạn ko thể thay đổi đinh dạng primary buffer(bộ đệm sơ cấp) DSSCL_PRIORITY Nếu bạn muốn nhiều điều khiển với đệm âm thanh, bạn nên dùng mức độ Hầu hết games dùng DSSCL_WRITEPRIMARY Mức độ giúp ứng dụng viết lên primary buffer Mức độ hợp tác thiết đặt hàm SetCooperativeLevel Giao tiếp IDirectSound8 hỗ trợ hàm Hàm định nghĩa sau: HRESULT SetCooperativeLevel( HWND hwnd, DWORD dwLevel ); Hàm cần hai tham số: hwnd Kênh điều khiển(handle) cửa sổ ứng dụng yêu cầu thay đổi mức độ hợp tác(cooperative level) Dwlevel Một ba mức độ hợp tác nêu bên Ví dụ: // biến lưu code trả HRESULT hr; // biến chứa thiết bị DS hợp lệ LPDIRECTSOUND8 g_pDS = NULL; hr = DirectSoundCreate8( NULL, & g_pDS, NULL ) ; // Thiết lập mức độ hợp tác hr = g_pDS->SetCooperativeLevel( hwnd, DSSCL_PRIORITY ); // Kiểm tra kết trả if FAILED ( hr ) return false; Ở đoạn code trên, mức độ hợp tác thiết lập DSSCL_PRIORITY Trước bạn gọi hàm SetCooperativeLevel, bạn phải có trả hợp lệ chứa thiết bị DS 167 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN Giờ thiết lập mức độ hợp tác rồi, bạn tạo đệm load liệu Files âm Bạn load liệu âm DS vào đệm sơ cấp trước dùng Bạn load nhạc hiệu ứng âm vào đệm tĩnh(static buffer) đệm luồng(streaming buffer) Bộ đệm tĩnh đệm có độ dài cố định có âm đầy đủ load vào Bộ đệm luồng đêm cần âm cần load lớn chỗ chứa đệm Trong trường hợp này, đệm nhỏ sử dụng, âm load vào play liên tục Đoạn bàn luận việc đệm dùng DS Bộ đệm thứ cấp(Secondary Buffer) DS Sử dụng đệm để chứa liệu audio cần Trước bạn play âm thanh, bạn phải tạo đệm thứ cấp để chứa Sau đệm tạo ra, âm load tồn bọ vào đó(hoặc phần với đệm luồng) say play DS cho phép tuỳ ý lượng đệm thứ cấp play đồng thời, tất trộn lẫn đệm sơ cấp Trước bạn tạo đệm sơ cấp, bạn cần biết định dạng loại âm chứa DS yêu cầu định dạng đệm phải giống định dạng âm chứa Ví dụ âm file 16-bit WAV cần kênh âm, đệm cần theo định dạng Hầu hết lúc, âm cho game định dạng chung, cho phép bạn biết trước định dạng đệm cần Nếu bạn có nhiệm vụ viết trình generic audio player, bạn ko thể đảm bảo files âm bạn load có định dạng Định dạng đệm DS miêu tả cấu trúc WAVEFORMATEX Cấu trúc định nghĩa say: typedef struct { WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; WORD wBitsPerSample; WORD cbSize; } WAVEFORMATEX; Cấu trúc bao gồm bảy biến: wFormatTag Kiểu audio dạng sóng(waveform audio) Với liệu hay kênh PCM, giá trị nên để là: WAVE_FORMAT_PCM nChannels Số lượng kênh cần tới nSamplesPerSec Tốc độ mẫu nAvgBytesPerSec Tốc độ tryền liệu trung bình giây 168 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN nBlockAlign Sự chỉnh bytes Bạn định giá trị cần cách nhân số kênh với bits per sample chia cho wBitsPerSample Số bits per sample Giá trị 16 cbSize Số bytes thêm vào để nối thêm liệu vào cấu trúc Bạn tạo cấu trúc chuẩn WAVEFORMATEX bạn biết định dạng liệu file WAV bạn sử dụng Nhưng ko chắn, bạn tạo cấu trúc điền vào say mở file audio Cấu trúc WAVEFORMATEX phần thông tin bạn cần tạo đệm thứ cấp Bên cạnh ghi rõ định dạng đệm, bạn phải biết thêm thơng tin, kích thước liệu audio đệm chứa Bạn cần cấu trúc thứ hai để miêu tả đệm thứ cấp: DSBUFFERDESC Cấu trúc định nghĩa sau: typedef struct { DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; DWORD dwReserved; LPWAVEFORMATEX lpwfxFormat; GUID guid3DAlgorithm; } DSBUFFERDESC, *LPDSBUFFERDESC; Cấu trúc có biến thành phần: dwSize Kích thước cấu trúc DSBUFFERDESC tính byte dwFlags Một tập hợp DWORD flags, ghi rõ khả đệm dwBufferBytes Kích thước đệm Đây số bytes liệu âm mà đệm chứa dwReserved Một giá trị dành riêng mà buộc phải = lpwfxFormat Địa cấu trúc WAVEFORMATEX Guid3Dalgorithm Một định danh GUID cho biết thuật toán twospeaker virtualization sử dụng Tham số dwFlags miêu tả chi tiết bảng 10.1 Bộ đệm, bên cạnh việc có định dạng, có điều khiển Chúng cho phép bạn điều chỉnh âm lượng, tần số, dịch chuyển(movement)??? Bạn phải nói rõ kiểu điều khiển bạn muốn cấu trúc DSBUFFERDESC nêu Bảng 10.1 DSBUFFERDESC Flags Giá trị DSBCAPS_CTRL3D Miêu tả Bộ đệm có điều khiển 3D DSBCAPS_CTRLFREQUENCY Bộ đệm có điều khiển tần số âm DSBCAPS_CTRLFX BĐ hỗ trợ hiệu ứng DSBCAPS_CTRLPAN BĐ thay đổi âm lượng kênh 169 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN DSBCAPS_CTRLPOSITIONNOTIFY phải kênh trái(pan) âm Đây vị trí thơng báo đệm DSBCAPS_CTRLVOLUME Bạn điều chỉnh âm DSBCAPS_GLOBALFOCUS Nếu cờ bật người dùng chuyển focus sang ứng dụng khác, âm bật Bạn đặt đệm vào nhớ phần cứng phần mềm vào lúc chạy Bộ đệm dùng hardware mixing Nếu cờ bật ko đủ nhớ, lời gọi đệm thất bại Bộ đệm đặt nhớ phần mềm, software mixing sử dụng Âm đệm giảm xuống vị trí ảo xa Đây đệm sơ cấp DSBCAPS_LOCDEFER DSBCAPS_LOCHARDWARE DSBCAPS_LOCSOFTWARE DSBCAPS_MUTE3DATMAXDISTANCE DSBCAPS_PRIMARYBUFFER DSBCAPS_STATIC DSBCAPS_STICKYFOCUS Bộ đệm đặt nhớ phần cứng on-board Khi bạn chuyển focus sang ứng dụng khác, bạn nghe đệm có stickyfocus Bộ đệm thường ko kêu khi điều xảy Tạo đệm thứ cấp(secondary buffer) Giờ bạn tạo cấu trúc DSBUFFERDESC, bạn sẵn sàng tạo đệm thứ cấp thực Bộ đệm thứ cấp tạo với lời gọi CreatSoundBuffer, định nghĩa sau: HRESULT CreateSoundBuffer( LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER * ppDSBuffer, LPUNKNOWN pUnkOuter ); Hàm cần tham số: pcDSBufferDesc Địa cấu trúc xác định DSBUFFERDESC ppDSBuffer Địa biến chứa đệm tạo pUnkOuter Địa tới điều khiển giao tiếp IunKnown đối tượng Giá trị nên để NULL Một lời gọi mẫu hàm sau: // định nghĩa cấu trúc WAVEFORMATEX WAVEFORMATEX wfx; // Khởi trị cấu trúc tất 170 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); // Thiết lập định dạng WAVE_FORMAT_PCM wfx.wFormatTag = (WORD) WAVE_FORMAT_PCM; // Thiết lập số kênh âm wfx.nChannels = 2; // Thiết lập tốc độ mẫu 22050 wfx.nSamplesPerSec = 22050; // Tính giá trị nBlockAlign wfx.wBitsPerSample = 16; wfx.nBlockAlign = (WORD) (wfx.wBitsPerSample / * wfx.nChannels); // Tính giá trị the nAvgBytesPerSec wfx.nAvgBytesPerSec = (DWORD) (wfx.nSamplesPerSec * wfx.nBlockAlign); // Định nghĩa cấu trúc DSBUFFERDESC DSBUFFERDESC dsbd; // Khởi trị cấu trúc tất ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); // Thiết lập kích thước cấu trúc dsbd.dwSize = sizeof(DSBUFFERDESC); // Thiết lập cờ dsbd.dwFlags = 0; // kích thước đệm dsbd.dwBufferBytes = 64000; // GUID thuật toán dsbd.guid3DAlgorithm = GUID_NULL; // địa cấu trúc WAVEFORMATEX dsbd.lpwfxFormat = &wfx; // Định nghĩa biến lưu đệm tạo LPDIRECTSOUNDBUFFER DSBuffer = NULL; // Tạo đệm hr = g_pDS->CreateSoundBuffer( &dsbd, &DSBuffer, NULL ); // Kiểm tra code trả để chắc lời gọi hàm CreatSoundBuffer thành công if FAILED (hr) return NULL; Nếu lời gọi hàm CreatSoundBuffer thành công, biến DSBuffer đệm DS hợp lệ Trong ví dụ trên, định dạng cấu trúc WAVEFORMATEX hard-coded, buộc tất files load vào đệm phải có kiểu định dạng xác định tối đa dài 64000 bytes Load file âm vào đệm Giờ bạn tạo đệm, bạn cần load liệu âm vào Load liệu âm vào đệm cần bạn trước hết phải mở file chứa liêu đó, 171 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN copy nội dung vào đệm tạo Với đệm tĩnh(static buffer), tất liệu copy vào đệm Bởi đệm âm diện tích nhớ điều khiển DS, bạn phải khố(lock) trước viết lên Khố đệm chuẩn bị nhớ để viết vào Sau khoá đệm, chương trình load âm vào Khi bạn hồn thành việc load, bạn phải nhớ mở khố(unlock) Mở khố đệm cho phép DS chế tác nội dung lần Khố(Lock) đệm Khoá đệm âm cho code hội chế tác, thay đổi liệu âm đệm Khoá đệm cần hàm Lock, sau: HRESULT Lock( DWORD dwOffset, DWORD dwBytes, LPVOID * ppvAudioPtr1, LPDWORD pdwAudioBytes1, LPVOID * ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags ); Hàm Lock yêu cầu tham số: dwOffset Biến định vị trí đệm nên bắt đầu lock dwBytes Số bytes bên đệm để lock ppvAudioPtr1 Biến nhận trỏ tới phần đầu đệm bị lock pdwAudioBytes1 Biến nhận số bytes khối nhớ trỏ ppvAudioPtr1 ppvAudioPtr2 Biến nhận trỏ tới phần thứ hai đệm bị lock Nếu bạn điền vào đệm với liệu âm thanh, biến nên để NULL pdwAudioBytes2 Biến nhận số bytes khối nhớ trỏ ppvAudioPtr2 Biến nên để NULL bạn điền vào đệm với liệu âm dwFlags Đây cờ(Flags) định lock nên diễn nào: DSBLOCK_FROMWRITECURSOR Bắt đầu lock từ trỏ ghi(write cursor) DSBLOCK_ENTIREBUFFER Lock đệm Nếu cờ bật, biến dwBytes bỏ qua Mở khoá(unlock) đệm Lúc này, bạn tuỳ ý đọc liệu âm load vào đệm Sau q trình hồn thành, bạn mở khố(unlock) đệm hàm Unlock, sau: HRESULT Unlock( 172 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2 ); Hàm Unlock cần tham số: pvAudioPtr1 Địa giá trị tham số ppvAudioPtr1 dùng hàm Lock dwAudioBytes1 Số bytes viết vào pvAudioPtr1 pvAudioPtr2 Địa giá trị tham số ppvAudioPtr2 dùng hàm Lock dwAudioBytes2 Số bytes viết vào pvAudioPtr2 Đọc từ liệu âm vào đệm Đọc liệu âm vào đệm thứ cấp (secondary buffer) phức tạp Để giải thích dễ hiểu hơn, tỗi giải thích q trình qua lớp CWaveFile lớp DS framework DS Framework cung cấp cách đơn giản để load liệu âm sử dụng định dạng file WAV Đây định dạng âm mặc định Windows, có WAV Chú ý: Các lớp DS framework khai báo file dsutil.cpp dsutil.h, cung cấp hàm chung gắn liền với DS Bạn tìm thấy chúng thư mục Samples\C++\Common\Src Samples\C++\Common\Inc, folder mà bạn cài DirectX Software Development Kit (SDK) Bước việc load file WAV vào đệm tạo đối tượng CWaveFile Đối tượng cung cấp cho bạn phương thức để mở, đóng đọc files WAV Dòng code sau cách tạo đối tượng CWaveFile CWaveFile wavFileObj = new CWaveFile( ); Tiếp theo, sử dụng phương thức Open cung cấp lớp CWaveFile, bạn có thê nhận quyền truy cập vào file WAV bạn muốn dùng Đoạn code sau sử dụng hàm Open kiểm tra xem file WAV có chứa liệu ko? // Mở file dạng WAV có tên test.wav wavFile->Open(“test.wav”, NULL, WAVEFILE_READ ); // Kiểm tra để chắn kích thước liệu file hợp lệ if( wavFile->GetSize( ) == ) return false; Đoạn code mở file tên test.wav để đọc Sau kiểm tra kích thước liệu bên file, file ko chứa liệu, dừng việc đọc Bước tạo đệm thứ cấp (secondary buffer) để chứa liệu Bước hướng dẫn Sau tạo đệm, bạn phải khố(lock) trước bạn viết liệu WAV vào Đoạn code giải thích cách dùng hàm Lock để chuẩn bị đệm đọc toàn file WAV 173 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN HRESULT hr; VOID* pDSLockedBuffer = NULL; // trỏ tới vùng nhớ đệm bị khố DWORD dwDSLockedBufferSize = 0; // kích thước đệm DS bị khoá // Bắt đầu từ phần đầu đệm hr = DSBuffer->Lock( 0, // Nhận đệm 64000 bytes 64000, // Biến lưu trỏ tới phần mở đầu // đệm &pDSLockedBuffer, // Biến lưu kích thước đệm bị khoá &dwDSLockedBufferSize, NULL,// Ko cần thứ hai NULL, // Ko cần thứ hai // Khoá đệm DSBLOCK_ENTIREBUFFER); // Kiểm tra code trả để chắc lock // thành công if FAILED (hr) return NULL; Đoạn code lock đệm cờ DSBLOCK_ENTIREBUFFER Cờ khiến đệm bị lock toàn Biến DSBuffer phải DirectSoundBuffer hợp lệ Giờ đệm lock đúng, bạn ghi liệu WAV vào Một lần tơi lại dùng phương thức có lớp CWaveFile Trước bạn đọc liệu WAV vào đệm, bạn phải reset lại liệu WAV phần đầu Bạn làm điều cách dùng phương thức ResetFile Tiếp theo bạn dùng phương thức Read để đưa liệu WAV vào đệm Đoạn code reset lại file WAV để đọc đưa liệu vào đệm HRESULT hr; // biến lưu kết trả lại DWORD dwWavDataRead = 0; // biến chứa lượng liệu đọc từ file // WAV wavFile->ResetFile( ); // Reset lại file WAV đầu file // Đọc file hr = wavFile->Read( ( BYTE* ) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ); // Kiểm tra để chắn thành công if FAILED (hr) return NULL; Biến wavFile phải chứa đối tượng CWaveFile hợp lệ trước sử dụng Đầu tiên, hàm ResetFile gọi, lời gọi hàm Read Hàm Read cần ba tham số Tham số thứ trỏ tới vùng nhớ 174 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN chứa đệm để copy liệu vào Tham số kích thước vùng đệm khoá, tham số cuối nhận khối lượng liệu đọc từ file WAV, tính bytes Sau gọi hàm Read, đệm điền liệu từ file WAV Bạn an tồn mở khoá đệm Play âm đệm Giờ bạn có liệu âm hợp lệ chứa DirectSoundBuffer, bạn play liệu mà chứa Sau tồn cơng việc cần để tạo đệm điền liệu vào đó, giừo việc play đơn giản Một hàm đơn giản Play hoàn thành việc Hàm phương thức cung cấp đối tượng DirectSoundBuffer Nó sau: HRESULT Play( DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags ); Hàm cần ba tham số: dwReserved1 Một giá trị để dành trước phải dwPriority Mức độ ưu tiên để play âm Nó giá trị khoảng 0xFFFFFFFF Bạn phải đặt mức độ ưu tiên cờ DSBCAPS_LOCDEFER chưa bật đệm tạo dwFlags Các cờ rõ âm play nào? Cờ tơi giải thích DSBPLAY_LOOPING Cờ khiến âm lặp lại đạt đến cuối đệm Nếu âm nên play lần, tahm số dwFlags nên truyền giá trị Đoạn code khiến đệm âm play nội dung nó: DSBuffer->Play( 0, 0, DSBPLAY_LOOPING); Biến DSBuffer phải chứa đối tượng DirectSoundBuffer hợp lệ, chứa liệu Trong trường hợp này, cờ DSBPLAY_LOOPING truyền vào hàm khiến âm lặp lại sau hoàn thành lượt Dừng âm Thường sau play âm thanh, bạn ko cần lo nữa, trừ bạn bảo âm lặp lại Trong trường hợp này, bạn cần lệnh dừng âm Bạn làm điều nhờ phương thức Stop, cung cấp đối tượng DirectSoundBuffer, sau: HRESULT Stop( ); Hàm ko cần tham số Nó trả lại kết cho biết hàm gọi thành cồng hay ko? Bạn tìm thấy ví dụ đầy đủ load file âm play thư mục chapter10\example2 đĩa Sử dụng điều khiển đệm(buffer control) Như đề cập, đệm DS điều khiển diện mạo âm Ví dụ, qua đệm, bạ thay đổi âm lượng, tần 175 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN số, pan(chỉnh âm lượng hai loa) âm Trong đoạn bạn học cách dùng chúng Thay đổi âm lượng Bạn thay đổi âm lượng âm qua đệm chứa Bạn điều chỉnh âm lượng khoảng giá trị DSBVOLUME_MIN DSBVOLUMEMAX Giá trị DSBVOLUME_MIN miêu tả im lặng DSBVOLUME_MAX miêu tả âm lượng gốc âm Chú ý: DS ko hỗ trợ khuếch đại âm, bạn ko thể tăng âm lượng Bạn điều chỉnh âm lượng âm qua hàm SetVolume sau: HRESULT SetVolume ( LONG lVolume ); Hàm cần tham số: lVolume Bạn cho giá trị từ 10000(DSBVOLUME_MIN) 0(DSBVOLUME_MAX) Bạn nhận giá trị âm lượng mà âm play hàm Getvolume Hàm sau: HRESULT GetVolume ( LPLONG plVolume ); Hàm cần tham số, trỏ tới biến nhận giá trị âm Chú ý: Trước dùng hai hàm trên, bạn phải thiết lập đệm cho phép dùng chúng, cách bật cờ DSBCAPS_CTRLVOLUME cấu trúc DSBUFFERDESC bạn tạo đệm thứ cấp (secondary buffer) Panning âm thanh(chỉnh âm lượng hai loa) Bộ đệm DS cho phép âm pan hai loa Pan giảm âm lượng loa tăng bên Âm nghe di chuyển Pan dùng tư tưởng chung hàm SetVolume Loa trái loa phải tăng giảm âm lượng phụ thuộc hai giá trị: DSBPAN_LEFT DSBPAN_RIGHT Giá trị đầu DSBPAN_LEFT, tương đương -10000, tăng âm lượng loa trái tới full, làm im loa Và giá trị DSBPAN_RIGHT, tương đương 10000, tăng âm lượng loa phải làm câm loa trái Bằng cách dùng giá trị DSBPAN_LEFT DSBPAN_RIGHT, âm bị pan từ loa sang loa Một giá trị thứ ba, DSBPAN_CENTER, 0, chỉnh hai tới full âm lượng Giá trị pan âm đặt hàm SetPan, sau: HRESULT SetPan( LONG lPan 176 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN ); Hàm cần tham số: lPan, nhận giá trị DSBPAN_LEFT DSBPAN_RIGHT(-10000->10000) Nếu bạn muốn biết giá trị pan tại, bạn dùng hàm GetPan: HRESULT GetPan( LPLONG plPan ); Hàm cần tham số: plPan, trỏ tới biến LONG nhận giá trị pan Chú ý: Trước dung hai hàm này, bạn phải thiết lập đệm cho phép dùng Bạn cần đặt cờ DSBCAPS_CTRLPAN cấu trúc DSBUFFERDESC tạo đệm Tổng kết chương Dùng vừa học, bạn play nhạc hiệu ứng âm đơn giản cho game Bạn mở rộng học để play nhiều âm đồng thời, hay tạo nhạc động, sửa điều khiển game Trong chương sau, đặt thứ học với để tạo game đơn giản sử dụng phần nói sách Những thứ bạn học Trong chương này, bạn học: DS dùng nào? Có kiểu đệm nào? Liệt kê thiết bị âm có hệ thống Load Play file WAV Điều khiển phát lại(playback) file âm Câu hỏi ơn tập Bạn tìm câu trả lời phụ lục A “Answers to End-of-Chapter Exercises” Khi bạn cần dùng hàm DirectSoundEnumerate? Ba mẩu liệu quan trọng truyền cho hàm callback liệt kê?(enumeration callback function)? Định dạng đệm có cần giống định dạng liệu chứa ko? Mục đích đệm sơ cấp (primary buffer)? Giá trị truyền cho hàm DirectSoundCreate8 để rõ thiết bị âm mặc định dùng? Về phần bạn Viết cí dụ cho phéo điều chỉnh âm lượng âm play nó? Viết ví dụ nhỏ cho phép âm pan sử dụng phím mũi tên 177 Beginning DirectX9 Dịch TransTeam diễn đàn Gamedev.VN 178 ... xác định phần tử khối lập phương, //hai phần tử mặt cube WORD IndexData[ ] = { 0,1 ,2, //0 2, 3,0, //1 4,5,6, / /2 6,7,4, //3 0,3,5, //4 5,4,0 //5 3 ,2, 6, //6 6,5,3, //7 2, 1,7, //8 7,6 ,2, //9 1,0,4,... D3DCOLOR_ARGB(0,0 ,25 5,0)}, / /2 { 1.0f, -1.0f, -1.0f, D3DCOLOR_ARGB(0,0,0 ,25 5)}, //3 {-1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0 ,25 5,0)}, //4 { 1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0,0 ,25 5)}, //5 { 1.0f,... lặp lại sử dụng cho nhiều phần tử, véctơ phần tử không nằm thứ tự có hiệu Khi tối ưu hóa mesh cách sử dụng “véctơ dùng chung” cho phép véctơ phần tử xếp lại, bạn tăng q trình thực kết xuất mesh

Ngày đăng: 29/01/2020, 23:12

Từ khóa liên quan

Mục lục

  • Tại sao DirectX lại cần thiết?

  • Tổng kết chương

  • Xây dựng một dự án mới.

  • Chèn thêm mã lệnh cho chương trình

  • Sử dụng DirectX

  • Cập nhật mã nguồn chương trình.

  • Chèn thư viện DirectX vào chương trình

  • Xác lập ứng dụng chạy ở chế độ toàn màn hình

  • Chế độ hiển thị màn hình và các kiểu định dạng

  • Tổng kết chương

  • You’ve just touched the surface

  • Sprites

  • Hiển thị một hình sprite động chính xác

  • Tổng kết chương

  • Không gian 3D

  • Khái niệm về vector

  • Nạp dữ liệu cho buffer

  • Hiển thị nội dung Buffer

  • Những kiểu cơ bản

  • Tạo một mô hình 3D

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan