Jump to content

Events library for RPG game


enriqueto
 Share

Recommended Posts

I'm new to the world of JS but haven't heard of libraries dealing with events - probably are but then you'd have to make them play nicely with phaser. 

Why not write your own event handling system? I've done it for a recent game - took me a couple of hours at most. Here's a copy/pasta directly from the project, you might want to adjust it. Also it works similarly to phaser event system.

So there's a callback holder object that you'll have to add to any objects that will support events:

    function CallbackHolder() {

        //private object 
        function CallbackObj(callback, context, argsArray) {
            this.callback = callback;
            this.context = context;
            this.argsArray = argsArray;
        }

        //Vars
        var callbacks = [];

        this.add = function(callback, context, argsArray) {
            callbacks.push(new CallbackObj(callback, context, argsArray));
        }

        this.remove = function(callback) {
            for (i = callbacks.length - 1; i >= 0; i--) {
                if (callbacks[i].callback === callback) {
                    callbacks.splice(i, 1);
                }
            }
        }

        this.removeAll = function(){
            callbacks.length=0;
        }

        this.executeCallbacks = function() {
            for (var a = 0; a < callbacks.length; a++) {
                var c = callbacks[a];

                c.callback.apply(c.context,c.argsArray);
            }
        }
    }

Then let's say I want an event triggered when an object is destroyed. Simply make an onDestroy callback holder variable


    function MyObject() {

        var self = this;
    
        this.destroy = function() {
                    self.onDestroy.executeCallbacks();             
            }

        this.onDestroy = new CallbackHolder();

    }

and add event listeners like this:

myObject.onDestroy.add(_onDestroyCallback,this,[34]);

 

Link to comment
Share on other sites

That's awesome @scheffgames, but there are literally 1 million JS modules for creating event emitters! And there used to be even more (with browserify and webpack you get access to node's event emitter in the client, but, its not the fastest implementation, I usually end up using eventemitter3, which is lightweight and performant). Unless for learning (or a very very specific use-case) I wouldn't advocate creating your own, they're fiddly and hard to test thoroughly and even harder to get really really performant, for example, it looks like your one will leak memory.

Link to comment
Share on other sites

Thanks @mattstyles for the info, like I said, relatively new to JS world, didn't knew there were such an abundance of event libraries. 

Also, would you care to point to the leaking memory issue? Cause I've looked the code over again and can't figure it out. Is it the splice function? Cause I've looked it up and apparently it doesn't cause memory leaks since the garbage collector will do its job. Thanks! :)

Link to comment
Share on other sites

I might be wrong, I'd have to look more closely but you're allowing users to pass data into the objects youre creating, which creates links, if those objects persist I'm not sure if the GC will know that your object is safe to remove/collect/destroy/delete. Manually deleting yourself (using `delete myObj`) won't help either (I dont think) as it doesn't really delete anything, just puts it as a candidate for deletion, the GC still makes a decision based on other factors, usually trying to resolve links.

Memory leaks are notoriously difficult to handle with JS but the simplest would probably be to have an algorithm that adds and removes hundreds of listeners with varying parameters and measure that over a few minutes, hardly conclusive and wouldn't catch everything but a start to testing things.

Link to comment
Share on other sites

@mattstylesThis is actually an interesting topic and I will definitely read up about JS GC. It's true though, the this.destroy function it's more of a cleanup function that removes sprites and events - and yes, I can start to see little cracks in the whole structure and a whole new level of subtleties - like if i'm calling this.destroy I should also call self.onDestroy.removeAll since this object shouldn't have any more event listeners attached to it.  Probably others but I'm tired so.

Curious how Phaser implenents event systems - haven't got the chance to take a good look in the source code. 

Link to comment
Share on other sites

@scheffgames In much the same way as you have done yourself I think, which is a pretty standard way of creating an event emitter and implementing pub/sub or the observer pattern. I'm not sure what the current state is with Phaser, I think they introduced a Signal construct as well, not sure how that differed or what extra stuff it handled.

In essence an event emitter has a really simple api right? add, remove and emit. From there things can get slightly more interesting. Usually events are tagged by string, such as how the DOM does it, they often also pass along an object to the handler, but, you could go one step further (as Flux or Redux do, which target React primarily) and emit objects to all listeners.

You could get even fancier and add more functionality, such as applying 'middleware' to transform each message coming out of your emitter, or allowing chaining of callback, or all manner of stuff, but, generic emitters need to be lightweight and performant above all else.

It's well worth reading up on how the GC works and what sort of pitfalls you can inadvertently fall in to which stops it from working or stops it working efficiently. It's also interesting to learn how memory is handled in 'proper' languages like C or Rust, Rust in particular has quite a bit of documentation on it as it styles itself as very similar to C/C++ but with better memory management. In particular, the stuff on creating an Arc in Rust, or anything to do with managing memory across a threaded application, is a very interesting and very difficult problem to solve.

Link to comment
Share on other sites

17 hours ago, mattstyles said:

It's well worth reading up on how the GC works and what sort of pitfalls you can inadvertently fall in to which stops it from working or stops it working efficiently. It's also interesting to learn how memory is handled in 'proper' languages like C or Rust,

Well I come from a C background so I've dealt with memory allocation/deallocation. Encountered GC in C# first - it does saves a lot of pain but like you said you have to be aware of it's pitfalls and optimization techniques. Not very familiar with JS GC but it's sure worth to check out major do's and dont's. 

 

17 hours ago, mattstyles said:

managing memory across a threaded application, is a very interesting and very difficult problem to solve.

Yes it is - I mean I've been avoiding writing multi-threaded apps  - that stuff requires a solid investment of time in order to properly use it and performance wise it's not mind-blowing when it comes to "regular stuff". Sure, renderers, 3d modelling software are faster/better with multi threading but a game will do just fine with single threading.

Writing a GC that manages memory across multi-threaded app - well, I'll let that to guys who can read Knuth's TACP without their head exploding from overheat. :) 

Link to comment
Share on other sites

21 hours ago, enriqueto said:

Thanks for the infos but I meant a game events library to edit without hardcoding events like key found, chest open, etc...

Create your own!

Craft your own object / class that does the both:

- Emits the event locally (ie: when user picks up item, eventemitter3 can raise an event!)

- Emits the event remotely (ie: when user picks up item, an eventhandler attached to the above eventemitter3 event SENDS / informs the server that ya picked dat item)

^_^ 

Link to comment
Share on other sites

1 hour ago, ClusterAtlas said:

Create your own!

We covered this earlier, why would you do that? There are loads of modules out there that are all better tested and more used than your own setup, and some of them are written by very good programmers so they might be better written too! Unless its for learning or you have a super unique use-case (you don't, your use-case will be an addition to what a 'generic' event emitter provides) I can't think why you'd want to do this.

It's one of those things that is really easy to write, but really hard to write well.

Link to comment
Share on other sites

54 minutes ago, mattstyles said:

We covered this earlier, why would you do that? There are loads of modules out there that are all better tested and more used than your own setup, and some of them are written by very good programmers so they might be better written too! Unless its for learning or you have a super unique use-case (you don't, your use-case will be an addition to what a 'generic' event emitter provides) I can't think why you'd want to do this.

It's one of those things that is really easy to write, but really hard to write well.

I actually agree XD pardon my vagueness

What I actually meant was to piece them working things (ie eventemitter3 & socket io) together into a client-side & server-side classes that both have their own common predefined events so they can work well with each othaa :rolleyes:

EDIT: I just re-read the main post, not sure if OP's creating a multiplayer one - hence he can just use eventemitter3 alone already ^_^ OP, w/ eventemitter3 it's already enough to emit & handle events wherever and however the hell you want

https://www.npmjs.com/package/eventemitter3

https://nodejs.org/api/events.html

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...