Change an object for a png image on javascript - javascript

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

Related

Html5 Canvas - drawing perfect lines using fabric.js or without

I am creating a game, I need to achieve a perfect canvas line on HTML5 under different types of screen resolutions and zooms.
To easily understand I am talking about, simply paste the two different codes into an HTML file(not jsFiddle, as it is too small to notice):
With fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script src = "https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
new fabric.Canvas('c', { selection: false });
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Without fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Now as you can see, fabric.js removes the blurriness that you get under different kind of browser zooms(Mouse wheel) once the page loads.
I have two problems with it though:
1) Once you click on the canvas the line is gone
2) It's a big framework/library, and I only need it to draw lines(Maybe not if it can achieve the same thing with PNG images)
So, is there a way to achieve the same sharpness result with a clean, short javascript code, without using fabric.js?
If not, how can I fix the clicking problem?
Thanks.
All lines drawn on the canvas are automatically given anti-aliasing to lessen the visual effect of "jaggies". This anti-aliasing also makes the line appear blurry.
If you ONLY are drawing horizontal and vertical lines you can make them crisp:
Before drawing the lines, context.translate(0.50,0.50),
Draw the lines using only integer coordinates,
After drawing the lines, context.translate(-0.50,-0.50),
If you are drawing non-horizontal and non-vertical lines, then you can use Bresenhan's Line Algorithm to draw crisp lines on the canvas by drawing lines pixel-by-pixel. This previous Q&A has example code using Bresenhan's algorithm.

JavaScript: Is it possible to cut a shape out of a rectangle to make a transparent hole in it?

I am trying to make a 2d top-down game in Javascript at the moment. I've currently got a day/night system working where a black rectangle gradually becomes more opaque (as the day goes on) before it finally is fully opaque, simulating the peak of the night where the player can not see.
I want to implement an artificial light system, where the player could use a torch that will illuminate a small area in-front of them. However, my problem is that I don't seem to be able to find a way to 'cut out' a shape from my opaque rectangle. By cutting out a shape, it would look like the player has a torch.
Please find an example mock-up image I made below to show what I mean.
http://i.imgur.com/VqnTwoR.png
Obviously the shape shouldn't be as roughly drawn as that :)
Thanks for your time,
Cam
EDIT: The code used to draw the rectangle is as follows:
context.fillStyle = "#000033";
context.globalAlpha = checkLight(gameData.worldData.time);
context.fillRect(0, 0, 512, 480);
//This is where you have to add the cut out triangles for light!
context.stroke();
Instead of drawing a rectangle over the scene to darken it when the "light" is on, instead draw an image with the "lit" area completely transparent and the rest of the "dark" area more opaque.
One way is to use declare a triangular clipping area and draw your revealed scene. The scene would display only inside the defined clipping area.
Example code and a Demo:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var offset = 50;
var img = new Image();
img.onload = function() {
knockoutAndRefill(50,100,300,50,75,350);
};
img.src = 'http://guideimg.alibaba.com/images/trip/1/03/18/7/landscape-arch_68367.jpg';
function knockoutAndRefill(x0,y0,x1,y1,x2,y2){
context.save();
context.fillStyle='black';
context.fillRect(0,0,canvas.width,canvas.height);
context.beginPath();
context.moveTo(x0,y0);
context.lineTo(x1,y1);
context.lineTo(x2,y2);
context.closePath();
context.clip();
context.drawImage(img,0,0);
context.restore();
}
<canvas id=myCanvas width=500 height=400>

Animating / Move canvas image that has been placed by putImageData

I have a jpeg image that has been decoded, and I am writing it to canvas with putImageData. Is it possible to then move this image around? I cannot find any documentation on it.
The idea is that I will crop a certain part of the decoded image with dirtyX and dirtyY, and now I would like to crop another part of the image. I'm using the decoded image like a spritesheet.
Use the clipping version of drawImage to draw your individual sprites to the canvas
(Don't use getImageData & putImageData for clipping since drawImage is easier and faster.)
If you want to use your decoded image as a spritesheet then you can use the canvas's clipping version of context.drawImage to clip a particular sub-section of your spritesheet and draw it to the canvas.
Here's a previous SO post about the clipping version of drawImage.
HTML / Java Script Canvas - how to draw an image between source and destination points?
Here's example code and a Demo:
Note that the way to "move" sprites on the canvas is to clear the canvas and redraw the desired sprite in it's new position. (You can't "move" an existing drawing on the canvas).
$(window).load(function(){
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// animation related variables
var lastFlap,lastMove;
// define a bird object
// x,y are the position of the bird on the canvas
// spriteX,spriteY is the position of the first desired
// sprite image on the spritesheet
// width,height is the size of 1 sprite image
// currentFrame is the index of which of the sprite images to display
// currentDirection. The sprite plays forward and then backward to
// accomplish 1 flap. This determines if the next frame index will
// be increased (play forward) or decreased (play backward)
var bird={
x:30,
y:30,
spriteX:0,
spriteY:52,
width:51,
height:51,
frames:4,
currentFrame:0,
currentDirection:1
}
// load the spritesheet and start the animation
var spritesheet=new Image();
spritesheet.onload=start;
spritesheet.src="https://dl.dropboxusercontent.com/u/139992952/multple/birdSpritesheet.png";
function start(){
requestAnimationFrame(animate);
}
function animate(time){
// request another animation frame
if(bird.x<canvas.width){
requestAnimationFrame(animate);
}
// if the lastFlap or lastMove times don't aren't set, then set them
if(!lastFlap){lastFlap=time;}
if(!lastMove){lastMove=time;}
// calculate the elapsed times since the last flap and the last move
var elapsedFlap=time-lastFlap;
var elapsedMove=time-lastMove;
// if 50ms have elapsed, advance to the next image in this sprite
if(elapsedFlap>50){
// advance to next sprite on the spritesheet (flap)
bird.currentFrame+=bird.currentDirection;
// clamp bird.currentFrame between 0-3 (0,1,2,3)
// (because there are 4 images that make up the whole bird sprite)
if(bird.currentFrame<0 || bird.currentFrame>bird.frames-1){
bird.currentDirection*=-1;
bird.currentFrame+=bird.currentDirection;
}
// reset the flap timer
lastFlap=time;
}
// locate the current sprite from the spritesheet
var sx=bird.spriteX+bird.currentFrame*bird.width;
var sy=bird.spriteY;
// if 100ms have elapsed, move the bird across the canvas
if(elapsedMove>100){
bird.x+=3;
lastMove=time;
}
// clear the whole canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw the current part of the bird sprite at the current bird.x
ctx.drawImage(spritesheet,
sx,sy,bird.width,bird.height,
bird.x,bird.y,bird.width,bird.height
);
}
}); // end $(function(){});
body{ background-color: white; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>The canvas animating a clipped sprite</h4>
<canvas id="canvas" width=300 height=100></canvas>
<br>
<h4>The spritesheet</h4>
<img id=spritesheet src='https://dl.dropboxusercontent.com/u/139992952/multple/birdSpritesheet.png'>
Yes and No :-)
Since canvas draws in immediate-mode it doesn't know that you have drawn an image on the canvas. So, you cannot draw it on the canvas one single time and move the painted image around. You will have to manually redraw the complete image in each animationframe at a new postion.
You can do that using the requestAnimationFrame() as Jonas Grumann explains.

Rotate image by 90 degrees on HTML5 Canvas

I am having trouble rotating an image using an HTML5 canvas. I suppose that I just have the math wrong, and would appreciate any help in getting this right.
On a mobile device I am capturing a user signature on a 150px by 558px canvas. I am than attempting to create a 558px by 150px image that is just the captured signature rotated 90 degrees. Below is a snippet of the code I've currently come up with. As you can likely surmise, I do not have a good grip on the math going into this. I believe I have the procedure correct, just not the numbers.
What I'm trying to do is:
1) set the center of the canvas to the middle, offsetting by the height and width of my image
2) rotate the canvas by 90 degrees
3) draw the image
4) translate the canvas back.
EDIT: Here's a JSFiddle: http://jsfiddle.net/x9FyK/
var $signature = $("#signature");
var signatureData = $signature.jSignature("getData");
console.log(signatureData);
var img= new Image();
img.onload = function() {
var rotationCanvas = document.createElement('canvas');
rotationCanvas.width = img.height;
rotationCanvas.height = img.width;
var context = rotationCanvas.getContext("2d");
context.translate((rotationCanvas.width/2) - (img.width/2), -(rotationCanvas.height/2) - img.height/4);
context.rotate(Math.PI/2);
context.drawImage(img,0,0);
context.translate(-((rotationCanvas.width/2) - (img.width/2)), -(-(rotationCanvas.height/2) - img.height/4));
var rotatedData = rotationCanvas.toDataURL();
...Handling rotated data here
};
img.src = signatureData;
If I can provide any more information, please let me know.
Thanks in advance for your help,
There are several ways of resetting a transformed (translated+rotated) canvas back to its original state.
Low-Pointer's answer is using context.save to save the context in is original un-transformed state and using context.restore to restore the context to its original state after the drawing is done.
The other way it to undo your transforms in the reverse order that they were performed.
Also, note that context.translate will actually move the canvas origin to the center of the canvas. Since images are drawn from their top-left (not their center), you must offset drawImage by half the image width and height if you want the image centered in the canvas.
Here's and example: http://jsfiddle.net/m1erickson/EQx8V/
// translate to center-canvas
// the origin [0,0] is now center-canvas
ctx.translate(canvas.width/2,canvas.height/2);
// roate the canvas by +90% (==Math.PI/2)
ctx.rotate(Math.PI/2);
// draw the signature
// since images draw from top-left offset the draw by 1/2 width & height
ctx.drawImage(img,-img.width/2,-img.height/2);
// un-rotate the canvas by -90% (== -Math.PI/2)
ctx.rotate(-Math.PI/2);
// un-translate the canvas back to origin==top-left canvas
ctx.translate(-canvas.width/2,-canvas.height/2);
// testing...just draw a rect top-left
ctx.fillRect(0,0,25,10);
this will surely help you >>HTML5 Canvas Rotate Image :)
use some SEPARATE js function for drawing your canvas :
function drawRotated(degrees){
contex_var.clearRect(0,0,canvas.width,canvas.height);
contex_var.save();
contex_var(canvas.width/2,canvas.height/2);
contex_var.rotate(degrees*Math.PI/180);
contex_var.drawImage(image,-image.width/2,-image.width/2);
contex_var.restore();
}
Suppy some angle to any buttonclick function:
$("#clockwise").click(function(){
angleInDegrees+=30;
drawRotated(angleInDegrees);
});

JavaScript Canvas - change the opacity of image

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

Categories

Resources