Skip to content

Instantly share code, notes, and snippets.

@sntran
Created June 25, 2012 05:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sntran/2986790 to your computer and use it in GitHub Desktop.
Save sntran/2986790 to your computer and use it in GitHub Desktop.
Entity System Prototype in Erlang
-module ('2d_component').
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init({X, Y, Width, Height, Rotation}) ->
{ok, {X, Y, Width, Height, Rotation}}.
handle_event({change, {x, NewX}}, {OldX, OldY, W, H, Rotation}) ->
io:format("Entity moved from (~p, ~p) to (~p, ~p).~n", [OldX, OldY, NewX, OldY]),
{ok, {NewX, OldY, W, H, Rotation}};
handle_event({change, {y, NewY}}, {OldX, OldY, W, H, Rotation}) ->
io:format("Entity moved from (~p, ~p) to (~p, ~p).~n", [OldX, OldY, OldX, NewY]),
{ok, {OldX, NewY, W, H, Rotation}};
% The failsafe callback for other events that this component does not care %
handle_event(_, State) ->
{ok, State}.
terminate(_Args, _State) ->
ok.
%% This is an entity manager that creates entity,
%% routes calls to gen_event methods.
-module (entity).
-export ([init/0, add_component/3, remove_component/3, components/1, notify/2]).
%% A Factory Method that generate a Event Manager with a Pid.
%% This Pid is the ID of the entity.
init() ->
{ok, Pid} = gen_event:start_link(),
%% TODO: add each one in Components as a handler
%% Maybe add a specific handler to keep track of the entities?
{ok, Pid}.
add_component(Pid, Component, Args) ->
gen_event:add_handler(Pid, Component, Args).
remove_component(Pid, Component, Args) ->
gen_event:delete_handler(Pid, Component, turn_off).
components(Pid) ->
gen_event:which_handlers(Pid).
notify(Pid, Event) ->
gen_event:notify(Pid, Event).
detroy(Pid) ->
gen_event:stop(Pid).
-module (health_component).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(HP) ->
{ok, HP}.
handle_event({hit, Damage}, HP) when Damage =< HP ->
NewHP = HP - Damage,
io:format("Entity got hit with ~p damage and has ~p HP left.~n", [Damage, NewHP]),
{ok, NewHP};
handle_event({hit, _Damage}, 0) ->
io:format("Entity is dead already -.-.~n"),
{ok, 0};
handle_event({hit, Damage}, _HP) ->
io:format("Entity took ~p damage and died.~n", [Damage]),
{ok, 0};
% The failsafe callback for other events that this component does not care %
handle_event(_, State) ->
{ok, State}.
terminate(_Args, _State) ->
ok.
Erlang R15B01 (erts-5.9.1) [64-bit] [smp:4:4] [async-threads:0]
Eshell V5.9.1 (abort with ^G)
1> cd("D:/Repos/erlang").
D:/Repos/erlang
ok
2> c(entity.erl).
entity.erl:17: Warning: variable 'Args' is unused
entity.erl:26: Warning: function detroy/1 is unused
{ok,entity}
3> c(health_component.erl).
health_component.erl:2: Warning: undefined callback function code_change/3 (behaviour 'gen_event')
health_component.erl:2: Warning: undefined callback function handle_call/2 (behaviour 'gen_event')
health_component.erl:2: Warning: undefined callback function handle_info/2 (behaviour 'gen_event')
{ok,health_component}
4> {ok, Entity} = entity:init().
{ok,<0.44.0>}
5> entity:add_component(Entity, health_component, 100).
ok
6> entity:notify(Entity, {hit, 10}).
Entity got hit with 10 damage and has 90 HP left.
ok
7> entity:notify(Entity, {hit, 95}).
Entity took 95 damage and died.
ok
8> entity:notify(Entity, {hit, 15}).
Entity is dead already -.-.
ok
9> c("2d_component.erl").
2d_component.erl:2: Warning: undefined callback function code_change/3 (behaviour 'gen_event')
2d_component.erl:2: Warning: undefined callback function handle_call/2 (behaviour 'gen_event')
2d_component.erl:2: Warning: undefined callback function handle_info/2 (behaviour 'gen_event')
{ok,'2d_component'}
10> entity:add_component(Entity, '2d_component', {10, 15, 20, 25, 0}).
ok
11> entity:notify(Entity, {change, {x, 20}}).
Entity moved from (10, 15) to (20, 15).
ok
12> entity:notify(Entity, {change, {y, 100}}).
Entity moved from (20, 15) to (20, 100).
ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment