If the design of your roguelike limits player vision so they only see their surroundings, then instead of generating the 512 x 512 map in one go, you can improve the performance/memory usage by generating only the blocks around the player.
This would save a lot of initial loading time and could support maps much larger than 512 x 512.
If your engine doesn't need to render objects outside the viewport, then you don't need to generate those objects until you actually need to render it.
In a similar fashion, storing user properties like whether or not they want email subscriptions, their notification settings, etc... Is something that I often use a bitmask field in my model to save space in the db.
These can be queried using bitwise operations and you can abstract all of it with synthetic instance properties.
User.email_enabled = true would translate to 0010 or something in, for example, a properties column.
Are you running out of space in your database? It just seemed like a way to needlessly complicate your database, make it difficult to query (what was email_enabled again? the third bit?), difficult for other developers to use (now it needs a comment to understand) and difficult to constrain for data integrity.
I think that unless you're having space issues, you're better off using boolean columns.
A solution that seems good right up until a bug starts flipping the wrong bit or someone decides that a flag needs 3 states instead of two.
Bitmasking is a useful technique in some places, but storing user preferences isn't one of them. It's 'cleverness' for the sake of being clever - the code is harder to read, new developers can't immediately understand it, experienced developers have to look up what flags mean, you can't just dump the database row to see what a user's preference are, and if your documentation ever gets out of sync you're screwed.
For the sake of saving DB space it's a really bad idea.
There are several minor erroneous points in this document. Here are the two that are probably the most egregious:
- The whole object and string representation thing is naïve to the point of total incorrectness. Where is the object and its length and type stored, for example? And browsers intern strings (store them once with garbage collection of some form to clear out the values when they are no longer needed) and don’t use null-terminated things (otherwise you couldn’t have "\0"), so your 320 bits is actually more likely to be 192 or 96, with the full 320 bits plus approximately three or six more words occurring only once. (I’m being a little vague about this because I’m not familiar with what specific techniques are actually used in browsers at present.) The end result of it all is that the actual figure will, I think, be more like 30–50 bytes per tile, not 60. (Then again, it may end up more, and it will definitely depend on the browser; I’m not up to date with the performance- and memory-efficiency techniques used.) I’m complaining here only because it’s misleading about how things are done; the concerns it raises are absolutely genuine.
- Bitwise operations on numbers are only 32-bit, not 64-bit. You want 64-bit bitwise operations? There’s no native support for it, you’ll need to emulate it. This is a part of the tangled mess that is a unified number type which can be either a 32-bit integer or a 64-bit floating point number.
Author here. There were a lot of ends that I tried to tie up that started to be difficult to find hard evidence for. Some of the string/object storage stuff is discussed casually in mailing lists, but there aren't great places I could point to and say: _this_ is the definitive answer. If you would point me in the right direction for some of these resources, I'd be happy to amend the article. Thanks for reading all the same.
This whole problem will probably be solved with Typed Objects, which looks as though they'll be standardised with ES7 next year. Plus, there's already a decent typed objects polyfill available, so don't go littering your code with bitwise operations.
That's good to hear, I wasn't aware of Typed Objects. I guess the library linked at the end of the post is basically a very non-specific polyfill already? Well, using it like that is one way to get around bitwise littering.
The library at the bottom isn't anywhere near a typed objects polyfill - it just packs data into small spaces. Typed Objevts would let you have objects where properties are of a static type (int8, Boolean, string) and they are stored using Array Buffers.
If there's one thing I've learned in a half year of JS game development, it's that there are usually good libraries to solve most low-level problems. Compactly storing a 512x512 array of binary values can be as simple as:
If there's one thing i've learned in ~5 years of game development (and ~1 of JS game development), it's that generic libraries are almost always inferior to a custom solution when you're performance tuning.
Awesome technique, thanks for posting. I have a very large grid of nodes for my game map (used for path finding) and this looks like it could save a lot of memory.
>Unbeknownst to some, Javascript comes equipped with a relatively good set of bitwise operators.
Never thought that there were people doing Javascript who didn't know about bitwise operators. I guess I know where 99% of the "Javascript sucks" posts come from.
It is a low level language, it is blazingly fast and powerful if you use it correctly.
It is also badly designed and disliked as far as I can tell just about universally in every aspect as a language. Objective C is also blazingly fast and powerful if you use it correctly but not everyone wants to. It isn't about not knowing it has access to bitwise operators.
My assumption was that JS bitwise misses the advantages of speed and space-compactness of bitwise in other langs, since you only have 64 bit floats to work with, thus forcing conversion to int and back for any bitwise stuff. I haven't read any good in-depth articles on the subject though.
30 comments
[ 2.9 ms ] story [ 68.3 ms ] threadhttps://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/...
This would save a lot of initial loading time and could support maps much larger than 512 x 512.
This is the first time I see someone giving a good real world example of bitwise operators that I can understand.
http://stackoverflow.com/questions/11400242/bit-vector-imple...
These can be queried using bitwise operations and you can abstract all of it with synthetic instance properties.
User.email_enabled = true would translate to 0010 or something in, for example, a properties column.
Really handy stuff!!!
I think that unless you're having space issues, you're better off using boolean columns.
Bitmasking is a useful technique in some places, but storing user preferences isn't one of them. It's 'cleverness' for the sake of being clever - the code is harder to read, new developers can't immediately understand it, experienced developers have to look up what flags mean, you can't just dump the database row to see what a user's preference are, and if your documentation ever gets out of sync you're screwed.
For the sake of saving DB space it's a really bad idea.
- The whole object and string representation thing is naïve to the point of total incorrectness. Where is the object and its length and type stored, for example? And browsers intern strings (store them once with garbage collection of some form to clear out the values when they are no longer needed) and don’t use null-terminated things (otherwise you couldn’t have "\0"), so your 320 bits is actually more likely to be 192 or 96, with the full 320 bits plus approximately three or six more words occurring only once. (I’m being a little vague about this because I’m not familiar with what specific techniques are actually used in browsers at present.) The end result of it all is that the actual figure will, I think, be more like 30–50 bytes per tile, not 60. (Then again, it may end up more, and it will definitely depend on the browser; I’m not up to date with the performance- and memory-efficiency techniques used.) I’m complaining here only because it’s misleading about how things are done; the concerns it raises are absolutely genuine.
- Bitwise operations on numbers are only 32-bit, not 64-bit. You want 64-bit bitwise operations? There’s no native support for it, you’ll need to emulate it. This is a part of the tangled mess that is a unified number type which can be either a 32-bit integer or a 64-bit floating point number.
Never thought that there were people doing Javascript who didn't know about bitwise operators. I guess I know where 99% of the "Javascript sucks" posts come from.
It is also badly designed and disliked as far as I can tell just about universally in every aspect as a language. Objective C is also blazingly fast and powerful if you use it correctly but not everyone wants to. It isn't about not knowing it has access to bitwise operators.