This is my first posted question, so be gentle lol. I am trying to make a little game that will display different animated sprites on a canvas element that is laid over a user's webcam feed. Right now I am just working with one sprite to get the functionality right. I only want the sprite to appear and follow the mouse when left-click is held down. Right now the sprite appears on mousedown and animates, but disappears if I move the mouse instead of following. I only want it to disappear on mouseup. I have looked all over for the answer, but haven't been able to find one. Here is the js I have:
'use strict';
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const errorMsgElement = document.querySelector('span#errorMsg');
canvas.width = window.innerWidth;
canvas.height =window.innerHeight;
const constraints = {
// audio: true,
video: {
// width: 1280, height: 720
width: window.innerWidth,
height: window.innerHeight
}
};
// Access webcam
async function init() {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
// Success
function handleSuccess(stream) {
window.stream = stream;
video.srcObject = stream;
}
// Load init
init();
//Code for drawing sprite on Canvas
var image = new Image();
image.src = "Starsprite.png";
var ctx = canvas.getContext("2d");
let magic = false;
var spriteWidth = 187;
var spriteHeight = 60;
var rows = 1;
var cols = 3;
var width = spriteWidth/cols;
var height = spriteHeight/rows;
var curFrame = 0;
var frameCount = 3;
let x =0;
let y =0;
var srcX=0;
var srcY=0;
function startPosition(e){
magic =true;
x =e.clientX;
y =e.clientY;
}
function movePosition(e){
ctx.clearRect(x,y,width,height);
x =e.clientX;
y =e.clientY;
}
function endPosition(){
magic =false;
ctx.clearRect(x,y,width,height);
}
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mousemove",movePosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousedown",draw);
function updateFrame(){
curFrame = ++curFrame % frameCount;
srcX = curFrame * width;
}
function draw(){
if (!magic) return;
ctx.clearRect(x,y,width,height);
updateFrame();
ctx.drawImage(image,srcX,srcY,width,height, x,y,width,height);
console.log(x + ", " + y);
}
setInterval(draw,200);
The movePosition function does update the x & y coordinates, but the sprite doesn't show while the mouse is moving. I tried creating an event listener to run the draw function on mousemove, but it messes up the animation because it fires every time the browser updates the mouse position. Any ideas on tackling this problem?
Ok, so I have worked some more on it and animated the movement instead of trying to call the function over again. I based this on instructions for animating keystroke inputs. It works fairly well, but if I move the mouse very quickly to a new position it doesn't follow it all the way.
//Code for drawing on Canvas
var image = new Image();
image.src = "Starsprite.png";
var ctx = canvas.getContext("2d");
let magic = false;
var spriteWidth = 187;
var spriteHeight = 60;
var rows = 1;
var cols = 3;
var width = spriteWidth/cols;
var height = spriteHeight/rows;
var curFrame = 0;
var frameCount = 3;
let x =0;
let y =0;
let mousex =0;
let mousey =0;
var stillx =0;
var stilly =0;
var srcX=0;
var srcY=0;
var left =false;
var right =false;
var up = false;
var down = false;
var speed = 60;
var lift = 30;
var buffer = 100;
function startPosition(e){
magic =true;
x =e.clientX;
y =e.clientY;
}
function moveDirection(e){
stillx = x + buffer;
stilly = y + buffer;
mousex = e.clientX;
mousey = e.clientY;
if(mousex>stillx){
left = false;
right = true;
}
if(mousex<stillx){
left = true;
right = false;
}
if(mousey>stilly){
down = true;
up = false;
}
if(mousey<stilly){
down = false;
up = true;
}
}
function endPosition(){
magic =false;
ctx.clearRect(x,y,width,height);
}
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mousemove",moveDirection);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousedown",draw);
function moveSprite(){
if(right && x<canvas.width-width){
x+=speed;
// x+=speed;
right =false;
}
if(left && x>0){
x-=speed;
left=false;
}
if(down && y<canvas.height-height){
y+=lift;
down=false;
}
if(up && y>0){
y-=lift;
up=false;
}
}
function updateFrame(){
curFrame = ++curFrame % frameCount;
srcX = curFrame * width;
moveSprite();
}
function draw(){
if (!magic) return;
ctx.clearRect(x,y,width,height);
updateFrame();
ctx.drawImage(image,srcX,srcY,width,height, x,y,width,height);
}
setInterval(draw,200);
If anyone has a better solution please let me know!
Related
I am trying to create a paint like application using canvas. I am able to draw with free hand tool but when i try to using shapes we need to use clearrect method which i am not able to use properly. I need to draw multiple shapes on canvas with mouse but unable to do so.
Here is a link to what i am trying
http://jsfiddle.net/6vq64sdh/
HTML:
<canvas width="800px" height="600px" id="drawing"></canvas>
JS
var isDown;
var start;
var end;
var canvasEl = document.getElementById("drawing");
var draw = canvasEl.getContext("2d");
draw.lineWidth = "2";
draw.strokeStyle = "blue";
var lastWidth = 0;
var lastHeight = 0;
$("#drawing").mousedown(function(e) {
isDown = true;
start = getMousePos(canvasEl, e);
end = getMousePos(canvasEl, e);
lastWidth = 0;
lastHeight = 0;
e.preventDefault();
});
$("#drawing").mouseup(function() {
isDown = false;
});
$("#drawing").mousemove(function(e) {
if (!isDown) return;
var end = getMousePos(canvasEl, e);
var h = end.y - start.y;
var w = end.x - start.x;
draw.clearRect(start.x-5, start.y-5, lastWidth + 6, lastHeight + 6);
draw.beginPath();
draw.rect(start.x, start.y, w, h);
lastWidth = w;
lastHeight = h;
draw.stroke();
draw.closePath();
});
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor(evt.clientX - rect.left),
y: Math.floor(evt.clientY - rect.top)
};
}
in above link able to draw multiple rectangles when i tried to drag mouse right side but unable to do when i drag it to left side. Could you please
I have just a little bit improved your code. It looks like you having some trouble when you trying to draw new rectangle over an already exists one.
I make a variable that will store the drawed rectangles. (Its like browser's brain) And the bottom of code, i created a setInterval() function that re-draw your rectangles that in the brain variable in 60fps.
var drawed_objects = []; //our brain variable
var isDown;
var start;
var end;
var canvasEl = document.getElementById("drawing");
var draw = canvasEl.getContext("2d");
draw.lineWidth = "2";
draw.strokeStyle = "blue";
var lastWidth = 0;
var lastHeight = 0;
$("#drawing").mousedown(function(e) {
isDown = true;
start = getMousePos(canvasEl, e);
end = getMousePos(canvasEl, e);
lastWidth = 0;
lastHeight = 0;
e.preventDefault();
});
$("#drawing").mouseup(function() {
drawed_objects.push({start:start,width:w,height:h});
isDown = false;
});
$("#drawing").mousemove(function(e) {
if (!isDown) return;
end = getMousePos(canvasEl, e);
h = end.y - start.y;
w = end.x - start.x;
draw.clearRect(start.x-5, start.y-5, lastWidth + 6, lastHeight + 6);
draw.beginPath();
draw.rect(start.x, start.y, w, h);
lastWidth = w;
lastHeight = h;
draw.stroke();
draw.closePath();
});
//in here we drawing old rectangles again again again..
//and all time clearing the canvas
setInterval(function(){
draw.clearRect(0,0,draw.canvas.width,draw.canvas.height);
for( let i=0; i <drawed_objects.length; i++ )
{
var obj = drawed_objects[i];
draw.beginPath();
draw.rect(obj.start.x, obj.start.y, obj.width, obj.height);
draw.stroke();
draw.closePath();
}
},1000/60);
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor(evt.clientX - rect.left),
y: Math.floor(evt.clientY - rect.top)
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas width="800px" height="600px" id="drawing"></canvas>
I'm trying to get an image in a canvas to move back and forth using setInterval. I've been struggling find the solution with no avail. Can anyone figure out the problem?
Here's my code:
...
var img = new Image;
var url = ["sprite-right.png","sprite-left.png"];
var ctx2;
for (i=0; i<3; i++) {
img.src = url[i];
}
img.onload = function() {
start();
}
function start() {
var canv2 = document.getElementById("canvas2");
ctx2 = canv2.getContext("2d");
var x = 50, y = 100;
var direction = "right";
var interval = setInterval(function() {
if (direction == "right") {
img.src=url[0];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x++;
if (x>690) {
direction = "left";
} // end if
} else if (direction == "left") {
img.src=url[1];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x--;
if (x<50) {
direction = "right";
} // end if
} // end if
},1); // end set interval
} // end function
Your code is infinite-looping.
(Working plunkr)
Everytime your Image loads, it runs the 'start' function; however, that function changes the image url, so it loads again, which runs the 'start' function, etc.
I got your code running by making multiple Images instead of using just one; this way, the Image isn't constantly reloading.
Notable changes were the addition of the 'img2' variable and reordering the code; everything else was fine the way it was.
var img = new Image(),
img2 = new Image();
var url = ["https://www.google.com/images/srpr/logo11w.png","http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/220px-Smiley.svg.png"];
var ctx2;
function start() {
console.log('whirrr');
var canv2 = document.getElementById("canvas2");
ctx2 = canv2.getContext("2d");
var x = 50, y = 100;
var direction = "right";
var interval = setInterval(function() {
if (direction == "right") {
//img.src=url[0];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img, x, y);
x++;
if (x>690) {
direction = "left";
} // end if
} else if (direction == "left") {
//img.src=url[1];
ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
ctx2.drawImage(img2, x, y);
x--;
if (x<50) {
direction = "right";
} // end if
} // end if
},1); // end set interval
} // end function
img.onload = function() {
start();
}
//for (i=0; i<3; i++) {
// img.src = url[i];
//}
img.src = url[0];
img2.src = url[1];
So I want to create a drawing app, and I did, I am able to change brush size and brush color, however, I want to save the stuff I draw including the brush size and the brush color. I am able to store the point I have drawn on the canvas now, but not the brush size and color.
var canvas;
var context;
var color = "black";
var brushSize = 13;
var mouseDown = false;
window.onload = function init() {
//Brush Size
var bigBrushSize = document.getElementById("bigBrush");
bigBrushSize.onclick = handleBigBrushclicked;
var mediumBrushSize = document.getElementById("mediumBrush");
mediumBrushSize.onclick = handleMediumBrushclicked;
var smallBrushSize = document.getElementById("smallBrush");
smallBrushSize.onclick = handleSmallBrushclicked;
//Brush Color
var redBrushColor = document.getElementById("red");
redBrushColor.onclick = handleRedBrushColorclicked;
var blueBrushColor = document.getElementById("blue");
blueBrushColor.onclick = handleBlueBrushColorclicked;
var yellowBrushColor = document.getElementById("yellow");
yellowBrushColor.onclick = handleYellowBrushColorclicked;
var greenBrushColor = document.getElementById("green");
greenBrushColor.onclick = handleGreenBrushColorclicked;
//Clear Button
var clearButton = document.getElementById("clearButton");
clearButton.onclick = handleClearButton;
canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
canvas.onmousedown = handleMouseDown;
canvas.onmouseup = handleMouseUp;
canvas.onmousemove = handleMouseMove;
var coords = localStorage["coords"];
if (coords) {
coords = JSON.parse(coords);
for (var i = 0; i < coords.length; i = i + 2) {
paintToCanvas(coords[i], coords[i + 1]);
}
}
}
function handleClearButton() {
context.clearRect(0, 0, canvas.width, canvas.height);
localStorage.removeItem("coords");
}
function handleMouseDown(event) {
paintFromMouse(event);
mouseDown = true;
}
function handleMouseUp(event) {
mouseDown = false;
}
function handleMouseMove(event) {
if (mouseDown) {
paintFromMouse(event);
}
}
// Bursh Size Start
function handleBigBrushclicked() {
brushSize = 32;
}
function handleMediumBrushclicked() {
brushSize = 16;
}
function handleSmallBrushclicked() {
brushSize = 6;
}
// Brush Size Ends
function paintFromMouse(event) {
var x = event.clientX - canvas.offsetLeft;
var y = event.clientY - canvas.offsetTop;
paintToCanvas(x, y);
var coords = localStorage["coords"];
if (coords) {
coords = JSON.parse(coords);
} else {
coords = [];
}
coords.push(x);
coords.push(y);
localStorage.setItem("coords", JSON.stringify(coords));
}
//color change starts
function handleRedBrushColorclicked() {
color = "red";
}
function handleBlueBrushColorclicked() {
color = "blue";
}
function handleGreenBrushColorclicked() {
color = "green";
}
function handleYellowBrushColorclicked() {
color = "yellow";
}
// color change ends
function paintToCanvas(x, y) {
context.fillStyle = color;
context.fillRect(x - brushSize / 2, y - brushSize / 2, brushSize, brushSize);
So here I used the local storage to store brush size and color, the alert shows it seems to work, but I still don't know how to actually store them, which means, if I refresh my page, nothing changes on my canvas.
var storeColorAndBrush = [color " ", brushSize]
var store = storeColorAndBrush
localStorage.setItem("store",store)
alert(localStorage.store);
}
Thank you very much, I am a beginner.
This is how I would do it: I would add a "save" button which, when clicked, stores the whole image and the current brush size and color. When you load the page you draw the stored image in the canvas and set the brush size and color:
$('.save').on('click',function() {
var data = context.getImageData(x, y, img.width, img.height).data;
localStorage.setItem('image', data); // save image data
localStorage.setItem('brushSize', brushSize);
localStorage.setItem('color', color);
});
on load:
brushSize = localStorage.getItem('brushSize');
color = localStorage.getItem('color');
var picture = localStorage.getItem('image');
context.putImageData(picture, 0, 0);
I'm trying to get mouse input in my game; any help would be appreciated.
I call the event listeners in my init() function, and I have both my mouseMoved() and mouseClicked() functions. But I just haven't been able to get any response.
(I was asked to make a jsFiddle for this project, so here it is. It's not rendering the images, for some reason. But once there's input, there should be text on the top left the shows the mouse coordinates. Also, when you click on the canvas, you should get an alert.)
var canvasBg = document.getElementById('canvasBg');
var ctxBg = canvasBg.getContext('2d');
var canvasEntities = document.getElementById('entities');
var entitiesCtx = canvasEntities.getContext('2d');
var isPlaying = false;
var player;
var enemy;
var mouseX, mouseY;
var playerImg = new Image();
playerImg.src = 'http://placekitten.com/g/50/50';
var enemyImg = new Image();
enemyImg.src = 'http://placehold.it/50x50';
window.onload = init;
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
// main functions
function init() {
console.debug('init()');
player = new Entity(250, // xpos
225, // ypos
0, // xd
0, // yd
3, // speed
50, // width
50, // height
playerImg, // imgSrc
true); // player?
enemy = new Entity(500,225,0,0,1,25,25,enemyImg,false);
canvasBg.addEventListener('mousemove', mouseMoved, false);
canvasBg.addEventListener('click', mouseClicked, false);
startLoop();
}
function loop() {
// console.debug('game loop');
if(isPlaying){
update();
draw();
requestAnimFrame(loop);
}
}
function startLoop() {
isPlaying = true;
loop();
}
function stopLoop() {
isPlaying = false;
}
function clearAllCtx() {
ctxBg.clearRect(0, 0, canvasBg.width, canvasBg.height);
Entity.clearCtx();
}
function draw(){
clearAllCtx();
player.draw();
enemy.draw();
}
function update(){
player.update();
}
// end of main functions
// input handling
function mouseMoved(e) {
mouseX = e.layerX - canvasBg.offsetLeft;
mouseY = e.layerY - canvasBg.offsetTop;
document.getElementById('mouseCoors').innerHTML = 'X: ' + mouseX + ' Y: ' + mouseY;
}
function mouseClicked(e) {
alert('You clicked the mouse!');
}
// end of input handling
// Entity functions
function Entity(xpos, ypos, xd, yd, speed, width, height, imagesrc, player) {
this.xpos = xpos;
this.ypos = ypos;
this.xd = xd;
this.yd = yd;
this.speed = speed;
this.width = width;
this.height = height;
this.imagesrc = imagesrc;
this.player = player;
}
Entity.clearCtx = function(){
entitiesCtx.clearRect(0,0,canvasBg.width,canvasBg.height);
};
Entity.prototype.draw = function () {
entitiesCtx.drawImage(this.imagesrc, this.xpos, this.ypos);
};
Entity.prototype.update = function () {
this.xpos += this.xd;
this.ypos -= this.yd;
};
// end of Entity functions
So theres a few things going on, first the fiddle loading was set incorrectly, once I changed it to no wrap in body everything works.
The actual issue you're having is due to the background canvas being under the entities canvas, so it cant get any of the mouse events.
One solution would be to use pointer-events and set it to none like so pointer-events: none on the entities canvas.
Live Demo
#entities {
margin: -500px auto;
pointer-events: none;
}
Another option if you need wider browser support is to have the entities canvas capture the mouse events instead.
Live Demo of Option 2
I'm beginning with an isometric game, and my canvas is blinking(Not in IE) when draws all the parts of the ground. When I set fps to 20 or less, the blinking stops. How can I solve that? Any ideas?
var camerax = 300, cameray = 100;
var fps = 60;
function draw() {
clearCanvas();
drawGround();
}
function drawGround() {
var img = new Image();
img.onload = function() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
img.src = "ground.png";
}
var loop = setInterval(function() {
update();
draw();
}, 1000/fps);
Right now you're reloading the image every frame and unless the onload callback fires within the 16ms of the frame you're going to see a blank canvas.
You should only need to call the new Image, img.onload sequence once, to preload your images. The onload callback would then kick off your first frame, and the draw calls are free to use the image in memory.
Something like:
var camerax = 300, cameray = 100;
var fps = 60;
var img;
var loop;
function init() {
img = new Image();
img.onload = function() {
loop = setInterval(function() {
update();
draw();
}, 1000/fps);
};
img.src = "ground.png";
}
function draw() {
clearCanvas();
drawGround();
}
function drawGround() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
}
Of course, it gets more complex once you're waiting for multiple images to preload since you need to start the loop only once all of them are done.
Nice tip, freejosh! Thanks! My screen now is not blinking and the code result was that:
var canvas = document.getElementById("game");
var ctx = canvas.getContext("2d");
var camerax = 300, cameray = 100;
var fps = 60;
var img;
var loop;
function update() {
}
function draw() {
clearCanvas();
drawGround();
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function drawGround() {
var width = img.width;
var height = img.height;
for (var x = 0; x < 3; x++) {
for (var y = 3; y >= 0; y--) {
mx = (x-y)*height + camerax;
my = (x+y)*height/2 + cameray;
ctx.drawImage(img, mx, my);
}
}
}
function init() {
img = new Image();
img.onload = function() {
drawGround();
};
img.src = "ground.png";
}
function keyListener(e){
e = e || window.event
if(e.keyCode==37){
camerax--;
}
else if(e.keyCode==39){
camerax++;
}
else if(e.keyCode==38){
cameray--;
}
else if(e.keyCode==40){
cameray++;
}
}
window.onkeypress = function(e) {
keyListener(e);
}
init();
var loop = setInterval(function() {
update();
draw();
}, 1000/fps);