What are Phaser 3 bad/best practices?

I’m new to Phaser, but old time javascript developer. The whole concept of game dev is also new to me.

I’d like to know which are the most basic bad/best practices when writting code with Phaser 3, like always use data manager instead of class attributes or stuff like that?

I’m pretty much coding and coming up with my own set of rules, but it would be nice to know whats the market default, or something like that.

Is there a documentation for it, or maybe could some of you guys write it down in here? Then maybe we can gather enough of those and make a wiki page or even eslint rules.

Thanks!

2 Likes

I guess there is no default. You can write Phaser games in multiple ways.

In my opinion, to write good JavaScript code you should use TypeScript.

1 Like

I also have no idea, but just for the sake of discussion here’s my list of best practices that I try to follow. For reference, this is the repo where I’m coming up with and following these rules: https://github.com/snowbillr/archer-adventure

Some of these are probably more useful as games get more complex. For simple games, it might not be worth it to take all of these rules as absolute.

Typescript > Javascript

This isn’t really a Phaser rule, but for any kind of development that involves lots of files and data structures being passed across them, this helps immensely.

Use a file for constants

Phaser is very string key based for loading and using assets, as well as scenes. I find that its easy to make typos with these keys and not have a good clue why things aren’t working. For example, I have a constants file for my scene keys so I don’t need to worry about making typos.

Extend Phaser.Scene for each scene

One file per Scene

Have a TestScene to try out new things before slotting them into your real scene

When I’m creating animations, or dealing with sprite bounds, I have a prefab test scene I load up and work in so I don’t have to worry about everything else going on in my game scene. Once I get things to the place where I want them, I’ll start actually adding whatever I’m doing into my real game scene.

Keep the Scene’s update method as empty as possible

I think this one is probably controversial.

I have plugins that listen for the update event (post update technically) and run code there. I feel like this gives me a way to separate out my logic nicely, so that my scene’s update method doesn’t get crowded and hard to reason about.

I have an ECS architecture that I’ve implemented in my repo that allows me to extract logic for individual systems into their own files.

Use finite state machines rather than a state variable with a big if/else statement

This also goes a long way for keeping logic separated and the update method clean. Its hard to navigate your code when you’re dealing with a giant if/else statement, rather than clean separated files that have implementations for each state of the FSM.

I also wrote a finite state machine in my repo (that I use primarily for game objects) that lets me isolate the logic for each state to its own file.

Use an ECS architecture

This is something that I also find helps me to organize my logic, rather than having a class that extends Phaser.GameObjects.Sprite with a giant update method. I also built something out in my repo that lets me do this.

Input is a piece of scene state, it doesn’t belong to the player

This took me a while to realize, but was kind of an epiphany when I did. It’s also just my opinion, so this might be controversial as well.

I originally built out my game such that the player’s entity had all the logic around dealing with input. But then I needed to build out a conversation system and had to awkwardly reach into my player entity so that I could get at the input to advance the conversation.

I realized that by putting my input controls at the scene level rather than on the player entity, I could access it from any system that needed to deal with input. Phaser definitely pushes you in this direction itself by having the input plugin at the scene level, but I always thought that was just for API reasons. But really, it’s telling you to use input as scene state rather than entity state.

Create custom plugins liberally

Whenever I have a piece of functionality that is responsible for something at a scene level (e.g. playing sound effects, loading an area from a tilemap, controls available to my scene) I make it a scene plugin.

Whenever I have a piece of functionality that’s responsible for something at a global level (e.g. data persistence) I make it a global plugin.

12 Likes

Does this help? I use it in all my books.
{width:80%}

2 Likes

Thanks, those are some really nice ideas.

That is true, using multiple files for you project is a must have and I’m really happy on how I have my projects setup with webpack.

Are you a gamedev coming from other frameworks? Because I noticed that game frameworks with “visual” IDEs (like Unity) you usually build your scene by creating the GameObjects and putting them were they are supposed to “spawn” and then making conditions for when to show them or not, etc.

I wonder if we should do the same with Phaser, like creating every single possible GameObject in the create() function and then toggling them on/off whenever needed. What do you think?

My codebase as it is now I’m creating some basic stuff in the create (like background, map etc) and the rest on demand.

Agreed on the multiple file front, my project has 172 files across 41 folders at the moment (and that’s for 5,696 lines of code not counting comments and empty lines).

I’m a software engineer by profession, and hobbyist game dev. I’ve really only worked with Phaser but dabbled with Crafty a while back.

I haven’t worked with Unity before but I’ve set up my project to be pretty tightly integrated with how I use Tiled to generate my area maps. In Tiled, I have properties that I put on objects and layers that determine a lot of things, like collisions, visibility, etc. I imagine that’s similar in functionality to Unity except Unity has it all built in to the same IDE.

I think it works really well, but its a little fragile, since one typo in Tiled can mess up a whole lot of things in my game. I also need to remember every property needed for the Tiled maps/layers/objects which is a pain too.

I think the Phaser Editor tries to encompass that idea in one IDE like Unity does, but I haven’t used it to see how well it works.

For my game so far, I took the approach of creating everything up front when a game area loads and then toggling them on/off as needed. This was a proactive approach to possible performance issues, but I may have jumped the gun on premature optimization /shrug

Im new, but this looks awesome, thanks ! :grinning: :

1 Like

You can configure Tiled to show you the properties for different types of objects. I’ve additionally solved this in my own project by preprocessing the tilemaps in the build system. It’s not too hard to check whether your properties are correct and it can save you a lot of headaches in the long run.

That’s great that Tiled lets you have different object types! Super useful. I’d love it if they had the same thing for layers and maps too haha.

That’s a great idea about preprocessing the tilemaps to validate all the properties. Definitely a great way to solve the issue I was talking about.

@snowbillr Would love to learn more about your use of ECS with Phaser. I was just thinking this morning about using ECSY with Phaser in some way.

1 Like

Oh that would be cool! I’ve seen the ECSY repo before but never used it, would love to hear about how it works if you go that route.

I ended up building out my own ECS plugin for phaser that I’m using in https://github.com/snowbillr/archer-adventure. It’s worked well for me, but lacks a few notable features, like adding/removing components to an entity after its already been instantiated.

I’m planning on flushing it out a little more and putting it into its own repo once I finish my current project.

1 Like

Oh, I started out from the phaser3-project-template, there is no linting. Maybe I orient myself on the lint-config of the sourcecode… Can be found here: phaser/.eslintrc.json at v3.52.0 · photonstorm/phaser · GitHub

And here are some useful templets with configured linting as well: ourcade · GitHub

Are there some community-standards about linting the code? In best case something like a .eslintrc.json file to share?

I like to use airbnb style guide, and always use clean architecture(Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series): Martin, Robert: 9780134494166: Amazon.com: Books) in my profissional games.

1 Like

yeah same