Rotating and moving object (follow into mouse) - Javascript - javascript

everybody!
I want to make a small tank that will follow the mouse and turn its cannon towards the mouse.
I made a deal following the mouse, but there is no way I can turn the gun towards the mouse.
My code:
// canvas variable
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// browser window size
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
//set canvas size
canvas.width = windowWidth;
canvas.height = windowHeight;
var mouseX = 0;
var mouseY = 0;
var baseAngle = 1;
class Cannon {
constructor(x,y, angle, size, speed){
this.x = x;
this.y = y;
this.angle = angle;
this.size = size;
this.speed = speed;
}
draw() {
// bullet
ctx.setTransform(1, 0, 0, 1, this.x, this.y - (this.size/2));
ctx.translate(this.x, this.y);
ctx.rotate(baseAngle);
ctx.beginPath();
ctx.rect(this.x, this.y - (this.size/2), this.size*2, this.size);
ctx.fillStyle = 'rgb(192,192,192)';
ctx.fill();
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(128,128,128)';
ctx.stroke();
ctx.closePath();
//body
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fillStyle = 'rgb(0,96,255)';
ctx.fill();
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(128,128,128)';
ctx.stroke();
ctx.closePath();
}
update() {
// mooving
var dx = (mouseX - this.x)*.125;
var dy = (mouseY - this.y)*.125;
var dist = Math.sqrt(dx*dx + dy*dy);
if(dist > this.speed){
dx *= this.speed / dist;
dy *= this.speed / dist;
}
this.x += dx;
this.y += dy;
// rootating
baseAngle = Math.atan2(mouseY - this.y, mouseX - this.x);
}
}
const newCannon = new Cannon(80,60, 1, 20, 7);
onmousemove = function(e){
mouseX = e.clientX;
mouseY = e.clientY;
}
function gameUpdate() {
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.clearRect(0, 0, canvas.width, canvas.height);
newCannon.draw();
newCannon.update();
requestAnimationFrame(gameUpdate);
}
gameUpdate();
<!DOCTYPE html>
<html>
<head>
<title>CRUSH DEMO</title>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
The cannon must be rotated in the direction of the mouse (the circle itself must not be rotated).
help me please fix the code!

Related

How to add SVG image to javascript html5 canvas animation?

I currently have a rotating bouncing ball within an html5 canvas and I am looking to insert an SVG image inside the ball that moves and rotates with it
I have this code from researching this but unsure if this is correct
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "";
Does anyone have any suggestion on how I might achieve this?
Here is my code
<canvas id="myCanvas"></canvas>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
// SPEED
var dx = 4;
var dy = -4;
var radius = 120;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = "#9370DB";
ctx.fill();
ctx.closePath();
if (x + dx > canvas.width - radius) {
dx = -dx;
}
if (x + dx < radius) {
dx = -dx;
}
if (y + dy > canvas.height - radius) {
dy = -dy;
}
if (y + dy < radius) {
dy = -dy;
}
x += dx;
y += dy;
}
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
x = canvas.width / 2;
y = canvas.height / 2;
setInterval(draw, 10);
var img = new Image();
img.src = ""; // Put the path to you SVG image here.
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
This should work
One way of doing it would be putting the image hidden in the HTML. In this case the image is an svg as data uri and has an id="apple" and you can say:
var img = apple;
To draw the image inside the ball you need to use the center of the ball, for example like this:
ctx.drawImage(img, x-img.width/2,y-img.height/2)
Also instead of using setInterval I'm using requestAnimationFrame and the image is not getting out of the screen on resize. I hope you will find my answer useful.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var rid = null;// request animation id
// SPEED
var dx = 4;
var dy = -4;
var radius = 120;
var img = apple;// the image is the one with the id="apple"
function draw() {
rid = window.requestAnimationFrame(draw);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = "#9370DB";
ctx.fill();
ctx.closePath();
//draw the image in the center of the ball
ctx.drawImage(img, x-img.width/2,y-img.height/2)
if (x + dx > canvas.width - radius) {
dx = -dx;
}
if (x + dx < radius) {
dx = -dx;
}
if (y + dy > canvas.height - radius) {
dy = -dy;
}
if (y + dy < radius) {
dy = -dy;
}
x += dx;
y += dy;
}
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
//stop the animation
if(rid){window.cancelAnimationFrame(rid); rid= null;}
//get the size of the canvas
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
x = canvas.width / 2;
y = canvas.height / 2;
//restart the animation
draw()
}
window.setTimeout(function() {
resizeCanvas();
window.addEventListener('resize', resizeCanvas, false);
}, 15);
<canvas id="myCanvas">
<img id="apple" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' width='106px' height='122px' viewBox='41 54 106 122'%3E%3Cg%3E%3Cpath fill='%23FFFFFF' stroke='%23ED1D24' stroke-width='2' stroke-miterlimit='10' d='M143.099,93.757c0,0-14.173,8.549-13.724,23.173 c0.449,14.624,11.954,23.413,15.974,24.073c1.569,0.258-9.245,22.049-15.984,27.448c-6.74,5.4-13.714,6.524-24.513,2.25c-10.8-4.275-18.449,0.275-24.749,2.612c-6.299,2.337-13.949-0.137-24.298-14.987c-10.349-14.849-21.823-49.271-6.074-66.146c15.749-16.874,33.298-10.124,38.022-7.875c4.725,2.25,13.05,2.025,22.499-2.25C119.7,77.782,138.374,86.782,143.099,93.757z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='%23FFFFFF' stroke='%23ED1D24' stroke-width='2' stroke-miterlimit='10' d='M118.575,54.609c0,0,0.9,5.625-1.35,10.349 s-10.718,20.936-22.994,17.999c-0.308-0.073-2.102-5.506,0.532-11.027C98.48,64.138,108.171,55.399,118.575,54.609z'/%3E%3C/g%3E%3C/svg%3E" />
</canvas>
Please run the code on full page.

How Can I make a element do something again on click

I need to have my ball jump again when I click, it, but I don't know how to put my functions together to make it do a jump again. Can anyone please help me with this? I repeat, I need the ball to jump agin when I click, and it needs to be able to do this in the air, no bounce needed.
var canvas, ctx, container;
canvas = document.createElement('canvas');
ctx = canvas.getContext("2d");
var ball;
var vy;
var gravity = 0.5;
var bounce = 0.7;
var xFriction = 0.1;
function init() {
setupCanvas();
vy = (Math.random() * -15) + -5;
ball = {
x: canvas.width / 2,
y: 100,
radius: 20,
status: 0,
color: "red"
};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.closePath()
ballMovement();
}
setInterval(draw, 1000 / 35);
function ballMovement() {
ball.y += vy;
vy += gravity;
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
vx *= -1;
}
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
vy *= -bounce;
vy = 0;
if (Math.abs(vx) < 1.1)
vx = 0;
xF();
}
}
function setupCanvas() { //setup canvas
container = document.createElement('div');
container.className = "container";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(container);
container.appendChild(canvas);
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 2;
}
I need it to be able to jump in the air, and it to be able to fall down a gain to a halting stop.

tracking canvas x and y coordinates animation on mousemove event

I am trying to make a circle moving animation with mousemove event, each time the circle will moving from my mouse.x and mouse.ycoordinates on the screen. so I declare my mouse coordinates object and drawCricleobject constructor:
var mouse = {
x:canvas.width/2,
y:canvas.height/2
}
function Circle (x,y,r,dy){
this.x = x;
this.y = y;
this.r = r;
this.dy = dy;
this.update = function(){
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
ctx.fillStyle = 'blue';
ctx.fill();
this.y+=this.dy;
if(this.y<this.r || this.y+this.r>canvas.height){
this.dy=-this.dy;
}
}
}
and after i add the mousemoveevent so i am thinking i can assign the mouse x/y coordinate through my mouvemove eventListenter:
var myCircle = new Circle(mouse.x,mouse.y,30,2);
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
myCircle.update();
requestAnimationFrame(animate);
}
window.addEventListener("mousemove",function(e){
mouse.x = e.clientX;
mouse.y = e.clientY;
animate();
});
the problem is the mouse.xandmouse.yvalue won't change from the original canvas.width/2value, so i have tried to wrapper my animation()function inside the window.addEventListener instead just calling it within, just like:
window.addEventListener("mousemove",function(e){
mouse.x = e.clientX;
mouse.y = e.clientY;
var myCircle = new Circle(mouse.x,mouse.y,30,2);
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
myCircle.update();
requestAnimationFrame(animate);
}
animate();
});
this could work a bit but it looks really stupid and makes my browser comes huge laggy spikes, is there any other way to do this?
You would also need to pass the mouse coordinates when calling the update function ...
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var mouse = {
x: canvas.width / 2,
y: canvas.height / 2
};
function Circle(x, y, r, dy) {
this.r = r;
this.dy = dy;
this.update = function(x, y) {
ctx.beginPath();
ctx.arc(x, y, this.r, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
this.y += this.dy;
if (this.y < this.r || this.y + this.r > canvas.height) {
this.dy = -this.dy;
}
};
}
var myCircle = new Circle(mouse.x, mouse.y, 30, 2);
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
myCircle.update(mouse.x, mouse.y);
requestAnimationFrame(animate);
}
canvas.addEventListener("mousemove", function(e) {
mouse.x = e.offsetX;
mouse.y = e.offsetY;
});
animate();
body{margin:10px 0 0 0;overflow:hidden}canvas{border:1px solid #e4e6e8}
<canvas id="canvas" width="635" height="208"></canvas>

How to use a function to change the property of another function?

I'm quite new to JS and have gone through courses online but, very frustratingly, I just seem to have such a hard time on my own so I'm sorry if this question has an obvious answer. Basically, this program bounces a colored ball around within a box. I want that color to change every time it hits a wall. I figured out a way to do so by putting all information under one function but the tutorial I'm using is saying (for tidy code purposes) that 2 functions will be better and so I really just want to understand how to do what I want to do when info is available in different functions since I know I will have to do that in the future. I will comment important code lines. Thank you so much to anyone who can help.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 4;
var dy = -4;
var ballRadius = 30;
function drawBall() { \\draws the ball
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#ff0000";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
x += dx;
y += dy;
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { \\says when to bounce
dx = -dx;
drawBall.ctx.fillStyle = "#ff0000"; \\this line and next line are lines I wrote
drawBall.ctx.fill(); \\that are obviously incorrect (same goes for
} \\ if statement below). What am I doing wrong?
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
drawBall.ctx.fillStyle = "#0095DD";
drawBall.ctx.fill();
}
}
setInterval(draw, 10);
what you can do is pass parameters that will alter the behavior of the function.
in this case you will be passing the color you want.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 4;
var dy = -4;
var ballRadius = 30;
function drawBall(color) { // draws the ball
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
x += dx;
y += dy;
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { // says when to bounce
dx = -dx;
drawBall("#ff0000");
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
drawBall("#0095DD");
}
}
It seems that you mix some concepts of JavaScript. So for reasons of readability and design, I would create a 'class' for the ball. Something like this:
function Ball(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
You can create an instance of your ball with this:
var ball = new Ball(x, y, radius, color);
and access the properties in Java-style:
ball.color = "#0095DD";
You can also add some methods to your ball:
function Ball(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
You can extend your code with this class and code. I think, you get it.

Particles won't accelerate?

I'm trying to make particles that accelerate using JavaScript and the HTML5 Canvas, but I cannot get them to accelerate, they just move at a constant speed. Does anyone know why?
document.addEventListener("DOMContentLoaded", init);
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
angle = Math.random() * (2 * Math.PI);
pArray = [];
for (i = 0; i<25; i++) {
angle = Math.random() * (2*Math.PI);
pArray[i] = new Particle(Math.cos(angle), Math.sin(angle));
}
setInterval(loop, 50);
}
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (x = 0; x < pArray.length; x++) {
pArray[x].draw();
}
}
function Particle(xVel, yVel) {
this.xVel = xVel;
this.yVel = yVel;
this.x = canvas.width/2;
this.y = canvas.height/2;
this.draw = function() {
this.x += xVel;
this.y -= yVel;
this.yVel += 1;
ctx.beginPath();
ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);
ctx.fillStyle = "rgb(0, 255, 0)";
ctx.fill();
}
}
Your draw function is using the yVel passed to the constructor.
try with this.y += this.yVel;
It looks like your draw function is using the xVel and yVel from the constructor instead of from the particle instance. Try changing this.y += yVel to this.y += this.yVel.
You can create extra variable with name speed and then speed up the balls like this:
function Particle(xVel, yVel) {
this.xVel = xVel;
this.yVel = yVel;
this.speed = 1;
this.x = canvas.width/2;
this.y = canvas.height/2;
this.draw = function() {
this.x += this.speed * this.xVel;
this.y += this.speed * this.yVel;
this.speed++;
ctx.beginPath();
ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);
ctx.fillStyle = "rgb(0, 255, 0)";
ctx.fill();
}
}
Here is example on jsfiddle https://jsfiddle.net/3nnm2omm/

Categories

Resources