I'm trying to draw shapes in libgdx that change constantly so I don't think using sprites will work, and I was wondering if it is possible to draw a shape using a function that is called for each pixel to determine if it should be drawn.
What I need to draw is part of a washer (an area bound by two concentric circles and two radiuses), with the circles and radiuses changing constantly.
What I want to know is wether here is a way to draw complex shapes that are determined by a function (the shape would consist of those (x,y) for wich theFunction(x,y)=true) instead of an image
Everything is possible. The best solution really depends on the details of what you want to create. Perhaps you can show an example of what you mean?
Without seeing an example, it looks you might want to start with ShapeRenderer. See the javadocs for detailed information on how to use it. That should get you started and if you find it to be insufficient in some way then you at least you have a more specific question.
Btw, using a Pixmap as suggested by #Ludevik is also possible, but since you want it to change constantly that would imply uploading the entire image each frame which is not very performant.
Would use of Pixmap help?
You can create a pixmap:
Pixmap pixmap = new Pixmap(300, 300, Pixmap.Format.RGBA8888);
and then draw pixels with specific color on that pixmap:
pixmap.drawPixel(x, y, color);
Then you can then create a texture from that pixmap and draw the texture. I'm not sure about the performance of such solution though.
See also Pixmaps in the libgdx wiki.
I'm new to html5. And I'm trying to create a basic painting tool.
What I want to do in this tool is to have one or more shapes(maybe overlapping) and to paint the shapes without getting the colors overlapped. If a circle is drawn inside a rectangle and if I start coloring the circle, the rectangle should not be painted even if the mouse is dragged over it unless the dragging starts inside it.
To achieve this should I use multiple canvases or shapes?
Thanks in advance.
Well, first you need to program in the idea of keeping track of separate shapes. If you haven't already done that see here for a tutorial.
I imagine your shapes will all be kept as images or in-memory canvases themselves. I'm not sure how else you can do it.
There are a million ways you could do this, here's one:
When you start your drawing operation you need to detect which shape you're on. Then you draw that shape to an in-memory canvas and switch that temporary canvas' globalcompositeoperation to source-atop. This will make sure the paint can only paint in the already opaque regions of that shape (if that's your intent here, which it seems to be).
All while you are painting you will want to update the temporary canvas and redraw the main canvas constantly. While you are redrawing the main canvas, instead of painting that shape's image file you'll want to paint the temporary canvas (if you use canvases to keep the shapes you can just update those in real time).
If you are not using temporary canvases for each shape, when you stop the drawing operation you are gonna have to update the image associated with the shape to complete the operation.
Using an in-memory canvas (not added to the DOM) for every shape (that is the size of the shape and no larger) will make coding things slightly easier and might not be that bad on performance. I'd give it a try with 100 and 1000 (or more) in-memory canvases on your targeted platforms to see though.
The alternative is to use one in-memory canvas and have an HTMLImageElement (png) that represents every shape, but using the canvas.toImageURL function can be a bit of a performance hit in itself. I'd try both methods to see which works best in your case. If the shape count is small enough, it probably doesn't matter which.
I have a basic paint application on a canvas, and I want to make a drawing-border and by that create a stencil. In other words, I want to make a shape, and then I want the user to be able to draw only inside it, even when he tries to draw outside.
Do you have any idea how can i do it?
thanks
This can be achieved by making a clipping region. The basic idea is that there is a path on the canvas that all drawing is constrained to.
Make the shape, and instead of calling stroke() or fill(), call clip()
If you don't quite get how clipping regions work, there are a few examples around.
Given an HTML canvas that has already been drawn to, what's the best way to shade the whole canvas except given circular regions? (in context: shadows except where are there light sources)
I was hoping it would be as simple as a rect() followed by subsequent arc()s, but AFAIK there's no way to "remove" those circular sections after the fact. I can get close ( http://jsfiddle.net/mW8D3/2/), but the overlapping regions of circles end up shaded (in XOR fashion, whereas I want OR). Using clip() has the same problem.
I've also tried using globalCompositeOperation but can't quite seem to achieve what I want.
Any ideas?
You could first create the shadow image on a second canvas and knock out holes from it with globalCompositeOperation 'copy' and a transparent fillStyle.
Like this: http://jsfiddle.net/mW8D3/4/
I'm trying to animate a circle and just moving it horizontally which works fine. However while the circle is moving, I have to do a clearRect over that circle so that it redraws it self in the horizontal direction. When I do a clearRect it also makes the background have white box around so effectively its going to be one white horizontal line in the direction the circle is moving.
Is there a way to clear the circle without clearRect?
If I have to keep redrawing the background after clearRect the canvas will flicker when theres say 10 circles moving in that area.
Any other approaches to solving this?
function drawcircle() {
clear();
context.beginPath();
context.arc(X, Y, R, 0, 2*Math.PI, false);
context.moveTo(X,Y);
context.lineWidth = 0.3;
context.strokeStyle = "#999999";
context.stroke();
if (X > 200)
{
clearTimeout(t); //stop
}
else
{
//move in x dir
X += dX;
t = setTimeout(drawcircle, 50);
}
}
function clear() {
context.clearRect(X-R, Y-R, 2*R, 2*R);
}
Basics: HTML5 Canvas as a Non-Retained Drawing Mode Graphics API
First, let us discuss the manner in which the HTML5 Canvas works. Like a real-world canvas with fast-drying oil paints, when you stroke() or fill() or drawImage() onto your canvas the paint becomes part of the canvas. Although you drew a 'circle' and see it as such, the pixels of the circle completely replaced the background (or in the case of anti-aliasing at the edges of the circle, blended with and forever changed them). What would Monet say if you asked him to 'move' one of the people in a painting a little bit to the right? You can't move the circle, you can't erase the circle, you can't detect a mouseover of the circle…because there is no circle, there is just a single 2D array of pixels.
Some Options
If your background is fully static, set it as a background image to your canvas element via CSS. This will be displayed and overlaid with content you draw, but will not be cleared when you clear your canvas.
If you cannot do the above, then you might as well just clear the entire canvas and re-paint it every frame. In my tests, the work needed to clear and redraw just a portion of the canvas is not worth the effort unless redrawing the canvas is very expensive.
For example, see this test: http://phrogz.net/tmp/image_move_sprites_canvas.html
In Safari v5.0.4 I see 59.4fps if I clear and re-draw the entire canvas once per frame, and 56.8fps if I use 20 clearRect() calls and 20 drawImage() calls to re-draw just the dirtied part of the background each frame. In this case it's slower to be clever and keep track of small dirty regions.
As another alternative, use a retained-drawing graphics system like SVG or HTML. With these, each element is maintained independently. You can change the position of the item and it will magically move; it is up to the browser to intelligently draw the update in the most efficient manner possible.
You can do this while retaining the power of custom canvas drawing by creating and layering multiple canvases in the same HTML page (using CSS absolute positioning and z-index). As seen in this performance test, moving 20 sprites via CSS is significantly faster than trying to do it all yourself on a single canvas.
Flickering?
You wrote:
If I have to keep redrawing the background after clearRect the canvas will flicker when theres say 10 circles moving in that area.
That has never been my experience. Can you provide a small example showing this 'flicker' problem you claim will occur (please specify OS, browser, and version that you experience this on)? Here are two comments by prominent browser developers noting that neither Firefox nor Safari should ever show any flickering.
This is actually very easy to accomplish by simply positioning more than one canvas on top of each other. You can draw your background on a canvas that is (wait for it...) in the background, and draw your circles on a second canvas that is in the foreground. (i.e. stacked in front of the background canvas)
Multiple canvases is actually one of the best ways to increase performance of anything animation where elements of the final image move independently and do not not necessarily move in every frame. This allows you avoid redrawing items that have not moved in every frame. However, one thing to keep in mind is that changing the relative depth (think z-index) of items drawn on different canvases now requires that the actual <canvas> elements be reordered in the dom. In practice, this is rarely an issue for 2D games and animations.
Contrary to what the accepted answer suggests; yes, you can restore previous draw states, and contrary to what the other answers imply; no, you don't need additional canvases to do so:
The CanvasRenderingContext2D API includes the functions getImageData() and putImageData(). After creating a background image, store the whole thing in a variable const background = context.getImageData(x, y, width, height) (a simple RGBA bitmap of type Uint8ClampedArray), then after wiping the canvas with clearRect() or whatever, restore the background image simply by passing that variable back in the opposite direction: context.putImageData(x, y, background).
There are two ways you can do it that may reduce the flickering, esp if you have many circles.
One is double buffering, and for a brief question on this you can look at:
Does HTML5/Canvas Support Double Buffering?
Basically, you draw on two canvases, and swap them in and out as needed.
This would be the preferable option, esp with many changes per frame, but, the other way I have done this is to just draw over the circle I want to erase, using the background color, then draw with the correct color the new circle.
The only problem is that there is a small chance that you may leave some evidence of the attempted erasing, as it seems that for some shapes it is hard to get it to draw exactly on top.
UPDATE:
Based on a comment you can look at this discussion about double buffering on the canvas:
HTML canvas double buffering frame-rate issues
The basic idea is to keep track of everything you have drawn, with the current position, then on a separate canvas, you redraw everything, then, flip them out, and then I would just redraw again, in the new positions, to ensure that the image looks exactly like it should. Swapping them in and out is a quick operation, the only problem would be if you put event handlers on the canvas, in this case, have them on the div or span surrounding the canvas, so this information doesn't get lost.