I'm trying to create a platform game in Canvas. I have main character and some enemies. When player touch enemy, he will lose some HP and he will be untouchable for about 3s. Now I have one problem. After loosing HP, I want to set opacity of character image to 0.5 (to show that untouchable thing).
var mainchar = new Image();
mainchar.src = 'mainch.png';
I don't want to use ctx.globalCompositeOperation = "lighter" or ctx.globalAlpha = 0.5 becouse both of them change the opacity of all elements (it's global). Is there any way to change the image opacity? For example 'mainchar.changeopacity' ?
You have to either change globalAlpha or draw the image to an off-screen canvas that has globalAlpha set, then draw this canvas onto the main canvas.
Just set alpha, draw the image and reset alpha back to full opacity. Setting alpha does not change the content that is already drawn to the canvas - it only applies to the next thing drawn (which would be the image in this case).
And of course, you can always prep your image with an alpha-channel in case of PNG images.
/// only image will have alpha affected:
context.globalAlpha = 0.5;
context.drawImage(image, x, y);
context.globalAlpha = 1.0;
You can also use save and restore.
context.save();
context.globalAlpha = 0.5;
....
context.restore(); //this will restore canvas state
Related
I adapted an open source game to fit for my fantasy book series, Eloik.
This game
I'd like to replace the blue arc for a png image (about same size).
I know I have to draw an image but how to??
Here's the portion of the code :`
// Shield - Boomlight
context.beginPath();
context.strokeStyle = '#0066cc';
context.lineWidth = 10;
context.arc( player.position.x, player.position.y, player.radius,
player.angle + 1.6, player.angle - 1.6, true );
context.stroke();`
I tried that following code but... The png image doesn't appears at the right spot and it's not interactive with the game as the arc...`
<html>
<body>
<img id="boom" width="176" height="134" src="http://eloik.com/wp/wp-
content/uploads/2017/05/BOOMLIGHT-jeu-bd.png" alt="">
*In the Javascript :
<script>
window.onload = function() {
var image = new Image();
image.src="http://eloik.com/wp/wp-content/uploads/2017/05/BOOMLIGHT-jeu-
bd.png";
context.beginPath();
context.drawImage(image, 10, 10);
}
</script>
</body>
</html> `
So now, what's wrong ?
Thanks ! :)
First, in order to use drawImage, we need to load it. You can do it like this:
/* core.js: line 57 */
// Create a handle for the image
var shieldImage;
/* core.js: line 133 */
// Create a new image
shieldImage = new Image();
// When it's loaded, execute animate
shieldImage.onload = animate;
// Set the src
shieldImage.src = "http://eloik.com/wp/wp-content/uploads/2017/05/BOOMLIGHT-jeu-bd.png";
This way, the animate function will only be called once the image has loaded. Then, in order to position your image and rotate it, you can do this:
/* core.js: line 420 */
// Set the origin of the canvas on the player position
context.translate(player.position.x, player.position.y);
// Rotate the canvas
context.rotate(player.angle + Math.PI + .2);
// Draw the shield
context.drawImage(shieldImage, -player.radius, -player.radius, player.radius*1.5, player.radius*2.3);
// Rotate the canvas back
context.rotate(-player.angle - Math.PI - .2);
// Reset the initial origin of the canvas
context.translate(-player.position.x, -player.position.y);
Since we cannot rotate the image itself, we use this trick, which consists in rotating the canvas, drawing, and reverting the rotation of the canvas. We also translate it in order to have the rotation axis on the player position.
You'll also notice I added some numbers in there. That's because your shield image is not a perfect circle. I distorted it so that it does not look weird with the current collision system (which is based on a circle). If you want to keep the oval shape of the image, you'll need to make more serious changes to the rest of the code so that collisions apply to that shape.
And that's it, your blue arc is replaced with your PNG image (Updated JS here)
PS: You have a cool last name ! - same as mine
I have a simple task - I need to draw one rectangle, rotate and copy it and clone its rotated version. I try to do it like so:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//1. rotate canvas
ctx.rotate(-30 * Math.PI / 180);
ctx.rect(10, 60, 80, 40);
ctx.stroke();
//2. copy rotated rectangle
var img = ctx.getImageData(0, 0, 140, 140);
//3. rotate back
ctx.rotate(30 * Math.PI / 180);
//4. draw rotated version of the rectangle
ctx.putImageData(img, 80, 100);
The idea is very simple. At first step I draw a rectangle, at the second step I rotate my canvas and do what I think is a snapshot (or create a copy of my rotated rectangle), at the third step I rotate my canvas back (so my rotated rectangle must not be rotated any longer) and at the final step I add a new object to the canvas - the copy of the rotated rectangle. But this is what I get:
Whereas I expected to get this picture:
What am I doing wrong and how can I get the desired result?
"putImageData is not affected by the transformation matrix"
See here: putImageData() on rotated canvas work incorrect
Instead, if you want a complex image to be copied into memory, and then repeatedly drawn on the screen at different angles, you might consider using a temporary canvas. This post gives a good example:
How to rotate the existing content of HTML5 canvas?
If you need to create multiple image sprites, and creating multiple canvases won't do, consider drawing your sprite to an appropriately sized temporary canvas, and then convert the contents of the temporary canvas to an image using canvas.toDataUrl
The post gives a nice example:
https://davidwalsh.name/convert-canvas-image
Is it possible to give a glow effect to an image automatically, say using canvas?
jsfiddle
The canvas tag would have to omit the transparent
and make it have an outter glow?
<canvas id="canvas" width=960 height=960></canvas>
Make a canvas path glow by applying a series of overlapping shadows with increasing blur
A Demo: http://jsfiddle.net/m1erickson/Z3Lx2/
You can change the styling of the glow by varying the number of overlays and the blur size.
Example code for a glow effect:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// glow
var glowColor="blue";
ctx.save();
ctx.strokeStyle = glowColor;
ctx.shadowColor = glowColor;
ctx.shadowOffsetX=300;
for (var i = 0; i < 10; i++) {
ctx.shadowBlur = i * 2;
ctx.strokeRect(-270, 30, 75, 150);
}
ctx.restore();
To get the outline path of your phone image, you can use the "marching ants" algorithm.
This algorithm will create a path that outlines an image.
In your case you would define the image as all pixels that are not transparent.
Here's a very good implementation of "marching ants" that is used in the excellent d3 library:
https://github.com/d3/d3-plugins/blob/master/geom/contour/contour.js
It's used like this:
DrawImage your phone on the canvas.
// draw the image
// (this time to grab the image's pixel data
ctx.drawImage(img,0,0);
Get the pixel color array from the canvas using ctx.getImageData
// grab the image's pixel data
imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
data=imgData.data;
Define a function that checks the pixel array for non-transparent pixels at any x,y on the canvas.
// This is used by the marching ants algorithm
// to determine the outline of the non-transparent
// pixels on the image
var defineNonTransparent=function(x,y){
var a=data[(y*cw+x)*4+3];
return(a>20);
}
Call the contour function:
// call the marching ants algorithm
// to get the outline path of the image
// (outline=outside path of transparent pixels
var points=geom.contour(defineNonTransparent);
Here's an example result:
the glow is automatically generated using overlapping shadows
the outline path of the phone is calculated using the marching ants algorithm
i want to set transparency for part of canvas
can I use globalAlpha like for all canvas except rectangle i create in the canvas ?
If you mean how to make a rectangle transparent after you have a bunch of things drawn to the canvas you can do the following:
/// clear a rectangle to make canvas transparent
ctx.globalCompositeOperation = 'destination-out';
/// set alpha using a fill color with transparency
ctx.fillStyle = 'rgba(0,0,0,0.5)';
/// fill rectangle which now will become partly transparent all the way
ctx.fillRect(40, 40, 320, 320);
/// reset composite mode
ctx.globalCompositeOperation = 'source-over';
Live demo here
If this is not what you mean then you need to plan your drawings. As mentioned elsewhere you can set globalAlpha before you draw something, draw it, then set globalAlpha back before you draw the next. Each draw after setting globalAlpha will be drawn with that alpha value (if the fill-style, stroke-style of image alpha uses transparency as well that will be a result of the two alpha values as they are multiplied).
globalCompositeOperation decides how it will be drawn, for example on top of existing content, instead of and so forth (see an overview here).
As I've said in the comments twice, you just have to set the global alpha to what you want, draw what you want with that alpha, then change the global alpha to a new value, then draw what you want in that alpha. That can be done as follows
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgba(255, 0, 0,1)';
ctx.fillRect(0, 0, 150, 50);
ctx.globalAlpha = 0.2;
ctx.fillRect(150,50,150,50);
Demo
I've got a canvas that includes images, I'm re-drawing 1 pixel lower each time to give the effect of falling. I've got the images in an array and I just place them 1 pixel lower without recreating the image.
Is it possible to add a border dynamically to images that reach a certain point and if so, how?
Yes, all you have to do is draw a path outside the image and call ctx.stroke() to make the border.
So say the image has the coordinates x and y, with a width and height of w and h, you just do:
ctx.rect(x, y, w, h);
ctx.stroke();
Want a different colored border?
ctx.strokeStyle = 'blue';
Thicker?
ctx.lineWidth = 5;
If you know your images' size and location and as you draw them you probably do, You can use the .rect canvas method to draw a rectangle around the image.