Jump to content

Introduction - HTML5 + Multiplayer Game


Damian Pastorini
 Share

Recommended Posts

Hi everyone,

Nice to meet you all, my name is Damian, I'm starting to work on a MMORPG using Phaser 3 for the frontend (that's how I've hit this great forum), and NodeJS for the server (using Colyseus.io).

This is the first time I'm working with NodeJS and in a game development (I've been working in e-commerce with PHP for the past 10 years), so lot of stuff to take in, but so far I'm doing quite cool.
In about 30hs of work I've already got a basic implementation between NodeJS + Colyseus + MySQL + plain HTML5, where you will be able to register/login and move a square with your name over the page :P

Side note: I know the main forum topic is HTML5 development (that's why I'm asking this here in the general topic), but I was thinking that will be a great idea for the admins if we could have a section for server-side integrations?
I did a quick search and read a few posts that have some tips but consolidate everything in a new section will be much better. Also considering that you can use any of the client frameworks to create some great multiplayer games. 

So, what I'm looking specifically is for some references on develop a Phaser 3 client by using npm and a builder like parcel or webpacket, here you will find cool examples for each:
https://github.com/endel/tic-tac-toe > this one implements Colyseus on the server to handle server side
https://github.com/jackyrusly/jrgame > this one use Phaser 3 and plain Sockets.io 

My idea is to create a mix between those two, but I still can't decide if I should use Webpacket (https://www.npmjs.com/package/webpack) or Parcel (https://www.npmjs.com/package/parcel), any recommendations?

I've did some research and it seems that Parcel is a bit new and better:
https://x-team.com/blog/rollup-webpack-parcel-comparison/
https://medium.com/@ibrahimbutt/if-youve-ever-configured-webpack-parcel-will-blow-your-mind-b615468cee78

Thanks in advance! Congratulations for the great forum! :D

Link to comment
Share on other sites

Hi, welcome to the forums, cracking first post!!

Server Integration Forum

Regarding a specific server-integration forum, I think this has been mooted a couple of times but didn't necessarily garner the interest to make it a worthwhile part of the scope of the forums. Maybe its time to revisit that and see if we add it in.

JS Bundlers

Both Parcel and Webpack are generally superb.

Webpack is extremely customisable and has a thriving community building plugins etc etc. If flexibility is key then Webpack is a superb choice, but, the downside is that the configuration is difficult and as the ecosystem moves very quickly (which is awesome) it often requires fairly consistent work to make sure you are getting all the good stuff.

Parcel is newer and works in a slightly different way, personally I love it but I'd worry it might fall over if you're working on really complex stuff. Having said that it is gathering a lot of traction and these sorts of issues are being ironed out, the main point being that actually all this build stuff should be a simple as possible, which is a great goal.

Webpack now has a lot of pre-configured stuff added in. Webpack is fairly low-level, I _think_ the intention was that lots of projects with opinionated configuration would arise on top but that hasn't really happened at scale, however, due to tools like Parcel simplifying how to scaffold and build projects Webpack now includes a really comprehensive set of default configurations to get you up and running quickly.

For some anecdotal evidence: I've never been a huge fan of Webpack but have migrated most of my personal projects away from my custom Browserify (etc) build pipeline and moved to Parcel and have really really enjoyed the switch and got loads of stuff (like code splitting, asset imports and HMR) basically for free, and these were things I was a little scared to add to my own system. Webpack can do all of these things too (possibly out of the box) but I've loved the experience of using Parcel. I also work in eCommerce (on a wholly JS powered app) and am looking at moving our extremely complex Webpack set up to Parcel, not sure how that will go though, server-rendering is always a little tricky.

Over the weekend I've started to release a small animation helper library and used Parcel to build some examples out, hosted https://mattstyles.github.io/animatron/. I had an issue with the root for serving assets via github pages, but it took 5 mins to find the answer. Apart from some very basic Babel config, everything else 'just worked', literally took 2 mins to set up a 'watching' dev build (with hot module replacement and progressive builds, the project is trivial but it rebuilds in milliseconds) and push out production code to github pages.

Link to comment
Share on other sites

Hi @mattstyles, thanks for you reply!

Yesterday I've started to implement Parcel:

- First had to fix some paths to avoid build errors :P 
- Then include some libs through npm and use require (like for jQuery, jquery-validation and so) instead of having links to  the CDN files (this to avoid some undefined issues, you can tell how new I am on this....)
- At this point I was able to even get Colyseus.JS (client side for colyseus working).
- And the last error I got was related to Pharser itself, something about global not been defined (global.performance in requestAnimationFrme) > If you have any ideas what's this about please tell me :P I'm guessing it's something related to how the libraries are been loaded by Parcel.

That said I feel that I'm really close to get it working properly and that I will stay with Parcel.

Best,

Link to comment
Share on other sites

1) oh yeah, I ran into some pathing stuff too, I'd forgotten that! Mine was related to commonJS and node module resolution, NODE_PATH is an env var that node will honour to help resolve modules, browserify used to honour it (possibly Webpack does too, after transforming your modules to commonJS), but Parcel did not so my `NODE_PATH=src` and `import {foo} from 'core/somefile'` which previously resolved to 'src/core/somefile' now didn't work. To get around it I used a babel transform (module-resolver, this one) to transform paths and supply certain roots. Of course, no-one needs this, but it can be a useful thing to do, although it does up the complexity and 'magic' of your codebase so its a +/- (I _think_ Webpack might do it via aliases or some other plugin for adding resolution roots other than the standard node_modules root).

2) Thats awesome, and probably the _best_ way to do it, but I wouldn't sweat adding some things globally with script includes. You'd want to do that sparingly. Interestingly there could actually be some advantages related to both browser and CDN caches, but, in practise, these advantages are extremely minimal and the make the whole thing more complex by relying on external sources.

3) Awesome

4) Phaser itself doesn't really like being npm installed, it's best just to include it as a script include and accept that it'll be available globally.

The actual error you get is related to some performance monitoring stuff and the browser timing API. Some questions:

* Which browser are you getting the error in? Support is superb for the timing API so it probably isn't a browser, it sounds a little like it might be executing some code on the server, is this running in node? where performance is not available, nor requestAnimationFrame.

* It also sounds like something that maybe Phaser would only include in a dev build to monitor any loop (game loop?), are you testing with a dev build or a prod build?

Glad you're getting on well though, it sounds really ambitious what you're doing and its really interesting hearing how you're getting on and solving problems.

Link to comment
Share on other sites

Hi @mattstyles, thanks for you great replies! :D 

1 - For now I will keep it "hardcoded" but I also saw some stuff around babel, but that will make it more complex for me so I will leave it for later.

2 - I've assumed that using npm was better since I'm now able to require and include the libs everywhere. I've tried to combine resources but I wasn't able to do it easily, for example I had jQuery from npm and jquery-validation.min.js and I didn't find an easy way to make jQuery available for the validator (yes, that newbie I am, maybe is not even possible and I was just trying stuff until I found jquery-validator was also on npm :D LOL). Anyway, it's good so far.

4 - Well, in this matter I will share some interesting links about it:

https://discuss.colyseus.io/topic/143/phaser-3-integration-server-and-client > I've created this one after I saw the last comments from this one > https://discuss.colyseus.io/topic/25/webpack-bundle-colyseus-typescript

Basically the main idea is to have client-side logic which executes first, then server-side logic which executes, and if they mismatch, the game state is updated to the authoritative one dictated by the server.

But as commented on the links, sounds hard as hell... I think I'm a bit safe in this matter anyway because the logic on my MMORPG will be the basics for a titled map, collision (between players, NPC, enemies, and "bullets" which could consider a lot of stuff, you understand what I mean, not actual bullets, but collision from "actions", magic, bullets, other throw items, etc)and that should all of it...
So I will need Phaser on both sides, that's why using it from npm.

That said and in reply to your questions:
A: I'm using any browser for tests, usually FF or Chrome (tried to avoid FF since it has a max-socket connection limit of 200 which is a pain...), in both cases I have the same issue, since it's happening on the client side. I didn't have time to check on possible fixes today, I'll do it tomorrow. Doing a quick double-check in Chrome I've got more details on the console:

Uncaught TypeError: Cannot read property 'performance' of undefined
    at Object.parcelRequire.../node_modules/phaser/src/polyfills/requestAnimationFrame.js (requestAnimationFrame.js:20)
    at newRequire (game.fbe42c12.js:48)
    at localRequire (game.fbe42c12.js:54)
    at Object.parcelRequire.../node_modules/phaser/src/polyfills/index.js../Array.forEach (index.js:8)
    at newRequire (game.fbe42c12.js:48)
    at localRequire (game.fbe42c12.js:54)
    at Object.parcelRequire.../node_modules/phaser/src/phaser.js../polyfills (phaser.js:7)
    at newRequire (game.fbe42c12.js:48)
    at localRequire (game.fbe42c12.js:54)
    at Object.parcelRequire.js/game.js.phaser (game.js:1)

Maybe that gives you a better clue.
B: I'm not even sure how to confirm what build I'm using (again, too newbie), but since I only have one "start" script in the package file I'm guessing it's a pro build? I only have 1 environment (maybe that also helps to confirm).

 

Hopefully I would get a cool code-base to share when I finish with the base implementation (only missing Phaser so far), it could be the start point for many projects.

Thanks again!

Link to comment
Share on other sites

2 - I completely agree with your approach. Yep, some plugins will be too old and not published to npm. In theory you can do something like the following in your main code base:

import $ from 'jQuery'

if (window) {
  window.$ = $
}

Then make sure your main codebase bootstraps first, then include the plugin script or, include the plugin script in your main bundle _after_ the above bit of code. It's a massive hack but would, in theory, (I've never had to do this) work. I have had to do something similar with Pixi (or maybe Phaser, I forget) plugins before ditching the whole idea as a huge mess and just including stuff globally via script includes.

To be sure though, I agree with your approach with attempting to let npm do you package management and harnessing all the advantages you get from it.

4 - 

Oooh, interesting, you might need to find someone with more Phaser knowledge than I regarding why this actually happens but I know exactly what the problem is.

You can see from the file path that the npm build (via the main field in the Phaser package.json) references the source files, so the src/phaser.js is the entry point, i.e. when you `import Foo from 'Phaser` or `require(Phaser)` it is this file that gets pulled in (any subsequent requires or imports being then pulled in and executed). Following that through the first thing that does is attempt to set up some polyfills and following that through we get to the point that the error message tells you about, specifically here when it attempts to check for the performance timing api.

It is at this point that hell is unleashed.

The cannot read property of undefined error is because your code (or, in this case, Phaser code) has asked the JS engine to inspect a property on an undefined variable type, quite specifically, `global.performance` i.e. you've instructed the engine to look for the prop `performance` on a `global` object, however, it is does not exist and is thus undefined and thus, hell unleashed.

I know from memory that Phaser used to include a prolog and epilog to their builds, which basically mimicked the UMD (universal module definition) definition, but you can see from poking through the code base and package.json file you eventually end up in the webpack config and this line is instructing webpack to use a UMD plugin, which takes the place of the prolog and epilog. Again, I know from past experience that `global` is used in the 'semi-official' UMD, but we can confirm this by taking a quick look at the built Phaser output (top of this file edit actually not the top, its down the bottom, specifically this bit `/* WEBPACK VAR INJECTION */(function(global) {/**`).

Anyway, I _think_ this means that Phaser plain won't work from npm, not unless maybe you also use a similar webpack build mechanism as Phaser does.

You can solve this just by removing Phaser from being managed from npm, grabbing the built distribution, and including it as a script tag (or pulling it from some place like cdnjs.com) and making sure that script tag is above your own code so you know Phaser will be available globally. Not sure how this affects your server-side job, you could probably get away with slightly different builds server and client side i..e just use the source (where global namespace will work) on the server and the built distribution on the client.

I don't really use Phaser so you'd probably need some more info on the _actual_ best course of action from something using it for this purpose.

Link to comment
Share on other sites

WOOOOWWWWWWWW!! ok... remember I'm too newbie (only 2 or 3 weeks old) LOL :D 

Let me process everything and get back to you :D

BTW: I'm following this example > https://github.com/jackyrusly/jrgame in which the guys is using Phaser with Socket.io, I basically copy/paste the code and started to replace Socket with Colyseus :P (not much brain needed for that and I'm still missing something....).

Thanks for all the info! It's really great to find people like you :D

Link to comment
Share on other sites

@mattstyles, now I have read and followed up with each line, I also understand the issue but can get with the fix.

I the commented example (the jrgame), Phaser is already configured and working with Parcel, and even after literally copy the same structure from that repo and using the same Phaser version (3.6 instead of 3.11 what I got with npm install), still throw the error.

What I read about was that some libs like jsdom can be not properly implemented and override the global value so I've started by simply removing the other modules one by one but I still get the same issue :(

I'll keep digging into now, hopefully I get the answer and final fix soon enough (before my head break apart :D )

Thanks for your help!

Link to comment
Share on other sites

OMG!! OMG!! OMG!!! YOU ARE NOT GOING TO BELIEVE THE ST...D ISSUE!!!!

Maybe this helps to someone else as well... if you are doing tests and you are new including or importing, or requiring scripts in your project as me, and at some point you like to go a bit deep and use something like Parcel... make sure you use the proper script tags for you scripts...

Just use plain:

<script src="path-to-your-file"></script>

Be smart don't go crazy like me and then forget something like this in your code:

<script type="module" src="path-to-your-file"></script>

Or nothing inside will work properly if it's not really a module....

Please someone set me on fire :)

Link to comment
Share on other sites

Believe me it was pure luck checking comparing my code with the original :P

Now I'm having other issues since I've been using require / module.export for my Colyseus code and the Phaser example is all about import and export, and it seems one is from commonjs and the other es6, so can't be mixed :P

I'll let you know and share a link to the game base as soon I get it fully working :)

Best,

Link to comment
Share on other sites

  • 2 weeks later...

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...