I am attempting to create an online phaserJS browser game and I want to split up my players into tiles so that each tile in the game can be an elixir process. Each tile will have a 100x100 2D grid coordination (x,y) that I want to store in a genserver and use a superviser to move my players around tiles. I want to store some metadata in each coordinate position such as cellType and tileSprite and if a player is located on that tile so that i can render the game world and players location.
I’m wondering if this is a good architecture to build ontop of. Im essentially trying to build a sprite open world game. Its super ambitious and I’m new to elixir but from my research it seems like a good fit for what I am trying to do but I don’t understand the nuances of the language. Hopefully that all made sense.
Seems like an interesting idea, but I wonder what the benefit of a process per tile would be. What would make a tile a good boundary for a process?
I have to imagine that players can easily move between tiles, so you’ll get an overhead there. It may make more sense to have a process per game/view and each player be a process. And keep those under a supervisor, or maybe each game is a single process, with a supervisor managing the players?
There are a ton of designs you could come up with, and I think the game play/interaction should really drive the design pattern you use.
Think of what would make logical sense as far as passing messages between the different processes, and what makes sense for a supervision tree.
My thought process for each tile being a process is two part; Part 1 being to limit the bandwidth of data being send to/from the web socket since I want the game real-time and part 2, to keep the memory per process small. If I’m keeping the state of 100x100 grid in memory, that is a 10,000 item 2D array with each item having some metadata. So given that I want 50 tiles (or 500,000 cells), it seems like a good idea to separate it.
If there is a way to only get changes from a “subsets” of data in the state, that would work as well. For instance if a player is at coordinates 30, 30 and only got changes from the server for a 50 cell radius, that would work as well but I’m not sure how I would do that. A players view distance will be will be around 20 to 30 cells.
The type of interactions the game will have will be base building where each tile is a piece of the structure and have unique properties that will determine the output of crafting/etc.
In no way does a process translate to network IO, so I’m not sure that can help you. How you send the data down the wire is totally outside of a tile process, or should be.
I would think the overall memory of a game would be more important than the memory of an individual tile, by adding more processes, you add more memory to the whole game.
You may have worked out a way to send the data down the wire, but again, if you are thinking each tile process would be responsible for encoding and pushing bits down the wire, I would rethink how you are utilizing processes here.
Heh okay well I am definitely still unclear about all this so I’ll spend some more time understanding processes and how to architecture my data flow. I haven’t started anything yet so this is all just me trying to wrap my head around it.
Do you have any suggestions on how I should think about memory given that I want to keep a grid in memory so that it is persistent.
Thanks so much for the information, I appreciate it a lot.
Hello and welcome,
One common advice when starting with GenServer is to read…
It explains when, and when not to use processes.
Well you’d have to describe persistent, like writing it to a database? Or just a long running process that will maintain it’s state?
Will this be running in a distributed manner? Multiple BEAMs in a mesh?
You can use :global process registration to have a single named process across all of your nodes.
If your just thinking a single node right now, then you shouldn’t have to worry about that yet, and could just get away with a named process per game. As long as your process doesn’t crash, the current game state will be maintained.
Where you really have to think about the size of the state is when you would be passing the whole state around to other processes. Which is pass by copy up until the size is over 64k (I think), then it is a pass by reference, hopefully you don’t have to do that though.
This video is about Phoenix and Phaser JS…