mattstyles

Moderators
  • Content Count

    1671
  • Joined

  • Last visited

  • Days Won

    24

Reputation Activity

  1. Like
    mattstyles got a reaction from socceronly in Is there any success case for mobile game using WebGl and Progressive Web Apps?   
    Might be worth asking in the Babylon forum, pretty sure Delta and others could reel off a list of use cases.
  2. Thanks
    mattstyles got a reaction from updeadup in How can I track on wich site game was running?   
    fetch('https://myanalytics.com/mygame', { method: 'POST', body: window.location.href }) That should do it.
    Won't work if its in an iframe though, you'll get the href of the iframe.
    If you use something like Google Analytics, and you embed that code in to your game code (i.e. if someone steals your game code they also steal your GA implementation) then I think it usually, by default, sends along the url. You'd be able to track urls that way.
  3. Like
    mattstyles got a reaction from Duckydoc in Point and click movement ?   
    You're super close. Welcome to the wonderful world of asynchronicity (spoiler alert: its tricky!).
    function (distanceX) { travelTime = distanceX * 400; while (time < travelTime) { this.x += 1; } } Step back a minute and think about what is happening with this loop.
    A while loop is a blocking construct, this means it blocks the thread JS executes in until it is done.
    That sentence contains 2 key bits:
    * Blocks the thread
    * Until it is done
    Tackle the 2nd problem first. 
    Until it is done.
    This loop does only one thing, it increments a variable. However, the conditional for the loop `time < travelTime` isn't the variable that is incrementing.
    In JS you could actually apply a side effect by using a setter such that whenever you apply a value to `this.x` something else happens which changes `time` or `distanceX` (as `travelTime` is calculated from `distanceX` a change in `distanceX` is actually the important change), however, I very much doubt you're doing this and nor should you, it's powerful for sure, it's also unexpected and confusing and best avoided.
    The reason the thread crashes is linked to both of the 2 things listed above, namely, time never exceeds travelTime so the `while` loop keeps on looping forever. Well, not forever, but until the JS thread crashes (exactly why it crashes I'm not sure, eventually you'd overflow the max value the `this.x` variable can accept, which is a big number, very big, but not infinite, even if it could be infinite you'd run out of memory, which means it isn't infinite, but, I think the JS thread knows it is borked after a set amount of time and crashes. This is all academic, it does crash).
    So, first things first, sort out that function so that the conditional eventually returns false. However, this is only part of the problem, and that is connected to issue 1 above.
    While is blocking
    JS is single-threaded, i.e. it'll only run one sequence of calculations (there are, sort of, ways around this with web workers, but, ignore that for now, threading is proper tricky and its best avoided, hence why JS doesn't entertain the idea). A while loop will continue to insert itself to the top of the call stack of operations i.e. it will keep running until it is done. Consider the following:
    var iterator = 10 while (iterator > 0) { console.log('Hello') --iterator } console.log('World') This hopefully works as you would expect i.e. it prints `Hello` ten times, then `World` (JS trivia, for some reason while loops are fastest decrementing not incrementing, you don't need the > 0 as 0 is falsy, does it print 10 or 9 times?, I'll let you play with the prefix -- operator, try changing it to postfix, you can also whack that in the conditional, clue, `while (--iterator)` is not the same as `while (iterator--)`).
    The while loop blocks the thread, `World` is only printed when it is done.
    Now extrapolate that out to what you actually want to happen, i.e.
    var iterator = 100 while (--iterator) { this.x = iterator this.render() } This looks like we are getting somewhere, but, its a bit of a red herring.
    This will render 100 times, and, the `x` value will decrease with each render.
    However, it'll happen as fast as possible, which is probably way too fast. (I'm not even sure if it'll get optimised away, so it won't actually render 100 times).
    What you probably want is for your sprite to go from current position to desired position in a set amount of time, or, at a set speed. Either is achievable.
    However, this is asynchronous, so here be dragons.
    For starters:
    * Ditch the while loop, it isn't what you want here.
    I'd probably approach this by structuring things ever so slightly differently and letting your update function do a bit more work.
    Let's assume you want to move based on a constant speed (let's ignore anything such as speeding up or slowing down, although, its a good extension exercise, as is doing this by time, but I doubt that's what you actually want here). edit: looks like you do want to do it based on time, the outline below wouldn't really change, your problem is handling asynchronicity, not the actual logic of what is happening over time.
    We'll need a couple more variables, some you already have modelled (I'll keep it in one plane for brevity):
    var speed = 1 var currentX = 100 var desiredX = 10 A click sets the desiredX, you're already doing this.
    Now add a little bit of logic to the update function (again, lots of ways you could achieve this):
    function update () { if (currentX === desiredX) { return } if (currentX < desiredX) { currentX = currentX + speed } if (currentX > desiredX) { currentX = currentX - speed } } You might want to work out what speed you want somewhere else. You have a move function that is called from the click user action, maybe there would be better. Doesn't much matter. There are also way better, but slightly more complex, ways too. Also, in this example we are checking that desired and current are equal, as we're only dealing with integers here and incrementing or decrementing by 1 we know we'll always hit the desired, if we use floats or any value besides 1 then we can't be sure they'll ever be equal so your 'bug-out' conditional would need to be a bit smarter. Google for shield pattern, it can be useful here.
    You're already calling update (and draw) on a period, namely every 16ms or so, or, more accurately, ~16ms or slower.
    Rather than update the position all in one go (via the while), you're now letting your update function actually update your world by taking the difference  of current state vs desired state and applying the changes required to get to the desired state over time. The over time bit means you are now doing it asynchronously and you'll get the movement you probably expect. In this example it'll take you 90 frames to hit your desired state, or, roughly 90 * 16 = 1440ms to get to the mouse click position.
    Once you get your head around making changes over time then the world is your oyster.
    Want to get there in a set time frame? Choose a speed based on the time left vs the distance left.
    Want to apply some rudimentary physics? Start modelling forces i.e. apply a force to the object and calculate speed based on the forces acting on the object (this route is awesome, clue, slowing down can be tricky).
    Good news is that all of these things have mathematical formulae that you can model in to your simulation, and its mega easy to find them with a quick google search.
    The other good news is that this approach is actually way simpler. If a user clicks again in the 1440ms it takes you to 'complete' this move then you just change the `desiredX` and everything just works. The mental shift is that a click does not equal a 'move', it sets a destination, the update function handles getting from one destination to another, it has no concept of moves or times, it just deals with the here and now of 'I want to be over there, how do I get there?', if the 'over there' changes, the previous question still remains the same, the answer will change, but you calculate that in the update i.e the code is the question, the output the answer, changing one is significantly easier than changing the other.
    Then you can deal with path-finding when you realise that in between your current position and the desired position is a wall/chasm/enemy/etc.
  4. Thanks
    mattstyles got a reaction from webdva in PVP matchmaking system   
    What you're after is heuristic-based searches, this might sound scary but every time you search and retrieve from a list you're setting a heuristic and applying it to retrieve an item from a list.
    So, the simplest case here is a time-based heuristic and you can use a FIFO (first-in-first-out) to achieve this.
    When each player connected they are pushed on to the end of the list of waiting players (Array.push). Whenever any of them hits the 'start' or 'find opponent' button you're getting in to the search. Remove the initiator from the list and your time-based heuristic is simply to take the head of the list (Array.shift), because they enter from the tail you know the first one in the list (at the head) has been waiting the longest. These 2 players are now matched, removed from the waiting list and can get going.
    From there you need to create a more complex heuristic (rather than Array.shift) that is going to match on win/loss ratio or player experience level or whatever.
    To prepare for this you take the code you already have, shove the Array.shift bit into its own function (find, maybe), write some test and now you're ready to 'play' with your matching algorithm.
    The api for the 'find' function needs to take the list of waiting players (search space) and the initiator player and spit out another player (whether you remove these players from the list of waiting players in this function or outside is up to you, you'd probably want to do it elsewhere and keep this searching function pure but its up to you). I'd suggest you pass a 'copy' of the search space into this function, then you can mutate it all you like, but, again, this is up to you.
    Now you have a sandboxed 'find' function and you can do what you like in here to implement whatever heuristic you want (there is a metric ton of info on heuristic based searches out there).
    You might want to pull out all players in the list with a similar win/loss ratio to the initiator and randomly pick one. You might want to just find the first player with a similar win/loss ratio (if you have kept with the ordered list, by time, then searching head to end will mean you tend to pick out the players waiting the longest, which is probably a good thing). You might want to pick a totally random opponent 10% of the time if you decide always picking a similarly matched opponent (by win/loss) gets a bit stale for users. There are lots of options and totally dependent on your use-case.
  5. Like
    mattstyles got a reaction from GreenCloversGuy in Do you use Visualisation Diagrams when game designing   
    How about a tool that create those sorts of diagrams by analysing your source? That would be good, and I bet it already exists.
    To your actual question, yes, I also find some diagramming to be helpful although I wouldn't be as granular as you are. I've also got reasonably good at splitting problems up so rarely need to diagram for side projects, however, at work (where problems are significantly more involved) we do this as a team regularly and refer to diagrams often. Hardest part is keeping things up to date, hence the requirement for a tool that do this for you from code analysis. Ditto for written documentation.
  6. Like
    mattstyles got a reaction from webdva in how to use DOM elements with Phaser?   
    Phaser isn't some magical framework, its just JS and so you'd access other elements in much the same way as you would for any web page.
    <canvas id='game' width=640 height=480></canvas> <div class='js-overlay overlay'>Hello World</div> Your CSS for this might look something like:
    .overlay { position: absolute; z-index: 1000; color: blue; background: rgba(0, 0, 0, 0.2); padding: 30px; } Now you've got a canvas element (which, given nothing else on the screen will end up top-left of the page) and an absolutely positioned overlay element that has a z-index of 1000 to keep it above the canvas (which it would be anyway in this case). It's got a semi-transparent background so you'll see the canvas through it and its cheerily says 'Hello World' in blue.
    Once you've initialised Phaser then you can attach that to the canvas element.
    For there you can continue to code your Phaser game as you would for any Phaser game, but, at any point you can grab the overlay div and 'muck' with it. For example, maybe one of your state create functions changes the text in the overlay:
    function create () { var overlay = document.querySelector('.js-overlay') overlay.innerHTML = 'Phaser is awesome!' } And thats it, I'd like to say you've reached out of the Phaser boundary in to the page and changed it, but, in reality, there is no boundary, its all just HTML, CSS and JS (in the case of Phaser the HTML and CSS portion is extremely minimal).
    An html canvas element is much like any other.
    Don't be afraid to do this either, for some stuff like text display and UI standard 'old-fashioned' DOM manipulation easily trumps canvas so if your game relies on these sort of things then it makes perfect sense to use it. Canvas shines for rendering stuff really quick. Use the right tool for the job you need doing.
  7. Thanks
    mattstyles got a reaction from Heramb89 in HTML Source Code Game   
    You always use that project as source material.
    I expect I ended up installing a newer version of socket.io and that is probably over a major version hence it is broken.
    So, yeah, maybe that project will help you get started.
    Either way, good luck getting something up and running. Multiplayer is hard so keep at it!
  8. Thanks
    mattstyles got a reaction from Heramb89 in HTML Source Code Game   
    Unfortunately the git repo you posted for chowka-bhara does not contain a package.json, which it should. To make matters worse now.js no longer exists, there is a git repo for it here but looks like the author has kindly donated the npm name to a project which is maintained (now.js was last touched, in github at least, 7 years ago).
    You can get around this as you have the zip (I used your zip for now, haven't looked at the other) or you could grab and build it yourself from the above repo link.
    I managed to get it running (see attached screenshot) using the following slightly awkward process:
    * Make sure you are using an old version of node, this project is old and won't even fire up. I used 6.14.3.
    * install socket and node-proxy (npm i socket.io node-proxy)
    * unzip now-master and copy in to node_module/now (this is almost like installing from npm)
    * run the main.js file using node (node main.js)
    This fires up the server and starts it serving up the stuff it needs.
    Unfortunately there is also a problem in the repo with the client code so it errors and the program does not work as expected (it is unplayable), see error screenshot.
     
     


  9. Like
    mattstyles reacted to Damian Pastorini in Base MMORPG - Node, MySQL, Colyseus, Parcel and Phaser 3   
    Hi everyone!
    Before anything I wasn't sure if this was the correct place to post this, please moderators move it as you consider if this should go to some other place like Projects and Demos.
    https://github.com/damian-pastorini/dwdgame
    Also, please consider that this is my first implementation ever!
    I've never used neither Node.js, even less Parcel, Colyseus or Phaser, my world before this first incursion in game development was all about PHP and Magento, so that should give you an idea from where I'm coming.
    This quite awful but working example took me 75hs, including the time I've used for research and for decide which platform use for the server and the client.
    After all the research, Node + Colyseus and Phaser 3 looked as the better start point since I was familiar with JS and HTML of course but had zero knowledge about Unity (the other option I would like to use), but I've prefered make the learn curve not so slow.
    So....
    This is a really simple base MMORPG game created based on the Colyseus samples:
    https://github.com/gamestdio/colyseus-examples
    And on the Phaser 3 implementation from Jacky Rusly:
    https://github.com/jackyrusly/jrgame
    As you will see I've considerable modified how the jrgame was interacting with Socket.io in order to make it works as how the Colyseus example was working, I've thought that was the better way to do it (follow up on server ready samples and break apart the client sorry Jacky!)
    The game basics are login through DB, loader, scene change, players sync, but nothing like chat, items, or attacks was implemented here (so far).
    Here's the link to the repo:
    https://github.com/damian-pastorini/dwdgame
    Please feel free to create any tickets or pull requests for questions, fixes or improvements, I would love to get good feedback!
    I don't have a public link to show it yet but I'm planning to create a dev server soon (for now you will need to install it and run it to see it), at the end it will look like:
    https://jrgame.herokuapp.com
    But you will see the login screen first which in the server side will connect to the DB and all the players sync was done with Colyseus.
    I saw comments from people looking for Colyseus integrated with a DB engine (in this case I've chosen MySQL), so at least that part should be useful.
    I really hope this help more than one person, maybe someone like me who would love to get this as starting point.
    Best,
    Damian
    Reply
  10. Like
    mattstyles reacted to Damian Pastorini in Introduction - HTML5 + Multiplayer Game   
    Hi @mattstyles, I've just published my first "working" base for the game:

    Best,
    Damian
  11. Thanks
    mattstyles got a reaction from Wilco93 in recommand UI Framework to create tool with pixi.js   
    dat.gui is fairly standard.
  12. Like
    mattstyles reacted to Prozi in A simple zero-dependency modular game engine for bootstrapping games.   
    Introduction
    Hi
    I am a long time programmer in JavaScript mostly But recently I switched to Unity Which has some great concepts.
    I tried to implement a simple framework to mimic the:
     
    Scene
       -> GameObjects
            -> Scripts / Components
     
    structure in JavaScript
     
    License: MIT
    https://www.npmjs.com/package/@minininja/engine
    https://www.npmjs.com/package/@minininja/pixijs
    https://www.npmjs.com/package/@minininja/threejs
    Base concept
    You create GameObjects + Scripts / Components.
    Each GameObject has a Transform property which is either a base Vector3 instance some kind of i.e. pixi.js or three.js object.
    Scripts have a many to one relationship with a GameObject.
    You append a script's Transform to a GameObject's Transform. Once you call one GameObjects onUpdate it propagates to all its children.
    You can reference a Transform's parent GameObject by this.gameObject accessor and GameObject's Transform by this.transform in GameObject context.
     
  13. Thanks
    mattstyles got a reaction from espace in listener in javascript   
    You're doing this very naively, so you'd need the flag.
    The alternative is to implement an actual event pub/sub system (ala addEventListener, or, any pub/sub implementation out there) on your object i.e.
    import EventEmitter from 'eventemitter3' export const onChange = 'sprite:onChange' export class Sprite extends EventEmitter { scale = { x: 1, y: 1 } setScale (x, y) { this.scale = { x, y } this.emit(onChange, { type: 'scale', payload: this.scale }) } } import { Sprite, onChange } from 'sprite' function doSomething () { console.log('doing something arguments:', ...arguments) } const sprite = new Sprite() sprite.once(onChange, doSomething) Note I'm using ES6 syntax (inc. module syntax) and I haven't tested any of this (I rarely use classes so might have mixed up context or some other stupid error) but hopefully it's easy enough to follow.
    eventEmitter3 is a really simple pub/sub module and is a really standard implementation. `on` and `off` functions are analogous to DOM `addEventListener` and `removeEventListener`, the `once` method used here is just sugar around removing the handler/callback after the first time it is triggered.
    This actually functionally gets you to the same place you're already at, albeit without some implicit state hanging around. Depending on your exact use-case this might be more or less useful to you.
    What this is doing:
    * Attach a function to list of functions, key it against a string identifier (this is the event)
    * On another function call (emit) check the list of functions for the string which was emitted
    * Fire the function when the string is matched
    * Remove the function from the list of functions to check i.e. the next time that string is used it won't match that function again
    What you are doing:
    * Inspecting an object for changes by polling
    * Reacting to any detected changes by invoking a function
    * Deciding a course of action from within the function
    In different scenarios both of these approaches have merit so it's up to you which you prefer. Probably the 'most popular' way of solving this sort of problem is with pub/sub.
  14. Like
    mattstyles got a reaction from ShrewdPixel in best way to convert ES6 syntax to ES5 ?   
    Oooo, this thread could get flamey! Ha ha.
    There are numerous advantages to using ES6, a quick google search will give you heaps of reasons, with the only con being that you probably have to up the complexity to transpile back to es5/3, however, all modern browsers support most of ES6 (and newer) syntax so unless you're supporting really old browsers (and you stick solely to ES6) then you probably don't need to transpile.
    The biggest advantages of ES6 (for me, and I've missed loads here):
    * ES6 was pushed through to create more complex applications, as such it has a lot of syntax that is more useful for doing so. Some are sugar methods only, some actually provide newer functionality (particularly those related to primitives and/or the DOM).
    * New built-in extensions which make many tasks way way easier (and easier means less error-prone)
    * Sugar methods mean less dev typing which generally means less mistakes. Some things ES6 makes easy are very very hard in ES5 and they are often things devs rely on regularly so making them easier to work with means writing code is less error-prone and reading code is clearer so you can focus on what your code does, not how it does it.
    The biggest advantages of setting up a transpilation pipeline are (again, I'm missing loads):
    * Access to a module system
    * Access to whatever new syntax you want
    The con of a transpilation system is increased project complexity and you have introduced a build step which takes some time to run, as your project grows this sometimes becomes prohibitive but you do have to have a very large project for this to happen and most modern build tools abstract away incremental builds and caching i.e. they only re-build the changes so incremental builds become smaller and faster.
    Another con is related to the module system. Modules are awesome, very awesome. However, JS doesn't (yet) natively support them in the browser and even when they do there are additional problems i.e. if you use modules heavily (as you probably should) then your list of dependencies could easily be hundreds or even thousands of files, loading each of these one by one in the browser isn't a good idea and won't be in the foreseeable future.
    A module system also implies that you need some way of getting dependencies. This isn't technically necessary but is often helpful. If you are writing games then often you'll be using one (or maybe two) large frameworks to help, unless they work nicely with a dependency management system (i.e. NPM) then I wouldn't worry about getting them as 'real' modules, just include them on the page and use them, then use a module system for your own code if you want to.
    Newer syntax and mobile games
    Any gaming is typical performance sensitive, newer syntax has a few things to consider:
    * Browsers are well optimised for ES5, this isn't always true to ES6 (although ES6 is pretty good now as its fairly old and almost universally adopted in browsers)
    * Given the above, transpiling is often better for performance
    * The code generated by these tools during transpilation is superb, it is written by many many superb developers and has great community support so the hours invested in it must be astronomical i.e. in many cases these tools will write better code than you or I do!
    * It is not a silver bullet -> if perf is a concern for you then you are still largely the sole arbiter of whether you achieve your perf goals.
    How to use newer language features:
    Babel is the defacto tool (although it isn't your only option). Babel requires a bit of setup work and additionally requires you to set up a build process for your code. Again, there is tooling for this. Additionally, there are many project scaffolds out there (and tools for creating them) that can abstract this away.
    The absolute easiest way of getting access to these new language features but supporting older browsers is to use parceljs.
    Parcel abstracts away most of the complicated build stuff and has a superb feature set. It involves a few pre-requisites:
    * You must know how to run simple commands from the command line
    * You must have Node and NPM installed
    Once you have these things (which is generally true of any JS build system you might want to employ) then running builds is a simple one-line command. A watch task is also bundled in, this is another simple one-line command to run and watches the file system, every time you save a change it rebuilds only what has changed and propagates that to the browser. Parcel relies heavily on caching and multi-threading so is very very fast.
    Other tools include webpack (which is very complicated, although newer versions I think make things way way easier for most use-cases) and browserify (which is simpler in scope, but can feel a little low-level for many people).
  15. Like
    mattstyles got a reaction from obiot in best way to convert ES6 syntax to ES5 ?   
    Oooo, this thread could get flamey! Ha ha.
    There are numerous advantages to using ES6, a quick google search will give you heaps of reasons, with the only con being that you probably have to up the complexity to transpile back to es5/3, however, all modern browsers support most of ES6 (and newer) syntax so unless you're supporting really old browsers (and you stick solely to ES6) then you probably don't need to transpile.
    The biggest advantages of ES6 (for me, and I've missed loads here):
    * ES6 was pushed through to create more complex applications, as such it has a lot of syntax that is more useful for doing so. Some are sugar methods only, some actually provide newer functionality (particularly those related to primitives and/or the DOM).
    * New built-in extensions which make many tasks way way easier (and easier means less error-prone)
    * Sugar methods mean less dev typing which generally means less mistakes. Some things ES6 makes easy are very very hard in ES5 and they are often things devs rely on regularly so making them easier to work with means writing code is less error-prone and reading code is clearer so you can focus on what your code does, not how it does it.
    The biggest advantages of setting up a transpilation pipeline are (again, I'm missing loads):
    * Access to a module system
    * Access to whatever new syntax you want
    The con of a transpilation system is increased project complexity and you have introduced a build step which takes some time to run, as your project grows this sometimes becomes prohibitive but you do have to have a very large project for this to happen and most modern build tools abstract away incremental builds and caching i.e. they only re-build the changes so incremental builds become smaller and faster.
    Another con is related to the module system. Modules are awesome, very awesome. However, JS doesn't (yet) natively support them in the browser and even when they do there are additional problems i.e. if you use modules heavily (as you probably should) then your list of dependencies could easily be hundreds or even thousands of files, loading each of these one by one in the browser isn't a good idea and won't be in the foreseeable future.
    A module system also implies that you need some way of getting dependencies. This isn't technically necessary but is often helpful. If you are writing games then often you'll be using one (or maybe two) large frameworks to help, unless they work nicely with a dependency management system (i.e. NPM) then I wouldn't worry about getting them as 'real' modules, just include them on the page and use them, then use a module system for your own code if you want to.
    Newer syntax and mobile games
    Any gaming is typical performance sensitive, newer syntax has a few things to consider:
    * Browsers are well optimised for ES5, this isn't always true to ES6 (although ES6 is pretty good now as its fairly old and almost universally adopted in browsers)
    * Given the above, transpiling is often better for performance
    * The code generated by these tools during transpilation is superb, it is written by many many superb developers and has great community support so the hours invested in it must be astronomical i.e. in many cases these tools will write better code than you or I do!
    * It is not a silver bullet -> if perf is a concern for you then you are still largely the sole arbiter of whether you achieve your perf goals.
    How to use newer language features:
    Babel is the defacto tool (although it isn't your only option). Babel requires a bit of setup work and additionally requires you to set up a build process for your code. Again, there is tooling for this. Additionally, there are many project scaffolds out there (and tools for creating them) that can abstract this away.
    The absolute easiest way of getting access to these new language features but supporting older browsers is to use parceljs.
    Parcel abstracts away most of the complicated build stuff and has a superb feature set. It involves a few pre-requisites:
    * You must know how to run simple commands from the command line
    * You must have Node and NPM installed
    Once you have these things (which is generally true of any JS build system you might want to employ) then running builds is a simple one-line command. A watch task is also bundled in, this is another simple one-line command to run and watches the file system, every time you save a change it rebuilds only what has changed and propagates that to the browser. Parcel relies heavily on caching and multi-threading so is very very fast.
    Other tools include webpack (which is very complicated, although newer versions I think make things way way easier for most use-cases) and browserify (which is simpler in scope, but can feel a little low-level for many people).
  16. Thanks
    mattstyles got a reaction from blossy in Lack of CoDs or CK2s that use HTML5/JS   
    For rendering a browser gets pretty much the same access to the GPU as any other application, albeit with less control (and via an older spec, webgl isn't quite as good as you'd have with different avenues).
    For running calculations JS is impressively fast for a JIT compiled language but can't match any AOT languages such as most modern games would use. There is no getting around this, WASM (web assembly) is mooted, but, it may not quite get to the same place.
    There is also an argument that JS is not a particularly good language for larger teams, such as those involved in more complex application (i.e. AAA games). Again, there are some solutions for this, such as Haxe, TypeScript, Elm or even using LLVM to convert your code in to WASM (or JS), as always, there are trade-offs.
    The browser has some interesting restrictions that make achieving optimal performance tricky i.e. reliant on a platform canvas implementation, no UDP sockets, cross-platform differences are much trickier than most AAA games have to deal with etc etc.
    Websites have different load requirements than local applications i.e. most games require a hefty download (or a large storage device such as a CD or memory stick) to a local storage device, would you accept this wait every time you wanted to play? Because the browser is not permitted to store so much information locally (there are hacks around this, but, they are nasty) so you'd have it for every play.
    Browser users have expectations of browser-based applications that they typically do not for a local application, expectations can be broken down, but its hard.
    I still think there is one issue that trumps all of these above: monetisation.
    Closed application stores and closed source applications are opposed to the fundamentals the web is built on so a new method is required, which hasn't really happened yet.
  17. Like
    mattstyles reacted to b10b in Encode Every Pixel into Array Quickly   
    Sounds like a fun programming exercise ... translating a 1D array into a 2D array based on a fixed length row.  Keywords might be "array", "slice", "splice", "chunk".  Many ways to do it.
    Or, given that it is a Boolean array, string expressions could be leveraged:
    var _1d = [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0]; var _2d = _1d.join('').match( /.{1,5}/g ).map( p_s => p_s.split('').map( Number ) ); This assumes a row width of 5.
    But probably tidier to do directly from the ImageMapData where you already know the width.  Map!
  18. Like
    mattstyles got a reaction from b10b in Lack of CoDs or CK2s that use HTML5/JS   
    For rendering a browser gets pretty much the same access to the GPU as any other application, albeit with less control (and via an older spec, webgl isn't quite as good as you'd have with different avenues).
    For running calculations JS is impressively fast for a JIT compiled language but can't match any AOT languages such as most modern games would use. There is no getting around this, WASM (web assembly) is mooted, but, it may not quite get to the same place.
    There is also an argument that JS is not a particularly good language for larger teams, such as those involved in more complex application (i.e. AAA games). Again, there are some solutions for this, such as Haxe, TypeScript, Elm or even using LLVM to convert your code in to WASM (or JS), as always, there are trade-offs.
    The browser has some interesting restrictions that make achieving optimal performance tricky i.e. reliant on a platform canvas implementation, no UDP sockets, cross-platform differences are much trickier than most AAA games have to deal with etc etc.
    Websites have different load requirements than local applications i.e. most games require a hefty download (or a large storage device such as a CD or memory stick) to a local storage device, would you accept this wait every time you wanted to play? Because the browser is not permitted to store so much information locally (there are hacks around this, but, they are nasty) so you'd have it for every play.
    Browser users have expectations of browser-based applications that they typically do not for a local application, expectations can be broken down, but its hard.
    I still think there is one issue that trumps all of these above: monetisation.
    Closed application stores and closed source applications are opposed to the fundamentals the web is built on so a new method is required, which hasn't really happened yet.
  19. Like
    mattstyles reacted to Thomas Hunter II in Cobalt Dungeon   
    Hey there!
    I recently released a mobile game called Cobalt Dungeon. This game is based on Phaser 2 and uses a fullscreen canvas and basically only touches the DOM during initialization. The application itself is wrapped in Cordova 8 and runs on iPhone and Android. It's currently available for both platforms in their respective stores:
    Cobalt Dungeon for iOS on the App Store Cobalt Dungeon for Android on the Play Store The game took me four months to create, from start to finish. I had created games before using HTML5 / canvas, and had released one before on the app stores (I later open-sourced it as Mobile Game Skeleton, if you're curious), so the process was familiar. This game is very Indie, like most of the games on this forum, with me being the only dedicated contributor. I made the music and sound effects, sourced /remixed existing graphics, etc. One thing that might make this game a little special is that 99% of the development was done on Linux, almost entirely using open source tools, though I do have a Macbook Air I use solely for iOS builds and I did use FL Studio for music. I'd like to talk a bit about the process I went through, hopefully someone else will find it useful as well!
    I have been producing a series of game development videos recently and will make a high-level one soon based on this post! I also have a blog with hundreds of development posts, if you are into the whole reading thing.
    Development Workflow
    Almost all of the day-to-day game development, e.g. the actual core gameplay of moving around the dungeon and attacking enemies and picking up items, is designed and debugged using the responsive view of the web debugger in Google Chrome. Personally I prefer Firefox for web browsing but there's no beating Chrome when it comes to dev tooling. This tool is great because once you tell it to pretend to be a particular device (e.g. an Android Nexus 5x or an iPhone 6s) it'll do everything from setting the user-agent to reconfiguring the pointer to send touch events. Being able to interact, alter game state, and read console messages in real time is a total must. Very little on-device development happened for the first three months (mostly occasional performance testing).
    Of course, testing locally is fine for a while, but you definitely do need to test on a real device. My daily driver is a Nexus 5x which is a little over 2 years old. I used this device for most of my testing. I figure the average phone is about as powerful as this one so I would constantly make sure the game ran at 60 FPS on this device. My other test device is an iPhone 5. This phone is like 5 years old, so it's mostly safe to say that any game that'll run on this phone will run on any modern iOS device. (One caveat is the new iPhone X notch, which I still need to fix. Resolution differences are also important to consider)
    You may find weird edge cases which only present themselves when your game runs on a physical device. A common example is related to touch inputs. When debugging these issues you can actually use a Chrome feature called Remote Debugging, which will allow you to use Chrome installed on your computer to interact with Chrome on your Android device (I'm not sure if such a feature exists with iOS Safari, but I didn't need such a feature). Normally Chrome will even show duplicate the view of the phone on your computer screen but it doesn't seem to work with Canvas.
    Artwork/Aesthetics
    The game uses 16x16 tiles and a palette of 24 colors. If you find yourself making a pixel art game, you must pick a palette and adhere to it! I found that having such a restriction really helped with creativity, as well as getting an overall cohesive feel. The basic terrain is based on free artwork I found on OpenGameArt.org. That website is amazing for getting assets and I highly recommend you check it out (here's a bunch of music I contributed if you're into that). The players / enemies are based on another art pack which I purchased a license for (around $30 at the time, I think). I would then touch up this artwork to get everything following the same palette. I would also have to stitch the graphics together to build spritesheets and get animations going.
    Any time I would create new artwork I then do my best to fir the same art style. For example, the first boss Shroomzilla I put togehter. It uses the same color palette, though the visual style is definitely more complex than the simpler graphics used throughout the rest of the game. The graphics for the Ice, Moss, and Fire worlds are altered from the base terrain, but still follow the same palette. The main menu graphic of a stairway going into the dungeon is also something I had to draw based on googled reference material (also with the same palette).
    The graphics I use do use 1x1 pixels in their source PNG files, despite being rendered on device as some arbitrary pixel size, e.g. 6x7. I do the stretching by dynamically scaling the viewport when the game first loads (I'll make a video explaining this process at some point). This is cool because it's impossible for me to address a sub pixel. You'll see this issue in a lot of pixel-art games where there's partial pixel overlap. Rendering on Android is done with Web GL, and on iOS with software. This was necessary to get the viewport scaling to work, prevent blurry pixels on iOS, and prevent slow performance. E.g., scaling the viewport when rendering Web GL on iOS is very slow and blurry and slow, and works perfectly on Android.
    Music/Sound Effects
    The audio was all custom made for this game, both the sound effects (SFX) and the background music (BGM), though the process for making both is very different.
    SFX: The Sound Effects were mostly made using the wonderful as3sfxr tool. This tool, despite being super old and written in Flash, is one of the best (if not the best) tools for making 8-bit (-esque?) sound effects. The workflow I use is to first figure out what part of the game needs a sound effect, then click the category which sounds most similar, and then start randomizing the sound until it sounds similar to what I'm looking for. If a randomization goes in the wrong direction then undo and try again. Once a sound is pretty I then modify individual parameters until it sounds correct. Once it's done I generate a WAV file and load it into FL Studio. The goal with FL Studio is to create a single MP3 file with all the sound effects, e.g. the first at 0 seconds, the next at 3 seconds, etc. Once this is done I specify the sound locations using JSON. Unfortunately I kept having issues with Phaser's audio library so I chose to use a library called Howler to play the audio. The code for using Howler looks something like this:
    const TIME = 2999; const SFX = { damage: [0, TIME], explode: [3000, TIME], door: [6000, TIME], wait: [9000, TIME], upgrade: [12000, TIME], }; const sfx = new Howl({ src: './audio/sfx.mp3', sprite: SFX, autoplay: false, volume: 1.0, onload: finishPhaserPreloading }); sfx.play('damage'); BGM: The music was entirely composed using FL Studio (overview video, some notes on how I made the music). One of my goals was for the game to feel familiar to the generation of 8-bit / 16-bit gamers. However, making actual 8-bit / chiptune music was not a requirement by any means. So what I chose to do was keep every song simple; most have only 2 or 3 instruments. With the exception of percussion/drums, the music is entirely synthesized. Whenever possible I would use simple waveforms and simple filters (e.g. for the ice levels the lead is a sine-wave with a touch of delay and reverb). Sometimes I would use more complex instruments, like the string instruments in the main menu / fire levels. With the exception of the main menu music, each song follows the same structure, which you can download as an FLP file here. The tempo does change which is why the songs are of different lengths.
    Overall I like the way the music turned out. I frequently listen to it while commuting. There's a few things that annoy me, like the bridge in the ice music or the repetitiveness of the moss/jungle music, but overall it's not too bad. The music is the largest part of the application, consuming about 18MB of the overall ~24MB binary. Since most people are listening to it via crummy mobile phone speakers I've compressed the audio at 96kbps in the game (higher bitrates are available for download on my Patreon).
    Libraries / Code
    As I mentioned, this game is built using Phaser 2 (I might upgrade to Phaser 3 soon, now that the children/group feature is being added), as well as the Howler library. Code is written in mostly ES2015 syntax. I use Browserify to combine my code, traversing import/export statements. Once browserify is done I then pipe the output through Google Closure Compiler to get a single JavaScript file without any comments or whitespace, and being minified as much as possible (e.g. dead code paths are removed). I don't, however, run any of the libraries through closure compiler. So in my final HTML file I'm loading four libraries: phaser.js, howler.js, cordova.js, and my games bundle.js. Many people seem to enjoy many weeks configuring webpack and getting bleeding-edge versions of the language transpiling but I try to avoid that as much as possible.
    The game is wrapped in Cordova 8. This requires a whole bunch of JDK and Java build tooling be installed, as well as Xcode on my Macbook. Configuring all that tooling is a nightmare! I also make use of the following four Cordova plugins:
    <plugin name="cordova-plugin-vibration" spec="^3.0.1" /> <plugin name="cordova-plugin-media" spec="^5.0.2" /> <plugin name="cordova-plugin-admobpro" spec="^2.31.1" /> Vibration is required to get vibration working on iOS (it's not required for Android, it just works out of the box). The media plugin is interesting. At first I would play all the music using Howler. This means the browser itself load the audio into memory. Unfortunately I found that the browser is incapable of destroying the music, even when the appropriate methods are called to unload the audio! Using the Cordova media plugin is necessary if you want to be able to play more than a few songs and not have a mobile browser segfault without a stacktrace in sight. The admobpro plugin is used display ads in the game. Unfortunately the author skims a few percent of your proceeds off the top unless you buy a license. I'm also trying to use an IAP module but am currently having compatibility issues with that and Cordova 8. Now that the game has released I'll try to get the plugin working as I'd like to offer players the ability to give me $2 and to have ads disabled (ads also hurt performance).
    I do load two JavaScript libraries installed via NPM into the compiled bundle.js by way of Browserify. These are two libraries I also made and open-sourced. Neither has any dependencies so that the output bundle is as straight-forward as possible. The first one is roguelike. This library has a ton of features! All the level and room generation is done using this library. I also use it for a lot of math / random / dice roll calculations as well. The second library is autotile. I use it for taking a 2D array of booleans (representing if the ground is a floor or a hole) and converting it into a format to represent the actual spritesheet offsets. This is very handy so that you don't need to perform the calculations yourself. This allows me to represent a floor using a simple array of booleans instead of tightly coupling it with spritesheet offsets.
    Tools
    As I mentioned, I use FL Studio to do the audio work. I bought the Producer version for $200 and have been really happy with it. Since I'm running on Linux that means I need to wrap it in Wine. This experience is a little iffy, e.g. if I attempt to scroll anywhere in the UI the app completely freaks out. Other than that it's been a pretty solid experience, especially since my songs only have a few instruments. For most music, however, this won't be true. The more instruments and effects running, the higher the CPU cost. Running FL Studio directly on Windows will be much more efficient than with Wine and Linux. There are of course free alternatives, especially native Linux tools, but I had used it years ago and was comfortable with it.
    All coding was done using VIM. Once you get used to those keybindings you'll be trapped using this editor forever.
    While most of the rooms are procedurally generated, I did want to create a bunch by hand. For example, all of the tutorials and challenges are done by hand. For those I used a tool called Tiled. (At first I hand-generated JSON. This would never scale and prevented creativity). Tiled allows me to edit a visual map, with different layers, using the actual spritesheets used in my game. Tiled will output an XML file format which can even be imported into Phaser! However, passing around a file format representing rooms which is so tightly coupled to the graphics is not a route I wanted to take. So I wrote a converter tool to convert the XML files created by Tiled into a very simple JSON representation which contains only exactly what I need to represent a level. As an example, enemies can be represented as an array of objects with an X/Y coordinate, an Enemy ID, and their Phase. The Tiled representation would contain lookup information for the enemies coordinate in the spritesheet, the layer then graphic is on, and wouldn't have the metadata I need. Here's a video of my Tiled workflow if you'd like a better idea of how I make rooms.
    For creating the Bitmap font format used by Phaser I used a tool called BM Font. This allows me to take a TTF font and create the XML/PNG files needed for rendering on the web. The process for doing this can be super complex so I even made a video on font conversion for Phaser.
    Graphic editing was done using GIMP, a free image editing app originally made for Linux but is available for all platforms. Coming from a Photoshop background it can take a while to get used to the keyboard shortcuts and the weird choices GIMP made (e.g. layers have different dimensions, what's up with that?!) I created a palette using the 24 game colors and that really helped my efficiency. I also tweaked the UI to be in single window mode (ala Photoshop) and also reconfigured the tools (mostly disabling anti-aliasing, enabling a 16x16 grid). Once you dig through the menus it's possible to save the tool configuration permanently, which really helps with efficiency.
    Hardware
    I did the drawing of the main menu graphic using an old Wacom Tablet bamboo, it's older but probably cost $100. The music was made using an Akai MPK Mini (two octave MIDI controller), also for $100. Neither of these tools were required to produce this game, but they sure make it a fun process. All development was done using a Lenovo Thinkpad Carbon X1 5th generation, by far the best laptop I've ever owned! Worth the $1600 price tag.
    Live Ops
    Once a game is live you don't want to have to release a new version of the app for every little update. This is when having a CMS is really helpful. I built a Node-based CMS specifically for game development called Grille. My workflow for this is that I edit a Google Sheet, change values (for example enemy attributes, shop costs, game text, etc). Once I'm satisfied with the result I use Grille to generate a JSON file which I can upload to a CDN.
    Of course, it's useful to know what in the game actually needs changing! For example, do most players get to level 7 and then stop playing because they get killed by a Mage and get frustrated? For that I use a service called Mixpanel. Throughout the codebase I make analytic calls with useful data. For example, when a player dies, goes to a new floor, buys a shop item, views and ad, etc. I can then use the Mixpanel UI to view a "funnel" of users as they progress through the game.
    [Attached is a screenshot from Mixpanel showing the level progression funnel]
    Monetization
    I make money with ads thanks to Admob. There are two types of ads; the first one is an ad shown when the player switches between rooms. This ad is displayed at most once every five minutes. The second ad is an ad the player can choose to view. When the player dies they can choose to view an ad to respawn in the room they died in. Otherwise they can choose to respawn at an older save point.
    Let me know if you have any other questions about the development process, or if you'd like me to produce a video explaining any of these topics. Thanks!

  20. Like
    mattstyles got a reaction from mazoku in Any other functional programmers out there?   
    I'm fully on the functional bandwagon, its a wonderful way to program.
    If you've ever experienced a race condition or problems with synchronising data structures then you'll know how painful they are. Functional is hardly a silver bullet here but if you follow along and do things properly with functional techniques then you rarely run in to these sort of difficult and time-consuming errors.
    At its essence functional program aims to eliminate (or reduce) transitional state, as an example, if you have a data structure representing a unit in your rts game then its likely you'll want to use bits and pieces of the full unit data in difference instance i.e. you'll want some of it for displaying an update view, you'll want some different bits of it to display in a tooltip, you'll want very different bits of it for when it attacks another unit.
    Functional languages force you to create transformation functions to change that data into what you want, the key here is that they force you to do it when you want it and get rid of it afterwards (JS doesn't force you at the language level but you can still use the theory, JS does have language support for most functional techniques making it a good candidate for writing in a functional style, it was designed this way too, not just a coincidence).
    By enforcing transforms to underlying data structures it pushes you down a few key avenues:
    * Each view on to the data is independent, they request data when they want it so that it is fresh, there are no syncing issues here, data is represented once (single source of truth) and can be minimally represented as your transforms can add specifics for their use-cases.
    * Changes to data are carefully managed (many functional languages enforce this with immutable data structures) so that it can become hard (or even impossible, depending on the language) to have data inconsistencies.
    * Race conditions aren't necessarily eliminated but as you're managing changes and actions in a single place its easy to manage things so you never hit a problem caused by it.
    You can't really do the above with OOP because OOP involves writing and creating objects (and classes usually) and having all this state hanging around, see the banana-gorilla-jungle explanation.
    Some of the most useful functional techniques can be adopted even if you're in an OOP world though.
    Creating pure, or referentially transparent, functions is a boon for developers. Pure functions take an input and produce an output based only on their inputs, they effectively do not touch the outside world, they are idempotent, i.e. you know that you will always get the same output given the same input/s. This means you can reason about what that function does, you can understand it fully by taking it in isolation, you don't have to understand the system around it to understand what it does. They become easily testable so any bug or error states can be discovered by automated unit tests but if one does sneak through your tests and you find you need to make changes later then you can do so easily because you know you won't create issues elsewhere in the code. This is absolutely golden.
    The downside is of course performance. For certain use-cases you're potentially running the same transforms multiple times when you don't need to i.e. being inefficient. Functional programming likes to do things on demand but games often want to work with an update loop as things are often changing very frequently so sometimes some transients states hanging around reduces load (at the expense of far greater complexity). This is the biggest problem I've faced for fast paced games using these techniques but you might be surprised at how far you can get and there are lots of techniques for improving this stuff without creating more state.
    The 2nd biggest problem is that many libraries out there don't want to play nicely with functional techniques, this isn't so much of a problem for the general web app/website world as there are numerous libraries out there for those use cases now but it is a problem for many games-related modules/libraries.
  21. Thanks
    mattstyles got a reaction from mazoku in Question on performance   
    Many callbacks from browser/DOM (such as `requestAnimationFrame`) bind the callback, in the case of `Element.addEventListener` this becomes the Element, in the case of `requestAnimationFrame` it'll be the window. Depending on your use-case this re-binding might be undesirable, e.g. consider the following (I'll use the time honoured OOP/inheritance example of cat speak, particularly relevant given your avatar ):
    var cat = { name: 'mazoku', speak: function (str) { console.log(this.name, 'says', str) } } cat.speak('hello') // mazoku says hello requestAnimationFrame(cat.speak) // undefined says 293878273.231 requestAnimationFrame(function () { cat.speak('hello') }) // mazoku says hello The above highlights 2 possible reasons you'd wrap in a function:
    * You don't want the re-binding
    * You want to call that function every tick, but supply your own parameters
    You can get around the binding issue by ditching OOP-like strategies and just pass plain functions in, however, you'll still want to handle the case of passing variables in, thankfully, JS supports closure and it's a very powerful thing to have at your disposal, and would work great here as one possible solution:
    function sayThis (str) { return function say () { console.log('hello', str) } } requestAnimationFrame(sayThis('world')) // hello world In this case `str` gets locked in the closure, this pattern is sometimes called a thunk, but, really, its just using closure.
  22. Like
    mattstyles got a reaction from syntaxidermy in Really Basic Setup question   
    @syntaxidermy
    You're loading Phaser from an external source, although I still have little idea why it doesn't work for you, the following is fine for me:

    I'm not using WAMP though, but a different server. It shouldn't make any odds though, but, in any case, you're not loading from the remote source for some reason, doesn't look related to your HTML though.
    You do get that EXACT error from file protocol though which won't access the internet.
    Are you absolutely sure you're hitting the WAMP server to grab the HTML file?
    Using `script src='./phaser.min.js'` should work from file though, not the `./` to make it a relative link.
     
  23. Thanks
    mattstyles got a reaction from hilderonny in HTML 5 GAME DEVS reputation system   
    Almost every app I use has this sort of thing, even with the ability to share your progress or 'compete' against others.
    Games nicked it from real life and now 'real life' apps have nicked it from games. A lot of the reward addiction stuff comes from gambling, but most comes from getting the best out of employees, particularly those that work in an intrinsically non-motivational environment (some jobs require a lot of 'grind', back in the day this would be done with fear and whips, nowadays we tend to use the carrot more than the stick).
    Most apps and games nowadays unfortunately use external motivators. These are things like 'play/use for an hour to get rewards' or 'play/use a certain amount of times in a day', they're external because the environment (the game) sets them and you, as a user, are just following along. They aren't particularly effective but they cheap and easy (usually) to implement.
    Some apps/games go a step further and use the human need for completion against users i.e. if you're on todo item 9 of 10 it'll tend to nag at you to get 9 and 10 finished and squared away. This todo list completion effect is still often implemented as external (win 2 battles today, post 3 times today, learn 3 words today etc etc) but slightly more involved as it uses the incomplete list effect to gain addiction. MMO's are rife for this sort of thing, they'll give you a couple of easy tasks to complete and then some more time-consuming ones when you're already 'invested' in completing that list. Many learning apps (such as language learning apps) do the exact same thing to great effect.
    Some of the best motivators are internal motivators. Sandbox games that truly are sandbox set out the rules of the world and let you go, they sometimes add reward tiers etc etc but, largely, you, as a user, set your own course of action. There are loads of superb examples in this field but it requires a whole heap more designing than many games go in to (particularly casual gaming, for good reason). Games/apps that leverage internal motivators are usually played by players for a long time (years is common) but its hard to set up world rules that allow for beginner and advanced players to get the same enjoyment, usually they have a steeper learning curve and 'deeper' gameplay. Some learning apps may leverage this type of motivator in some way.
    Business/lifestyle apps are pretty tricky to get into the internal motivator category as users will already come for a very specific reason, hence, the scope of the app is small and focussed (which is good) but it makes exploration and personal/group goal-setting difficult.
    Many business/lifestyle apps go down the Weight Watchers style route of group motivation i.e. they can be very aggressive about sharing with a group or competing so that human interaction (rather than app nagging) will keep you engaged and they will reward both the bragger and the supporter in any dynamic.
  24. Like
    mattstyles got a reaction from onlycape in how to call a function as argument ?   
    Nah, its not even a scope problem, whatever `myFunction` is in the original post, it wasn't a function.
    However, I do agree that you don't need to wrap the callback function again, but, you don't even need the `wait` function as it has just become a marginally slower alias. I'm assuming this is all simplified for the purposes of illustration though and that you're actually planning to do more with your wait function (like make it a little easier to cancel it, or extend it, or whatever).
    Functions in JS can be passed around as first-class citizens, which is an extremely useful language feature.
    function add (a, b) { return a + b } You can think of the `add` variable as a pointer to a block of code (rather than a pointer to a memory allocation), using newer syntax makes this even more obvious:
    const add = (a, b) => a + b Where you actually assign the anonymous (lambda) function to the constant variable (ha ha, that proper sounds odd!) `add`.
    Note: there are subtle differences between the two code snippets above, but you're extremely unlikely to need to worry about it, particularly for pure functions like the ones above.
    Either way you can pass the `add` function around, including using it as a parameter for other functions.
    Consider the following:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const d2 = () => Math.random() < 0.5 const tweak2 = (a, b) => d2() ? add(a, b) : subtract(a, b) Calling the `tweak2` function has a 50/50 chance of either adding or subtracting those numbers, but, imagine we wanted to add other operations:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const multiply = (a, b) => a * b const divide = (a, b) => a / b const d2 = () => Math.random() < 0.5 const tweak2addsubtract = (a, b) => d2() ? add(a, b) : subtract(a, b) const tweak2addmultiply = (a, b) => d2() ? add(a, b) : multiply(a, b) This is a pretty terse example but you can imagine how this is going to grow. Now imagine you end up changing some of the implementation, would be pretty error-prone. Imagine trying to test all combos, again, a little annoying.
    However, you could refactor this slightly and use another helper function:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const multiply = (a, b) => a * b const divide = (a, b) => a / b const d2 = () => Math.random() < 0.5 const tweak2 = (fnA, fnB) => (a, b) => d2() ? fnA(a, b) : fnB(a, b) const addSubtract = tweak2(add, subtract) console.log(addSubtract(10, 2)) // 8 or 12 Now the tweak function can be 'pre-loaded' with functions it uses to operate, which we've passed through.
    If you're not comfortable with arrow functions then its a little confusing to follow as it uses closure and explicit return to work, but, have a look as this pattern can be generalised to be useful in a wide variety of situations.
    When you get really good you can do stuff like the following:
    const isNumber = _ => typeof _ === 'number' const add = (a, b) => a + b const total = compose( reduce(add, 0), filter(isNumber) ) total([1, 2, 'a', 3]) // 6 All functions used here a low-level pieces and trivial to test and re-compose.
    Unless you're comfortable with passing functions around it's probably a little tricky to see exactly what is going on (there are lots of good places to read up on it though) but you should be able to see that the `total` function can take an array, filter out only the numbers, and then add them all up.
  25. Like
    mattstyles got a reaction from espace in how to call a function as argument ?   
    Nah, its not even a scope problem, whatever `myFunction` is in the original post, it wasn't a function.
    However, I do agree that you don't need to wrap the callback function again, but, you don't even need the `wait` function as it has just become a marginally slower alias. I'm assuming this is all simplified for the purposes of illustration though and that you're actually planning to do more with your wait function (like make it a little easier to cancel it, or extend it, or whatever).
    Functions in JS can be passed around as first-class citizens, which is an extremely useful language feature.
    function add (a, b) { return a + b } You can think of the `add` variable as a pointer to a block of code (rather than a pointer to a memory allocation), using newer syntax makes this even more obvious:
    const add = (a, b) => a + b Where you actually assign the anonymous (lambda) function to the constant variable (ha ha, that proper sounds odd!) `add`.
    Note: there are subtle differences between the two code snippets above, but you're extremely unlikely to need to worry about it, particularly for pure functions like the ones above.
    Either way you can pass the `add` function around, including using it as a parameter for other functions.
    Consider the following:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const d2 = () => Math.random() < 0.5 const tweak2 = (a, b) => d2() ? add(a, b) : subtract(a, b) Calling the `tweak2` function has a 50/50 chance of either adding or subtracting those numbers, but, imagine we wanted to add other operations:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const multiply = (a, b) => a * b const divide = (a, b) => a / b const d2 = () => Math.random() < 0.5 const tweak2addsubtract = (a, b) => d2() ? add(a, b) : subtract(a, b) const tweak2addmultiply = (a, b) => d2() ? add(a, b) : multiply(a, b) This is a pretty terse example but you can imagine how this is going to grow. Now imagine you end up changing some of the implementation, would be pretty error-prone. Imagine trying to test all combos, again, a little annoying.
    However, you could refactor this slightly and use another helper function:
    const add = (a, b) => a + b const subtract = (a, b) => a - b const multiply = (a, b) => a * b const divide = (a, b) => a / b const d2 = () => Math.random() < 0.5 const tweak2 = (fnA, fnB) => (a, b) => d2() ? fnA(a, b) : fnB(a, b) const addSubtract = tweak2(add, subtract) console.log(addSubtract(10, 2)) // 8 or 12 Now the tweak function can be 'pre-loaded' with functions it uses to operate, which we've passed through.
    If you're not comfortable with arrow functions then its a little confusing to follow as it uses closure and explicit return to work, but, have a look as this pattern can be generalised to be useful in a wide variety of situations.
    When you get really good you can do stuff like the following:
    const isNumber = _ => typeof _ === 'number' const add = (a, b) => a + b const total = compose( reduce(add, 0), filter(isNumber) ) total([1, 2, 'a', 3]) // 6 All functions used here a low-level pieces and trivial to test and re-compose.
    Unless you're comfortable with passing functions around it's probably a little tricky to see exactly what is going on (there are lots of good places to read up on it though) but you should be able to see that the `total` function can take an array, filter out only the numbers, and then add them all up.