Skip to content
Andrea Catania edited this page Jul 19, 2021 · 5 revisions
How to create an Event in Godex - Youtube

How to create an Event in Godex

Event

The event is a concept that we use a lot in game dev, since it's a lot useful when something occurs: A character walks into a campfire and takes damage.

To implement a campfire we would use an Area and we would bind a function to the OverlapStart event of that area: Each time a character walks in, such function is called. In Godex instead, on the Area we can specify the OverlapStart event emitter name: in this case we would set Campfire.

We can fetch the events directly from a system, using the EventReceiver.

GDScript

extends System

func _prepare():

	with_event_receiver(ECS.OverlapStart, "Campfire") # <--- Notice

	var query = DynamicQuery.new()
	query.with_component(ECS.Health, MUTABLE)
	with_query(query)

func _execute(campfire_overlaps, health_query):
	for event in campfire_overlaps.fetch():
		if health_query.has(event.other_body):
			# This is a damageable Entity.
			health_query.fetch(event.other_body)
			health_query["Health"].health -= 10

C++

void process_campfire_damage(EventReceiver<OverlapStart, EMITTER(Campfire)> &p_campfire_overlaps, Query<Health> &p_health_query){
	for(const OverlapStart* overlap : p_campfire_overlaps) {
		if (p_health_query.has(everlaps.other_body)) {
			// This is a damageable Entity.
			auto [health] = p_health_query[everlaps.other_body];
			health.health -= 10;
		}
	}
}

Custom event and how to emit it.

Let's suppose you need to add the Death event, emitted when the character reaches 0 health.

First, you need to create the event, and you can use the following code:

GDScript

[WIP]

C++

struct DeathEvent {
	EVENT(DeathEvent)
	EntityID character;
};

📝 Notice: In C++ you need to register the event using: ECS::register_event<DeathEvent>();. Usually this line goes inside register_types.cpp of your module.

Now it's time to emit this event, and you can do it using the following code:

GDScript

extends System

func _prepare():
	with_event_emitter(ECS.DeathEvent)

	var query = DynamicQuery.new()
	query.with_component(ECS.Health, IMMUTABLE)
	with_query(query)


func _execute(death_event_emitter, query):
	while query.next():
		if query["Health"].health <= 0:
			death_event_emitter.emit("All", {'character': query.get_current_entity()})

C++

void detect_death(EventEmitter<DeathEvent> &p_death_event_emitter, Query<EntityID, Health> &p_query) {
	for( auto [entity, health] : p_query ) {
		if (health.health <= 0){
			p_death_event_emitter.emit("All", DeathEvent(entity));
		}
	}
}

Conclusion

In Godex, the events are emitted by the EventEmitter and received by the EventReceiver. Those can be used directly by a system, to emit or receive events. Thanks to this concept, it's much simpler code event base mechanisms, but still in full ECS style!