If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Your opinions on my Game Loop and Code Organization

Hello all, brand new to the forums. I read the "Read First" post and hopefully I'm not starting off bad. I'm developing a JavaScript/HTML5 game for fun, but wasn't sure if my code implements good practices.

I'll try to condense what I have in order to make this post shorter. Just a little overview to help out hopefully:

Create Namespaces. I've only provided one in this post.

canvases[] and canvasCache (private vars):

- One is an array for storing one or more canvases.

-The other I use to cache the canvas element when I create a new one in order to avoid the garbage collector. I turn it back to null before the createCanvas function is done. Perhaps this is overkill since I won't create new divs or canvases during runtime.

I've considered eliminating the array and creating a function that gets the canvas or div when needed.

timeStamp: For exactly that. I use performance.now since it's a lot more accurate, but I also provide a fallback for browsers that don't support it.

Game.run: is called when I want to start the loop. No need to get into details here. Unless it can be optimized

Game.getBody, getBrowserWidth, getBrowserHeight: I read it's more efficient creating a temporary reference of document.body before creating a new canvas or div. I assume calling getBrowserWidth/Height is better than creating a variable I won't use as much.

STOP using $ prefix on JavaScript variable names...
Please remember to wrap any code you have in forum tags:- [CODE]...[/CODE] [HTML]...[/HTML] [PHP]...[/PHP]If you can't think outside the box, you will be trapped forever with no escape...

Thanks for the quick response. Regarding the Anonymous function, it's a way I can give vars in several js files their own local scope. Global variables are still shared among files. At least that's what I've read. In production I'd put everything in one file. Minimized.

A while loop would block the UI thread, and most modern browsers support requestAnimationFrame which will turn into the standard for animation on the web. The loop already works perfectly it also implements a fallback to setTimer.

I wanted to know if this organization can use optimization or it's nice the way it is. As far as I know, it looks okay. But who knows, putting it out there for further opinions.

I wouldn't attach game() to window, you shouldn't need to do that given what you're doing with it.

Little tip, if you are declaring a bunch of VAR in a row, you only need to say VAR once -- you can then comma delimit the list.

The delta you are using of aiming for 60fps as your average is going to have problems in browsers that don't support window.performance; when it drops through to that Date.getTime() you're going to be having that function return the same time multiple times in a row, as the Date functions timer granularity is way down at 36.4ms on most browsers. (which of course is why we have Performance in the first place). You might want to run some sort of granularity check to make sure you aren't drawing frames that don't update because of the low timer granularity (which is below 30fps). I'd suggest dropping your desired 1:1 rate (step) to 24. It runs faster, great, and it will reduce the number of systems that will run at a slower playrate thanks to falling back on getTime to nil.

That said, it's nice to see someone doing it properly, separating playrate from framerate.

Oh, and because you're going to use document and window so much, this cute trick:

(function(d,w) {
})(document,window);

Can not only save you some typing, it will actually run a hair faster since as an interpreted language, less code == faster, and shorter variable names == faster lookups.

... and yeah, @nogDog if you don't release scripting execution, nothing gets drawn -- EVER. That's why EVERY javascript animation has to use setTimeout, setInterval, requestAnimationFrame, or something similar to actually be usable... hence all white(true) will do is send the browser off to never-never land, effectively locking it up until (if you are in a good browser) it comes up with the message about the script taking too long to run and asking if you want to kill it.

WAIT -- if using requestAnimationFrame, the only browsers that support it also by definition support Performance -- so there's no reason to have a fallback to Date.gettime --- or is there some sort of polyfill for that we're not seeing?

I'd consider simply seeing if both requestAnimationFrame and window.performance exist, and if they don't simply bomb out with an error and lose the attempts to have fallbacks... Well, unless you REALLY care about Safari in which case you'd still need the webkitRequestAnimationFrame crap and have no window.performance; Even before Chrome forked off into Blink, the Safari builds of webkit have been such horrible code-rot lagging behind Chrome they've made IE 10+ look good on stuff like this.

... and yeah, I prefer creating CANVAS from the scripting because it's a scripting only element that to be frank, has no business even having a HTML tag in the first place. Scripting off fallback is NOSCRIPT's job, no support for the scripting is scripting's job.

Just another of those things people call HTML 5 that isn't, or at the very least shouldn't be.

Hey Shadow thanks for the great answer. You're right about the vars, I should have just used commas. Thanks for the tip.

I actually made my previous version re-size based on the browser width/height so it takes up the browser viewing area. window.resize would fire and resize everything. Well, you already know this Were you suggesting the use of it because of performance or an aesthetic opinion?

I checked out your demo and I don't think it's crappy. The water animation was pretty cool and the boats are floating nicely. Are they "floating" based on the water or independently?

Code:

(function(d,w) {
})(document,window); // THANKS FOR THIS TIP :)

I'm going to remove window.performance. After your post, I went ahead and read up on it at MDN , and I have a feeling it's better to use it for debugging. In fact, according to the article, Safari completely doesn't support it. Our beloved IE only supports it in version 10.0.

WAIT -- if using requestAnimationFrame, the only browsers that support it also by definition support Performance -- so there's no reason to have a fallback to Date.gettime --- or is there some sort of polyfill for that we're not seeing?

Ooops sorry for not including the Polyfill. I'm using the famous Paul Irish solution:

... and yeah, I prefer creating CANVAS from the scripting because it's a scripting only element that to be frank, has no business even having a HTML tag in the first place. Scripting off fallback is NOSCRIPT's job, no support for the scripting is scripting's job.

Just another of those things people call HTML 5 that isn't, or at the very least shouldn't be.

Were you suggesting the use of it because of performance or an aesthetic opinion?

More a usability issue -- I've seen a few too many canvas games that are annoying to try and play because they're stuck in a little tiny window (you'll see flash games on sites similarly afflicted) or worse, too big for the display I'm on.

Originally Posted by Infinite Loop

The water animation was pretty cool and the boats are floating nicely. Are they "floating" based on the water or independently?

Independently, but on purpose. It tricks the brain into seeing more waves than are actually drawn. Trick I picked up back in the '80's working on true parallax depth of field scrolling -- A great example is the ground in the SMS version of Choplifter. If you moved the enemy tanks with the ground tile, it actually looks wrong so it gets it's own sideways scroll rate in-between the tile-row in front of it and the tile-row behind it.

Originally Posted by Infinite Loop

Ooops sorry for not including the Polyfill. I'm using the famous Paul Irish solution:

Like most of his solutions I wonder if he even understands the languages he's writing for... See that garbage he did with the endless stupid malfing IE CC around the HTML tag crap that he came up with that damned near every framework pisses on websites with. REALLY not a fan of anything of his.

I mean, setting self to self? Would that ONE if statement REALLY hurt that much? Much less there is no such thing as msRequestAnimationFrame -- never even existed -- and of course setTimeout just doesn't work at 16.6~ms (1000/60), as the minimum across browsers hovers between 30ms and 36.4ms -- so sending that low a timeout is never going to work right.

Originally Posted by Infinite Loop

What if I do the same thing for window.performance?

I'd actually handle that a bit differently if I were to go that route. I'd probably set my own function name instead of recycling, but make it an alias of the ones that exist... THOUGH, Performance.now only has a -webkit prefix, none of the other ones have ever bothered having it.

I find writing code for fun on the older narrower targets makes me a better programmer when I have the endless resources of today. It makes you think more, and when you're done it feels like way more of an accomplishment.

Sad part being in many ways writing DOS games is simpler and more powerful than what JS can do today... admittedly much of that is the dreadful state of AUDIO in browsers, which is what made me shelve that CANVAS demo which was originally going to be "Missile Command on Steroids".