I'm trying to make a moving object on canvas, but each time the set interval goes off it gives me the error: "update is not defined" even though update's definition is right there before init. How do I get set interval to call update correctly?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<meta name="description" content="An HTML5 Test">
<meta name="author" content="William Starkovich">
<link rel="stylesheet" href="css/styles.css?v=1.0">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var angle = 0.0;
var increment = 0.1;
function incrementAngle(angle, increment){
angle += increment;
if(angle > Math.PI * 2)
angle -= (Math.PI * 2);
}
function update(angle, increment){
incrementAngle(angle, increment);
//get a reference to the canvas
var ctx = $('#canvas')[0].getContext("2d");
//draw a circle
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.arc(20, 20, 15, angle, angle + Math.PI, true);
ctx.lineWidth = 5;
ctx.stroke();
ctx.closePath();
}
function init(angle, increment){
update(angle, increment)
setInterval("update(angle, increment)",1000);
}
init(angle, increment);
});
</script>
</head>
<body>
<canvas id="canvas" width="800px" height="100px">
<p>Your browser doesn't support canvas.</p>
</canvas>
</body>
</html>
You appear to be looking to use global variables, so why not go all the way?
http://jsfiddle.net/mblase75/8L62c/3/
var angle = 0.0;
var increment = 0.1;
function incrementAngle() {
angle += increment;
if (angle > Math.PI * 2) angle -= (Math.PI * 2);
}
function update() {
incrementAngle();
//get a reference to the canvas
var ctx = $('#canvas')[0].getContext("2d");
//draw a circle
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.arc(20, 20, 15, angle, angle + Math.PI, true);
ctx.lineWidth = 5;
ctx.stroke();
ctx.closePath();
}
function init() {
update();
setInterval(update, 1000);
}
$(document).ready(function() {
init();
});
Don't use strings in eval because they are executed in global scope and your function is defined in the document.ready handler. Use an anonymous function if you want to provide arguments:
setInterval(function() { update(angle, increment); } ,1000);
Related
hi im a newbie and im currently trying to build an app called sink ships.
I already drew the the circles with a css property and the tanks which look like this <------00000 are also moving with a with javascript I used for that the window.addEventlistener and giving each movement a property case going left right up down. Now I want the circle which symbolices the tanks to move down and up and up again and disappearing when I the bazooka touched the circle (tank) my code looking like this:
let circle = document.getElementById(".circle");
let moveBy = 10;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
window.addEventListener("load", () => {
circle.style.position = "absolute";
circle.style.left = 0;
circle.style.top = 0;
});
window.addEventListener("keyup", (e) => {
switch (e.key) {
case "ArrowLeft":
circle.style.left = parseInt(circle.style.left) - moveBy + "px";
break;
case "ArrowRight":
circle.style.left = parseInt(circle.style.left) + moveBy + "px";
break;
case "ArrowUp":
circle.style.top = parseInt(circle.style.top) - moveBy + "px";
break;
case "ArrowDown":
circle.style.top = parseInt(circle.style.top) + moveBy + "px";
break;
}
});
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
x += dx;
y += dy;
}
setInterval(draw, 10);
.circle {
height: 100px;
width: 100px;
border-radius: 50%;
background-color: rgb(0, 0, 0);
text-align-last: grid;
justify-content: center;
align-items: center;
ast: right;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body style="background-color: rgb(177, 133, 133)">
<canvas id="myCanvas"></canvas>
<div id=".circle"><------000</div>
<div class="circle"></div>
</body>
</html>
Now my question could someone help me with a code that could make my circle move up and down I already copied a code from the internet maybe it could help with the first steps
The question is a little vague to me. I interpret it to mean that you want the large black circle to move up and down, the ASCII art to move with the keyboard, and if the front of the ASCII art touches the big circle, the big circle disappears.
Traditionally, one would write a game for the browser using a canvas object. In your code you have some content that is trying to use a canvas, but since you do not declare a canvas or create a canvas element in javascript, the canvas code is throwing exceptions. My recommendation would be stop using html elements and move to a canvas. However, to keep the answer as close to the origin code as possible, I'll provide some code that uses the original HTML elements followed by a canvas implementation.
Element-base solution
If you want to build the game using just html elements, you would need to make the following changes to your script:
// var canvas = document.getElementById("myCanvas");
// var ctx = canvas.getContext("2d");
// var x = canvas.width/2;
// var y = canvas.height-30;
let x = 100;
let y = 100;
let ticks = 0;
var dx = 2;
var dy = 100;
let bigCircle = document.getElementsByClassName('circle')[0];
// ctx.beginPath();
function drawBall() {
// ctx.arc(x, y, 10, 0, Math.PI*2);
// ctx.fillStyle = "#0095DD";
// ctx.fill();
// ctx.closePath();
}
function styleStringToNumber(string) {
return +(string.substring(0, string.length - 2));
}
function draw() {
//ctx.clearRect(0, 0, canvas.width, canvas.height);
// drawBall();
ticks++;
animatedY = Math.cos(ticks / 100) * 100 + dy;
bigCircle.style.top = animatedY;
let circleBoundary = document.getElementById(".circle").getBoundingClientRect();
let tip = { x: circleBoundary.left, y: (circleBoundary.top + circleBoundary.bottom) / 2 }
let distance = Math.sqrt((styleStringToNumber(bigCircle.style.top) + 50 - tip.y) ** 2 + (styleStringToNumber(bigCircle.style.left) + 50 - tip.x) ** 2)
if (distance < 50)
bigCircle.style.visibility = "hidden"
}
setInterval(draw, 10);
You also have some ill-formatted code in you css. You can resolve the issues to removing the end of the last line so it only reads "align-items: center;" and by appending a final closing curly brace.
Description
Lines that have to do with a canvas have been commented out
We get a reference to the big circle by querying for a list of elements with the class circle and grabbing the first one in the list.
We add a function "styleStringToNumber" that will take the positional data from the big circle's style and convert it from a string with a trailing "px" to a number.
Move the big circle up and down with time. There are many ways to do this. I chose to use a simple trigonometric function since it eases in and out of it's vertical movement.
Get the boundary of the element referenced by circle
Use the Pythagorean theorem to find the distance from the center of the big circle and the left side of the 'circle' bounding box.
If the distance is less than the radius of the big circle, then change the visibility to hidden.
Using a Canvas
If you were to convert to using a canvas, you could reproduce this behavior this:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<style>
html,
body {
overflow: hidden
}
</style>
</head>
<body onkeyup='keyup(event)'>
<canvas id="canv" width=640 height=480></canvas>
<script>
let ctx = document.querySelector("#canv").getContext("2d")
let asciiPosition = { x: 0, y: 10 }
let circlePosition = { x: 0, y: 0 }
let ticks = 0;
let showBigCircle = true;
function main() {
//update and draw every 10ms
setInterval(update, 10)
}
//Change the state of the game
function update() {
ticks++
circlePosition.y = Math.cos(ticks / 100) * 100 + 100;
//Check if they are in collision
let distance = Math.sqrt((asciiPosition.x - (circlePosition.x + 50))**2 + (asciiPosition.y - (circlePosition.y + 50))**2)
if(distance < 50)
showBigCircle = false;
draw();
}
//Draw the game
function draw() {
ctx.fillStyle = "lightgreen";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = "black"
ctx.fillText("<------000", asciiPosition.x, asciiPosition.y)
if (showBigCircle) {
ctx.beginPath();
ctx.arc(circlePosition.x + 50, circlePosition.y + 50, 50, 0, Math.PI * 2);
ctx.fill();
}
}
//Respondto keyboard events
function keyup(e) {
let jump = 10;
switch (e.key) {
case 'ArrowLeft':
asciiPosition.x -= jump;
break;
case 'ArrowRight':
asciiPosition.x += jump;
break;
case 'ArrowUp':
asciiPosition.y -= jump;
break;
case 'ArrowDown':
asciiPosition.y += jump;
break;
}
}
//Start the game loop
main();
</script>
</body>
</html>
I have two circles that same color, and I am trying to figure out find a way to have different color circles on the canvas. I am wondering if I can use the CanvasRenderingContext2D.save() and CanvasRenderingContext2D.restore()
method to create a different color. If the methods work, how can I attempt this?
Edit: I was able to color the circles in different colors after I tried
beginPath, 2. draw 3. closePath 4. set color 5. stroke/fill. Do that for both circles:
that Chris G suggested.
enter code here
var canvas = document.getElementById("canvasGame");
var ctx = canvas.getContext("2d");
var model = {
circle1: { x: 300, y: 200},
circle2: { x: 200, y: 200 }
};
var radius = 50;
function view(ctx, model) {
function circle(c) {
ctx.beginPath();
ctx.save();
ctx.arc(c.x, c.y, radius, 0, 2 * Math.PI, true);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.arc(c.x, c.y, radius, 0, 2 * Math.PI, true);
ctx.fill();
ctx.stroke();
}
// clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle(model.circle1);
circle(model.circle2);
}
function redraw() {
view(ctx, model);
}
redraw();
function getCircleForPosition(x, y) {
function intersect(a, b) {
var d2 = Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
r2 = Math.pow(radius, 2);
return d2 < r2;
}
return [model.circle1, model.circle2].find(circle => intersect(circle, { x, y }));
}
canvas.addEventListener('mousedown', function(e) {
model.dragging = getCircleForPosition(e.pageX, e.pageY);
}, 0);
canvas.addEventListener('mouseup', function() {
model.dragging = undefined;
}, 0);
canvas.addEventListener('mousemove', function(e) {
if (model.dragging) {
model.dragging.x = e.pageX;
model.dragging.y = e.pageY;
redraw();
}
}, 0);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Canvas</title>
</head>
<body>
<canvas id="canvasGame" style='background-color:#EEE;' width='600px' height='500px'>
</canvas>
<div>
<script src="JS/object.js"></script>
</body>
</html>
I've taken nearly every possible countermeasure to prevent my program from drawing two dots instead of one on my chart. I want the dot in the middle to be shown, not the one in the top left. It seems to me the dot is being drawn once in the top left, matching the coordinates and everything, but then it draws a second dot with the translate method. Of course this is just speculation from what's happening on screen. The problem is occurring somewhere in the draw() function, init() function, or the anim() function - I can't pinpoint where the problem is.
let graph = document.getElementById('chart');
let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;
function algebra() {
xVertex = 2 * 10;
yVertex = 5 * 10;
let radius = 3;
let node = [];
function Node(xVertex, yVertex, radius) {
this.r = radius;
this.xV = xVertex;
this.yV = yVertex;
this.draw = function() {
c.beginPath();
c.arc(this.xV, this.yV, this.r, 0, Math.PI * 2, false);
c.fillStyle = "red";
c.fill();
c.translate(377, 377);
c.stroke();
c.closePath();
};
this.update = function() {
this.draw();
};
};
function init() {
node.push(new Node(xVertex, yVertex, radius));
anim();
};
function anim() {
requestAnimationFrame(anim);
for (let i = 0; i < node.length; i++) {
node[i].update(node);
};
c.clearRect(0, 0, graph.width, graph.height);
console.log(node);
};
init();
};
#graph {
left: 100px;
background-color: grey;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Proof of concept </title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="graph">
<canvas id="chart"></canvas>
<div id="y-axis"></div>
<div id="x-axis"></div>
</div>
<div id="button" onclick="algebra()">
<div id="btext">Calculate</div>
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
I think I found your errors:
1) When you call anim() it must first clear the canvas and then redraw all points.
2) Call the next animation frame after all points are drawn on the canvas
And the main problem:
3) You are doing a translate of the canvas origin on each point drawn (and a large one (377, 377)). Since the origin is changing at every iteration or point drawn also the canvas section that is being erased is moving. The two points you got were the first and second iterarions, the others were offscreen.
What you need to do is translate the canvas origin to its middle only once, just after:
let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;
//Translate the origin to the canvas' center (do this only once)
c.translate(graph.width/2, graph.height/2);
If the canvas origin has moved to the center, then you must also erase the canvas from -width/2 to width/2 and height/2 to height/2. To do this you must use:
c.clearRect(-graph.width/2, -graph.height/2, graph.width, graph.height);
Just for fun, I've added three more points to the node array and adding a random number between -1 and 1 to each coordinate in every iteration. This results in a Brownian like motion simulation.
let graph = document.getElementById('chart');
let c = graph.getContext('2d');
graph.height = 754;
graph.width = 754;
//Translate the origin to the canvas' center (do this only once)
c.translate(graph.width/2, graph.height/2);
function algebra() {
//Changed to 0 to plot at center
xVertex = 0;
yVertex = 0;
let radius = 3;
let node = [];
function Node(xVertex, yVertex, radius) {
this.r = radius;
this.xV = xVertex;
this.yV = yVertex;
this.draw = function() {
c.beginPath();
c.arc(this.xV, this.yV, this.r, 0, Math.PI * 2, false);
c.fillStyle = "red";
c.fill();
c.stroke();
c.closePath();
};
this.update = function() {
//this will generate random movement in x and y.
this.xV += Math.random()*2-1;
this.yV += Math.random()*2-1;
this.draw();
};
};
function init() {
node.push(new Node(xVertex, yVertex, radius));
node.push(new Node(xVertex, yVertex, radius));
node.push(new Node(xVertex, yVertex, radius));
node.push(new Node(xVertex, yVertex, radius));
anim();
};
function anim() {
//First clear the canvas then redraw
c.clearRect(-graph.width/2, -graph.height/2, graph.width, graph.height);
for (let i = 0; i < node.length; i++) {
node[i].update(node);
};
//After all are drawn, call the next Animation Frame
requestAnimationFrame(anim);
};
init();
};
#graph {
left: 100px;
background-color: grey;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Proof of concept </title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="graph">
<canvas id="chart"></canvas>
<div id="y-axis"></div>
<div id="x-axis"></div>
</div>
<div id="button" onclick="algebra()">
<div id="btext">Calculate</div>
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
I want the HTML5 canvas to never end so that the square never stops moving, it keeps on "running" so that it can jump over obstacles and the score increases etc. I really do not know how to do this. Please help and thanks in advance. I have posted my code below for everyone to see, I incorporated the JS into the HTML, yep.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<meta charset="UTF-8">
<title>Move Square</title>
</head>
<body>
<div id="centre">
<canvas id="myCanvas" height="100px" width="200px"></canvas>
</div>
<script>
function draw(){
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle = "grey";
ctx.fillRect(0,0,300,300);
ctx.fillRect(0,0,300,300);
ctx.closePath();
x+=dx/4;
//Draw Square
ctx.fillStyle = "red";
ctx.fillRect(x,y,20,20);
clearRect(0, 0, canvas.width, canvas.height);
}
var x = 20;
var y = 20;
var dx = 5;
var dy = 5;
setInterval(draw,10);
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 39) {
x+=dx;
}
}
</script>
</body>
</html>
You need to make every other object on the canvas move backward if you want your block to run endlessly "forward." Of course, to do this you would need to add another object for reference.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<meta charset="UTF-8">
<title>Move Square</title>
</head>
<body>
<div id="centre">
<canvas id="myCanvas" height="100px" width="200px"></canvas>
</div>
<script>
function draw(){
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle = "grey";
ctx.fillRect(0,0,300,300);
ctx.fillRect(0,0,300,300);
ctx.closePath();
//Draw Square
ctx.fillStyle = "red";
ctx.fillRect(x,y,20,20);
//Two extra green squares
ctx.fillStyle = "green";
ctx.fillRect(x2,50,20,20);
ctx.fillRect(x3,50,20,20);
//make them move backwards at the same speed
x2 -= dx/4;
x3 -= dx/4;
}
var x = 20;
var y = 20;
var dx = 5;
var dy = 5;
//X coordinates for green blocks:
var x2 = 50;
var x3 = 250;
setInterval(draw,10);
document.addEventListener("keydown", keyDownHandler, false);
//document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 39) {
x+=dx;
}
}
</script>
</body>
</html>
I am trying to animate a line in HTML5 canvas. The line is supposed to move according to the keyboard strokes (just as the red square). Unfortunately it gets longer but it should just move sideways...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Test</title>
</head>
<body onload="init();">
<canvas id="myCanvas" width="600" height="400">Your browser does not support the canvas tag.</canvas>
<script>
var canvas;
var ctx;
var incrementX = 0;
var x = 250;
var y = 350;
function init() {
// This function is called after the page is loaded
// 1 - Get the canvas
canvas = document.getElementById('myCanvas');
// 2 - Get the context
ctx = canvas.getContext('2d');
// 3 add key listeners to the window element
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
// 4 - start the animation
requestId = requestAnimationFrame(animationLoop);
}
function handleKeydown(evt) {
if (evt.keyCode === 37) {
//left key
incrementX = -1;
} else if (evt.keyCode === 39) {
// right key
incrementX = 1;
}
}
function handleKeyup(evt) {
incrementX = 0;
}
function animationLoop() {
// 1 - Clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2 Draw
drawLine(x, y);
// 3 Move
x += incrementX;
// call again mainloop after 16.6 ms (60 frames/s)
requestId = requestAnimationFrame(animationLoop);
}
function drawLine(x, y) {
ctx.save();
ctx.translate(x, y);
ctx.moveTo(0,0);
ctx.lineTo(100,0);
ctx.stroke();
ctx.fillStyle='red';
ctx.fillRect(35,30,20,20);
ctx.restore();
}
</script>
</body>
</html>