Can anyone explain why (indeed, if) it's best to abstract the major parts of a canvas game to different layers when using something like Kinetic?
It of course feels like you should, and so far I have been: one layer for the background, one for the player's character, and others.
Then I ran into a situation where I needed a shape of one layer to sit behind a shape on another layer - but moving the entire layer behind the other layer was not an option, so I reluctantly re-coded so the entire game sits on one layer.
To my surprise, though, I can still do everything I need. I can still animate or handle events on individual shapes or groups.
So in short: what advantage does explicit layering bring? What pitfalls might I face with the one-layer approach?
Actually, layers usually give a huge advantage. However, sometimes they are not necessary. Just to give an idea - compare PhotoShop (layers) and MS Paint (no layers). If this gives you the idea then that's it!
If not: layers is an organizational concept. It lets you to deal with data in pieces. They allow:
Apply certain transformations to a whole layer.
Automatically categorize your objects on a per-layer basis, so that you can get
all objects of a layer and work with them pretty easily.
Isolate anything that happens in a layer from happening in other layers.
Disable/enable whole layers.
Much-much more!
As you see, layers, generally, allow such abstractions as encapsulation and, to some extent, polymorphism to be enforced on content organization level. Pitfall that one-layer approach brings is just that - too tight coupling - a beast from the world of permanent chaos that encapsulation and polymorphism fight for the eternity. Nuff said!
If your game contains a lot of different stuff, it might take time to draw everything. Too much in the same layer reduces performance. Although too many layers does so aswell.
Check out: http://www.html5canvastutorials.com/labs/html5-canvas-kineticjs-drag-and-drop-stress-test-with-1000-shapes/
In organizational terms, noncom's answer was spot on. However, as he has noted his answer is more in regards to canvas animations in general, and you are quite correct in pointing out that KineticJS provides it's own tools to offer those same organizational benefits.
So, with organisation irrelevant, all we have is performance. With that said, the main difference is that each 'layer' corresponds to a distinct canvas tag.
The simple answer then, is that having multiple layers allows you to selectively redraw only one canvas tag at a time. Think about it, if you have objects moving on top of a background, do you want to be clearing and redrawing the background every time those objects move?
If you're not using layers, that's what is happening. What you want is a background that only ever gets drawn again when the background changes, that means a layer for the background.
Whether this is actually worthwhile depends highly upon your application, but that's the idea. The point of layers (outside of organisation) is to isolate the required drawing processes to things that actually need to be drawn. With complex animations this can be incredibly important to maintaining decent performance.
Here's a jsperf for reference: http://jsperf.com/layered-canvases/3
Related
I'm trying to do a game development API for Google's GWT to make Canvas Games, and I got a question with the prerendering issue.
First: I am not entirely sure how browsers/Javascript/GWT manage a deleted canvas, if its data stay on memory or not, after using a removeChild() or RootPanel.Remove() (with GWT), or even the correct method to remove it from memory.
So the solution I've came about is using multiple (as needed) big, hidden canvases as a pre-render palette and use drawImage() magic to jump around the prerendered images drawing on the main context, and having my own problems with insertion, removal, empty spaces, etc.
Is this the best solution? Or should I try using one little canvas for every little image and texture that is prerendered? Or should I try something completely different whatsoever?
Thanks in advance, and sorry for my spelling.
using a canvas to pre-render your items is a good idea, however it's not always the best choice.
If your items are complex (with gradient, shadows and visual effect), so yes it will be good. But if your items are simple (images, polygons, simple bezier curves, ...), your framerate won't increase but can decrease (because of the drawImage). It's then better to render in realtime.
From my experiments, you won't lose performance by using several small canvas (may be few memory) but it can be easier to manage than a big canvas (like an object oriented scene).
If your items change sometimes, you are sure to easily manage the size of your temporary canvases.
Hope this help.
I'm making a flash game, and I can't decide to use a bigger stage or a smaller one, with scrolling background to make it run smoother. I's going to be some kind of strategy game if it matters.
Thanks
One option is to have a bitmap object the size of your stage for example 800x600, then draw your objects into the bitmapdata of that bitmap using copyPixels this is known as blitting and is pretty fast.
Another option is to just use the flash display list and add every object as sprites onto the stage.
Second method is easier to handle in terms of mouse events and stuff.
My advice is to start with the second option and see if performance is enough, if not go with option 1.
There are many, many variables that determine the performance of your application.
To answer your question, a smaller stage area will make your program run faster. The amount of difference will depend on the way your application deals with display objects. Flash will not render things that are completely outside the stage bounds. So keeping only those objects that are needed at any given time on the stage is a good practice.
using flash player 11's new stage3D features (even for 2D stuff) will likely make your game very smooth. Lots of good frameworks out there that can take care of the low-level stuff if you don't want to get into it. For 2D, starling is very easy to get started with, and seems to be Adobe's favored framework.
At a bare minimum, make sure you use GPU acceleration in your output/compiler options.
There are LOTS of other tips for optimization people could get into, but that is better suited for google searches as Stackoverflow is about specific questions.
I am trying to choose the right technology to use for updating a project that basically renders thousands of points in a zoomable, pannable graph. The current implementation, using Protovis, is underperformant. Check it out here:
http://www.planethunters.org/classify
There are about 2000 points when fully zoomed out. Try using the handles on the bottom to zoom in a bit, and drag it to pan around. You will see that it is quite choppy and your CPU usage probably goes up to 100% on one core unless you have a really fast computer. Each change to the focus area calls a redraw to protovis which is pretty darn slow and is worse with more points drawn.
I would like to make some updates to the interface as well as change the underlying visualization technology to be more responsive with animation and interaction. From the following article, it seems like the choice is between another SVG-based library, or a canvas-based one:
http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/
d3.js, which grew out of Protovis, is SVG-based and is supposed to be better at rendering animations. However, I'm dubious as to how much better and what its performance ceiling is. For that reason, I'm also considering a more complete overhaul using a canvas-based library like KineticJS. However, before I get too far into using one approach or another, I'd like to hear from someone who has done a similar web application with this much data and get their opinion.
The most important thing is performance, with a secondary focus on ease of adding other interaction features and programming the animation. There will probably be no more than 2000 points at once, with those small error bars on each one. Zooming in, out, and panning around need to be smooth. If the most recent SVG libraries are decent at this, then perhaps the ease of using d3 will outweigh the increased setup for KineticJS, etc. But if there is a huge performance advantage to using a canvas, especially for people with slower computers, then I would definitely prefer to go that way.
Example of app made by the NYTimes that uses SVG, but still animates acceptably smoothly:
http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html . If I can get that performance and not have to write my own canvas drawing code, I would probably go for SVG.
I noticed that some users have used a hybrid of d3.js manipulation combined with canvas rendering. However, I can't find much documentation about this online or get in contact with the OP of that post. If anyone has any experience doing this kind of DOM-to-Canvas (demo, code) implementation, I would like to hear from you as well. It seems to be a good hybrid of being able to manipulate data and having custom control over how to render it (and therefore performance), but I'm wondering if having to load everything into the DOM is still going to slow things down.
I know that there are some existing questions that are similar to this one, but none of them exactly ask the same thing. Thanks for your help.
Follow-up: the implementation I ended up using is at https://github.com/zooniverse/LightCurves
Fortunately, drawing 2000 circles is a pretty easy example to test. So here are four possible implementations, two each of Canvas and SVG:
Canvas geometric zooming
Canvas semantic zooming
SVG geometric zooming
SVG semantic zooming
These examples use D3's zoom behavior to implement zooming and panning. Aside from whether the circles are rendered in Canvas or SVG, the other major distinction is whether you use geometric or semantic zooming.
Geometric zooming means you apply a single transform to the entire viewport: when you zoom in, circles become bigger. Semantic zooming in contrast means you apply transforms to each circle individually: when you zoom in, the circles remain the same size but they spread out. Planethunters.org currently uses semantic zooming, but it might be useful to consider other cases.
Geometric zooming simplifies the implementation: you apply a translate and scale once, and then all the circles are re-rendered. The SVG implementation is particularly simple, updating a single "transform" attribute. The performance of both geometric zooming examples feels more than adequate. For semantic zooming, you'll notice that D3 is significantly faster than Protovis. This is because it's doing a lot less work for each zoom event. (The Protovis version has to recalculate all attributes on all elements.) The Canvas-based semantic zooming is a bit more zippy than SVG, but SVG semantic zooming still feels responsive.
Yet there is no magic bullet for performance, and these four possible approaches don't begin to cover the full space of possibilities. For example, you could combine geometric and semantic zooming, using the geometric approach for panning (updating the "transform" attribute) and only redrawing individual circles while zooming. You could probably even combine one or more of these techniques with CSS3 transforms to add some hardware acceleration (as in the hierarchical edge bundling example), although that can be tricky to implement and may introduce visual artifacts.
Still, my personal preference is to keep as much in SVG as possible, and use Canvas only for the "inner loop" when rendering is the bottleneck. SVG has so many conveniences for development—such as CSS, data-joins and the element inspector—that it is often premature optimization to start with Canvas. Combining Canvas with SVG, as in the Facebook IPO visualization you linked, is a flexible way to retain most of these conveniences while still eking out the best performance. I also used this technique in Cubism.js, where the special case of time-series visualization lends itself well to bitmap caching.
As these examples show, you can use D3 with Canvas, even though parts of D3 are SVG-specific. See also this force-directed graph and this collision detection example.
I think that in your case the decision between canvas and svg is not like a decision between »riding a Horse« or driving a »Porsche«. For me it is more like the decision about the cars color.
Let me explain:
Assuming that, based on the framework the operations
draw a star,
add a star and
remove a star
take linear time. So, if your decision of the framework was good it is a bit faster, otherwise a bit slower.
If you go on assuming that the framework is just fast, than it becomes totally obvious that the lack of performance is caused be the high amount of stars and handling them is something none of the frameworks can do for you, at least I do not know about this.
What I want to say is that the base of the problem leads to a basic problem of computational geometry, namely: range searching and another one of computer graphics: level of detail.
To solve your performance problem you need to implement a good preprocessor which is able to find very fast which stars to display and is perhaps able to cluster stars which are close together, depending on the zoom. The only thing that keeps your view vivid and fast is keeping the number of stars to draw as low possible.
As you stated, that the most important thing is performance, than I would tend to use canvas, because it works without DOM operations. It also offers the opportunity to use webGL, what increases graphic performance a lot.
BTW: did you check paper.js? It uses canvas, but emulates vector graphics.
PS: In this Book you can find a very detailed discussion about graphics on the web, the technologies, pros and cons of canvas, SVG and DHTML.
I recently worked on a near-realtime dashboard (refresh every 5 seconds) and chose to use charts that render using canvas.
We tried Highcharts(SVG based JavaScript Charting library) and CanvasJS(Canvas based JavaScript Charting library). Although Highcharts is a fantastic charting API and offers way more features we decided to use CanvasJS.
We needed to display at least 15 minutes of data per chart (with option to pick range of max two hours).
So for 15 minutes: 900 points(data point per second) x2(line and bar combination chart) x4 charts = 7200 points total.
Using chrome profiler, with CanvasJS the memory never went above 30MB while with Highcharts memory usage exceeded 600MB.
Also with refresh time of 5 seconds CanvasJS rendering was allot more responsive then Highcharts.
We used one timer (setInterval 5 seconds) to make 4 REST API calls to pull the data from back end server which connected to Elasticsearch. Each chart updated as data is received by JQuery.post().
That said for offline reports I would go with Highcharts since its more flexible API.
There's also Zing charts which claims to use either SVG or Canvas but haven't looked at them.
Canvas should be considered when performance is really critical. SVG for flexibility. Not that canvas frameworks aren't flexible, but it takes allot more work for canvas framework to get the same functionality as an svg framework.
Might also look into Meteor Charts, which is built on top of the uber fast KineticJS framework: http://meteorcharts.com/
I also found when we print to PDF a page with SVG graphics, the resulting PDF still contains a vector-based image, while if you print a page with Canvas graphics, the image in the resulting PDF file is rasterized.
In actionscript3 (cs5.5 or flashdevelop), what is the best practice for managing off-screen display objects?
Option A: While loading the level, place all objects on the stage (even the ones way waaay offscreen)
or
Option B: Keep track of which objects should be on screen, adding them to the screen when they should be there, and removing them when they shouldn't.
Option A is definitely far easier to manage, but which is actually the more performant of the two options? Is one better in certain scenarios?
(ie. a tile map may benefit from managing which tiles are on screen (especially for huge maps), but perhaps flash takes care of all this behind the scenes?)
Option B is going to be a lot faster, most of the time. But for tile maps and similar, I would recommend avoiding the scene-graph and use manual bitmapdata-blitting instead.
I hope this isn't too open ended.
I'm wondering if there is a better (more battery-friendly) way of doing this --
I have a small HTML 5 game, drawn in a canvas (let's say 500x500). I have some objects whose positions I update every 50ms or so. My current implementation re-draws the entire canvas every 50ms. I can't imagine that being very good for battery life on mobile platforms.
Is there a better way to do this? This must be a common pattern with games.
EDIT:
as requested, here are some more updates:
Right now, the objects are geometric primitives drawn via arcs and lines. I'm not opposed to making these small png/jpg/gif files instead of that'd help out. These are small graphics -- just 15x15 or so.
As the game progresses, more and more of the screen changes at a time. However, at the start, the screen changes relatively slowly (the objects randomly moved a few pixels every 50ms).
Nearly every game with continuous animation like this redraws everything every frame; clever updating algorithms are only applicable when a small part of the screen is changing and there is a nice rule to figure out what is overlapping that part.
Here is some general optimization advice:
Make sure that as much as possible of your graphics are handled by the GPU and not the CPU. (This may be impossible if the user's browser does not use the GPU for 2D canvas rendering, but you can expect upgrades may change that as HTML5 gaming gains popularity.)
This means that you should avoid elaborate clever algorithms in favor of doing as little work as possible in JS code — except that avoiding performing a lot of drawing when it is easy to determine that it will be invisible (e.g. outside the bounds of the screen) is generally worthwhile.
If your target platforms support it (generally not the case for current mobile devices), try using WebGL instead of 2D Canvas. You will have to do more detail work, but WebGL allows you to use operations which are much more likely to be provided efficiently by the GPU hardware.
If your game becomes idle — that is, nothing is actually animating at the moment — stop redrawing. Stop your update loop until the user interacts with the game or a timeout occurs.
It may be helpful for you to add to your question details of what types of graphics you are drawing (e.g. are you using sprites, or geometric primitives? Are you drawing images rotated/scaled? Does most of the screen change or just a few small objects? Are you blending many layers?) and perhaps even a screenshot or two; then we can suggest what sort of optimizations are suitable for your particular game.
Don't draw a background, make it an image and set the CSS background-image of the canvas.
Using requestAnimationFrame should help with battery life.
http://paulirish.com/2011/requestanimationframe-for-smart-animating/
Only do a redraw if something has actually changed. If you haven't already, introduce the concept of invalidations. (ie, the canvas is valid so nothing redraws until something moves. Anything moving within the window of the canvas causes the canvas to become invalid, thus needing a redraw)
If you want to be battery friendly you can use Crafty. This game engine is using modern CSS3 technology so it doesn't need to update a canvas all the time. Look at this example game here.
The way you don't want to redraw entire canvas every frame, it only can be the "Dirty-Check" or "Dirty Matrix" algorithms.
Dirty-check seems more efficient than entire redraw. but I think it depends on your render implementation.
it is not necessary to use it if you are using canvas2D to render. Nearly every game has complex sprites and animation. if you use dirty-check, when a part of sprite or background map need to update, you have to figure out what is overlapping this part. and then clearRect this small area of canvas, and then redraw every sprite or map. etc, what is overlapping.
It means your had to run canvas render api more times than normal render implementation because of the overlapping part. And Canvas2d render performance usually does't sounds efficient.
But if you use WebGL, that maybe quite difference. even though I am not family with WebGL, I do knew that maybe more efficient. Dirty-Check should be a good Choice to match your propose.