As part of my studies i'm modifying some parts in an open-sourced "Pong" game I found online (created by Kushagra Agarwal).
Game's Fiddle
I'm trying to set a nice background image to the game,
that will not disturb the gameplay experience.
I've tried many ways but so far Iv'e only managed to change the background color into a different color, but not to an actual image :
// Function to paint canvas
function paintCanvas() {
ctx.fillStyle = "blue/black/whatever";
ctx.fillRect(0, 0, W, H);
Trying to work out ctx.fillStyle to display an image didn't went well since paintCanvas() is constantly looping, and if gets other value then a "color" string (for example a background image that weighs 500kb) it will create huge delays in the game.
Anyone has an idea?
Thank's,
Roy
I think it looks nice if your just put a background image on the body tag!
<body background="someImage">
</body>
I commented out your paintCanvas(), inserted a clear, and inserted a body tag!
http://jsfiddle.net/XLKFC/11/
// Function to paint canvas
function paintCanvas() {
canvas.width = canvas.width; // Will clear the canvas
//ctx.fillStyle = "blue";
//ctx.fillRect(0, 0, W, H);
}
Related
I am creating a html5 canvas game and the main idea is that there is a loop at every animation that redraws everything on my canvas in every frame.
For some reason the objects drawn don't appear in the order i want them to. i want the background image first, then a rectangle and finally an other image to be shown on top of each other.However, the rectangle blocks the view of the second image not other way around.
my relevant code:
function playerdraw(p){
ctx.rect(p.x,p.y,100,150);
ctx.stroke();
//irrelevant stuff here...
ctx.drawImage(p.im,p.x,p.y+25,100,100);
}
I run the whole thing on window.onload so image loading shoudn't be a problem.
Why is this happening?
(as you haven't provided enough code, I assume this could be the issue.)
You need to redraw the background image each time you run the playerdraw() function (if you're clearing the entire canvas each time). So, the following code should work :
function playerdraw(p) {
// clear entire canvas
ctx.clearRect(...);
// draw background image
ctx.drawImage(...);
// draw rectangle
ctx.rect(p.x, p.y, 100, 150);
ctx.stroke();
// irrelevant stuff here...
// draw other image
ctx.drawImage(p.im, p.x, p.y + 25, 100, 100);
}
Note: You need to clear the entire canvas at the very beginning (if you're doing so). There's is also a possibility that you're doing some kind of canvas translating or scaling stuff which if done in wrong order, things can get pretty messed up.
I now know what my issue was. I forgot to add
ctx.beginPath();
in my code. I called my function again and again and it drew more rectangles then I wanted to. I feel so silly.
I'm trying to use a canvas for two things in my application. First is to display a video on canvas (which I already did). After that, I need to draw squares over this video, and it's in that part that I've got some trouble. When I try to use one canvas over another, the video always stays on top of the squares I'm creating. If i use only one canvas the same thing happens. Can someone help me please?
With canvas it's all about order of operations, in your example you are drawing a video and want the sqaures on top, so you need to draw the squares AFTER you draw the video.
Simple example:
https://jsfiddle.net/a3z5hb45/
ctx.fillStyle = "red"
ctx.fillRect(x, y, 100, 100);
ctx.fillStyle = "blue"
ctx.fillRect(x + 50, y + 50, 100, 100);
Here you see that red goes under blue. Imagine that red is your video, so if you drew something after it will appear above.
If you reverse the order you get this:
https://jsfiddle.net/a3z5hb45/1/
I'm building a website and I need a user to be able to select an image (a transparent gif with black sign on it) and select a color. I have all the gifs in black with transparent background.
How can I change the color of the gif (the black only) to the color the user chose? I was thinking about using a canvas for this but I'm not sure...
You can use a canvas for this. There is no need to iterate the pixel buffer as many suggests and I would recommend avoiding if possible for two reasons:
CORS restriction may apply if image is loaded from a different origin
Performance
There is a much easier way involving composite modes:
Live demo
/// load image here, then:
function render() {
/// this composite mode clears the canvas as well
ctx.globalCompositeOperation = 'copy';
ctx.drawImage(img, 0, 0);
/// this mode fills in whatever, in the image
ctx.globalCompositeOperation = 'source-in';
/// color to change GIF to:
ctx.fillStyle = '#00c';
/// fill color into non-alpha pixels
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
The copy mode works here as the image is the only thing we want to draw to the canvas. If you need to draw in other details as well then use source-over instead and manually clear the canvas using clearRect().
Tip: You can also draw another image on top instead of a fill color.
Original GIF
Changed to blue color
ctx.fillStyle = '#00c';
Changed to red color
ctx.fillStyle = '#c00';
etc.
Assuming that you want to change the color of the black parts of the image (not the transparent parts) you'll have to use canvas to get the black pixels of the image and draw a new image replacing these pixels with the color your user has chosen.
If you want to replace the transparent parts, simply setting a background color using CSS will do the trick.
I'm seeking to create a custom fade in with jQuery or JS. I'd like the fade to be exaggerated and go from very blurry, to pixelated, to then the clear crisp image. On page load, one time.
This is for one image. Yes, tradditionaly done via making an animated gif I suppose. But can I write the effect with jQuery?
On page load. Grabbing the image #div >
Image loads blurry > then pixelates in > and then the clear original HQ image resolves.
To pixelate an image you can use canvas directly in a simple way like this (here assuming image has already been loaded):
/// get a block size (see demo for this approach)
size = blocks.value / 100,
w = canvas.width * size,
h = canvas.height * size;
/// draw the original image at a fraction of the final size
ctx.drawImage(img, 0, 0, w, h);
/// turn off image aliasing (see comment below)
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false; /// future
/// enlarge the minimized image to full size
ctx.drawImage(canvas, 0, 0, w, h, 0, 0, canvas.width, canvas.height);
Here is an online demo.
You can use the slider at the bottom to see various sizes and the speed which would be needed for your transition (use Chrome to see live update when moving the slider) or simply hit the animate button.
As we turn off interpolation (image smoothing) the new enlarged image will appear blocky. This method is also faster than most other approached mainly due to image smoothing can now be turned off in the major browsers.
See this answer for a more complete instruction on how to turn smoothing off in most browsers:
Images in web browser are slightly blurred. How to disable it?
The last drawImage will use a clipped part of the source (here: canvas itself). See here for more details on how to use this method.
As for blur effect I would recommend you to pre-blur the image as this process has a large overhead and the pause will be noticeable on most common computers.
In case you still want to blur the image "live" you can use this stack-blur:
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
You could use Close Pixelate by David DeSandro. The Pixelator is a good example of it in action.
Right now I have one large canvas where everything is drawn. The canvas is created directly in the JS file:
var canvas = document.createElement ("canvas");
var ctx = canvas.getContext("2d");
canvas.width = document.width;
canvas.height = document.height;
document.body.appendChild(canvas);
It resizes itself to the browser window.
I have a gradient background being drawn onto the one canvas along with all the other elements. The colors for the background are randomly generated at each game mode change (eg when the main menu is toggled to the game, then the level end screen, etc). Currently I'm drawing these onto the canvas like this:
var grad1 = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, 500);
grad1.addColorStop(0, bgGradStop1);
grad1.addColorStop(1, bgGradStop2);
ctx.fillStyle = grad1;
ctx.fillRect(0, 0, canvas.width, canvas.height);
I read numerous times that having a separate canvas for the background is better for performance. Is there anything specific that I need to do to make this effective or can I simply create another canvas and draw the background using the same exact code, only modified to use the other canvas, like this:
var grad1 = ctxBg.createRadialGradient(canvasBg.width / 2, canvasBg.height / 2, 0, canvasBg.width / 2, canvasBg.height / 2, 500);
grad1.addColorStop(0, bgGradStop1);
grad1.addColorStop(1, bgGradStop2);
ctxBg.fillStyle = grad1;
ctxBg.fillRect(0, 0, canvasBg.width, canvasBg.height);
Or does getting any performance benefit involve some totally different method of using the second canvas?
Also, if it really is just a matter of doing the exact same thing but on a different canvas, would there be any benefit to also for example moving the HUD text to its own canvas while other entities are moving? Even separating various types of entities onto their own canvases? How far does the benefit of multiple canvases actually stretch?
Or does getting any performance benefit involve some totally different method of using the second canvas?
You've got the right idea of how to do it, though I don't think a second canvas is necessary in your case.
The important thing from a performance perspective is that you don't want to have to keep constructing and filling the gradient. If all you're doing in your draw loop is:
ctx.fillStyle = grad1;
ctx.fillRect(0, 0, canvas.width, canvas.height);
Then you should be pretty swell here. I don't think having a second canvas in the background will help you much after that. There might be a slight performance boost, but who wants to have to keep track of additional DOM elements if you don't have to?
It's a little hard to test the performance of having a second canvas behind your main one, but instead of having two large canvases in the DOM one similar alternative is to draw the gradient an in-memory canvas and always call ctx.drawImage(inMemCan, 0, 0); instead of setting the gradient and drawing it. Drawing images is known to be fast, and using two canvases this way is probably close to the speed you could expect from two on-page canvases (and hopefully it would be faster).
So we could test drawing the gradient from an in-memory canvas to your main canvas versus drawing the plain old gradient. Here's a simple test with a large canvas:
http://jsperf.com/gradient-vs-immemcan
They're pretty equal it seems. If this one thing is the only thing in your background I wouldn't worry about it. There are probably bigger performance fish for you to fry first.
I'd save the benefit of multiple canvases for when a relatively complicated background updates rarely but independently of the foreground. If your background was instead made with 30 gradients and some paths, then using a second canvas (or an in-memory canvas to cache an image) would give you a sizable boost.
It resizes itself to the browser window.
Just a reminder that the full screen API works pretty well in webkit and firefox if you want to look into it in the future.