Cách tốt để phát âm thanh khi có điều gì đó xảy ra? Làm thế nào để âm thanh này?


10

Vì vậy, tôi đã suy nghĩ về cách các lớp học nguyên khối của tôi có được rất nhiều thời gian. Ví dụ, trong phương thức Charactercủa lớp Jump, người ta có thể có một tham chiếu đến một đối tượng hiệu ứng âm thanh và phát nó. Bản thân nó cũng ổn nhưng khi tính đến vật lý, hoạt hình, va chạm, v.v., phương thức Jump trở nên rất lớn và Characterlớp có rất nhiều phụ thuộc vào nhiều thứ khác nhau. Tuy nhiên, điều này có thể tốt. Tuy nhiên, điều gì sẽ xảy ra nếu chúng ta không còn muốn phát ra âm thanh khi nhân vật nhảy? Bây giờ, chúng ta phải tìm dòng mã cụ thể đó trong mớ hỗn độn của Jumpmã và nhận xét nó hoặc bất cứ điều gì.

Vì vậy, tôi đã suy nghĩ ..

Điều gì sẽ xảy ra nếu, thay vào đó, có một số loại AudioSystemlớp và tất cả những gì nó đã làm là đăng ký vào các sự kiện ngẫu nhiên mà nó quan tâm đến các lớp khác. Ví dụ, Characterlớp có thể có một Jumpedsự kiện (tĩnh quá, tôi cho là) ​​được nêu ra trong Characterlớp trong phương thức. Sau đó, Characterlớp sẽ không biết gì về hiệu ứng âm thanh nhỏ được phát khi nhân vật nhảy. Đây AudioSystemsẽ chỉ là một lớp lớn mà lập trình viên có thể rút lui để kết nối các hiệu ứng âm thanh với các sự kiện nhất định xảy ra trong trò chơi thông qua việc sử dụng các sự kiện tĩnh. Sau đó, nếu nó đã quá lớn nó có thể được tách ra để lớp con như EffectsAudioSystem, BackgroundAudioSystem, AmbientAudioSystem, vân vân.

Sau đó, trong các tùy chọn cho trò chơi, người ta có thể có một hộp kiểm để bật hoặc tắt các loại âm thanh này và tất cả những gì cần làm chỉ là vô hiệu hóa một hệ thống đó bằng một cờ Boolean đơn giản và duy nhất. Ý tưởng về các hệ thống này cũng có thể được mở rộng sang những thứ như vật lý, hoạt hình, v.v. đến mức hầu hết các phản hồi của trò chơi do hành động của người chơi được nối qua các hệ thống phức tạp và tách rời này.

Được rồi, vì vậy câu hỏi của tôi có thể hơi mơ hồ, nhưng làm thế nào loại điều này nghe? Tôi chưa bao giờ thực sự nghe nói nhiều về loại hệ thống này. Đây là tất cả trong đầu tôi ngay bây giờ mà không có bất kỳ mã hóa nào được thực hiện cho đến nay có lẽ đó là một trong những thỏa thuận "tốt về lý thuyết nhưng không thực tế". Loại hệ thống này sẽ hoạt động với một trò chơi lớn hơn hay cuối cùng nó sẽ bị hỏng và thậm chí trở thành một mớ hỗn độn hơn so với hệ thống ban đầu?


5
Nghe có vẻ như là một ý tưởng âm thanh :) (Một lưu ý nghiêm trọng hơn: Sử dụng tin nhắn để liên lạc giữa các hệ thống / lớp con được liên kết lỏng lẻo nói chung là một ý tưởng thiết kế tốt)
bummzack

1
đây là cách nó được thực hiện, bạn nên đặt kết xuất của mình vào một lớp riêng biệt, nếu bạn chưa có (như trong, bạn không nên có hàm draw () trong lớp Nhân vật).
dreta

Câu trả lời:


2

Tin nhắn là một địa ngục để gỡ lỗi và duy trì. Về mặt lý thuyết nghe có vẻ tốt, nhưng một khi được đưa vào thực tế, nó trở nên lộn xộn với rất nhiều dữ liệu trùng lặp được gửi xung quanh. Hiệu ứng âm thanh nhảy sẽ cần nhiều dữ liệu hơn ở cuối, ví dụ như vị trí, vận tốc, vật liệu của nhân vật được bật, bạn đặt tên cho nó, danh sách sẽ dài ở cuối.

Vì vậy, bạn sẽ cần phải thu thập dữ liệu này và gửi nó đến AudioManager thông qua một sự kiện / tin nhắn rất cụ thể với dữ liệu được sao chép trong đó hoặc bạn sẽ gửi một tham chiếu đến ký tự trong tin nhắn, để AudioManager có thể truy cập dữ liệu những cách kết thúc lộn xộn, và bây giờ người quản lý âm thanh phải chọn âm thanh cho vật liệu dưới lòng đất, v.v.

Vì vậy, vào cuối sự kiện cụ thể (là một lớp rất cụ thể chỉ dành cho thông điệp này) sẽ kết hợp các lớp đó lại rất sâu. Không có nhiều chiến thắng và cuối cùng, bạn sẽ có một danh sách lớn các sự kiện / lớp rất cụ thể chỉ phục vụ mục đích gửi dữ liệu xung quanh, đã tồn tại và có thể bị lỗi thời và sẽ gặp phải tất cả các vấn đề khác của dữ liệu trùng lặp .

Vì vậy, sẽ có một danh sách lớn các lớp không cần thiết để duy trì, giới thiệu một khớp nối sâu giữa nhân vật và AudioManager, ngoại trừ bây giờ nó nằm rải rác trên khắp mã nguồn. Không chỉ trong các lớp Nhân vật và AudioManager.

Vẫn là một ý tưởng tốt để tách mã của bạn, nhưng Tin nhắn thực sự chỉ là một cách khác để ghép nối sâu. Một số mã chỉ cần được ghép nối, sử dụng cách trực tiếp nhất để ghép chúng, đừng quá kỹ sư.


1
Làm thế nào là một hệ thống nhắn tin được thiết kế tốt "chỉ là một cách khác của khớp nối sâu"? Gửi tin nhắn là khớp nối tối thiểu tuyệt đối mà không có đối tượng không bao giờ giao tiếp. Cách bạn thiết kế có thể gây ra sự cố nhưng nếu hệ thống chỉ phát ra âm thanh, vị trí và nhập, nó sẽ giải quyết tất cả các vấn đề của anh ấy và không đưa ra bất kỳ vấn đề nào bạn đề xuất có thể xảy ra. Hệ thống âm thanh không nên tính toán những gì âm thanh cần thiết, nó nên trừu tượng hóa tất cả các cài đặt và tốt nhất là các vấn đề khuếch tán. vi.wikipedia.org/wiki/Coupling_(computer_programming)
ClassicThunder 15/212

1
@ClassicThunder điểm là trong thực tế phương pháp này không mở rộng rất tốt. Nó hoạt động tốt cho các ứng dụng đơn giản và miễn là tất cả những gì bạn cần là một PlaySoundEvent chung. Nhưng câu hỏi là về Trình quản lý âm thanh nghe một sự kiện OnJump () chuyên biệt, để nhân vật có thể thoát khỏi công việc âm thanh. Tuy nhiên, điều này sẽ không xảy ra với PlaySoundEvent đơn giản vì nhân vật phải chọn âm thanh và gửi nó đến AudioManager, điều này làm mất hiệu lực điểm ban đầu của việc giới thiệu OnJumpEvent để loại bỏ công việc âm thanh.
Maik

1
Tuy nhiên, khi sử dụng OnJumpEvent, bạn có thể chọn thêm tham chiếu cho nhân vật vào sự kiện hoặc sao chép tất cả dữ liệu quan trọng từ nhân vật vào sự kiện. Tất nhiên là bạn đúng, cái sau sẽ không giới thiệu một khớp nối sâu, nhưng nó sẽ gặp phải vấn đề sao chép dữ liệu và một đối tượng truyền dữ liệu mới phải được duy trì, như đối với tất cả các sự kiện mới khác.
Maik

1
-1 nguyên nhân trong khi tôi đồng ý rằng việc có các tin nhắn đặc biệt (OnJump) có thể là một ý tưởng tồi, đây chỉ là một ý tưởng dài 'Không phải đây là một ý tưởng tồi' thay vì thông tin hữu ích để khiến người đó tạo ra một sự kiện PlaySound có tên của hiệu ứng âm thanh và vị trí 3D và / hoặc âm lượng mà nó xảy ra.
James

@James cảm ơn về đầu vào, tôi không có ý nói sử dụng sự kiện PlaySound, ý tôi là nói các sự kiện là một sự trừu tượng tốt đẹp cho ứng dụng cơ sở dữ liệu GUI, nhưng không thực tế cho một trò chơi phức tạp.
Maik

2

Tôi không nghĩ rằng một hệ thống chuyển tin nhắn là trên kỹ thuật cả. Trong thực tế, nó có thể làm cho nó dễ dàng hơn để hoàn thành công việc trong giai đoạn đánh bóng. Bạn đang làm đúng!

Những gì bạn mô tả là chính xác những gì tôi đã ném cho trò chơi Global Game Jam của chúng tôi năm ngoái. Tôi chịu trách nhiệm tạo và chỉnh sửa SFX, đồng thời tích hợp âm nhạc mà bản thân tôi và một nhà soạn nhạc khác đã viết vào trò chơi theo cách không hút.

Điều tuyệt vời về cách tiếp cận này từ góc độ âm thanh là nó cho phép bạn thực hiện nhiều điều thú vị hơn với âm thanh của mình. Nếu bạn nghĩ rằng hiệu ứng âm thanh trong trò chơi chỉ là một tệp âm thanh, âm lượng và lia máy, thì bạn đã làm sai.

Thí dụ

Đối với trò chơi của chúng tôi, bạn là một con khủng long bay tàu vũ trụ chạy vào các hành tinh để ghi điểm. Chúng tôi đã làm việc trong Flash, vì vậy cơ sở hạ tầng điều khiển dữ liệu là không cần thiết. AudioManager là một lớp bao gồm một loạt các phương thức tĩnh với mục đích duy nhất là kiểm soát những âm thanh xảy ra để đáp ứng với một sự kiện trò chơi.

Nếu tôi viết nó bằng C ++, thì sẽ mất thêm một chút thời gian để trừu tượng hóa tất cả các hành vi có thể có mà âm thanh có thể có. Các yêu cầu cho một thông báo thông báo cho hệ thống một hành động đã diễn ra sẽ không quá phức tạp. Nó sẽ chỉ cần loại thông báo, đối tượng nguồn gốc hoặc đối tượng bị ảnh hưởng, truy cập vào một số loại bối cảnh trạng thái trò chơi, và không nhiều thứ khác. Giao thức có thể phát triển khi nhu cầu của trò chơi tăng lên. Đương nhiên, nếu bạn thực hiện tất cả những điều này trong việc triển khai mã (như mã GGJ kém chất lượng của chúng tôi), bạn sẽ gặp vấn đề về lớp nguyên khối tồi tệ hơn. Nhưng điều đó dễ dàng được giảm nhẹ bằng cách tạo ra một hệ thống dựa trên dữ liệu.

Dù sao, đây là cách hệ thống âm thanh trò chơi của chúng tôi phản ứng với các thông điệp khác nhau:

  • Người chơi va chạm với hành tinh: Điều này sẽ kích hoạt âm thanh vụ nổ hành tinh, đủ cơ bản. sau đó ngay lập tức sau khi nó sẽ truy vấn bộ đếm kết hợp đang chạy. Nếu nó đủ cao, nó sẽ tạo ra hiệu ứng âm thanh để phát nửa giây hoặc lâu hơn sau đó là con khủng long đang gầm lên chiến thắng. Ngoài ra, trong giá trị dân số hành tinh ngẫu nhiên đã được tính toán (khoảng 600 đến 3000 - tôi không biết tại sao phạm vi đó được chọn, đó là một cơ chế chơi trò chơi bị bỏ rơi và vẫn nằm xung quanh để tôi sử dụng để làm cho âm thanh trở nên thú vị), và vì vậy tôi đã sử dụng nó để mở rộng âm lượng của tiếng hét xa (công dân hành tinh gặp một số phận không kịp thời).

  • Người chơi giữ phím cách để tăng tốc: Khi nhận được âm thanh đẩy "whoosh" nhỏ này, nhưng đồng thời một tiếng gầm động cơ thấp lặp đi lặp lại trong hơn 1,5 giây. Hệ thống hạt cũng sử dụng điều này để bắn IIrc phát

  • Trình phát cho phép thoát khỏi phím cách để giảm tốc: Bây giờ trình phát đã thoát khỏi phím cách, hệ thống âm thanh biết rằng nó phải chuyển vòng lặp động cơ xuống. Nếu tôi có nhiều thời gian hơn, tôi sẽ muốn tạo ra một âm thanh khác trên đó là một loại âm thanh rên rỉ xuống.

  • Người chơi va chạm với mỏ không gian tà ác: Mỏ không gian rất tệ, do đó, không chỉ có âm thanh va chạm kim loại kết hợp với tiếng nổ (mà chỉ phát ra thành một âm thanh), mà còn có một âm thanh khủng long được chọn ngẫu nhiên phát ra. Có nhiều khả năng chọn nhiều tiếng "khóc" hơn khi sức khỏe của người chơi thấp hơn.

Một trò chơi thú vị đã trở thành một trò chơi thú vị khi nhạc nền của nó hoạt động và năng động, ngay cả chỉ với những hành vi đơn giản như tôi đã mô tả ở trên. Có một số hậu cần để làm việc với việc đảm bảo dữ liệu chính xác được thông qua. Nhưng này, BFD. Nó sẽ khác xa với những điều phức tạp nhất bạn phải viết trong phạm vi lớn hơn của mã trò chơi.

Trong thực tế, FMOD và Wwise hoạt động như thế này. Họ không có bộ điều phối thông điệp trung tâm, nhưng bạn đăng các sự kiện lên hệ thống trung tâm của họ một cách hiệu quả và họ phản ứng bằng cách phát hiệu ứng âm thanh được thiết kế sẵn bởi người triển khai âm thanh trong một công cụ tác giả. Hãy nghĩ về nó như cho trò chơi của bạn một DJ sống. Anh ấy ngồi và xem những gì đang diễn ra, và kích hoạt các clip âm thanh vào đúng thời điểm để giữ cho mọi thứ thú vị, trộn chúng để chúng phù hợp với môi trường âm thanh có sẵn.

[EDIT] Ngoài ra, tôi thấy bạn đã gắn thẻ C # này. Đây có phải là XNA không, và nếu vậy bạn có đang sử dụng XACT không? Nếu bạn đang sử dụng XNA, bạn nên sử dụng XACT.


1
Điều này có thể làm việc cho một dự án nhỏ, nó thậm chí có thể vui vẻ. Tuy nhiên, trong một trường lớn, bạn kết thúc với một số lượng lớn các lớp thông báo, cần phải được duy trì, trong khi một cuộc gọi chức năng đơn giản sẽ có tác dụng tương tự. Đó là lý do tại sao hệ thống sự kiện không có quy mô tốt, thật khó để quản lý dự án lớn hơn.
Maik

1
Btw chúng tôi làm việc với FMOD tại studio của tôi, không có hệ thống tin nhắn / sự kiện, bạn không gửi sự kiện tới FMOD, bạn chỉ cần gọi một hàm c hoặc phương thức c ++ để chơi một cái gì đó. Họ chỉ gọi âm thanh của mình là "sự kiện", điều đó không làm cho nó trở thành một hệ thống sự kiện, đó chỉ là thuật ngữ họ sử dụng thay vì âm thanh.
Maik

Không, tại sao? Bạn chỉ cần gọi hàm trực tiếp thay vì sử dụng một sự kiện để truyền tham số. Một sự kiện ở cuối không có gì khác như một lời gọi hàm, chỉ truyền các tham số trong đối tượng sự kiện, thay vì truyền trực tiếp chúng. Sự khác biệt duy nhất là sự gián tiếp mới được giới thiệu bởi hệ thống sự kiện, nhưng cuối cùng, một cuộc gọi chức năng đơn giản của nó, chỉ quá phức tạp không cần thiết.
Maik

@MaikSemder Làm thế nào để các cuộc gọi phương thức không kết thúc trong mạng lưới rối rắm của chính họ? Ngoài ra, tôi đã cố gắng ghi chú sự khác biệt đó giữa một hệ thống sự kiện và "sự kiện" được sử dụng bởi Wwise và FMOD. Ý tưởng tôi nhận được là logic âm thanh phức tạp không thuộc về các lớp đối tượng trò chơi và trừu tượng hóa logic âm thanh sao cho giao diện giống với việc gửi một sự kiện giúp dễ dàng có logic âm thanh phong phú hơn. Tôi thực sự thấy ít sự khác biệt chức năng giữa EventManager->dispatch("Sound:PlayerJump")soundSystem->playFMODEvent("/MyGame/Player/Jump").
michael.bartnett

2
Có thể có lợi ích của việc mã hóa dễ dàng hơn, nhưng nó không miễn phí, nó đi kèm với hiệu năng-, bảo trì - và chi phí sửa lỗi khó hơn. Quan điểm của tôi là, lợi ích không đáng có cho các dự án lớn. Bạn đang đối phó với nhiều đối tượng hơn là không có sự kiện và phải trả giá cho nó. Nơi duy nhất tôi sẽ xem xét sử dụng một hệ thống tin nhắn là để liên lạc giữa các luồng để ngăn chặn khóa giữa các luồng.
Maik

0

Tôi đồng ý với Maik Semder, rằng một hệ thống chuyển tin nhắn có thể là quá kỹ thuật (bây giờ dù sao đi nữa).

Từ những gì tôi hiểu, lớp học của bạn hiện trông giống như Bjorn "class nguyên khối" như có thể thấy trong "Một lớp nguyên khối" ở đây .

Tôi khuyên bạn nên đọc bài viết đó, và mặc dù bây giờ một hệ thống thành phần đầy đủ sẽ quá mức cần thiết, nếu bạn đọc để "Chia phần còn lại", điều đó sẽ cho bạn một cách tốt để trừu tượng hóa các hành vi của bạn và cuối cùng có thể chuyển sang phức tạp hơn giải pháp. Nó sẽ cung cấp cho bạn một cơ sở tốt để bắt đầu từ dù sao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.