I'm developing a HTML5 game and I need to know if updating localStorage properties frequently can slow down the page.
I'm actually storing my hero's position in four localStorage properties (two for the actual position and two for the past position to use in a collision detection system) and updating it every 1 second interval, but I want to update it at 60fps to save every hero movement.
Using localStorage in that frequency can result in performance issues?
Local storage stores the data on your user's hard drive. It takes a bit longer to read and write to the hard drive than it does to RAM.
The conclusion to take away from this is that you could optimize your performance by reading from local storage on start up and only write to it when the user logs out.
Now, whether or not that optimization will significantly affect your project is something you'll have to figure out, and, as R3tep said, http://jsperf.com/ is a good solution.
My advice, though, is to just go with the optimization anyway, just because it's less "satisfying", I guess, to have a program run more slowly than it could for no good reason.
Save your data to object {} and save it to locatlStorage then use I/O don't active or when user going away (onunload event):
var DATA = {},
syncTimer;
function syncFunction () {
localStorage.set('myData',JSON.stringify(DATA));
}
function someHandler() {
// some handler that change your DATA
// which can be called many times per second
//if calling many times, data will not sync
if (syncTimer) {
clearTimeout(syncTimer);
}
//change data
DATA.somefield = 'some data';
//set timer if data not changed - save it
syncTimer = setTimeout(syncFunction, 100)
}
window.onunload = syncFunction;
P.S. Test saving to var with saving to storage. Storage sync is more expensive.
Related
I am trying to design a hangman game in lucidchart. Just start to thinking about the data. If I decide to store them in database, what kinds of columns do I need?
I can think of columns:
(1) word: To store the actual word; (2) numberOfWrongGuesses: To store the wrong guess number (3) currentWord: The word currently has guessed etc.
One problem is once the user done the game or prepare to start a new game, the database needs to be cleaned up right?
If I decide to store them in database, what kinds of columns do I
need?
It depends on how you want the game to work, not just gameplay (guessing the current word) but also managing what happens once the current game is finished - did you want to keep score, etc?
I don't know how Lucid chart works (what sort of runtime, API and programming environment it supports; or how users will interact with it, can it maintain state, etc), but you may be able to run the game entirely in-memory and not need a database at all.
Before diving straight into the physical columns, do a logical design on paper or a whiteboard.
One problem is once the user done the game or prepare to start a new
game, the database needs to be cleaned up right?
That also depends on how you want the game to work. It also depends how many people will be playing this - if two people play it at once, they'll need their own separate set of data.
Cleaning up the data helps keep the database size smaller over time, but it also means you wouldn't be able to track a players history, or allow you to see things like "hardest 5 letter words of all time" etc.
Not necessary, you can create a js file with let object like this:
data.js
const words = [
{ id: 1, name: 'spring' },
{ id: 2, name: 'promise' },
];
after you import this file to your html file.
In general: Start with an analysis of what you want the application to do. Only after that, you can decide if you need persistent storage, and if a database would be the best persistent storage for your application.
Note that databases are used for persistent storage. Since you are thinking about wiping the database after each game, this makes me think you do not need a database.
In this case, I think that you might not need any storage at all. Since you mention Javascript, you might be building a game that runs in the browser. Perhaps cookies would be enough to keep track of the score of your user.
I want to know how I can save the progress a player has made in a game that I am making. Could I do this through cookies or how else can I save to the players computer? Thanks for all of the help!
You have pretty much two options for saving localy using Javascript, which are cookies and localStorage.
With Cookies:
The document.cookie property is used for setting, reading, altering and deleting browser cookies.
To set a cookie, document.cookie="cookiename=Foo Bar";, alternatively like so if you want an expiry date: document.cookie="cookiename=Foo Bar; expires=Mon, 18 Jan 2016 12:00:00 UTC";
To read a cookie, just the code document.cookie will return all of your site's cookies on that page. It doesn't put them in an array, but instead a single string in the format of cookiename=foobar; nextcookiename=foobar;, etc. You can turn this into an array easily using document.cookie.split("; ");
To alter a cookie, simply set it again as described above, as that will overwrite it
To delete a cookie, set it again with an expiry date in the past. This will overwrite it, and then it will expire, deleting it.
With localStorage:
The new HTML5 localStorage Object is another way to store data locally:
To set an item in localStorage, use localStorage.setItem('itemname','contents');
To read an item, it's localStorage.getItem('itemname');. You can check if an item exists using "truthy" values (i.e. if(localStorage.getItem('itemname')))
You can alter a localStorage item using localStorage.setItem as described above.
You can delete a localStorage item using localStorage.removeItem('itemname').
Which should I use?
Cookies are supported in just about any browser that you can think of, however they expire (they get deleted after a set amount of time) and also can be disabled by users. Personally, I also find document.cookie a clunky interface.
localStorage on the other hand cannot be easily disabled by the user, and provides a more accessible interface for the programmer. As far as I'm aware, there is no expiration for localStorage. Since localStorage is new with HTML5, it may not work in some older browsers (however it's got great coverage on new browsers, see http://caniuse.com/#feat=namevalue-storage). Note that there is a limit for storing data on your entire site, not just for one item.
In the end, it's up to you. Pick the one you think is going to work best for your game - if you're already using other HTML5 content (such as <canvas>) then there's no harm in localStorage and you'll be using a more reliable storage method. However, if you're happy with cookies then they are a perfectly viable option used by thousands of extremely popular sites - some even use both! One advantage to cookies is that they can be accessed by your web server, whereas localStorage cannot be.
Either way, you'll need to check out the cookie law, which effects all types of storage on the user's computers by a web app.
The hardest part of this problem is not finding a way to persist the data, but instead designing your game in such a way that you have a "game state" that can be serialized for saving between sessions.
Imagine you are writing a game with a player and a score and you're using two variables to represent them.
var player = { x: 4, y: 3 };
var score = 10;
It's relatively easy to save these variables with localStorage.
function save() {
localStorage.setItem('player', JSON.stringify(player));
localStorage.setItem('score', JSON.stringify(score));
}
function load() {
player = JSON.parse(localStorage.getItem('player'));
score = JSON.parse(localStorage.getItem('score'));
}
We have to remember to convert them to JSON before storing, because localStorage can only accept string values.
Each time you make your game state more complex you have to come back and edit both of these functions. It also has the undesirable effect of forcing the game state to be represented with global variables.
The alternative is to represent the entire state with one atom — in this case a Javascript object.
var state = {
player: { x: 4, y: 3 },
score: 10
};
Now you can write much more intuitive save and load functions.
var SAVE_KEY = 'save';
function save(state) {
localStorage.setItem(SAVE_KEY, JSON.stringify(state));
}
function load() {
return JSON.parse(localStorage.getItem(SAVE_KEY));
}
This pattern allows you to keep state as a local variable and use these functions to work with it.
var state = load();
state.score += 10;
save(state);
In actuality it's quite easy to switch between storage mechanisms, but localStorage is probably the easiest to get started with.
For a small game you'll probably never reach the 5MB size limit and if you do, then you'll also find that the synchronous JSON.stringify and localStorage.setItem operations are causing your game to freeze for a few seconds whenever you save.
If this becomes a problem, then you should probably look for a more efficient way to structure your state and maybe consider designing an incremental saving technique, targeting IndexedDB rather than localStorage.
It really depends on what your looking for.
Cookies are a great way to store data but can be edited by the client and some browsers have cookies turned of.
Web storage has its goods and bads too. If your game has to write masses of data and has lots of players it will quickly use up your bandwidth and may also take time to transfer depending on the clients connection. The upside is that it is fully controllable by you. Once the data has been sent, it can not be edited by the client.
Javascript has some great file I/O utils to help you on the way. Here is a great tutorial: https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O
If you decide to go with cookies it can be harder or easier depending on your skill. Again, here is a great tutorial: http://www.w3schools.com/js/js_cookies.asp.
Hope this helps!!!
Edit---
When I mentioned client I was really meaning to say player :D
I am developing a web-based interface for a hardware sensor that produces approx. 250kB/s of raw data (125 kS/s, 16 bit per sample). The web application is designed to visualize (using Canvas) and store (using IndexedDB) this data in real-time. I am having performance issues with indexedDB storage.
This application is designed to run for days or even weeks and should reliably store large amounts of data (tens to the low hundreds of MB)
Because write commits seem to be the general performance issue, I have rewritten my application to only store a big chunk of data every 5 seconds as a non-sparse integer array object. This kind of works, but I still get very choppy visualization performance, high CPU and high memory usage. The exact storage code:
//dataDB = indexedDB database opened in another function
//slice = data to be stored
//sessionID = object store index
//this function is called about once every 5 seconds
//with 700 000 values in the slice array
//slice is a multidimensional array
function storeFastData(slice, sessionID){
var s = dataDB.transaction(["fastData"],"readwrite").objectStore("fastData");
var fdreq = s.get(sessionID);
fdreq.onsuccess = function(e){
var d = fdreq.result;
for(i = 0; i < slice.length; i++){
d.data[i][1] = slice[i][1];
}
s.put(d);
}
}
Concretely:
Is IndexedDB the right choice for this application?
Am I being an idiot in the way I implemented this? This is the first IndexedDB-based project I am doing
I have read that using WebWorkers may at least fix the stuttering issues as it can run on another thread. Would this solve my performance problems?
I am willing to use new (draft) functionality, but requiring user interaction for storage beyond 5MB (e.g. using Quota Management API) every time the application is opened, is quite bothersome and if at all possible I would like to avoid this.
I do not use jquery. This cannot be written as a native application (it has to run inside a browser).
IndexedDB is excellent choice for your case. If you store as soon as data are available quickly and frequently, it should be OK. You don't wait for 5 sec, store right away around 200 ms interval. Generally an indexeddb write op takes 20ms.
From what I understand, if you want to have an array stored in the Chrome Storage API to which you want to continually add items, you need something like this:
function addToHistory(url) {
chrome.storage.sync.get('history', function(obj) {
var history = obj.hasOwnProperty('history') ? obj.history : [];
history.push(url);
chrome.storage.sync.set({'history': history}, function() {
if (chrome.runtime.lastError)
console.log(chrome.runtime.lastError);
else
console.log("History saved successfully");
});
});
}
This code bothers me; loading and then saving the same array every time you push a single item onto the end is horribly inefficient (especially if your history array starts getting several thousand entries).
Is there a more efficient way of doing this? I'm assuming I'm not the first to want to push to an array, so is there already a recommended way of achieving this?
I don't think that chrome.storage.sync API is ideal for what you need. Basically this API is great for remembering user preferences or simple and short data.
Sync API have limitations for usage like:
- 102.4 KB for all data kept in the storage
- 8 KB of data per item
- 1,800 writes per hour
So if you planning to use this API to store some historical data the app may exceed limits very fast.
I'm assuming you are developing an extension, not the app. In app you have access to the chrome.syncFileSystem API which may be used to save syncable data in a file.
Answering your question there's no one way to optimize your function. You can try to store the data periodically - for example every 30 seconds or so. You just need to remember to save data after a user closes the app.
You can also store this value as a variable in memory and save it when the user leave the screen or close the app but it is dangerous because the app may close before asynchronous task complete.
Anyway I think that this API is not the best solution for your app.
Any player can easily cheat on this game by changing the amount of cupcakes through the browser console. I wanted to know if there was a way to prevent the user from doing so. This is also posted on github.
var numberOfCupcakesDisplay = document.getElementById("numberOfCupcakes");
var cupcake = document.getElementById("cupcake");
function updateValues() {
numberOfCupcakesDisplay.innerHTML = amountOfCupcakes.toString();
//displays number of cupcakes to screen
document.getElementById("amountOfToasters").innerHTML = amountOfToasters.toString();
//displays number of toasters to screen
document.getElementById("toasterButton").innerHTML = "        " + Math.round(costOfToasters).toString() + " cc";
//changes cost of toaster every time it is bought by 110%
}
cupcake.addEventListener('webkitAnimationEnd', function(e){
e.preventDefault();
this.style.webkitAnimationName = '';
}, false);
function clickCupcake() {
++amountOfCupcakes;
cupcake.style.animation = "shiftCupcake";
cupcake.style.webkitAnimationName = "shiftCupcake";
}
updateValues();
Yeah!! As other answers mention it is IMPOSSIBLE to prevent users from changing the values from browser console. In other words, You are simply asking How to write JS code so that user can not debug it. You can always use some methods which make life hard for people who want to cheat on the game.
1.Obfuscate the code.
Look at these links for more information on obfuscation.
SO: How to obfuscate Javascript
Jsobfuscate.com
2.Do not store the game's control values in global variable.
Do not store control values in global variables. Instead define a class and have these variables as private to it So that user has to dig in deep in order to find out where to put the breakpoints.
3.Minify/Compress your javascripts.
Obfuscation more or less covers minification as well.
You cannot prevent this. The best you can do is minify the JS so it's harder for players to find the right values to change. In fact, you can't prevent this with any game or indeed application; the user's computer controls all of the information so they can do anything they want to it.
The only way to be secure against this is to do all of the processing on a server you control. Even though, players can lie about their input data (hence aimbotting or other hacks).
by changing the amount of cupcakes through the browser console
Well, technically you can prevent this by creating a new scope:
(function(){
var cupcakes = 10;
})();
console.log(cupcakes); // ReferenceError: cupcakes is not defined
But note that there are still ways to "cheat," even with this protection (i.e. edit the JS source code). And if you are sending the result to a server... well, that will be even harder if not impossible to secure, since you can easily send a simple HTTP request via XMLHttpRequest.
There may actually be a way to reach your goal. But it depends on the game's logic.
If you can simulate the game on your server, you can generate random IDs for the cakes and when the game creates a new cake (on client), it would request an ID for it. Later when the cake is "destroyed", it would contact the server and provide it with the cake's ID. The final score is then computed on the server from the IDs it received.
This way you can track what was actually done by the user.
But an adversary can listen the network requests and determine the request for creating a new ID. The same way he can determine the request to tell the server this ID has been "destroyed".
If your game logic allows, you can e.g. tell the server to only generate one ID every 5 seconds or so. You can also mark as spoofed all results where all cakes were "destroyed" and none was missed (if the game is difficult enough).
So, it's still not 100% secure, but you might be able to reach a relatively high level of spoofing protection. On the other hand, it adds a lot of code complications and you must weigh the pros and cons.