I'm completely new to HTML 5 Canvas, so I apologize in advance if I'm asking stupid question...
I've studied some basic example for implementing animations. All of those are not "object oriented" examples, meaning that there is a central draw() method which is called at regulr interval and clears & redraws everything each time.
From the knowledge I have in graphic programming with other languages / toolkits, a more efficient way should be using an "object oriented" approach where every "object" on the stage has its own draw method which checks if the object actually need to be redrawn against an invalidated clipping region.
Does it make sense with canvas too in terms of performance and CPU load? Is there another more efficient approach (examples)?
Not sure if it is efficient performance wise, but Dojo GFX is very efficient development wise. It is a proxy between your shape objects and their visual representation using different rendering facilities including HTML5 Canvas.
With GFX you will surely not require a central draw method clearing and redrawing everything each time you need to make a transformation to some of the shapes.
Related
We are developing a web-based game. The map has a fixed size and is procedually generated.
At the moment, all these polygons are stored in one array and checked whether they should be drawn or not. This requires a lot of performance. Which is the best rendering / buffering solution for big maps?
What I've tried:
Quadtrees. Problem: Performance still not as great because there are so many polygons.
Drawing sections of the map to offscreen-canvases. A test run: http://norizon.ch/repo/buffered-map-rendering/ Problem: The browser crashes when trying to buffer that much data and such big images (maybe 2000x2000) still seem to perform badly on a canvas.
(posting comments as an answer for convenience)
One idea could be, when the user is translating the map, to re-use the part that will still be in view, and to draw only the stripe(s) that are no longer corrects.
I believe (do you confirm ?) that the most costly operation is the drawing, not to find which polygon to draw.
If so, you should use your QuadTree to find the polygons that are within the strips. Notice that, given Javascript's overhead, a simple 2D bucket that contains the polygons that are within a given (x,y) tile might be faster to use (if the cost of the quadtree is too high).
Now i have a doubt about the precise way you should do that, i'm afraid you'll have to experiment / benchmark, and maybe choose a prefered browser.
Problems :
• Copying a canvas on itself can be very slow depending on devices/Browsers. (might require to do 2 copy, in fact)
• Using an offscreen canvas can be very slow depending on devices/Browsers. (might not use hardware acceleration when off-screen).
If you are drawing things on top of the map, you can either use a secondary canvas on top of the map canvas, or you'll be forced to use an off-screen canvas that you'll copy on each frame.
I have tried a lot of things and this solution turned out to be the best for us.
Because our map has a fixed size, it is calculated server-side.
One big image atlas with all the required tiles will be loaded at the beginning of the game. For each image on the atlas, a seperate canvas is created. The client loads the whole map data into one two-dimensional array. The values determine, which tile has to be loaded. Maybe it would be even better if the map was drawn on a seperate canvas, so that only the stripes have to be painted. But the performance is really good, so we won't change that.
Three conclusions:
Images are fast. GetImageData is not!
JavaScript has not yet great support for multi threading, so we don't calculate the map client-side in game-time.
Quadtrees are fast. Arrays are faster.
I am writing a web visualization tool which involves displaying a processed image ~30 times a second.
I have been using the standard canvas tag and using functions such as getImageData/putImageData to perform some pixel manipulation along with drawing circles, squares and paths using beginPath() and bezierCurveTo(), stroke(), etc
Everything is working great but I am getting horrible performance even with hardware acceleration.
Is canvas inherently slow at these types of operations?
I have been researching into using WebGL/THREE.JS for performance, but all I need is to do pixel manipulation with some basic shape drawing. Is WebGL overkill for this? Is there a better alternative?
Ideally I believe I want something that wraps the canvas API but displays it using the WebGLRenderer for performance.
I am in the middle of process of making a HTML5 game. Now I have a problem related to performance.
I have some irregular Shapes. So detecting if {x,y} is in the Shape or not using a custom function is near impossible(At least as I think).
There are two big Shapes, so I need to call Shape.intersects({x,y}) twice for multiple times per second to detect if current {x,y} is in the shape or not.
{x,y} are variable and are not touch/mouse events. So I can not use onmousemove,etc events.
Each twice call of Shape.intersects({x,y}) on Nexus 5 has a ~45ms overhead. ~45ms each 100ms! This make some hiccups in game experience.
The most straight solution is to make Shape.intersects({x,y}) non-blocking. But how? or do anyone have any idea around this problem?
I am using Kinetic v5.0.1
RESULT:
.intersects will re-generate the Shape in memory, this is why it is very costly. According the to the #MarkE answer below, using native canvas function context.isPointInPath(x, y) would be very efficient. But:
Note that this will only work for the last path (after using beginPath()). If you need to iterate several paths (ie. shapes) you need to re-construct the paths (no need to stroke or fill though). This is perhaps a reason why some don't use it.
Source: https://stackoverflow.com/a/17268669/172163
In my shapes, I had solid colors. Also there are multiple shapes dynamically generated. so I ended up with context.getImageData(x, y, 1, 1) to get the color of specific pixel, and if it is the color of my Shapes are not. It is more efficient than .intersects(). It costs only ~3ms.
Why intersects gives you a performance hit (pun intended!)
Internally, KineticJS uses context.getImageData to do hit-tests in the intersects method.
getImageData provides pixel-perfect hit testing but it's slow on mobile devices (as you've discovered).
To answer your question:
No, you cannot run KineticJS's internal methods on a background worker thread.
But...
If you really need to squeeze performance out of hit-testing, you can write your own custom hit-test.
One possibility for such a custom hit test would be to maintain 2 offscreen html5 canvas elements that mirror your 2 irregular shapes.
That way you can use canvas's context.isPointInPath(x,y) to do your hit-testing.
The importance is that isPointInPath uses GPU acceleration and is therefore quite fast.
If you feel ambitious you could even create an asynchronous background worker thread to execute isPointInPath while your UI thread continues.
You mention the Nexus5. You can spawn a background worker thread with Android's AsyncTask.
Your background task can return the results of your hit-test using it's onPostExecute(Result) callback which invokes on the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
Good luck with your project!
I want to build a simple modelviewer. In fact that most 3D Engines for javascript/canvas out there are way too complex for my purpose I'd prefer building a small one on my own. By writing a z-buffer I'd like to check wether canvas API should draw a pixel over the existing image. At the moment I am using the method fill() to draw triangles. I do so because I'd like to avoid writing my own anti-aliasing stuff. Are there any callbacks or is there any other way I can implement my check into the native script?
In fact that's going to be in Adobe AIR, are there any native ressources I could use to speed up(molehill/Stage3D WebGL? Dunno). Or are there any ways in combination of Flash? Actually I'd prefer Javascript but if there are native solutions I'd also like to check them as long as I can implemenet them into my HTML mock-up.
EDIT: A more simply question: Is it possible to implement a check for each pixel the canvas API should draw to abort drawing the pixel if it doesn't fit some conditions? I don't think that the chance is high that the question becomes affirmed but its really woth it.
I'm currently reading up on the canvas, but I'm finding it hard to find practical benefits of using canvas, when a lot can be done using simple css overlays/JavaScript (+ jquery lib).
This is probably because I don't know the FULL practicalities of using canvas.
Looking at this game:
http://www.pirateslovedaisies.com/
Could someone help explain how and why canvas is being used as opposed to just css?
This is a 4k js/canvas demo I wrote to experiment with the 2d context (here is a video if your browser doesn't work). I tested it only on chrome, opera, firefox, safari and nexus one browser.
Note that no external resources are loaded (i.e. the texture and the raytraced envmap are built dynamically), so this is just a single self-contained 4096 bytes HTML file.
You can do something like that with DIVs?
But indeed I agree that the game you linked IMO could be done also with DIVs; apparently there are no transformations - not even in the falling daisy loading scene - and the action areas for the pirates are just circles. Not sure but could be that even shooting only happens at fixed angles.
Canvas could have been used instead for:
Drawing general sloped lines and polygons (the map could be created dinamically from a compact description or could have been generated randomly). Shooting could be done at any angle...
Procedural image creation (e.g. textures or special pixel effects)
Gradients, texture mapping
General 2d matrix transforms
Of course a game using an image+DIVs approach is probably way easier to make (a lot of photoshop and simple xy animation).
Creating tons of HTML elements is extremely slow and memory-hungry. The canvas object is made for graphics operations and thus optimized for it. Besides that.. how would you draw a curve with plain HTML/CSS? ;)
Using <canvas> you have a per-pixel control of what's shown on the screen. You don't have to deal with specific browser CSS or DOM compatibility.
Also, that's actually a pretty similar programming model to 2D non-browser games, like those created using SDL o DirectDraw.
Here's a game I wrote in a few hours using Canvas; note that the scaling of the tiles, the anti-aliasing of the lines, is perfect. This would not be the case with image tiles that were being resized by the browser.
Click the tiles to rotate them in an attempt to make all connections. Click the row of buttons at the top for a new board of a different size; click the row of buttons below that for a new board with different numbers of connections.
The game concept is not mine, only the implementation.