JavaScript general utility module example
When I start a new project I often want to have a generic dumping ground for usual suspect type methods, in other words a kind of lodash like library only with methods that I am actually going to use in the project, and not a whole much of bulk that I am not going to be using like with lodash.
Many methods that I might park in this kind of library might ultimately end up in some other library that has to do with something more specific such as working with angles, or creating and working with canvas elements. However when first starting out I just need a place to put any and all methods that I might want to use in one or more additional modules, or libraries throughout an over all application. So I need to just park it in some kind of general utilities type library until I find a more appropriate home for it.
So in todays post I will be going over a general utility module and the kind of methods that I might place in such a module that will serve as yet another one of my JavaScript example type posts. While in the process of writing about the various method I may link to additional posts on various game prototypes, and projects that are relevant to use usage of these methods.
1 - The utils module
In this section I will then be going over a few usual suspect methods that I end up with in a generic utility module. It is important to stress that this is an example, and not the example, as the nature of this kind of module will differ fro one project to then next. For example in my canvas example on a beach invasion type game prototype I have the xp system as a stand alone method in the utils module of that example. This is one example of something that might start out in a module such as this, but should really maybe be in its own stand alone experience point system module actually.
1.1 - Start of the module and noop
When I make this kind of module often it is just one massive collection of public methods, so the module pattern of just a simple object literal works more often than not. In some cases I might switch to a pattern that involves an IIFE or some other kind of option when it comes to this sort of thing, but that is often what I reserve for other kinds of specific modules that will contain at least a few private helper functions and objects that I do not need or want to make public.
One method that I might have in a utils module is just a simple noop function, or no operation function. This is just a function that does nothing actually, which may seem odd, but never the less it is something that I often used when it comes to setting a default value for a call back option for example.
|
|
1.2 - A distance formula
Another usual suspect that I might have in a module like this is a distance formula. In many of the projects that I make this is just a basic must have tool. For example say I have to circle objects and I want to know if they have hot each other, or say that I have this singe pixel position and I want to know if it is in the radius of a circle or not. When working out game logic I am often working out all kinds of expressions where distance between two objects is a factor that will set an attack value when dealing damage to which a distance formula will come into play. Yet another use case would be making a grid module, and selecting all cells in the grid that are within a given radius. The list goes on and one with this one, so I should have it at the ready somewhere.
|
|
1.3 - Bounding box collision detection
The distance formula can be used as a kind of collision detection, but only for a circle like area rather than a box like area. So another useful method to have in a generic utility module is a bounding box collision detection module.
|
|
1.4 - Mathematical Modulo
The built in JavaScript modulo operator may fall short, and not work as one might expect now and then in some situations. It is not that there is something wrong with it, it is just that the operator follows a different convention compared to other programing environments. So I often might want to have a module that provides an alternative convention, such as mathematical modulo on top of what is built into javaScript. Often this is the kind of convention I would prefer to use in most cases oddly enough so this is also often a kind of must have method in most projects.
|
|
1.5 - clamp a number
In lodash there is a clamp number method that will just simply clamp a number to a given range. This is a kind of method that I find myself using often so I have one in this utilities lib that I have made for this post. However what is strange about lodash is that they have a clamp number method but not a wrap number method, if I want one in lodash I need to add one as a mixin.
|
|
1.6 - wrap a number
If I am going to have a clamp number method then I am also going to want to have a wrap number method. I have based this wrap method off of the source code of the wrap method in phaser that seems to work well in most situations.
|
|
1.7 - Format a number
This format number method uses the Format Number internationalization constructor to format a number as a string. The returned string does not just have a dollar sign attached to it when it comes to displaying as USD, or any desired symbol depending on the set currency property, but it also places a comma after every three digits.
|
|
1.8 - Http methods
A useful tool to have ready is a decent http client as scripting http requests is something that just happens a great deal when working things out with client side javaScript. There is working with the fetch api or the xml http request method directly, but when doing that I have found that there are some things that I should pull into some kind of abstraction so I do not have to repeat the code each time.
|
|
1.9 - Logging methods
There is just using the console log method as a way to see what is going on with some code at a given point. However using that method alone is a bit lacking, I often would like to have a log method that will just log once in a loop. Also another helpful method would be a method that will log just once for a given expression. Also I think it is a good idea to at least wrap the console log in a custom log method, that way I can just comment out just one line to stop logging, or redefine what logging is in just one place.
|
|
1.10 - A deep clone method
When it comes to working with objects I will often want a way to go about deep cloning objects. This can often prove to be a not so easy task when it comes to making a vanilla javaScript solution. Also often user space library methods might not always work great when working with custom made constructor functions. There are many deep clone methods on the open web, but often I do not see every little detail covered when making this sort of metho9d, such as checking for recursive references, and how to go about dealing with them.
|
|
1.11 - traverse an object
On top of deep cloning another useful object method to have is something that can be used to traverse over the full depth of an object. This kind of method is often referred to as a traverse method as it will go over every nested key value pair of an object calling a function for each set.
|
|
1.12- Create a create canvas element method
I often like to make canvas projects so it is a good idea to have a method that will create and return a new canvas element with all the options set up just the way that I like it. There are many little details when it comes to canvas elements such as making it so that a context menu will not show up when the canvas is right clicked, adjusting the translation of the matrix and so forth.
|
|
Using a method such as this is no replacement for a full blown canvas module of some kind though of course. There are many other little details surrounding canvas elements such as the topic of layering, and not always appending a canvas to a container that come to mind. Still this is a step in the right direction compared to starting over from the ground up each time I start a new project.
1.13 - Get a canvas relative position method
Another method that I might have in a general utilities module would be a method that I can use to adjust pointer positions so that they are relative to a canvas element rather than that of the browser window. This is a kind of method that I find myself refining a little now and then, so I have wrote a post in which I get into this topic of getting a canvas relative pointer position in greater detail.
|
|
1.14 - Create a canvas pointer handler
This is a method that will create and return a single handler that will work with a range of events given a single event object.
|
|
1.15 - Attach pointer handlers for a canvas element
I then have a method that I can call from the source code of a project just once, and given it a canvas element, state object, and an object of events for pointer methods. It will then use the create pointer hander method once to create a uniform handler with methods given in the events object that will act on the given state object. It will then attach the handler for all relevant pointer events for the given canvas element.
|
|
1.16 - Having a basic EXP System
Many of my projects are basic game prototypes, and one thing I need to have in many of them is some kind of experience point system. It might be best to start to work out some kind of full module for an experience point system, however the same could be used for many of the canvas methods that I have in this module also. This xp object contains two methods that I first worked out for my beach canvas example game prototype, and further refined in my post on the math pow method.
|
|
1.17 - Create state machine objects
In my canvas example on what I am just calling an Orb Module I am working out a lot of logic that has to do with these objects called orbs that are composed of a certain number of elements. I will not be getting into detail about he module here of course if you want to read more on it check out the post I wrote on it. However in the project folder of the orbs module I am starting to make a full game prototype that makes use of the module called orb match. As such when it comes to the utils library I am using in that game prototype I have started a bunch of methods that can be used to create and extend a basic state machine.
When it comes to using these methods the first thing I would wan to to is create a state machine object, for this I have two methods actually. One of which can be used to create a main state machine object that would be used in a main javaScript file. This main state machine object contains the main app loop, and has a number of other features that are appropriate for such a main state machine object. The other method can be used to create and return a far more minimal form of this kind of state machine object. This more minimal from of state machine object is what I have been using in various game logic modules as a way to go about creating sub states within a state.
|
|
1.18 - Push a new state object to a state machine object
I then have a utils method that I can use as a standard way to go about pushing state objects to a state machine object create with one of the create methods. For now this method is just used as a way to fill in blanks, but there may be a need to set up a few other things if I put more time into this.
|
|
1.19 - Set the current state
I have a method that I can use to set the current state object to use in the states object of a sm object. By using this method rather than just setting the current state string value, and end and start hook methods will be called.
|
|
2 - Demos of the utils module
In this section I have some quick demos of this utility module just for the sake of having some use case examples of the methods in the module. These demos are just some quick code examples that I put together for the sake of this post alone, that make use of this rendition of a generic utility module. For some real project examples that make use of a utility module such as this you might want to check out my canvas examples. Many of my canvas examples will feature a module like the one I am using in this post, but what is it it will very from one project to the next.
2.1 - Using the create canvas method
Many of my projects will involve the use of one or more canvas elements. ALthough it may be best to go with some kind of canvas library when it comes to doing things from the ground up I am going to want to have something that will serve as at least some kind of crude starting point for what might eventuality be some kind of canvas module. When it comes to a serious protect the process of creating a canvas element is not always so simple, often I might want to create a canvas element that I will be drawing to and will need to be appended to the hard coded html. however in some cases I might want to use a canvas element to create a sprite sheet that was created by way of some javaScript code, and I want to use the canvas element as an image source to which I will then draw from to another canvas element, in that case I would want to not append such an canvas element to the hard coded html. However when it comes to just creating a simple game prototype of one kind or another I may not ever get to the point where I need to worry about these things. So A simple create canvas method that just created ans appends a single canvas element with everything set up just the way that I like it will work just fine.
|
|
2.2 - Get canvas relative demo
Canvas elements are great not just for the sake of drawing to it by way of a little javaScript code that just runs but dos not do anything with user input. What is really cool about canvas is that it is not just a means of drawing to the screen, it is also a means by which a user can interact with a screen. In this example I ma making use of the get canvas relative method of the utils module to get a canvas rather than window relative pointer position. I am then just using that position to set the position of a circle.
|
|
2.3 - Bounding box collision detection demo
In all kinds of various projects I will want to make use of bounding box collision detection. Say I have two box areas on of which represents a shot from a gun, and the other represents some kind of enemy unit. If the shot object is fired from a player controlled unit I will want to know if the shot has hit an enemy unit or not, one way to fin out would be to use bounding box. In this example I am not going to do anything that advanced, but this is a simple example where I am using the bounding box method to set the color of box objects that over lap to a certain color.
For this example I have a create box helper function that will create and return an object that contains properties like x, y, width , and height. these are the properties that I need to find out if two areas over lap or not when calling this bounding box method. I then also have a get overlapping helper method that will use the array reduce method to return an array of objects from an array of objects that overlay a given object.
|
|
2.3 - distance method example
The distance method is a usual suspect method that I will want to have in some kind of module if not a general utilities module such as this. The method just comes into play with all kinds of things, for example it can be used as a way to go about implanting a from of collision detection. In this demo of the module I will be using the distance method to do just this. Here in this example I am using the distance method as a way to go about fining out if a canvas relative pointer position is withing, or outside of the radius of a given circle.
|
|
2.4 - Pointer events example
On top of the create canvas method of the utils module there are also a number of other methods that I have that are closely related to using canvas elements. I covered some example that make use of the create canvas element, as well as the get canvas relative method. However I have also found that it is nice to have a few more methods that have to do with creating a kind of standard when it comes to handling pointer events.
|
|
2.5 - deep clone an object demo
The deep clone method seems to work pkay when I play around with it a little.
|
|
2.6 - logging demo
In this demo I am just testing out my logging methods, and they seem to work just fine. When debugging some code the log for method will come in handy a whole lot of times as I just want something to be logged for a given condition. For example say I have some weird bug where an hp value for a display object goes out of range some times.
|
|
3 - Conclusion
This is not the end all solution for this kind of module of course, in practice this kind of module will change from one project to another. Also the idea here is to just have a temporary dumping ground for methods that should ultimately be placed in a module that is not so generic. For example that canvas methods in this utils module might end up in a whole other module that has to do with creating and working with one or more canvas elements, and not much of anything else. This distance, and bounding box methods might end up being static methods in a module that is some kind of display object pool module maybe. However often I still end up with a few odd ball methods that I just do not know where to go with, so I place them in a module like this.