Saving a game with Javascript - javascript

Suppose I have a Javascript game that draws on a HTML5 canvas, it loops through updating and drawing a bunch of objects. What's the best way to go about saving the current state of the game? I guess I could loop through all the objects and write all values in text form in a format that can be read by a loading function, but that seems like quite a lot of work for both me and the game, as well as a large save file size. Is there a better way to do this? I've never done something like that before, I don't really know where to start.
Thanks.

A standard practice for something like this is to maintain a data model which represents your system, and a view that represents your model. The model should be mostly data, which can be relatively complex, but it has all the information necessary for your view to render.
Assuming this model is an object tree, you can just call var serialized = JSON.stringify(model) to serialize your data model to a string and then var model = JSON.parse(serialized) to get it back. This is a very simple, yet inflexible approach, but it is a start.
A quick way to store this information would be with localStorage but you will likely want to move to a back-end storage where you are putting values up to a REST service (or something like that) so that this data can be retrieved from anywhere.
I recommend looking into MVC-like frameworks like Backbone.js (for instance) which helps you to separate your models from your views, and also does a great job of persisting/hydrating your data from your data store.

You'll want to do some research on the keyterms of 'serialize' and 'unserialize'.
Instead of doing a recursive loop on every object, I'd suggest that you have all your game objects implement a function for serialization. You can use JSON to build up your entire object tree, with each object deciding what properties need to be kept, and which properties can be derived from the rest. While this does appear to do the same thing as a recursive loops on some levels, the huge difference is that each object can define, on it's own, how to serialize/unserialize itself and it's contents..
Depending no how precisely you want to save your game state, you can reduce a LOT of data that way. For example, maybe you can simply reset them to the beginning of the current level, or you could dump some data that's available elsewhere (level data, for example, probably shouldn't be stored in the save file, only the information on game state that lets you reproduce the level using your existing level data store).

Related

Vue js prototype function to rerender template

I'm trying to create a very basic key-based translation system since our system doesn't have to be as expansive as something like vuei18n. I'm simply loading a json with a key and each key has four translations. About a hundred items in total. Now; I'm using a seperate Translator window component that I link to Vue like this;
Vue.prototype.translate = function(key){
window.addEventListener('switchedLanguage', function(event) {
console.log(event.detail);
return window.translator.getTranslation(key);
});
return window.translator.getTranslation(key);
}
and in order to render them in the templates I do the following:
{{ translate('key') }}
I understand that connecting scripts like a translator directly to the window isn't the best of practices, but is what's working in the application right now.
The thinking behind it is that when the language is changed within the translator, it will try to get back the key. While this technically works, in the application I am not seeing the keys get re-rendered to the different language. I've been deep down the rabbit hole now and don't seem to get a clear answer why except for the fact that it's not bound to the data model. But for some of the components, they can have up to fifteen keys or more depending on input. It's not feasible to store all the keys in the data model of each component since that will, in my view, unnecessarily clutter the data model.
So, what I've tried so far is the following:
Use a filter with the key as an input (this results in Vue freaking the hell out because it can't resolve the filter since it isn't able to find the translator through Window.translator)
Reload the entire window (while working, very ugly solution since it takes the user back to the main screen)

Is there a standard way of change tracking with a Knockout bound page?

I have a rather complex web page with various tabs, forms, radio buttons, drop downs, etc. It's all bound using Knockout.js to a very complex JavaScript object that was loaded via an AJAX call. Of course the user can muck with stuff to their heart's content, at which point they hit a Save button to persist all their changes back to the server.
I'm in the process of coming up with a good design to track exactly what was changed on the page so I can implement saving. So, I've come up with a few possible implementations.
Option 1) Just send everything back and let the server sort it out: With this method, I'd let Knockout just update the data source. The Save button would call .toJS() and send that data back to the server. Pros: It's super easy, and takes very little work on the client. Cons: The server doesn't really know what changed and has to either load the data from the database to compare, or just save all the fields again. These fields come from multiple tables and have complex relations. It also treats the entire document as a single atomic unit. If someone else changed Field A and you changed field B, one user is going to lose their change.
Option 2) Use JavaScript to compare the original data and the current data: Using this technique, when the user clicks on the Save button, I would systematically compare the original data and current data and generate a graph of changes. Pros: This would ideally result in a compact graph of exactly what the user changed, and could even no-op if nothing was changed. Cons: The data I'm binding to is complex. It consists of strings, arrays, objects, arrays of objects, arrays of objects with other objects, etc. Looking for changes would be a rather complex nested loop.
Option 3) Track changes as they are being made in the UI: I would have to observe changes as they happen, and keep a delta as UI elements were changed. The Save button would simply send that change graph to the server if it had any pending changes. Pros: No need to compare two huge JavaScript objects looking for changes, but still has all the benefits of option 2. Cons: Knockout doesn't appear to have a standard way to listen to all changes using a single event handler. I believe I would have to resort to binding to all the UI elements, or creating custom bindingHandlers in Knockout to implement this real-time change tracking.
My Question:
My question is mostly for Knockout.js experts. Is there a standard approach, or recommended guidelines to solving this obviously common scenario? Is sending back all the data, even stuff that hasn't changed, a common design? Or are people implementing custom change trackers? Does Knockout provide any sort of framework that eases this requirement?
Update: Found this thing, not sure if it could be useful or if anyone has any feedback on it.
If it's a question of enabling/disabling the Save button, allowing the user to navigate "from" that page/state, then you can check with the https://github.com/CodeSeven/kolite
check the knockout.dirtyFlag.js
Hope this helps.
Edit: remember that you should "never" trust the data coming from the "UI". The real comparison and validation, ultimately goes in your "controlled" environment within the server.
What I would probably do is take option 2 - the comparison itself can be as simple as stringifying the JS object and comparing it with a cached version of itself.
A few other options are discussed here.
P.S. Maybe ko.mapping can help you manage this monster of a JS object?
I wrote a change tracker extension for knockout that Pete Smith greatly expanded on...
Take a look here:
https://roysvork.wordpress.com/2014/01/12/tracking-changes-to-complex-viewmodels-with-knockout-js/
It works on the principle of extending the observable to track initial state vs. changes the user has made on the client. I think this works really great and can give users real-time feedback to know what they've modified. In practice, we actually implement a save panel that shows all pending changes and even lets them undo individual changes, all by using the change tracker's reusable capability.
ko.extenders.trackChange = function (target, track) {
if (track) {
target.isDirty = ko.observable(false);
target.originalValue = target();
target.subscribe(function (newValue) {
// use != not !== so numbers will equate naturally
target.isDirty(newValue != target.originalValue);
});
}
return target;
};

Is it okay to use data-attributes to store Javascript 'state'

I often use data-attributes to store configuration that I can't semantically markup so that the JS will behave in a certain way for those elements. Now this is fine for pages where the server renders them (dutifully filling out the data-attributes).
However, I've seen examples where the javascript writes data-attributes to save bits of data it may need later. For example, posting some data to the server. If it fails to send then storing the data in a data-attribute and providing a retry button. When the retry button is clicked it finds the appropriate data-attribute and tries again.
To me this feels dirty and expensive as I have to delve into the DOM to then dig this bit of data out, but it's also very easy for me to do.
I can see 2 alternative approaches:
One would be to either take advantage of the scoping of an anonymous Javascript function to keep a handle on the original bit of data, although this may not be possible and could perhaps lead to too much "magic".
Two, keep an object lying around that keeps a track of these things. Instead of asking the DOM for the contents of a certain data-attribute I just query my object.
I guess my assumptions are that the DOM should not be used to store arbitrary bits of state, and instead we should use simpler objects that have a single purpose. On top of that I assume that accessing the DOM is more expensive than a simpler, but specific object to keep track of things.
What do other people think with regards to, performance, clarity and ease of execution?
Your assumptions are very good! Although it's allowed and perfectly valid, it's not a good practice to store data in the DOM. Sure, it's fine if you only have one input field, but, but as the application grows, you end up with a jumbled mess of data everywhere...and as you mentioned, the DOM is SLOW.
The bigger the app, the more essential it is to separate your interests:
DOM Events -> trigger JS functions -> access Data (JS object, JS API, or AJAX API) -> process results (API call or DOM Change)
I'm a big fan of creating an API to access JS data, so you can also trigger new events upon add, delete, get, change.

Javascript/AJAX car make/model form

I am trying to create a car make/model form using Javascript or AJAX, problem is that I don't have a lot of experience with either, but here it goes. . .
I need to create a form that has a car make and model drop down list in it, and when a user chooses a specific make, the model drop down will be populated with all of the models for that make, now I have a few ideas on how to accomplish that, but I would like some input on what the best way would be to approach this, to cut down on dev time.
I was thinking of creating an array within an array, one with the makes, and within each "make" array have the models array in there, so when the user clicks on a make, a AJAX/Javascript function will fire which will take the value of the current field and use that to get the location of the make in the array, which will then traverse through the inner models array and generate the drop down menu for that specific make.
Now I am not sure if this is a sound idea, or if there is a better way of doing it, but I have very little time to test, so process of elimination is out of the question, so could someone please point me in the general direction I need to go in, or maybe point me to a ready made script? as my understanding of Javascript syntax is little to none at the moment!
Thanx in advance!
The key decision is whether you want to load all of the information at the beginning (in which case the user may experience a delay while you load all of the models for the makes that they don't care about) or whether you want to retrieve the models as they choose a make. The answer will depend on
how much data there's likely to be
how fast you need the page to be
how much load will be on the server
etc.
Basically, can you afford the performance impact of loading all of the models at the beginning?
If you decide that you can afford to load everything at the beginning, I think the approach you describe is reasonable, although I wouldn't actually use an array for the outer container. I'd do this:
var models = {
Audi: ["Quattro","A4", ...],
BMW: ["M3", "M6", ...],
...
};
The thing stored in the "models" variable is actually a javascript object, although people do sometimes call it an "associative array".
Note that in this scenario you aren't really doing "AJAX", as you aren't retrieving data from the server on-the-fly.
The alternative scenario is that you set up a URL where you can query it with a model, and it will respond with a list of makes. Then you fire off the query when the user selects a model. That's AJAX.

Should I store data in a Javascript object, or just use the table on the screen?

I have a pretty big chat app I'm working on, and had a question about best practices for JS data storage...
I have a table populated with AJAXed data from the server, and the Javascript gets some info from that, and also from an internal object, also populated with AJAXed data. I was starting to store information about each chat in an object, like user status, name, etc., and realized... I have this table right here that I can use as data storage. It's persistent, it stays there at least as long as they're in the chat, so why not just add some hidden TDs or spans to it to hold this data, rather than dealing with a Javascript object? I don't know if there'd be a noticeable change in speed (dealing with an object vs having to parse ID tags and strings), but I was just wondering if there was any fundamental reason why using the table for data storage was A Bad Thing.
And, on the flip side, should I cease looking up data using the table altogether, and instead store all the data in an object (along with displaying it in the table)? Or is my current hybrid system (looking up in table for things that are in the table; using an object for things that aren't, rather than using hidden spans/tds) pretty good?
Populating the table, whether using innerHTML or DOM methods, is going to be worse performance-wise. Retrieving the data (particularly if via iteration) also becomes less verbose, easier to maintain and, again, better performance-wise. Using an HTML table is also a more fragile option, as if something goes wrong, other markup on the page could become invalid or, worse, it might end up displayed to the user.
There's also the simple fact it just seems hacky, workaroundy and dirty. It's an HTML table that is to present tabular data, it's not an SQL table for data storage.
JavaScript objects are pretty much made for what you're describing. Using an object makes even more sense and is a nice and clean option if the data you're getting from the server is already in a suitable form (i.e. JSON). Then it's ready for you and all you have to do is parse it.
I was just wondering if there was any fundamental reason why using the table for data storage was A Bad Thing.
I'd say it's fundamentally "bad" for the same reasons we strive not to mingle javascript or css in with the markup. The page HTML should be used for presentation purposes only. I don't think there's going to be a huge difference performance wise whether you use the table or a javascript object, but the javascript object would be much cleaner, IMO.
Set eg. each <tr> element to have a custom property eg .customData and place your javascript object there. Its a nice compromise - the data is seperated from the markup but directly related in the dom.
Storing the data in an object would make it easier to manage, but it would be good practice to also store a reference alongside of that to the element (makes crud easier).

Categories

Resources