The script below draws 4 curved rectangles with images in them. It draws them all at once despite using a setInterval of 2500 milliseconds before calling the function that draws them. I would like the first rectangle (i.e. top-left) to be drawn immediately, and then the other rectangles to be drawn after that one (with one being drawn every 2.5 seconds). Why does this function not do this and how can it be done? Any help will be appreciated.
var c=document.getElementById('game'),
ctx=c.getContext('2d');
var images = ['https://i.stack.imgur.com/tXmPa.png', 'https://i.stack.imgur.com/KGhCL.png', 'https://i.stack.imgur.com/s5xu4.png', 'https://i.stack.imgur.com/g6BO0.jpg']
var curvedRect = function(id, selectionnum, x, y, w, h) {
this.id = id;
this.selectionnum = selectionnum;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
curvedRect.prototype.makeCurvedRect = function() {
var img=new Image();
img.src=images[this.selectionnum];
ctx.beginPath();
ctx.lineWidth='8';
ctx.strokeStyle='white';
ctx.moveTo(this.x+10, this.y);
ctx.lineTo(this.x+this.w-10, this.y);
ctx.quadraticCurveTo(this.x+this.w, this.y, this.x+this.w, this.y+10);
ctx.lineTo(this.x+this.w, this.y+this.h-10);
ctx.quadraticCurveTo(this.x+this.w, this.y+this.h, this.x+this.w-10, this.y+this.h);
ctx.lineTo(this.x+10, this.y+this.h);
ctx.quadraticCurveTo(this.x, this.y+this.h, this.x, this.y+this.h-10);
ctx.lineTo(this.x, this.y+10);
ctx.quadraticCurveTo(this.x, this.y, this.x+10, this.y);
ctx.stroke();
ctx.drawImage(img, this.x+2.5, this.y+2.5, this.w-5, this.h-5);
}
var Paint = function(element) {
this.element = element;
this.shapes = [];
}
Paint.prototype.addShape = function(shape) {
this.shapes.push(shape);
}
Paint.prototype.render = function() {
ctx.clearRect(0, 0, this.element.width, this.element.height);
for (var i=0; i<this.shapes.length; i++) {
try {
setInterval(this.shapes[i].makeCurvedRect(), 2500);
}
catch(err) {}
}
}
var paint = new Paint(c);
var img1 = new curvedRect(1, 0, 200, 55, 150, 150);
var img2 = new curvedRect(2, 1, 375, 55, 150, 150);
var img3 = new curvedRect(3, 2, 200, 230, 150, 150);
var img4 = new curvedRect(4, 3, 375, 230, 150, 150);
paint.addShape(img1);
paint.addShape(img2);
paint.addShape(img3);
paint.addShape(img4);
paint.render();
canvas {
z-index: -1;
margin: 1em auto;
border: 1px solid black;
display: block;
background: #FF9900;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='game.css' media='screen'></style>
</head>
<body>
<canvas id="game" width = "750" height = "500"></canvas>
</body>
</html>
Replace
setInterval(this.shapes[i].makeCurvedRect(), 2500);
which executes makeCurvedRect() immediately and supplies setInterval() with the return value with a bound function
setTimeout(curvedRect.prototype.makeCurvedRect.bind(this.shapes[i]), 2500 * i);
or a fat arrow function
setTimeout(() => this.shapes[i].makeCurvedRect(), 2500 * i);
where the delay increases by 2500 for each rectangle.
Related
I'm doing the typical Pong game with just HTML canvas and JavaScript, but I've been stuck on this issue for a while now. I have checked similar Stackoverflow questions, but none of the answers worked for me.
Basically I have a window.onload function that renders the game (draw and move) every second. The ball moves, but draws a replica of itself with each movement. I think it's got something to do with the fact that I'm rendering both things each second, but I can't figure it out.
var framesPerSecond = 60;
setInterval(function() {
drawGame();
move();
}, 1000/framesPerSecond);
Here's the Fiddle.
Thanks.
Canvas needs to be cleared before redrawing:
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
Otherwise, it would keep modifying existing canvas state
See in action - https://jsfiddle.net/ew2d1quL/2/
You have to redraw from beginning or you save another canvas/image somewhere and draw this first before you draw the rest of the game
var canvas;
var canvasContext;
var printScore = document.createElement("p");
var score = 0;
window.onload = function() {
canvas = document.getElementById("gameCanvas");
canvasContext = canvas.getContext('2d');
var framesPerSecond = 60;
setInterval(function() {
drawGame();
move();
}, 1000/framesPerSecond);
var leftPaddle = {
x: 0,
y: (canvas.height/2) - 50,
width: 10,
height: 100,
color: "yellow",
score: 0
}
var rightPaddle = {
x: canvas.width - 10,
y: (canvas.height/2) - 50,
width: 10,
height: 100,
color: "yellow",
score: 0
}
var ball = {
x: canvas.width/2,
y: canvas.height/2,
radius: 9,
color: "white",
speed: 5,
velocityX: 5,
velocityY: 5,
}
function drawGame() {
// redraw background
canvasContext.fillStyle = 'black';
canvasContext.fillRect(0, 0, canvasContext.canvas.width, canvasContext.canvas.height);
drawRect(leftPaddle.x, leftPaddle.y, leftPaddle.width, leftPaddle.height, leftPaddle.color);
drawRect(rightPaddle.x, rightPaddle.y, rightPaddle.width, rightPaddle.height, rightPaddle.color);
drawCircle(ball.x, ball.y, ball.radius, ball.color);
}
function drawRect(x, y, w, h, color) {
canvasContext.fillStyle = color;
canvasContext.fillRect(x, y, w, h);
}
function drawCircle(x, y, r, color) {
canvasContext.fillStyle = color;
canvasContext.beginPath();
canvasContext.arc(x, y, r, 0, Math.PI*2, false);
canvasContext.fill();
canvasContext.closePath();
}
function move() {
ball.x += ball.velocityX;
ball.y += ball.velocityY;
if ( (ball.y + ball.radius > canvas.height ) || (ball.y - ball.radius < 0) ) {
ball.velocityY =- ball.velocityY;
} else if ( (ball.x + ball.radius > canvas.width ) || (ball.x - ball.radius < 0)) {
ball.velocityX =- ball.velocityX;
}
drawGame();
}
}
canvas {
margin-top: 0px auto;
border: 2px solid black;
background-color: black;
border-radius: 10px;
display: block;
width: 50%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Pong</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script src='main.js'></script>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
</body>
</html>
I wrote the following code on my text editor:
!DOCTYPE html><html><head><script>
window.onload = function()
{
canvas = document.getElementById("canvasArea");
context = canvas.getContext("2d");
var smallIMage = new Image();
smallImage.src = "https://vignette.wikia.nocookie.net/cardfight/images/8/89/De.jpg/revision/latest?cb=20130414214050";
smallImage.onload = function()
{
context.shadowOffsetX = 4;
context.shadowOffsetY = 4;
context.shadowBlur = 20;
context.shadowColor = "lavender";
context.strokestyle = "gray";
context.lineWidth = 1;
var repeatPattern = context.createPattern(smallImage, "repeat");
var noRepeatPattern = context.createPattern(smallImage, "no-repeat");
var repeatXPattern = context.createPattern(smallImage, "repeat-x");
var repeatYPattern = context.createPattern(smallImage, "repeat-y");
context.fillStyle = repeatPattern;
context.fillRect (125, 125, 325, 325);
context.strokeRect (125, 125, 325, 325);
context.fillStyle = noRepeatPattern;
context.fillRect (0, 0, 100, 100);
context.strokeRect (0, 0, 100, 100);
context.fillStyle = repeatXPattern;
context.fillRect (125, 0, 350, 100);
context.strokeRect (125, 0, 350, 100);
context.fillStyle = repeatYPattern;
context.fillRect (0, 125, 100, 350);
context.strokeRect (0, 125, 100, 350);
}
}
</script></head><body>
<div style = "width:500px; height:500px;
margin:0 auto; padding:5px;">
<canvas id = "canvasArea"
width = "500" height = "500"
style = "border:2px solid black">
Your browser doesn't currently support HTML5 canvas.
</canvas>
</div>
</body>
</html>
This code s supposed to create a pattern from an online image, but it's not showing as the canvas is completely blank. Can you please tell me what I did wrong.
There wasn't much wrong with your code apart from correcting a few spelling inconsistencies and defining the new Image() event handler before assigning it's .src property. Also, remember to declare the charset of the document in the head section of the file. E.G...
<head>
<meta charset="utf-8">
... etc ...
</head>
Anyway, after a little editing the major components of your page look like this.
document.addEventListener('DOMContentLoaded', function() {
var canvas = document.getElementById("canvasArea"),
ctx = canvas.getContext("2d"),
smallImage = new Image();
/* set canvas dimensions */
canvas.width = canvas.height = 500;
smallImage.addEventListener("load", function() {
/* the image is bound to the
function's 'this' property */
var repeatPattern = ctx.createPattern(this, "repeat"),
noRepeatPattern = ctx.createPattern(this, "no-repeat"),
repeatXPattern = ctx.createPattern(this, "repeat-x"),
repeatYPattern = ctx.createPattern(this, "repeat-y");
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.shadowBlur = 20;
ctx.shadowColor = "rgb(230,230,250)";
ctx.strokestyle = "rgb(128,128,128)";
ctx.lineWidth = 1;
ctx.fillStyle = repeatPattern;
ctx.fillRect (125, 125, 325, 325);
ctx.strokeRect (125, 125, 325, 325);
ctx.fillStyle = noRepeatPattern;
ctx.fillRect (0, 0, 100, 100);
ctx.strokeRect (0, 0, 100, 100);
ctx.fillStyle = repeatXPattern;
ctx.fillRect (125, 0, 350, 100);
ctx.strokeRect (125, 0, 350, 100);
ctx.fillStyle = repeatYPattern;
ctx.fillRect (0, 125, 100, 350);
ctx.strokeRect (0, 125, 100, 350);
}, !1);
/* define Image.onload event handler
before assigning Image.src */
smallImage.src = "https://vignette.wikia.nocookie.net/cardfight/images/8/89/De.jpg/revision/latest?cb=20130414214050";
}, !1);
body {
background:rgb(90,90,110);
padding:33px 0 }
#box {
width:500px;
height:500px;
background:rgb(50,50,70);
margin:0 auto;
box-shadow:0 0 0.25em 0.5em rgba(0,0,0,0.25) }
#canvasArea {
width:100%;
height:100%;
border:2px solid rgb(22,22,22) }
<div id="box">
<canvas id="canvasArea">
Your browser doesn't currently support HTML5 canvas.
</canvas>
</div>
BP ;)
I am trying to develop a game and i am starting to dip my toes into the HTML <canvas> tag and using it with javascript. My program here is my work in progress clone of PONG. I have managed to add the two paddles with no error but as i have added the Ball function it simply refuses to draw anything on the screen and thus i am given a page covered in black.
Could it be because i am using classes?
Here is the code:
// ctx.fillStyle = 'rgba(red, green, blue, alpha)';
// ctx.fillRect(x, y, width, height);
var canvas;
var ctx;
var dx = 5;
var dy = 5;
//Class Definitions
function Game(width, height, colour) {
this.width = width;
this.height = height;
this.colour = colour;
}
function Player(width, height, colour, x, y, up, down) {
this.width = width;
this.height = height;
this.colour = colour;
this.x = x;
this.y = y;
this.up = up;
this.down = down;
this.move = function(ny) {
this.y = this.y + ny;
ctx.fillStyle = this.colour;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
}
function Ball(width, height, colour, x , y, isTouched, isInGoal) {
this.width = width;
this.height = height;
this.colour = colour;
this.x = x;
this.y = y;
this.isTouched = isTouched;
this.isInGoal = isInGoal;
this.move = function() {
clear();
this.x = this.x + 1;
ctx.fillStyle = this.colour;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
}
//Creating new Classes
var gameStage = new Game((window.innerWidth), (window.innerHeight), 'rgb(0,0,0)');
var paddleOne = new Player(10, 150, 'rgb(255,255,255)', (gameStage.width/10), (gameStage.height/2), 38, 40);
var paddleTwo = new Player(10, 150, 'rgb(255,255,255)', (gameStage.width/1.1), (gameStage.height/2), 87, 83);
var ball = new Ball(20, 20, 'rgb(255,255,255)', (gameStage.width/2), (gameStage.height/2), 0, 0);
//Initialisation
function init(){
canvas = document.getElementById('game');
canvas.setAttribute('width', gameStage.width);
canvas.setAttribute('height', gameStage.height);
canvas.setAttribute('tabindex', 0);
if (game.getContext){
ctx = canvas.getContext('2d');
return setInterval(ball.move, 10);
return setInterval(draw, 10);
}
}
//Canvas Functions
function clear(){
ctx.clearRect(0, 0, gameStage.width, gameStage.height);
}
function draw() {
clear();
ctx.fillStyle = gameStage.colour;
ctx.fillRect(0, 0, gameStage.width, gameStage.height);
ctx.fillStyle = paddleOne.colour;
ctx.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);
ctx.fillStyle = paddleTwo.colour;
ctx.fillRect(paddleTwo.x, paddleTwo.y, paddleTwo.width, paddleTwo.height);
console.log("PlayerOne Y Coordinate: " + paddleOne.y + "\n");
console.log("PlayerTwo Y Coordinate: " + paddleTwo.y + "\n");
}
//Player Control
function doKeyDown(e) {
if (e.keyCode == paddleOne.up){
paddleOne.move(-5);
} else if (e.keyCode == paddleOne.down) {
paddleOne.move(5);
} else if (e.keyCode == paddleTwo.up) {
paddleTwo.move(-5);
} else if (e.keyCode == paddleTwo.down) {
paddleTwo.move(5);
}
}
//For HTML
function beginStuff(){
init();
window.addEventListener('keydown', doKeyDown, true);
}
* { margin: 0; padding: 0;}
body, html {height: 100%;}
#game {
position: absolute;
width:100%;
height:100%;
background-color: #000000;
}
<!DOCTYPE HTML>
<htmL>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A game</title>
<script type="text/javascript" src="game.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body onload="beginStuff();" >
<canvas id="game">
Please upgrade your browser to support HTML5. <br/>
</canvas>
</body>
</htmL>
This looks wrong to me:
return setInterval(ball.move, 10);
return setInterval(draw, 10);
Firstly, you've got 2 returns. Secondly, you've lost the binding on the move method:
return setInterval(ball.move.bind(ball), 10);
If that doesn't fix it I suggest stepping through in a debugger, line-by-line, making sure that everything is doing exactly what you expect it to.
With help from #skirtle, i moved the ball.move(); to the draw() function and removed the clear() call from the ball.move() function.
i write a canvas rotate image and trying to add drop shadows.
anyone can help me to how i can add a different shadow style for images inside canvas. i need drop shadows like as this image for result :
enter image description here
context.shadowColor = "rgba( 0, 0, 0, 0.3 )";
context.shadowOffsetX = 6;
context.shadowOffsetY = 6;
context.shadowBlur = 3;
context.drawImage( brolly, 25, 250 );
full code :
window.addEventListener("load", init);
var canvas = document.getElementById('c');
canvas.width = 360;
canvas.height = 360;
var context = canvas.getContext('2d');
var counter = 0;
var logoImageh = new Image();
logoImageh.src = 'http://sirati.info/tmp/h.png';
var logoImagem = new Image();
logoImagem.src = 'http://sirati.info/tmp/m.png';
TO_RADIANS = Math.PI / 180;
function init() {
setInterval(loop, 100 / 30);
}
function loop() {
context.clearRect(0, 0, canvas.width, canvas.height);
drawRotatedImage(logoImageh, 180, 180, counter++);
drawRotatedImage(logoImagem, 180, 180, counter++);
counter += 1;
}
function drawRotatedImage(image, x, y, angle) {
context.save();
context.translate(x, y);
context.rotate(angle * TO_RADIANS);
context.drawImage(image, -(image.width / 2), -(image.height / 2));
context.restore();
}
body {
margin: 0px;
padding: 0px;
text-align: center;
}
canvas {
outline: 0;
border: 1px solid #000;
margin-left: auto;
margin-right: auto;
}
<html>
<head>
<title>Simple</title>
</head>
<body>
<canvas id='c'></canvas>
</body>
</html>
i write
Add shadows to your images using in-memory canvases.
Then drawImage those in-memory canvases instead of the images. Yes, drawImage can draw other canvases as well as images!
[Addition: example code using question's code as a basis]
var canvas = document.getElementById('c');
canvas.width = 360;
canvas.height = 360;
var context = canvas.getContext('2d');
var counter = 0;
TO_RADIANS = Math.PI / 180;
var nextTime=0;
var delay=1000/60*2;
var logoImageh = new Image();
logoImageh.onload=start;
logoImageh.src = 'http://sirati.info/tmp/h.png';
var logoImagem = new Image();
logoImagem.onload=start;
logoImagem.src = 'http://sirati.info/tmp/m.png';
var imageCount=2;
//
function start(){
canvasLogoImageh=addShadowToImage(logoImageh);
canvasLogoImagem=addShadowToImage(logoImagem);
requestAnimationFrame(loop);
}
function addShadowToImage(img){
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
c.width=img.width;
c.height=img.height;
cctx.shadowColor='black';
cctx.shadowBlur=10;
cctx.drawImage(img,0,0);
return(c);
}
function loop(time) {
if(time<nextTime){requestAnimationFrame(loop);return;}
nextTime=time+delay;
context.clearRect(0, 0, canvas.width, canvas.height);
drawRotatedImage(canvasLogoImageh, 180, 180, counter++);
drawRotatedImage(canvasLogoImagem, 180, 180, counter++);
counter += 0.25;
requestAnimationFrame(loop);
}
function drawRotatedImage(image, x, y, angle) {
context.save();
context.translate(x, y);
context.rotate(angle * TO_RADIANS);
context.drawImage(image, -(image.width / 2), -(image.height / 2));
context.restore();
}
body{ background-color: ivory; }
canvas{border:1px solid red; margin:0 auto; }
<canvas id="c" width=300 height=300></canvas>
I am trying to make a screen following the player so that the player is in the middle of the screen. I have already made it in another game, but here it doesn't work. Here is my code :
var c = document.getElementById("main");
var ctx = c.getContext("2d");
var screen = document.getElementById("screen").getContext("2d");
var WhatUSeeWidth = document.getElementById("screen").width;
var WhatUSeeHeight = document.getElementById("screen").height;
ctx.beginPath();
for (i = 0; i < 100; i ++) {
if (i % 2) {
ctx.fillStyle = "red";
}
else {
ctx.fillStyle = "blue";
}
ctx.fillRect(0, i * 100, 500, 100);
}
var player = {
x : 700,
y : 800
}
setInterval(tick, 100);
function tick() {
screen.beginPath();
screen.drawImage(c, player.x - WhatUSeeWidth / 2, player.y - WhatUSeeHeight / 2, WhatUSeeWidth, WhatUSeeHeight, 0, 0, WhatUSeeWidth, WhatUSeeHeight);
}
canvas {
border: 2px solid black;
}
<canvas id="main" width="500" height="500"h></canvas>
<canvas id="screen" width="500" height="500"></canvas>
I want to draw The Blue and red canvas in The "screen" canvas Using drawImage
Ok , from your comment I understood what you are looking for. But the problem is that you probably start by an example without having understood. I try to give you my interpretation of what you do , but you should look for a good guide that starts with the basics and deepen animations (for example this: http://www.html5canvastutorials.com/).
HTML
<canvas id="canvasLayer" width="500" height="500"></canvas>
Javascript
var canvas = document.getElementById("canvasLayer");
var context = canvas.getContext("2d");
var WhatUSeeWidth = document.getElementById("canvasLayer").width;
var WhatUSeeHeight = document.getElementById("canvasLayer").height;
var player = {
x : 0,
y : 0
}
function drawBackground() {
for (i = 0; i < 100; i ++) {
if (i % 2) {
context.fillStyle = "red";
}
else {
context.fillStyle = "blue";
}
context.fillRect(0, i * 100, 500, 100);
}
}
function playerMove() {
context.beginPath();
var radius = 5;
context.arc(player.x, player.y, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 1;
context.strokeStyle = '#003300';
context.stroke();
}
setInterval(tick, 100);
function tick() {
context.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
player.x++;
player.y++;
playerMove();
}
This is the JSFiddle.
EDIT WITH THE CORRECT ANSWER
The error is in the position of the object "player". It is located outside of the canvas, width:500 height:500 and the "player" is in position x:700 y:800.
Changing the position of the player your copy will appear.
var player = {
x : 50,
y : 50
}
Here the jsfiddle example.