Rotation of a shape in HTML5 - javascript

I want to create an array that is having an angle of this.dAngle with the horizontal line. This is my code of the function that creates the arrow.
var offset;
if (this.dLength < 10) offset = this.dLength;
else offset = Math.min(this.dLength * 0.1, 10);
this.shape = new createjs.Shape();
//rotation
this.canvasId = this.stage.canvas.id;
this.canvas = document.getElementById(this.canvasId);
if(this.canvas) {
this.ctx = this.canvas.getContext("2d");
}
if(this.ctx) {
console.log('rotate');
this.ctx.save();
this.ctx.rotate(this.dAngle);
}
this.canvasId = this.stage.canvas.id;
this.canvas = document.getElementById(this.canvasId);
this.ctx = this.canvas.getContext("2d");
this.shape.graphics.clear();
this.shape.graphics.beginStroke("black");
this.shape.graphics.moveTo(0, 50);
this.shape.graphics.lineTo(this.dLength, 50);
this.shape.graphics.moveTo((this.dLength - offset), 50+(offset / 2));
this.shape.graphics.lineTo(this.dLength, 50);
this.shape.graphics.lineTo((this.dLength - offset), 50+(-offset / 2));
this.ctx.restore();
But the rotation is not being done. Any solutions?

Related

Image gets stuck when using context.rotate to change orientation upon collision [Brick Breakout Game]

I'm trying to make a simple Brick Breakout style game using JS, HTML, CSS. I've done this before so trying to add some additional complexity, including using an image of an asteroid with a tail as the ball. I'd like to rotate the image so that the asteroid is oriented the correct way(not tail first). With my current code, when the collision happens my "ball" gets stuck, and the game loop seems to freeze (my paddle isn't moveable either), then after a few seconds it restarts, but you can see the tail of the asteroid in the correct orientation on the other side of the screen. It's hard to explain, so I put a codepen link up here Brick breakout.
Here's the code I believe to be related to the problem, specifically the ctx.rotate function in Ball.JS.
Ball.js:
class Ball {
constructor(gameWidth, gameHeight) {
this.image = document.getElementById('ball');
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
this.posX = 250;
this.posY = 400;
this.height = 80;
this.width = 80;
this.speed = { x:20, y:20};
};
draw(ctx) {
ctx.drawImage(this.image, this.posX, this.posY, this.width, this.height);
};
update(deltaTime, ctx) {
if(!deltaTime) return;
this.posX += this.speed.x/deltaTime;
this.posY += this.speed.y/deltaTime;
if(this.posX >= this.gameWidth - this.width) {
this.speed.x = -this.speed.x;
ctx.rotate(90*Math.PI/180)
};
if(this.posX <= -15) {
this.speed.x = -this.speed.x;
}
if(this.posY >= this.gameHeight - this.height +15 || this.posY <= -15) {
this.speed.y = -this.speed.y;
};
};
};
Index.js:
import Paddle from '/paddle.js';
import inputHandler from '/input.js';
import Ball from '/ball.js';
const canvas = document.getElementById('gameScreen');
const ctx = canvas.getContext('2d');
const gameWidth = 800;
const gameHeight = 500;
const paddle = new Paddle(gameWidth, gameHeight);
const ball = new Ball(gameWidth, gameHeight);
new inputHandler(paddle);
let lastTime = 0;
const gameLoop = timeStamp => {
let deltaTime = timeStamp - lastTime;
lastTime = timeStamp
ctx.clearRect(0, 0, 800, 500);
paddle.update(deltaTime);
paddle.draw(ctx);
ball.draw(ctx);
ball.update(deltaTime, ctx)
requestAnimationFrame(gameLoop)
};
gameLoop();
The game was crashing because whole canvas was rotated so the ball coordinates were off. You need to remove line ctx.rotate(90*Math.PI/180) from the update function.
You can rotate just the image using ctx.save() and ctx.restore in the draw function. This way you can translate and rotate the picture and then restore after the image is drawn.
class Ball {
constructor(gameWidth, gameHeight) {
this.image = document.getElementById('ball');
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
this.posX = 250;
this.posY = 400;
this.height = 80;
this.width = 80;
this.speed = { x:20, y:20};
};
draw(ctx) {
ctx.save();
ctx.translate( this.posX, this.posY );
let rotation = 0
if(this.speed.y<0){
rotation = Math.PI
}else{
rotation = 0
}
if(this.speed.x<0&&this.speed.y<0){
rotation-=Math.PI/2
}
ctx.rotate( rotation );
ctx.translate( -this.posX, -this.posY );
ctx.drawImage(this.image, this.posX, this.posY, this.width, this.height);
ctx.restore()
};
update(deltaTime, ctx) {
if(!deltaTime) return;
this.posX += this.speed.x/deltaTime;
this.posY += this.speed.y/deltaTime;
if(this.posX >= this.gameWidth - this.width) {
this.speed.x = -this.speed.x;
};
if(this.posX <= -15) {
this.speed.x = -this.speed.x;
}
if(this.posY >= this.gameHeight - this.height +15 || this.posY <= -15) {
this.speed.y = -this.speed.y;
};
};
};

How do I get this canvas animation script to work in Firefox?

I wrote this canvas animation script in hopes to use it on my portfolio website, but it is basically non-functional in Firefox, and I am not sure why. The script draws stars on the canvas that slowly rotate, and if you hold down the mouse button they spin faster creating trails. It works awesome in chrome, but is extremely slow and choppy in Firefox.
let canvas = document.querySelector('canvas');
let c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let mouse = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
}
let stars = [];
const starCount = 800;
class Star {
constructor(x, y, radius, color){
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = () => {
c.save();
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
c.fillStyle = this.color;
c.shadowColor = this.color;
c.shadowBlur = 15;
c.fill();
c.closePath();
c.restore();
};
this.update = () => {
this.draw();
};
}
}
let colors = [
"#A751CC",
"#DE9AF9",
"#F9E0F9",
"#B5ECFB",
"#5F86F7"
];
(initializeStars = () =>{
for(let i = 0; i < starCount; i++){
let randomColorIndex = Math.floor(Math.random() * 5);
let randomRadius = Math.random() * 2;
let x = (Math.random() * (canvas.width + 400)) - (canvas.width + 400) / 2;
let y = (Math.random() * (canvas.width + 400)) - (canvas.width + 400) / 2;
stars.push(new Star(x, y, randomRadius, colors[randomColorIndex]));
}
})();
let opacity = 1;
let speed = 0.0005;
let time = 0;
let spinSpeed = desiredSpeed => {
speed += (desiredSpeed - speed) * 0.01;
time += speed;
return time;
}
let starOpacity = (desiredOpacity, ease) => {
opacity += (desiredOpacity - opacity) * ease;
return c.fillStyle = `rgba(18, 18, 18, ${opacity})`;
}
let animate = () => {
window.requestAnimationFrame(animate);
c.save();
if(mouseDown){
starOpacity(0.01, 0.03);
spinSpeed(0.012);
}else{
starOpacity(1, 0.01);
spinSpeed(0.001);
}
c.fillRect(0,0, canvas.width, canvas.height);
c.translate(canvas.width / 2, canvas.height / 2);
c.rotate(time);
for(let i = 0; i < stars.length; i++){
stars[i].update();
}
c.restore();
}
window.addEventListener('mousemove', e => {
mouse.x = e.clientX - canvas.width / 2;
mouse.y = e.clientY - canvas.height / 2;
});
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
stars = [];
initializeStars();
});
let mouseDown = false;
window.addEventListener("mousedown", () =>{
mouseDown = true;
});
window.addEventListener("mouseup", () => {
mouseDown = false;
});
animate();
Here is the link to the demo on Code Pen; any help is appreciated.
You can use rect instead of arc to draw your stars:
c.rect(this.x, this.y, 2*this.radius, 2*this.radius);
remove the blur It's extremely expensive:
//c.shadowBlur = 15;
You can use a radial gradient going from opaque in the center to transparent in his stead.

Pixi.js - How to separate code to each file as function?

I'm very new with JS and Pixi.js and I want some advices, Below is my example code. I want to know How to separate code to main.js, boss.js as function? I try but it's not work stage is show but boss that i draw not show so, I want to know how to. Thank you
var stage = new PIXI.Container();
var renderer = PIXI.autoDetectRenderer();
document.body.appendChild(renderer.view);
var screenWidth = window.innerWidth;
var screenHeight = window.innerHeight;
var circle = new PIXI.Graphics();
var rect = new PIXI.Graphics();
var rectWidth = 160;
var rectHeight = 200;
var boss = new PIXI.Container();
rect.lineStyle(0);
rect.beginFill(0xffdbac, 1);
rect.drawRect((screenWidth / 2) - (rectWidth / 2), (screenHeight / 2) - 60, rectWidth, rectHeight);
rect.endFill();
boss.addChild(rect);
circle.lineStyle(0);
circle.beginFill(0xffdbac, 1);
circle.drawCircle(screenWidth / 2, (screenHeight / 2) - 140, 80);
circle.endFill();
boss.addChild(circle);
stage.addChild(boss);
stage.interactive = true;
renderer.view.style.position = "absolute";
renderer.view.style.display = "block";
renderer.autoResize = true;
renderer.resize(screenWidth, screenHeight);
rect.lineStyle(0);
rect.beginFill(0xffdbac, 1);
rect.drawRect((screenWidth / 2) - (rectWidth / 2), (screenHeight / 2) - 60, 160, 200);
boss.addChild(rect);
circle.lineStyle(0);
circle.beginFill(0xffdbac, 1);
circle.drawCircle(screenWidth / 2, (screenHeight / 2) - 140, 80);
boss.addChild(circle);
stage.addChild(boss);
animate();
function animate() {
renderer.render(stage);
requestAnimationFrame( animate );
}
Here is an example of boss creation separated to it's own file and function:
http://plnkr.co/edit/43GgC3nPvFKEpflGhwvV?p=preview
main.js
document.addEventListener("DOMContentLoaded", function(event) {
var stage = new PIXI.Container();
var renderer = PIXI.autoDetectRenderer();
document.body.appendChild(renderer.view);
var screenSize = {
width: window.innerWidth,
height: window.innerHeight
}
var rectSize = {
width: 160,
height: 200
};
var boss = createBoss(screenSize, rectSize);
stage.addChild(boss);
stage.interactive = true;
renderer.view.style.position = "absolute";
renderer.view.style.display = "block";
renderer.autoResize = true;
renderer.resize(screenSize.width, screenSize.height);
boss = window.createBoss(screenSize, rectSize);
stage.addChild(boss);
animate();
function animate() {
renderer.render(stage);
requestAnimationFrame( animate );
}
});
boss.js
function createBoss(screenSize, rectSize) {
var circle = new PIXI.Graphics();
var rect = new PIXI.Graphics();
var boss = new PIXI.Container();
rect.lineStyle(0);
rect.beginFill(0xffdbac, 1);
rect.drawRect((screenSize.width / 2) - (rectSize.width / 2), (screenSize.height / 2) - 60, rectSize.width, rectSize.height);
rect.endFill();
boss.addChild(rect);
circle.lineStyle(0);
circle.beginFill(0xffdbac, 1);
circle.drawCircle(screenSize.width / 2, (screenSize.height / 2) - 140, 80);
circle.endFill();
boss.addChild(circle);
return boss;
}

animated shapes at the same time using canvas

1.I want to be able to animated shapes at the same time using canvas, but each to one side.
2.Then when the mouse was placed on each circle appears around it with a text.My canvas knowledge isn't amazing, Here is an image to display what i want.
anyone shed some light on how to do it? Here is a fiddle of what I've managed
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas01 = document.getElementById("canvas01");
var ctx01 = canvas01.getContext("2d");
canvas.width = 600;
canvas.height = 600;
canvas01.width = 600;
canvas01.height = 600;
var centerX = canvas01.width / 2;
var centerY = canvas01.height / 2;
var cw = canvas.width;
var ch = canvas.height;
var nextTime = 0;
var duration = 2000;
var start = Date.now();
var end = start + duration;
var endingPct = 100;
var endingPct1 = 510;
var pct = 0;
var pct1 = 0;
var i = 0;
var increment = duration;
var angle = 0;
var background = new Image();
var img = new Image();
img.src = "http://uupload.ir/files/2fhw_adur-d-01.jpg";
//http://uupload.ir/files/2fhw_adur-d-01.jpg
background.src = "http://uupload.ir/files/9a2q_adur-d-00.jpg";
//http://uupload.ir/files/9a2q_adur-d-00.jpg
Math.inOutQuart = function(n) {
n *= 2;
if (n < 1)
return 0.5 * n * n * n * n;
return -0.5 * ((n -= 2) * n * n * n - 2);
};
background.onload = function() {
ctx.drawImage(background, 0, 0);
};
function animate() {
var now = Date.now();
var p = (now - start) / duration;
val = Math.inOutQuart(p);
pct = 101 * val;
draw(pct);
if (pct >= (endingPct )) {
start = Date.now();
return animate1();
}
if (pct < (endingPct )) {
requestAnimationFrame(animate);
}
}
function animate1() {
var now1 = Date.now();
var p1 = (now1 - start) / duration;
val = Math.inOutQuart(p1);
pct1 = centerY + 211 * val;
SmallCircle(pct1);
if (pct1 < (endingPct1 )) {
requestAnimationFrame(animate1);
}
}
function draw(pct) {
var endRadians = -Math.PI / 2 + Math.PI * 2 * pct / 100;
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, 180, -Math.PI / 2, endRadians);
ctx.lineTo(canvas.width / 2, canvas.height / 2);
ctx.fillStyle = 'white';
ctx.fill();
ctx.save();
ctx.clip();
ctx.drawImage(img, 0, 0);
ctx.restore();
}
animate();
function SmallCircle(pctt) {
ctx01.clearRect(0, 0, canvas01.width, canvas01.height);
ctx01.beginPath();
ctx01.arc(centerX, pctt, 7, 0, 2 * Math.PI, false);
ctx01.closePath();
ctx01.fillStyle = 'green';
ctx01.fill();
}
You can use transformations to draw your small circles extending at a radius from the logo center.
Here is example code and a Demo:
The smallCircle function let you specify these settings:
X & Y of the logo center: cx,cy,
The current radius which the small circle is from the logo center: pctt,
The angle of the smallCircle vs the logo center: angle,
The text to draw: text,
The smallCircle fill color: circlecolor,
The arc-circle stroke color: arccolor (if you don't want the arc-circle to appear you can specify transparent as the arccolor),
The text color: textcolor (if you don't want the text to appear you can specify transparent as the textcolor),
var canvas=document.getElementById("canvas01");
var ctx01=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
var cx=canvas.width/2;
var cy=canvas.height/2;
var PI2=Math.PI*2;
var smallCount=8;
var pctt=0;
var chars=['A','B','C','D','E','F','G','H'];
var circleFill='green';
var arcStroke='lawngreen';
var textFill='white';
ctx01.textAlign='center';
ctx01.textBaseline='middle';
animate(performance.now());
function animate(time){
ctx01.clearRect(0, 0, canvas01.width, canvas01.height);
for(var i=0;i<smallCount;i++){
smallCircle(
cx,cy,pctt,PI2/smallCount*i,
chars[i],circleFill,'transparent','transparent');
}
pctt+=1;
if(pctt<100){
requestAnimationFrame(animate);
}else{
for(var i=0;i<smallCount;i++){
smallCircle(
cx,cy,pctt,PI2/smallCount*i,
chars[i],circleFill,arcStroke,textFill);
}
}
}
function hilightCircle(n){}
function smallCircle(cx,cy,pctt,angle,text,circlecolor,arccolor,textcolor){
// move to center canvas
ctx01.translate(cw/2,ch/2);
// rotate by the specified angle
ctx01.rotate(angle);
// move to the center of the circle
ctx01.translate(pctt,0);
// draw the filled small circle
ctx01.beginPath();
ctx01.arc(0,0,7,0,PI2);
ctx01.closePath();
ctx01.fillStyle = circlecolor;
ctx01.fill();
// stroke the outside circle
ctx01.beginPath();
ctx01.arc(0,0,7+5,0,PI2);
ctx01.closePath();
ctx01.strokeStyle=arccolor;
ctx01.stroke();
// unrotate so the text is upright
ctx01.rotate(-angle);
// draw the text
ctx01.fillStyle=textcolor;
ctx01.fillText(text,0,0);
// reset all transforms to default
ctx01.setTransform(1,0,0,1,0,0);
}
body{ background-color:gray; }
canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>After animation, click the mouse.</h4>
<canvas id="canvas01" width=300 height=300></canvas>

Drawing circle and keeping the first uploaded sprite

So first, I uploaded a car to the canvas and gave it turning and motion properties. I tried to draw a circle to go alongside the car but it is not working properly. The circle is alone and flickering for some reason. I removed the timeout completely, and both the circle and car disappeared. Adjusting the timeout rate doesn't remove the flicker. Help me get them on the screen and keep them there together please?
http://jsbin.com/zogeraduze/1/edit?html,js,output
I don't have your car image, but it seems like you have a setInterval set to 30ms and you call a timeout every 10ms (which is equivalent to a setInterval), each time clearing the canvas, hence creating a flickering. You should have only one repaint function that should clear the canvas, draw the car and then draw the circle.
try
//Setting the canvas and context
var canvas = document.getElementById('gameCanvas');
var context = canvas.getContext('2d');
//Uploading car
var car = new Image();
car.src = "file:///H:/Desktop/Game/img/car.png";
//Setting properties of car
var x = 450;
var y = 730;
var speed = 10;
var angle = 990;
var mod = 0;
//Event listeners for keys
window.addEventListener("keydown", keypress_handler, false);
window.addEventListener("keyup", keyup_handler, false);
//Drawing the car turning and changing speed
function draw() {
x += (speed * mod) * Math.cos(Math.PI / 180 * angle);
y += (speed * mod) * Math.sin(Math.PI / 180 * angle);
context.save();
context.translate(x, y);
context.rotate(Math.PI / 180 * angle);
context.drawImage(car, -(car.width / 2), -(car.height / 2));
context.restore();
}
//Setting the keys
function keyup_handler(event) {
console.log('a');
if (event.keyCode == 38 || event.keyCode == 40) {
mod = 0;
}
}
//Setting all of the keys
function keypress_handler(event) {
console.log(event.keyCode);
if (event.keyCode == 38) {
mod = 1;
}
if (event.keyCode == 40) {
mod = -1;
}
if (event.keyCode == 37) {
angle -= 5;
}
if (event.keyCode == 39) {
angle += 5;
}
}
var context = $('#gameCanvas')[0].getContext('2d');
var width = $('#gameCanvas').width();
var height = $('#gameCanvas').height();
var circleX = width / 2;
var circleY = height / 2;
var circleVX = 1.0;
var circleVY = 0.0;
var circleR = 30;
function update() {
context.clearRect(0, 0, width, height);
/*
circleX = Math.random() * (width - 2 * circleR) + circleR;
circleY = Math.random() * (height - 2 * circleR) + circleR;
*/
draw();
drawCircle(circleX, circleY, circleR);
setTimeout(update, 10);
}
function canvasClick(event) {
var clickX = event.pageX;
var clickY = event.pageY;
var edgeX = clickX - circleX;
var edgeY = clickY - circleY;
var r = Math.sqrt(edgeX * edgeX + edgeY * edgeY);
if (r < circleR) {
context.clearRect(0, 0, width, height);
}
}
function drawCircle(x, y, r) {
context.beginPath();
context.arc(x, y, r, 0, 2 * Math.PI, false);
context.fillStyle = 'red';
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
}
$('#gameCanvas').click(canvasClick);
update();
Also, look into https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame instead of using timeouts

Categories