preface
Event mechanism, I believe many people know, understand, and often used.
In design mode, it is called the observer mode (aka publish-subscribe mode).
It’s everywhere:
In Java, it is the core Java library java.utils.Observable,
In **C#**, syntactic sugar support is provided for it: the event keyword
In the web browser Javascript, with built-in Event mechanism: window. AddEventListener, Event
In Nodejs, there is also a built-in library events
It’s also built into the game engine
- The cc CocosCreator EventTarget
- Laya Laya. EventDispatcher
- All the other engines have it
Using this pattern allows us to better decouple the game’s business logic.
but
The implementation of these event mechanisms in Js and TS was not satisfactory to me (I used them all), and something was missing.
- No type prompt for carrying data
- The message sender could not get a hint for the data type to be sent with the message
- The message receiver could not get a hint for the data type being sent
- There is no built-in support for complex communication situations
- Want to receive the data returned by the message receiver at the message sending point (if you implement it yourself, pass the callback packet in the data to the message receiver to execute the callback)
- The event was sent, but the message recipient was not registered, missed
- There is no built-in support for state management
- A lot of times, we have a requirement like this:
- Many places need to listen for the role level change event and then go to the role information interface to obtain the role level status for business processing
- That is, we need to listen for the same state change in multiple places, and then go to an interface to fetch the current state for business processing.
- Such processing is repetitive and inelegant.
- A lot of times, we have a requirement like this:
All of a sudden, one day walking around the Nuggets, I saw this article shared:
FBroadcast, a great tool for building complex applications
After reading it, I could only think of one word: This is the artifact I want
- Although it is written to Flutter in Dart
- But that’s okay, take a leaf out of the book and rewrite it in typescript
- (PS: Part of the description is also copied)
I love going to nuggets, and while they mostly share their knowledge of the web front end, they also have a lot to learn from using the game front end. Benefited a lot.
introduce
An efficient and flexible TypeScript broadcast system helps developers easily and orderly build games and applications with complex relational interactions and state changes.
features
- Support for the underlying event mechanism
- Messages support carrying any type of data (with type hints)
- Support the function this binding or any type as the environment, one line of code can remove all receivers in the environment
- Easy to build local/global state management
- Support for two-way communication
- Support for incredibly sticky broadcasts
- Typescript-based and provides extremely comfortable type hints
Install/Obtain
-
The source code for
git clonehttps://github.com/AILHC/EasyGameFrameworkOpen / / file path: EasyGameFrameworkOpen/packages/broadcastCopy the code
-
NPM install
npm i @ailhc/broadcast Copy the code
-
Note ⚠ ️
-
If your project does not support using the NPM package directly
-
You need to go to the dist folder and retrieve the module specification type files that you can use
-
CocosCreator3D, for example, supports the SystemJS specification
- You can take the systemJS folder file, copy to the project, set as a plug-in can be introduced to use
-
-
use
- Through broadcast registration, it is very easy to send broadcasts
// Register the receiver
this._broadcast.on("testA".(str) = > {
//do something
})
// Send a message
this._broadcast.broadcast("testA"."string")
Copy the code
-
Broadcast allows you to register and send messages with any type of data and supports type prompts
-
Broadcast allows you to pass data transparently to yourself when registering a message (rather than fetching data from outside the closure via a closure)
Inspired by Laya’s EventDispatcher
Closures can be problematic when used incorrectly.
-
Developers can choose to persist certain types of messages, making it easy to implement broadcast global state management.
⚠️ Note that a message type, once persisted, can only be removed from the broadcast system through brocast.offall (key).
broadcast.broadcast( Message type key "objTypeTest"./ / data {a:1.b:"".c:false}, / / callback undefined./ / persistence true ) Copy the code
-
Sticky broadcast
broadcast.stickyBroadcast( Message type key "stringTypeTest"./ / data ""); Copy the code
When there is no receiver of the corresponding type in the broadcast system, the sticky broadcast will stay in the system temporarily until a receiver of the corresponding type is registered, and then the broadcast will be immediately issued (when there is a receiver of the corresponding type in the broadcast system, it will have the same performance as normal broadcast).
-
Two-way communication
Two-way communication, double efficiency
Broadcast Supports receiving messages returned by receivers at the broadcast sending point.
// Send a message
broadcast.broadcast(
Message type key
"numberTypeTest"./ / data
1.//// Message returned by the receiver
(data) = > {
// do something
})
// Register the receiver
broadcast.on("numberTypeTest".(data, callback) = > {
/// do something
var result = logic();
// Returns a message
callback(result);
})
Copy the code
-
Supports the function this binding or any type as an environment binding
Registering events in CocosCreator does this
this.node.on(cc.Node.EventType.TOUCH_START, this.showAnimView, this) Copy the code
This can be used to call the showAnimView method without losing this if this is used in the method called
It is also supported in Broadcast, and allows developers to easily remove all receivers registered in the environment at once during environment deconstruction.
broadcast.offAllByContext(this) Copy the code
-
Batch registration of recipients is supported
broadcast.on([ { // Message type key: "numberTypeTest"./ / receiver listener: this.onNumberTypeTest, / / environment context: this }, { // Message type key: "stringTypeTest"./ / receiver listener: this.onStringTypeTest, / / environment context: this } // ]) Copy the code
That’s all for basic use
Specific use examples can be cloned repository :EasyGameFramework
Look at the demo based on CocosCreator2.4.2 examples/egf – CCC – full/assets/tests/broadcastTest
Open this scenario: BroadcastTest.fire
So before you see the demo, you need to install the environment,
Install NPM, then go to the egf-CCC-full root directory
npm install Copy the code
Extremely comfortable type tips demo
// When you need a message definer, add the following type declaration
declare global {
interface ITestKey extends broadcast.IMsgKey {
testA: "testA".testB: "testB".testC: "testC".testD: "testD".// Message type key prompt
objTypeTest: "objTypeTest"
}
interface ITestValueType extends broadcast.IMsgValueType {
testA: string.testB: string.testC: string.testD: string.// Type declarations for sending and receiving messages of the corresponding message types
objTypeTest: { a: number.b: string.c: boolean}}interface ITestResultType extends broadcast.IResultType {
testC: string.// Two-way communication returns a data type declaration
objTypeTest: { callbackDataA: { hahah: string}}}}// Then inject the type when instantiating broadcast
export default class TestBroadcast extends cc.Component {
private _broadcast: Broadcast<ITestKey, ITestValueType, ITestResultType>
start() {
this._broadcast = newBroadcast<ITestKey, ITestValueType, ITestResultType>(); }}Copy the code
demo
Demo Test Demonstration
The last
Welcome to pay attention to my public account, more content to continue to update
Public number search: play game development
QQ group: 1103157878
Blog homepage: ailhc.github. IO /
The Denver nuggets: juejin. Cn/user / 306949…
github: github.com/AILHC