This is a very simple game I'm trying to write but I have a really bad performance problem.
I'm not using an HTML5 Canvas—just plain javascript—so that may be the problem.
Here's the game: http://ivcdn.net/aga2/dead.html
Currently I'm using divs as game objects. And to move them, I increase or decrease their position on the page (and they're all positioned absolute). But (I think) doing so is causing serious performance issues.
What can I do to increase performance? And do I have have any other options than to use HTML5 and/or a better language?
One suggestion to improve performance in that would be instead of moving each individual div, move the container of the divs instead. That way you're only moving one thing instead of many.
Also limit how many setTimeout calls you're making. Ideally make one that encompasses all your game logic, and at the end of that game logic, call setTimeout again to call itself (provided the game is not over).
Related
I am trying to make my website a live background of space. I am attempting to get the stars to spawn on the left of the screen and slowly move over. And occasionally their will be stars that come in from other directions. My question is, how should I go about doing this?
Would it be smartest to make a Javascript, script that would make a LOT of <div>'s and then move them all randomly? Or would it be smartest to use a canvas? I've never used a canvas before so I don't know all it's uses yet.
Here's a link to the effect I'm trying to emulate (It's a YouTube video with music) - https://www.youtube.com/watch?v=y8MsE-4dygY&list=PL21A7A915E7020E73&index=16
I'm trying to emulate what the stars or partices are doing in the background of that video, so how should I go about this? (I'm not asking for all the code, I'm just making that clear.) Thanks in advance! :)
well, you can obviously use a Parallax background with some overlays for an easy effect, but you can go further by using any of the many scripts out there, search Google for that. Or you can learn how to do it via scripting with this great tutorial that makes use of HTML5 and CSS3
Canvas may be more performant than adding lots of divs as you won't need to create a large DOM tree. DOM operations are expensive and can cause memory thrashing if you repeatedly create and destroy lots of elements. Using multiple overlaid images and CSS3 translate transitions should be more performant still, but may make it harder to achieve all the effects that you want - randomized movement, separation of stars on the same plane, etc. etc.
How can I control the rendering loop frame rate in KineticJS? The docs for Kinetic.Animation show a frame rate being passed to the render callback, and Kinetic.Tween seems to have no frame rate logic, but I don't see anyway to force, say, a 30fps when 60fps is possible.
Loads of context for the curious follows, but the question is that simple. If anyone reads on, other advice is welcome. If you already know the answer, don't waste your time reading on!
I'm developing a music app that combines some DOM-based GUI controls (current iteration using jQuery Mobile) and Canvas-based GUI controls (using KineticJS). The latter involve some animation. Because the animated elements are triggered by music playback, I'm using Kinetic.Tween to avoid the complexity of remembering how long a given note has been playing (which Kinetic.Animation would require doing).
This approach works great at 60fps in Chrome (on a fast machine) but is just slow enough on iOS 6.1 Safari (iPad 2) that manipulating controls while animations are happening gets a little janky. I'm not using WebGL (unless KineticJS or Chrome does this by default for canvas?), and that's not an option when I package for native UIWebView.
As I'm getting beyond prototype into wanting to make more committed tech decisions, I see the following options, in order of perceived goodness:
Figure out how to cap the frame rate. Because my animations heavily use alpha fades but do not involve motion, I believe I could get away with 20-30fps and look fine. Could also scale this up on faster devices.
Don't respond immediately to touch inputs, but add them to a queue which I poll at a constant interval and only use the freshest for things like touchmove. This has no impact on my non-interactive animated elements, but tackles the problem from the other direction, trying to reduce the load of user interaction. This would require making Kinetic controls static and manually tracking touch coordinates (not terrible effort if it actually helped).
Rewrite DOM-based GUI to canvas-based (KineticJS); rewrite WebAudio-based engine to HTML5 audio; leverage CocoonJS or Ejecta for GPU-acceleration. This means having to hand-code stuff like file choosers and nav menus and such (bad). Losing WebAudio is pretty serious as it eliminates features like DSP effects and very fine-grained, low-latency timing (which is working just fine on an iPad 2).
Rewrite the app to separate DOM based GUI and WebAudio from Canvas-based elements, leverage CocoonJS. I'm not sure if/how well this works out, but the fact that CocoonJS passes JavaScript code as strings between the 2 components makes me very skittish about how solid this idea is. It's probably doable, but best case I'm very tied to CocoonJS moving forwards. I don't like architecting this way, but maybe it's not as bad as it sounds?
Make animations less juicy. This is least good not because of its design impact but because, as it is, I'm only animating ~20 simple shapes at any time in my central view component, however they include transparency and span an area ~1000x300. Other components like sliders are similarly bare-bones. In other words, it's not very juicy right now.
Overcome severe allergy to Objective-C; forget about the browser, Android, and that other mobile OS. Have a fast app that performs natively and has shiny Apple-approved widgets. My biggest problem with this approach is not wanting to be stuck in Objective-C reality for years, skillset-wise. I just don't like it.
Buy an iPad 3 or later. Since I already am pretending Android doesn't exist (I don't have any devices to test), why not pretend no one still has iPad 2? I think this is passing the buck -- if I can get acceptable performance on iPad 2, I will feel confident about the app's performance as I add more features.
I may be overlooking options or otherwise naive about how to tackle this. Some would say what I'm trying to build is just silly. But it's working pretty well just not ready for prime time on the iPad 2.
Yes, you can control the Kinetic.Animation framerate
The Kinetic.Animation sends in a frame object which has a frame.time property.
That .time is a running timer that you can use to throttle your animation speed.
Here's an example that throttles the Kinetic.Animation: http://jsfiddle.net/m1erickson/Hn3cC/
var lastTime;
var frameDelay=1000;
var loop = new Kinetic.Animation(function(frame) {
var time = frame.time
if(!lastTime){lastTime=time;}
var elapsed = time-lastTime;
if(elapsed>=frameDelay){
// frameDelay has expired, so animate stuff now
// set lastTime for the next loop
lastTime=time;
}
}, layer);
loop.start();
Working from #markE's suggestions, I tried a few things and found a solution. It's ultimately not rocket science, but sharing what I figured out:
First, tried the hack of doubling Tween durations and targets, using a timer to stop them at 50%. This kinda sorta worked but was hard to get to look good and was pretty error prone in coding bogus targets like negative opacity or height or whatnot.
Second, having read the source to Tween and looked at docs again for Animation, decided I could locally use Animation instances instead of Tween instances, and allow the closure scope to hang onto the relevant note properties. Eventually got this working smoothly and finally realized a big Duh! which is that throttling the frame rate of several independently animating things does not in any way throttle the overall frame rate.
Lastly, decided to give my component a render() method that calls itself in a loop with requestAnimationFrame, exits immediately if called before my clamp time, and inside render() I update all objects in the Kinetic canvas and call layer.drawScene(). Because there is now only one animation, this drops frame rate to whatever I need and the app is fast on iPad 2 (looks exactly the same to my eyes too).
So Kinetic is still helping for its higher level canvas API, and so far my other control widgets are still easy code using Kinetic to handle user input and dragging, now performing much better as the big beast component is not eating up the CPU.
The short answer to my original question is that no, you can't lock the overall frame rate for very complex animations, but as Mark said, you can for anything that fits in a single Animation instance.
Note that I could have still used Animation without giving it a layer or explicitly calling any draw() methods, but since I'd still have to write all the logic to determine individual element's current visual state, there was no gain to doing this. What would be very useful would be if Tween could accept a parameter to not automatically render. This would simplify code like mine, as I could shorthand the animation on individual objects but still choose when to actually do the heavy lifting of rendering everything. Seeing how much this whole exercise gained in performance on the iPad 2, might be worth adding this option to the framework.
I am new to programming games. I'm just wondering, so for a simple board game (let's say Tic Tac Toe or Checkers), would it be a good idea to use multiple canvas for the board? I mean, each canvas could represent each square on the board.
I feel that many people tend to do it like this because it keeps the logic simple. You let the CSS do all the spacing and annoying square separation. But I don't know if it's good practice to do it like that.
Since I am new, I feel that avoiding shortcuts now will be beneficial when I create something complex. So, what's your take on separate canvas for each board square?
The most important thing is to find a balance and understand why you would use one canvas versus layered canvases.
For a tic-tac-toe game only one is needed as there is nothing there that needs constantly updates. If would be easier to maintain as well. Event-driven (ie. nothing happens until you click/do something) games/apps such as this would typically not benefit from several layers.
When you use more than one canvas it is usually because you have a static or complex background (or foreground for that matter), and some objects moving over it that needs to move smoothly. This would be a good candidate for layering canvases as this allow you to clear and redraw only the region of the moving object instead of rendering the background as well (particular in cases where the background is a composite).
It's not much more complex to handle layered canvases than one, but you would need to keep track of where you do the draw operations. You can use objects with embedded information to do this, or for extra performance use arrays/variables.
Is there a standard (accepted/easy/performant) way to determine how fast a client machine renders javascript?
When I'm running web apps (videos, etc) on my other tabs my JS animations slow to a crawl.
If I could detect slowness from my JS, I would use simpler animations to provide a better user experience.
Update:
Removing animations for everyone is not the answer. I am talking about the simplest of animations which will stutter depending on browser / computer. If I could detect the level of slowness, I would simply disable them.
This is the same as video games with dynamic graphics quality: you want to please people with old computers without penalizing those who have the extra processing power.
One tip is to disable those hidden animations. if they are on another tab that is not in focus, what's the use of keeping them animated?
Another is to keep animations to a minimum. I assume you are on the DOM, and DOM operations are expensive. keep them to a minimum as well.
One tip I got somewhere is if you are using image animation manipulation, consider using canvas instead so that you are not operating on the DOM.
Also, consider progressive enhancement. Keep your features simple and work your way up to complicated things. Use the simple features as a baseline every time you add something new. That way, you can easily determine what causes the problem and fix it accordingly.
The main problem you should first address is why it is slow, not when it is slow.
I know this question is old, but I've just stumbled across it. The simplest way is to execute a long loop and measure the start and end time. This should give you some idea of the machine's Javascript performance.
Please bear in mind, this may delay page loading, so you may want to store the result in a cookie, so it's not measured on every visit to the page.
Something like:
var starttime = new Date();
for( var i=0; i<1000000; i++ ) ;
var dt = new Date() - starttime;
Hope this helps.
I am using setInterval(foo,ms) to carry out an animation. I really don't want to post all the code for the animation here as it spans multiple files. It's basically a bunch of images falling. Every second I call ctx.drawImage(img,...) while updating the coordinates to simulate gravity.
I have divided the canvas into two sections, one animation on the left and one on the right. When one of them is activated the frame rate is stable at 30 fps. If, however, I activate both of them, the performance plummets. This has nothing to do with overloading my computer, as I can cut the complexity of each animation by a factor of 10 and the problem persists. My guess is the setIntervals are interfering with each other.
My question is whether it is safe to execute more than one setInterval calls. Thanks
You can have many setIntervals() without issue but be aware that JS is fundamentally single-threaded (per-page). Multiple "Concurrent" threads are actually handled by jumping one thread about the code.
What this means is that timing won't be consistent - especially if one of the methods takes a considerable length of time to run.
As the others say, you can have as much as possible. Nevertheless, you should have as few as necessary for good performance. Maybe you can find a way to use only one intervala for both animations.
There might be a problem though if you use global variables. This could have an influence on the animations (maybe even on the performance, depends on what you use them for).
I would advise using setTimeout it could avoid performance issuse.
Take a look at this question setTimeout or setInterval?
It does a great Job of explaining the difference between the two and why you should you generally use setTimeout.
My question is whether it is safe to execute more than one setInterval calls
Short answer: yes, absolutely.
Yes its safe to have multiple setIntervals running.. There's no underlying performance issue with using setIntervals.. profile your own code, you'll almost certainly find the problem there.