Asteroid - Computer Space Mix Up in JavaScript - javascript

I've been making a coding project in which I simply create a 2 player shooter with asteroids. For some reason my asteroids occasionally disappear and I can't find a way to stop it. I tried some debugging strategies that i got off the internet. Forgive me for the messy code because I'm relatively new to coding and would love to have some help. This is my entire code -
const FPS = 60;
const FRICTION = 0.7;
const PROJ_DIST = 0.6;
const PROJ_EXPLODE_DUR = 0.3;
const PROJ_MAX = 3;
const PROJ_SPEED = 600;
const ROIDS_JAG = 0.4;
const ROIDS_NUM = 5;
const ROIDS_SPEED = 50;
const ROIDS_SIZE = 100;
const ROIDS_VERT = 10;
const PLAYER_SIZE = 30;
const ROT_SPEED = 250;
const PLAYER_THRUST = 5;
const PLAYER_MAX_SPEED = 12;
const SHOW_BOUNDING = false;
const SHOW_CENTER = false;
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
addEventListener("resize", () => {
canvas.width = innerWidth
canvas.height = innerHeight
})
class Player {
constructor(x, y, r, c, a, pc, p, scoreEl) {
this.x = x;
this.y = y;
this.or = r;
this.r = r;
this.p = p
this.c = c;
this.a = a
this.rot = 0
this.pc = pc
this.v = {
x: 0,
y: 0
}
this.thrusting = false
this.projectiles = []
this.destroy = []
this.top = {
x: this.x + 4 / 3 * this.r * Math.cos(this.a),
y: this.y - 4 / 3 * this.r * Math.sin(this.a)
}
this.left = {
x: this.x - this.r * (2 / 3 * Math.cos(this.a) + Math.sin(this.a)),
y: this.y + this.r * (2 / 3 * Math.sin(this.a) - Math.cos(this.a))
}
this.right = {
x: this.x - this.r * (2 / 3 * Math.cos(this.a) - Math.sin(this.a)),
y: this.y + this.r * (2 / 3 * Math.sin(this.a) + Math.cos(this.a))
}
this.thrustdir = 0
this.canShoot = false
this.scoreEl = scoreEl
this.score = 0
this.exploding = false;
}
draw() {
ctx.fillStyle = this.c
ctx.beginPath();
ctx.moveTo(this.top.x, this.top.y);
ctx.lineTo(this.left.x, this.left.y);
ctx.lineTo(this.right.x, this.right.y);
ctx.closePath();
ctx.fill();
}
update() {
this.setPoints();
this.move();
this.edge()
this.Update();
this.scoreEl.innerHTML = this.score
this.draw()
}
rotate(dir) {
this.rot = toRadians(ROT_SPEED * dir) / FPS
}
move() {
if (!this.exploding) {
if (this.thrusting) {
this.v.x += (Math.abs(this.v.x) < PLAYER_MAX_SPEED) ? PLAYER_THRUST * this.thrustdir * Math.cos(this.a) / FPS : 0;
this.v.y -= (Math.abs(this.v.y) < PLAYER_MAX_SPEED) ? PLAYER_THRUST * this.thrustdir * Math.sin(this.a) / FPS : 0;
} else {
this.v.x -= FRICTION * this.v.x / FPS
this.v.y -= FRICTION * this.v.y / FPS
}
this.a += this.rot
this.x += this.v.x
this.y += this.v.y
}
}
thrust(dir) {
this.thrustdir = dir;
this.thrusting = (dir == 0) ? false : true
}
edge() {
if (this.x < 0 - this.r) {
this.x = canvas.width + this.r
} else if (this.x > canvas.width + this.r) {
this.x = 0 - this.r
}
if (this.y < 0 - this.r) {
this.y = canvas.height + this.r
} else if (this.y > canvas.height + this.r) {
this.y = 0 - this.r
}
}
setPoints() {
this.top = {
x: this.x + 4 / 3 * this.r * Math.cos(this.a),
y: this.y - 4 / 3 * this.r * Math.sin(this.a)
}
this.left = {
x: this.x - this.r * (2 / 3 * Math.cos(this.a) + Math.sin(this.a)),
y: this.y + this.r * (2 / 3 * Math.sin(this.a) - Math.cos(this.a))
}
this.right = {
x: this.x - this.r * (2 / 3 * Math.cos(this.a) - Math.sin(this.a)),
y: this.y + this.r * (2 / 3 * Math.sin(this.a) + Math.cos(this.a))
}
}
Update() {
this.projectiles.forEach((projectile, index) => {
projectile.update();
if (projectile.kill()) {
this.projectiles.splice(index, 1)
}
asteroids.forEach((asteroid, index2) => {
this.explode(asteroid, projectile, false, () => {
asteroids.splice(index2, 1)
var radius = Math.random() * (ROIDS_SIZE - 4) + 4
if (Math.random() < 0.5) {
var x = Math.random() < 0.5 ? 0 - radius * 2 : canvas.width + radius * 2
var y = Math.random() * canvas.height
} else {
var x = Math.random() * canvas.width
var y = Math.random() < 0.5 ? 0 - radius * 2 : canvas.height + radius * 2
}
asteroids.push(new Asteroid(x, y, radius, {
x: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1),
y: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1)
}))
},
(asteroid) => {
if (!this.exploding) {
this.score += 5
}
this.projectiles.splice(index, 1)
if (asteroid.r > 35) {
gsap.to(asteroid, 0.5, {
r: asteroid.r - 30
}).then(asteroid.or = asteroid.r)
return false;
}
return true;
})
})
});
asteroids.forEach((asteroid, index) => {
this.explode(this, asteroid, true, () => {
this.respawn(this);
}, () => {
this.v = {
x: 0,
y: 0
}
})
})
this.projectiles.forEach((projectile, index) => {
this.explode(players[this.p == 0 ? 1 : 0], projectile, false, () => {
this.respawn(players[this.p == 0 ? 1 : 0]);
console.log("hit")
}, () => {
if (!players[this.p == 0 ? 1 : 0].exploding) {
this.score += 10
};
players[this.p == 0 ? 1 : 0].v = {
x: 0,
y: 0
};
this.projectiles.splice(index, 1);
return true
})
})
}
shoot() {
if (this.canShoot && this.projectiles.length < PROJ_MAX) {
this.projectiles.push(new Projectile(this.top.x, this.top.y, 5, this.pc, {
x: PROJ_SPEED * Math.cos(this.a) / FPS,
y: -PROJ_SPEED * Math.sin(this.a) / FPS,
}));
this.canShoot = false
}
}
respawn(object) {
if (object.exploding) {
object.v = {
x: 0,
y: 0
}
do {
var x = Math.random() < 0.5
var y = Math.random() < 0.5
object.x = x ? object.or * 2 : canvas.width - object.or * 2
object.y = y ? object.or * 4 : canvas.height - object.or * 2
} while (this.hitAsteroid(object.x, object.y))
object.a = this.getStartAngle(x, y)
gsap.to(object, {
r: object.or
})
object.exploding = false
}
}
explode(object1, object2, place, t = function() {}, f = function(object1 = null, object2 = null, object3 = null) {
return false
}) {
if (this.hit(object1, object2)) {
var x = place ? object1.x : object2.x
var y = place ? object1.y : object2.y
for (var i = 0; i < object1.r * 2; i++) {
particles.push(new Particle(x, y, Math.random() * 2, object1.c, {
x: (Math.random() - 0.5) * object1.r / 15,
y: (Math.random() - 0.5) * object1.r / 15
}))
}
if (f(object1, object2, this)) {
gsap.to(object1, 0.5, {
r: 0
}).then(t)
}
object1.exploding = true
}
}
hit(object1, object2) {
return Math.hypot(object2.x - object1.x, object2.y - object1.y) < object2.r + object1.r
}
hitAsteroid(x, y) {
asteroids.forEach((asteroid) => {
if (this.hit({x: x, y: y}, asteroid)) {
return true
}
})
return false;
}
getStartAngle(x, y) {
if (x && y) {
return toRadians(315)
} else if (x) {
return toRadians(45)
} else if (y) {
return toRadians(225)
} else {
return toRadians(135)
}
}
}
class Projectile {
constructor(x, y, r, c, v) {
this.x = x;
this.y = y;
this.r = r;
this.c = c;
this.v = v;
this.dist = 0
}
draw() {
ctx.fillStyle = this.c
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
}
update() {
this.x += this.v.x
this.y += this.v.y
this.dist += Math.hypot(this.v.x, this.v.y)
this.edge();
this.draw()
}
kill() {
return (this.dist > PROJ_DIST * canvas.width)
}
edge() {
if (this.x < 0 - this.r) {
this.x = canvas.width + this.r
} else if (this.x > canvas.width + this.r) {
this.x = 0 - this.r
}
if (this.y < 0 - this.r) {
this.y = canvas.height + this.r
} else if (this.y > canvas.height + this.r) {
this.y = 0 - this.r
}
}
}
class Asteroid {
constructor(x, y, r, v) {
this.x = x;
this.y = y;
this.r = r;
this.c = `hsl(${Math.random() * 360}, 50%, 50%)`;
this.v = v;
this.a = toRadians(Math.random() * 360);
this.vert = Math.floor(Math.random() * (ROIDS_VERT + 1) + ROIDS_VERT / 2);
this.offset = this.createOffset();
this.or = r;
}
draw() {
ctx.fillStyle = this.c
ctx.beginPath();
ctx.moveTo(
this.x + this.r * this.offset[0] * Math.cos(this.a),
this.y + this.r * this.offset[0] * Math.sin(this.a)
);
for (var j = 1; j < this.vert; j++) {
ctx.lineTo(
this.x + this.r * this.offset[j] * Math.cos(this.a + j * Math.PI * 2 / this.vert),
this.y + this.r * this.offset[j] * Math.sin(this.a + j * Math.PI * 2 / this.vert)
)
}
ctx.closePath();
ctx.fill();
}
update() {
this.x += this.v.x
this.y += this.v.y
this.edge()
this.draw()
}
edge() {
if (this.x < 0 - this.r) {
this.x = canvas.width + this.r
} else if (this.x > canvas.width + this.r) {
this.x = 0 - this.r
}
if (this.y < 0 - this.r) {
this.y = canvas.height + this.r
} else if (this.y > canvas.height + this.r) {
this.y = 0 - this.r
}
}
createOffset() {
var off = [];
for (var i = 0; i < this.vert; i++) {
off.push(Math.random() * ROIDS_JAG * 2 + 1 - ROIDS_JAG)
}
return off
}
hit(projectile) {
return (Math.hypot(projectile.x - this.x, projectile.y - this.y) < this.r + projectile.r)
}
}
class Particle {
constructor(x, y, r, c, v) {
this.x = x;
this.y = y;
this.r = r;
this.c = c;
this.v = v;
this.al = 1
}
draw() {
ctx.save()
ctx.globalAlpha = this.al
ctx.fillStyle = this.c
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
ctx.restore();
}
update() {
this.draw()
this.x += this.v.x
this.y += this.v.y
this.al -= 0.01
}
}
const player1 = new Player(canvas.width / 2, canvas.height / 2, PLAYER_SIZE / 2, "blue", toRadians(Math.random() * 360), "blue", 0, document.getElementById("score1"));
const player2 = new Player(canvas.width / 2, canvas.height / 2, PLAYER_SIZE / 2, "red", toRadians(Math.random() * 360), "red", 1, document.getElementById("score2"));
const asteroids = []
for (var i = 0; i < ROIDS_NUM; i++) {
var radius = Math.random() * (ROIDS_SIZE - 4) + 4
if (Math.random() < 0.5) {
var x = Math.random() < 0.5 ? 0 - radius : canvas.width + radius
var y = Math.random() * canvas.height
} else {
var x = Math.random() * canvas.width
var y = Math.random() < 0.5 ? 0 - radius : canvas.height + radius
}
asteroids.push(new Asteroid(x, y, radius, {
x: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1),
y: Math.random() * ROIDS_SPEED / FPS * (Math.random() < 0.5 ? 1 : -1)
}))
}
const particles = []
const players = [player1, player2]
addEventListener("keydown", (event) => {
switch (event.keyCode) {
case 32:
player1.shoot()
break;
case 37:
player1.rotate(1)
break;
case 39:
player1.rotate(-1)
break;
case 38:
player1.thrust(1)
break;
case 40:
player1.thrust(-1)
break;
case 69:
player2.shoot()
break;
case 65:
player2.rotate(1)
break;
case 68:
player2.rotate(-1)
break;
case 87:
player2.thrust(1)
break;
case 83:
player2.thrust(-1)
break;
}
});
addEventListener("keyup", (event) => {
switch (event.keyCode) {
case 37:
case 39:
player1.rot = 0
break;
case 38:
case 40:
player1.thrust(0);
case 32:
player1.canShoot = true;
case 65:
case 68:
player2.rot = 0
break;
case 87:
case 83:
player2.thrust(0);
case 69:
player2.canShoot = true;
}
});
var animationId;
function animate() {
animationId = requestAnimationFrame(animate);
ctx.fillStyle = "rgba(0, 0, 0, 0.1)"
ctx.fillRect(0, 0, canvas.width, canvas.height);
asteroids.forEach((asteroid) => {
asteroid.update()
})
particles.forEach((particle, index) => {
if (particle.al <= 0) {
particles.splice(index, 1)
} else {
particle.update();
}
})
player1.update();
player2.update()
}
function toRadians(a) {
return a / 180 * Math.PI
}
animate();
body {
margin: 0;
height: 100vh;
width: 100vw;
}
.scores {
width: 100vw;
}
#score1 {
display: inline-flex;
flex: right;
}
#score2 {
position: absolute;
top: 0;
left: calc(100vw - 4rem);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="./tailwind.min.css">
<title>Asteroids</title>
</head>
<body>
<div class="flex scores w-full">
<div class="fixed text-white ml-4 mt-1 text-4xl text-left" id="score1">0</div>
<div class="fixed text-white ml-4 mt-1 text-4xl text-right" id="score2">0</div>
</div>
<canvas id="gameCanvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js" integrity="sha512-IQLehpLoVS4fNzl7IfH8Iowfm5+RiMGtHykgZJl9AWMgqx0AmJ6cRWcB+GaGVtIsnC4voMfm8f2vwtY+6oPjpQ==" crossorigin="anonymous"></script>
<script src="./game.js"></script>
</body>
</html>

Related

How to make Javascript font responsive?

I'm trying to rework this codepen: https://codepen.io/christhuong/pen/XxzNWK
const data = {
font: {
family: 'Oswald',
size: 70,
weight: 'bold'
},
colors: ['rgb(248, 225, 0)', 'rgb(232, 0, 137)', 'rgb(0, 170, 234)'],
text: `INTERACTIVE * DEVELOPER`,
textlength: 0
}
const canvas = {
elem: document.querySelector('canvas'),
init() {
return this.elem.getContext('2d')
},
resize() {
canvas.elem.width = innerWidth;
canvas.elem.height = innerHeight;
}
}
canvas.resize();
const ctx = canvas.init();
const pointer = {
x: innerWidth/2, y: innerHeight/2,
r: 220
}
class CHAR {
constructor(char, x, y, color, layer) {
this.char = char;
this.cx = x;
this.cy = y;
this.color = color;
this.layer = layer;
this.r = 0;
this.alpha = 0;
this.dx = this.cx;
this.dy = this.cy;
}
static measuretext(text) {
return ctx.measureText(text).width;
}
static dist(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
static getAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
static init(text, x, y) {
ctx.font = `${data.font.weight} ${data.font.size}px ${data.font.family}`;
ctx.textBaseline = 'middle';
ctx.globalCompositeOperation = 'darken';
for (let color = 0; color < data.colors.length; color++) {
let layer = 1;
switch (color) {
case 0:
layer = 0.5;
break;
case 1:
layer = 0.7;
break;
case 2:
layer = 1;
break;
}
const strs = text.split(' * ');
const textlength = strs.map(str => this.measuretext(str));
data.textlength = Math.max(...textlength);
const textheight = this.measuretext('M') * 1.5;
for (let i = 0; i < strs.length; i++) {
let ww = 0;
for (let j = 0; j < strs[i].length; j++) {
const xx = x - textlength[i] / 2 + ww;
const yy = i == 0 ? y - textheight / 2 : y + textheight / 2;
chars.push(new CHAR(strs[i][j], Math.round(xx), Math.round(yy), data.colors[color], layer));
ww += this.measuretext(strs[i][j]);
}
}
}
}
static draw() {
for (let i = 0; i < data.colors.length; i++) {
ctx.fillStyle = data.colors[i];
for (let j = 0; j < chars.length; j++) {
if (chars[j].color == data.colors[i]) {
ctx.fillText(chars[j].char, chars[j].dx, chars[j].dy);
}
}
}
}
render() {
this.dx += (this.cx - this.dx) * 0.2;
this.dy += (this.cy - this.dy) * 0.2;
}
update() {
const dis = CHAR.dist(pointer.x, pointer.y, this.cx, this.cy);
if (dis < pointer.r) {
this.alpha = CHAR.getAngle(pointer.x, pointer.y, this.cx, this.cy) + Math.PI;
this.r = this.layer * dis * (pointer.r - dis) / pointer.r;
this.dx += (this.cx + this.r * Math.cos(this.alpha) - this.dx) * 0.2;
this.dy += (this.cy + this.r * Math.sin(this.alpha) - this.dy) * 0.2;
} else {
this.render()
}
}
}
let chars = [];
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
setTimeout(() => {
chars = [];
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
}, 10);
window.addEventListener('mousemove', e => {
pointer.x = e.clientX; pointer.y = e.clientY;
})
window.addEventListener('touchmove', e => {
e.preventDefault();
pointer.x = e.targetTouches[0].clientX;
pointer.y = e.targetTouches[0].clientY;
})
window.addEventListener('resize', () => {
canvas.resize();
chars = [];
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
})
const run = () => {
requestAnimationFrame(run);
ctx.clearRect(innerWidth / 2 - data.textlength, innerHeight / 2 - 0.7 * data.textlength, 2 * data.textlength, 1.4 * data.textlength);
if (Math.abs(pointer.x - innerWidth / 2) < data.textlength &&
Math.abs(pointer.y - innerHeight / 2) < 0.7 * data.textlength) {
chars.forEach(e => e.update())
} else { chars.forEach(e => e.render()) }
CHAR.draw();
}
setTimeout(run, 50);
#import url('https://fonts.googleapis.com/css?family=Oswald')
*
margin: 0
padding: 0
font-family: 'Oswald', sans-serif
body
overflow: hidden
canvas
filter: blur(1px)
<canvas>
I'm struggling to make whole text responsive, there is const size, It's not reacting to any css styling, so I guess there is need to adapt responsivness in script, but I don't know how adapt any ready solutions like for example this one: http://jsfiddle.net/xVB3t/2/ please help!
Something like this ?
function magicFunctionToGetSize() {
return parseInt(window.innerWidth/10);
}
const data = {
font: {
family: 'Oswald',
size: 70,
weight: 'bold'
},
colors: ['rgb(248, 225, 0)', 'rgb(232, 0, 137)', 'rgb(0, 170, 234)'],
text: `INTERACTIVE * DEVELOPER`,
textlength: 0
}
const canvas = {
elem: document.querySelector('canvas'),
init() {
return this.elem.getContext('2d')
},
resize() {
canvas.elem.width = innerWidth;
canvas.elem.height = innerHeight;
}
}
canvas.resize();
let ctx = canvas.init();
const pointer = {
x: innerWidth/2, y: innerHeight/2,
r: 220
}
class CHAR {
constructor(char, x, y, color, layer) {
this.char = char;
this.cx = x;
this.cy = y;
this.color = color;
this.layer = layer;
this.r = 0;
this.alpha = 0;
this.dx = this.cx;
this.dy = this.cy;
}
static measuretext(text) {
return ctx.measureText(text).width;
}
static dist(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
static getAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
static init(text, x, y) {
const fontSize = magicFunctionToGetSize();
ctx.font = `${data.font.weight} ${fontSize}px ${data.font.family}`;
ctx.textBaseline = 'middle';
ctx.globalCompositeOperation = 'darken';
for (let color = 0; color < data.colors.length; color++) {
let layer = 1;
switch (color) {
case 0:
layer = 0.5;
break;
case 1:
layer = 0.7;
break;
case 2:
layer = 1;
break;
}
const strs = text.split(' * ');
const textlength = strs.map(str => this.measuretext(str));
data.textlength = Math.max(...textlength);
const textheight = this.measuretext('M') * 1.5;
for (let i = 0; i < strs.length; i++) {
let ww = 0;
for (let j = 0; j < strs[i].length; j++) {
const xx = x - textlength[i] / 2 + ww;
const yy = i == 0 ? y - textheight / 2 : y + textheight / 2;
chars.push(new CHAR(strs[i][j], Math.round(xx), Math.round(yy), data.colors[color], layer));
ww += this.measuretext(strs[i][j]);
}
}
}
}
static draw() {
for (let i = 0; i < data.colors.length; i++) {
ctx.fillStyle = data.colors[i];
for (let j = 0; j < chars.length; j++) {
if (chars[j].color == data.colors[i]) {
ctx.fillText(chars[j].char, chars[j].dx, chars[j].dy);
}
}
}
}
render() {
this.dx += (this.cx - this.dx) * 0.2;
this.dy += (this.cy - this.dy) * 0.2;
}
update() {
const dis = CHAR.dist(pointer.x, pointer.y, this.cx, this.cy);
if (dis < pointer.r) {
this.alpha = CHAR.getAngle(pointer.x, pointer.y, this.cx, this.cy) + Math.PI;
this.r = this.layer * dis * (pointer.r - dis) / pointer.r;
this.dx += (this.cx + this.r * Math.cos(this.alpha) - this.dx) * 0.2;
this.dy += (this.cy + this.r * Math.sin(this.alpha) - this.dy) * 0.2;
} else {
this.render()
}
}
}
let chars = [];
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
setTimeout(() => {
chars = [];
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
}, 10);
window.addEventListener('mousemove', e => {
pointer.x = e.clientX; pointer.y = e.clientY;
})
window.addEventListener('touchmove', e => {
e.preventDefault();
pointer.x = e.targetTouches[0].clientX;
pointer.y = e.targetTouches[0].clientY;
})
window.addEventListener('resize', () => {
canvas.resize();
chars = [];
ctx = canvas.init();
CHAR.init(data.text, innerWidth / 2, innerHeight / 2);
})
const run = () => {
requestAnimationFrame(run);
ctx.clearRect(innerWidth / 2 - data.textlength, innerHeight / 2 - 0.7 * data.textlength, 2 * data.textlength, 1.4 * data.textlength);
if (Math.abs(pointer.x - innerWidth / 2) < data.textlength &&
Math.abs(pointer.y - innerHeight / 2) < 0.7 * data.textlength) {
chars.forEach(e => e.update())
} else { chars.forEach(e => e.render()) }
CHAR.draw();
}
setTimeout(run, 50);
#import url('https://fonts.googleapis.com/css?family=Oswald')
*
margin: 0
padding: 0
font-family: 'Oswald', sans-serif
body
overflow: hidden
canvas
filter: blur(1px)
<canvas>

Canavs is not drawing all the dots. Only one is showing up

In this script I’m trying to make a coordinate plane with two dots/circles. When I add the second dot in the code, it only shows the second one.
The part with the dots is this piece of code:
point(AX, AY, false, 'red', 6)
point(BX, BY, false, 'red', 6)
Can someone please help me with this problem? Thanks a lot!
start();
function start() {
console.clear();
document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var AX = document.getElementById("AX").value;
var AY = document.getElementById("AY").value;
var BX = document.getElementById("BX").value;
var BY = document.getElementById("BY").value;
var SQUARE_SIZE = 30;
var XSCALE = 1;
var YSCALE = 1;
var centerX = 0;
var centerY = 0;
selected = [];
points = [];
lines = [];
segments = [];
history = [];
circles = [];
function point(x, y, isSelected, color, r) {
this.x = x;
this.y = y;
this.color = color;
this.r = r;
this.add = function () {
plotPoint(this.x, this.y, this.color, this.r);
};
points.push(this);
if (isSelected) {
selected.push(this);
}
this.distance = function (gx, gy) {
return Math.sqrt(Math.pow(this.x - gx, 2) + Math.pow(this.y - gy, 2));
};
}
function point1(x, y, isSelected, color, r) {
this.x = x;
this.y = y;
this.color = color;
this.r = r;
this.add = function () {
plotPoint(this.x, this.y, this.color, this.r);
};
points.push(this);
if (isSelected) {
selected.push(this);
}
this.distance = function (gx, gy) {
return Math.sqrt(Math.pow(this.x - gx, 2) + Math.pow(this.y - gy, 2));
};
}
function circle(x, y, color, r) {
this.x = x;
this.y = y;
this.color = color;
this.r = r;
this.add = function () {
ctx.beginPath();
ctx.arc(convertX(x), convertY(y), r, 0, 2 * Math.PI);
ctx.stroke();
};
}
function line(m, b, color, width) {
this.m = m;
this.b = b;
this.color = color;
this.width = width;
lines.push(this);
}
function segment(a, b, color, width) {
this.a = a;
this.b = b;
this.color = color;
this.width = width;
this.getSlope = function () {
return (b.y - a.y) / (b.x - a.x);
};
this.getIntercept = function () {
var m = this.getSlope();
return a.y - m * a.x;
};
this.getLength = function () {
return Math.sqrt(this.a.x - this.b.x + this.a.y - this.b.y);
};
this.distance = function (gx, gy) {
//var m = (b.y-a.y)/(b.x-a.x)
//var bb = a.y-m*a.x
var m = this.getSlope();
var bb = this.getIntercept();
var pim = 1 / -m;
var pib = gy - pim * gx;
if (m === 0) {
pix = gx;
piy = this.a.y;
} else if (Math.abs(m) === Infinity) {
var pix = this.a.x;
var piy = gy;
} else {
var pix = (pib - bb) / (m - pim); //((gy-(gx/m)-bb)*m)/(m*m-1)
var piy = pim * pix + pib;
}
//console.log("m:"+m+" pim:"+pim+" pib:"+pib+" pix"+pix+" piy:"+piy)
if (
((this.a.x <= pix && pix <= this.b.x) ||
(this.b.x <= pix && pix <= this.a.x)) &&
((this.a.y <= piy && piy <= this.b.y) ||
(this.b.y <= piy && piy <= this.a.y))
) {
var d = Math.sqrt(Math.pow(gx - pix, 2) + Math.pow(gy - piy, 2));
return d;
} else {
var d = Math.min(this.a.distance(gx, gy), this.b.distance(gx, gy));
return d;
}
};
this.add = function () {
if (selected.indexOf(this) > -1) {
plotLine(this.a.x, this.a.y, this.b.x, this.b.y, color, width, [5, 2]);
} else {
plotLine(this.a.x, this.a.y, this.b.x, this.b.y, color, width);
}
};
segments.push(this);
}
// var a = new point(1,1)
// var b = new point(3,4)
// new segment(a,b)
//var testline = new line(1, 2, 'red', 1)
function drawLine(x1, y1, x2, y2, color, width, dash) {
ctx.save();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = color;
ctx.lineWidth = width;
if (dash !== undefined) {
ctx.setLineDash(dash);
}
ctx.stroke();
ctx.restore();
}
function convertX(x) {
return ((x - xmin - centerX) / (xmax - xmin)) * width;
}
function revertX(x) {
return (x * (xmax - xmin)) / width + centerX + xmin;
}
function convertY(y) {
return ((ymax - y - centerY) / (ymax - ymin)) * height;
}
function revertY(y) {
return (y * (ymin - ymax)) / height - centerY - ymin;
}
function addAxis() {
var TICK = 0;
for (
var i = Math.floor(xmin + centerX);
i <= Math.floor(xmax + centerX);
i += XSCALE
) {
drawLine(
convertX(i),
convertY(0) + TICK,
convertX(i),
convertY(0) - TICK
);
}
for (
var i = Math.floor(ymin - centerY);
i <= Math.floor(ymax - centerY);
i += YSCALE
) {
drawLine(
convertX(0) - TICK,
convertY(i),
convertX(0) + TICK,
convertY(i)
);
}
}
function addGrid() {
for (
var i = Math.floor(ymin - centerY);
i <= Math.floor(ymax - centerY);
i += YSCALE
) {
drawLine(0, convertY(i), width, convertY(i), "lightgrey", 1);
}
for (
var i = Math.floor(xmin + centerX);
i <= Math.floor(xmax + centerX);
i += XSCALE
) {
drawLine(convertX(i), height, convertX(i), 0, "lightgrey", 1);
}
}
function addPoints() {
for (const p of points) {
p.add();
}
}
function addCircles() {
for (const c of circles) {
c.add();
}
}
function addLines() {
for (const l of lines) {
plotLine(
xmin + centerX,
l.m * (xmin + centerX) + l.b,
xmax + centerX,
l.m * (xmax + centerX) + l.b,
l.color,
l.width
);
}
}
function addSegments() {
for (const s of segments) {
s.add();
}
}
function plotPoint(x, y, color, r) {
if (r === undefined) {
r = 2;
}
if (color === undefined) {
color = "black";
}
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(convertX(x), convertY(y), r, 0, 2 * Math.PI);
ctx.fill();
}
function plotCircle(x, y, color, r) {
if (r === undefined) {
r = 2;
}
if (color === undefined) {
color = "black";
}
ctx.beginPath();
ctx.arc(convertX(x), convertY(y), r, 0, 2 * Math.PI);
ctx.stroke();
}
function plotLine(x1, y1, x2, y2, color, width, dash) {
ctx.save();
ctx.beginPath();
ctx.moveTo(convertX(x1), convertY(y1));
ctx.lineTo(convertX(x2), convertY(y2));
ctx.strokeStyle = color;
ctx.lineWidth = width;
if (dash !== undefined) {
ctx.setLineDash(dash);
}
ctx.stroke();
ctx.restore();
}
function snap(x) {
if ((x - Math.round(x)) * (x - Math.round(x)) < 0.01) {
return Math.round(x);
} else {
return x;
}
}
function mouseDown(evt) {
x = evt.clientX;
y = evt.clientY;
ocx = centerX;
ocy = centerY;
if (evt.buttons === 2) {
for (const p of points) {
if (
nx * nx - 2 * convertX(p.x) * nx + convertX(p.x) * convertX(p.x) <
36 &&
ny * ny - 2 * convertY(p.y) * ny + convertY(p.y) * convertY(p.y) < 36
) {
s = new segment(p, new point(revertX(x), revertY(y), true));
selected.push(s);
return;
}
}
new point(snap(revertX(x)), snap(revertY(y)));
}
if (evt.buttons === 1) {
for (const p of points) {
if (p.distance(revertX(x), revertY(y)) < 0.2) {
selected.push(p);
}
console.log(p.distance(revertX(x), revertY(y)));
}
for (const s of segments) {
if (s.distance(revertX(x), revertY(y)) < 0.2) {
selected.push(s);
}
console.log(s.distance(revertX(x), revertY(y)));
}
}
onresize();
}
function mouseUp() {
selected = [];
}
function mouseMove(evt) {
console.clear();
nx = evt.clientX;
ny = evt.clientY;
gx = revertX(nx);
gy = revertY(ny);
if (evt.buttons === 1) {
if (selected.length > 0) {
for (const p of selected) {
p.x = snap(gx);
p.y = snap(gy);
}
} else {
centerX = (x - nx) / SQUARE_SIZE + ocx;
centerY = (y - ny) / SQUARE_SIZE + ocy;
}
}
if (evt.buttons === 2) {
for (const p of selected) {
p.x = snap(gx);
p.y = snap(gy);
}
}
console.log("coords: " + gx + ", " + gy);
console.log("points: " + points);
console.log("segments:" + segments);
console.log("selected: " + selected);
onresize();
}
function keyPress(evt) {
if ((evt.keyCode = 32)) {
//space
if (selected.length > 0) selected = [];
}
onresize();
}
point(AX, AY, false, "red", 6);
point(BX, BY, false, "red", 6);
window.onresize = function () {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
xmin = -width / SQUARE_SIZE / 2;
xmax = width / SQUARE_SIZE / 2;
ymin = -height / SQUARE_SIZE / 2;
ymax = height / SQUARE_SIZE / 2;
addGrid();
addAxis();
addPoints();
addLines();
addSegments();
addCircles();
ctx.font = "12px Arial";
ctx.fillStyle = "black";
ctx.fillText("Number of Points: " + points.length, 20, 30);
ctx.fillText("Points Slected: " + selected.length, 20, 50);
};
onresize();
}
<h2>LocusCreator v1.0 - © Niels Langerak</h2>
<p>Use the inputboxes to fill in all the info to make the locus.</p>
<p>Circle A - X:</p>
<input type="number" id="AX" value="0">
<p>Circle A - Y:</p>
<input type="number" id="AY" value="0">
<p>Circle B - X:</p>
<input type="number" id="BX" value="1">
<p>Circle B - Y:</p>
<input type="number" id="BY" value="1">
<button onclick="start()">Reload</button>
<canvas width=600px height=600px id='canvas'>
You should use the new keyword when creating your point:
new point(AX, AY, false, 'red', 6)
new point(BX, BY, false, 'red', 6)
It creates a new instance of point, but not overwrite it, as it works in your code.

canvas event listener to switch argument state

Hi I'm trying to add interactivity to the canvas element.
below you can see the electric canvas. I wonder how can i add a mouse click event listener on the switch in order to open and close it. Is it possible to change the switch open argument from true to false on click ?
I could define a specific position and capture the mouse click event on that position but this circuit should be use by anybody to create his circuit so It isn't possible to give a predifined position to the switch
/*Basic Circuit symbol toolset, still alot missing
credit to: https://stackoverflow.com/users/434421/mindoftea*/
class Circuit {
constructor(name="canvas", ix=50, iy=50) {
this.canvas = document.getElementById(name);
this.ctx = canvas.getContext("2d");
this.d = 0;
this.ix = ix;
this.iy = iy;
this.cx = ix;
this.cy = iy;
this.dx = 1;
this.dy = 0;
this.px = 0;
this.py = 0;
this.pd = 0;
this.pdx = 0;
this.pdy = 0;
this.ctx.beginPath();
this.ctx.moveTo(this.cx, this.cy);
}
start(ix=10, iy=10) {
this.d = 0;
this.ix = ix;
this.iy = iy;
this.cx = ix;
this.cy = iy;
this.dx = 1;
this.dy = 0;
this.px = 0;
this.py = 0;
this.pd = 0;
this.pdx = 0;
this.pdy = 0;
this.ctx.beginPath();
this.ctx.moveTo(this.cx, this.cy);
}
finish(close=true) {
if (close) {
this.ctx.lineTo(this.ix, this.iy);
}
this.ctx.stroke();
}
save() {
this.px = this.cx;
this.py = this.cy;
this.pd = this.d;
this.pdx = this.dx;
this.pdy = this.dy;
}
restore() {
this.cx = this.px;
this.cy = this.py;
this.d = this.pd;
this.dx = this.pdx;
this.dy = this.pdy;
this.ctx.moveTo(this.cx, this.cy);
}
newelement(len=50) {
this.ctx.save();
this.ctx.translate(this.cx, this.cy);
this.ctx.rotate(this.d*Math.PI/2);
if (this.dx < -0.5 ) {
this.ctx.rotate(Math.PI);
this.ctx.translate(-len, 0);
}
this.ctx.moveTo(0,0);
}
endelement(len=50) {
this.ctx.restore();
this.cx += this.dx * len;
this.cy += this.dy * len;
this.ctx.moveTo(this.cx,this.cy);
}
wire(len=50) {
this.newelement(len);
this.ctx.lineTo(len,0);
this.endelement(len);
}
drawWire(len=50) {
this.cx += this.dx * len;
this.cy += this.dy * len;
this.ctx.lineTo(this.cx, this.cy);
}
power(len=50, n=2, label="") {
var space = 5;
var wl = (len - (2*n-1)*space)/2;
this.newelement(len);
this.ctx.lineTo(wl,0);
this.ctx.fillText(label, wl, 4*space);
while (n--) {
this.ctx.moveTo(wl+space*(2*n+1), -space);
this.ctx.lineTo(wl+space*(2*n+1), space);
this.ctx.moveTo(wl+space*(2*n), -2*space);
this.ctx.lineTo(wl+space*(2*n), 2*space);
}
this.ctx.moveTo(len-wl, 0);
this.ctx.lineTo(len,0);
this.endelement(len);
}
drawPower(len=50, n=2, label="") {
var space = 5;
var wl = (len - (2*n-1)*space)/2;
this.drawWire(wl);
this.ctx.fillText(label, this.cx + 30 * this.dy, this.cy + 30 * this.dx);
while (n--) {
this.ctx.moveTo(this.cx + 15 * this.dy, this.cy + 15 * this.dx);
this.ctx.lineTo(this.cx - 15 * this.dy, this.cy - 15 * this.dx);
this.cx += this.dx * space;
this.cy += this.dy * space;
this.ctx.moveTo(this.cx + 2*space * this.dy, this.cy + 2*space * this.dx);
this.ctx.lineTo(this.cx - 2*space * this.dy, this.cy - 2*space * this.dx);
if (n != 0) {
this.cx += this.dx * space;
this.cy += this.dy * space;
}
}
this.ctx.moveTo(this.cx, this.cy);
this.drawWire(wl);
}
capacitor(len=50, label="") {
var space=5;
var hh = space*1.8;
var cl = (len-space)/2;
this.newelement(len);
this.ctx.lineTo(cl,0);
this.ctx.fillText(label, cl, hh+10)
this.ctx.moveTo(cl, -hh);
this.ctx.lineTo(cl, hh);
this.ctx.moveTo(cl+space, -hh);
this.ctx.lineTo(cl+space, hh);
this.ctx.moveTo(cl+space, 0);
this.ctx.lineTo(len,0);
this.endelement(len);
}
drawCapacitor(len=50, label="") {
var space=5;
var cl = (len-space)/2;
this.drawWire(cl);
this.ctx.fillText(label, this.cx + 20 * this.dy, this.cy + 20 * this.dx )
this.ctx.moveTo(this.cx + 10 * this.dy, this.cy + 10 * this.dx);
this.ctx.lineTo(this.cx - 10 * this.dy, this.cy - 10 * this.dx);
this.cx += this.dx * space;
this.cy += this.dy * space;
this.ctx.moveTo(this.cx + 10 * this.dy, this.cy + 10 * this.dx);
this.ctx.lineTo(this.cx - 10 * this.dy, this.cy - 10 * this.dx);
this.ctx.moveTo(this.cx, this.cy);
this.drawWire(cl);
}
inductor(len=50, n=4, label="") {
var xs, ys;
xs = 1;
ys = 2;
var space = 6;
var wl = (len-(n+1)*space)/2;
this.newelement(len);
this.ctx.lineTo(wl, 0);
this.ctx.fillText(label, wl, 25);
this.ctx.scale(xs, ys);
while (n--) {
this.ctx.moveTo(wl+space*(n+2), 0);
this.ctx.arc(wl+space*(n+1), 0, space, 0, Math.PI, 1);
this.ctx.moveTo(wl+space*(n), 0);
if (n>0) {
this.ctx.arc(wl+space*(n+1/2), 0, space/2, Math.PI,0, 1);
}
}
this.ctx.scale(1/xs, 1/ys);
this.ctx.moveTo(len-wl,0);
this.ctx.lineTo(len,0);
this.endelement(len);
}
drawInductor(len=50, n=4, label="") {
var xs, ys;
xs = 1 + Math.abs(this.dy);
ys = 1 + Math.abs(this.dx);
var space = 6;
var wl = (len-n*space)/2;
this.drawWire(len);
this.ctx.fillText(label, this.cx+(10+space)*this.dy, this.cy+(10+space)*this.dx)
this.cx += this.dx * space;
this.cy += this.dy * space;
this.ctx.scale(xs, ys);
while (n--) {
//ctx.moveTo(x/xs+5*Math.abs(dx),y/ys+5*dy);
this.ctx.moveTo(this.cx / xs + space * Math.abs(this.dx), this.cy / ys + space * this.dy);
this.ctx.arc(this.cx / xs, this.cy / ys, space, Math.PI / 2 * this.dy, Math.PI + Math.PI / 2 * this.dy, 1);
this.cx += space * this.dx;
this.cy += space * this.dy;
if (n != 0) {
if (this.dx >= 0) {
this.ctx.moveTo(this.cx / xs - space * this.dx, this.cy / ys - space * this.dy);
}
this.ctx.moveTo(this.cx / xs - space * this.dx, this.cy / ys - space * this.dy);
this.ctx.arc(this.cx / xs - space / 2 * this.dx, this.cy / ys - space / 2 * this.dy, 1.5, Math.PI + Math.PI / 2 * this.dy, Math.PI / 2 * this.dy, 1);
}
}
this.ctx.moveTo(this.cx / xs - 1.75 * this.dx, this.cy / ys - 1.75 * this.dy);
this.ctx.scale(1 / xs, 1 / ys);
this.ctx.lineTo(this.cx, this.cy);
this.drawWire(len);
}
trimmer(len=50, label="") {
//capacitor
var space=5;
var hh = space * 1.8;
var cl = (len-space)/2;
var size=1.4*hh;
var psize = size*Math.cos(Math.PI/4);
this.newelement(len);
//draw capacitor
this.ctx.moveTo(0,0);
this.ctx.lineTo(cl,0);
this.ctx.fillText(label, cl, hh+10)
this.ctx.moveTo(cl, -hh);
this.ctx.lineTo(cl, hh);
this.ctx.moveTo(cl+space, -hh);
this.ctx.lineTo(cl+space, hh);
this.ctx.moveTo(cl+space, 0);
this.ctx.lineTo(len,0);
var x = len/2-psize;
var y = 0+psize;
this.ctx.moveTo(x,y);
var x1 = len/2+psize;
var y1 = 0-psize;
this.ctx.lineTo(x1,y1);
//short line
psize /= 3;
x = x1-psize;
y = y1-psize;
this.ctx.moveTo(x,y);
x = x1+psize;
y = y1+psize;
this.ctx.lineTo(x,y);
this.endelement(len);
}
drawTrimmer(len=50, label="") {
var size=12;
var psize = size*Math.cos(Math.PI/4);
var x = this.cx+len/2*this.dx;
var y = this.cy+len/2*this.dy;
var x1 = x-psize*Math.abs(this.dx-this.dy);
var y1 = y+psize*Math.abs(this.dy-this.dx);
this.ctx.moveTo(x1,y1);
x1 = x+psize*Math.abs(this.dx-this.dy);
y1 = y-psize*Math.abs(this.dy-this.dx);
this.ctx.lineTo(x1,y1);
//short line
psize /= 3;
x = x1-psize*Math.abs(this.dx-this.dy);
y = y1-psize*Math.abs(this.dy-this.dx);
this.ctx.moveTo(x,y);
x = x1+psize*Math.abs(this.dx-this.dy);
y = y1+psize*Math.abs(this.dy-this.dx);
this.ctx.lineTo(x,y);
this.ctx.moveTo(this.cx, this.cy);
this.drawCapacitor(len, label);
}
resistor(len=50, n=5, style=1, label="") {
var size = 5;
var wl = (len-(n+1)*size)/2;
this.newelement(len);
this.ctx.lineTo(wl,0);
this.ctx.fillText(label, wl, size+15);
if (style == 1) {
var x = wl+size;
var y = -size;
while (n--) {
this.ctx.lineTo(x,y);
this.ctx.lineTo(x,y+2*size);
x += size;
}
this.ctx.lineTo(len-wl, 0);
} else {
this.ctx.rect(wl,-size, size*(n+1), 2*size);
}
this.ctx.moveTo(len-wl, 0);
this.ctx.lineTo(len,0);
this.endelement(len);
}
drawResistor(len=50, n=5, style=1, label="") {
var size = 5;
var wl = (len-(n+1)*size)/2;
this.drawWire(wl);
this.ctx.fillText(label, this.cx+this.dy*(size+15), this.cy+this.dx*(size+15));
if (style == 1) {
this.cx += this.dx * size;
this.cy += this.dy * size;
while (n--) {
this.ctx.lineTo(this.cx - size * this.dy, this.cy - size * this.dx);
this.ctx.lineTo(this.cx + size * this.dy, this.cy + size * this.dx);
this.cx += size * this.dx;
this.cy += size * this.dy;
}
this.ctx.lineTo(this.cx, this.cy);
} else {
this.ctx.rect(this.cx-size*this.dy, this.cy-size*this.dx, size*(n+1)*this.dx+2*size*this.dy, size*(n+1)*this.dy+2*size*this.dx);
this.cx += this.dx * size*(n+1);
this.cy += this.dy * size*(n+1) ;
this.ctx.moveTo(this.cx, this.cy);
}
this.drawWire(wl);
}
drawSwitch(len=50, open=true, label="S") {
var size=len/2;
var wl = (len-size)/2;
this.drawWire(wl);
var x = this.cx;
var y = this.cy;
this.ctx.fillText(label, x - 15*this.dy, y+15*this.dx);
//this.ctx.arc(x,y,2, 0, Math.PI*2);
x += size*this.dx;
y += size*this.dy;
if (open) {
this.ctx.lineTo(x-size/2*this.dy, y-size/2*this.dx);
} else {
this.ctx.lineTo(x, y);
}
this.ctx.arc(this.cx, this.cy, 2, 0, Math.PI*2);
this.ctx.moveTo(x, y);
this.ctx.arc(x,y, 2,0, Math.PI*2);
this.ctx.moveTo(x, y);
this.cx = x;
this.cy = y;
this.drawWire(wl);
}
switch(len=50, open=true, label="S") {
var size=len/2;
var circle = 2;
var wl = (len-size)/2;
this.newelement(len);
this.ctx.lineTo(wl,0);
this.ctx.moveTo(wl+circle,0);
this.ctx.fillText(label, wl+circle, circle+15);
this.ctx.arc(wl+circle,0, circle, 0, Math.PI*2);
this.ctx.moveTo(wl+size-circle, 0);
this.ctx.arc(wl+size-circle,0,circle, 0, Math.PI*2);
this.ctx.moveTo(wl+circle,-circle);
if (open) {
this.ctx.lineTo(wl+size, -circle-size/2);
} else {
this.ctx.lineTo(wl+size, -circle);
}
this.ctx.moveTo(len-wl,0);
this.ctx.lineTo(len,0);
this.endelement(len);
}
turnClockwise() {
this.d++;
this.dx = Math.cos(Math.PI/2 * this.d);
this.dy = Math.sin(Math.PI/2 * this.d);
}
turnCounterClockwise() {
this.d--;
this.dx = Math.cos(Math.PI/2 * this.d);
this.dy = Math.sin(Math.PI/2 * this.d);
}
}
var cc = new Circuit("canvas",100, 100);
cc.ctx.lineWidth = 2;
cc.start(100, 300);
cc.wire();
cc.power(50, 2, "E");
cc.resistor(50,4,1,"R");
cc.switch(50,false)
//cc.wire();
//cc.turnCounterClockwise();
cc.capacitor(50,"C");
cc.trimmer(50,"T");
cc.wire();
cc.turnClockwise();
//cc.wire();
cc.trimmer(50,"T");
cc.inductor(50, 4, "Inductor");
cc.wire();
cc.turnClockwise();
//cc.wire();
cc.capacitor(50,"CC");
//cc.trimmer(50,"T2");
cc.inductor(50,5,"Ind");
//cc.wire();
cc.resistor(50,4,2,"R");
cc.switch();
cc.save();
cc.turnCounterClockwise();
cc.wire(20);
cc.turnClockwise();
cc.resistor(50,6,1,"R6");
cc.turnClockwise();
cc.wire(20);
cc.restore();
cc.turnClockwise();
cc.wire(20);
cc.turnCounterClockwise();
cc.resistor(50,5,1,"R5");
cc.turnCounterClockwise();
cc.wire(20);
cc.turnClockwise();
cc.wire();
cc.resistor(50,4,1,"R");
cc.turnClockwise();
cc.wire();
//cc.drawSwitch(50,false, "S3");
cc.power(50, 1, "E2");
cc.finish();
cc.start(100,250);
cc.wire();
cc.capacitor();
cc.turnClockwise();
cc.wire(20);
cc.turnCounterClockwise();
cc.capacitor();
cc.turnCounterClockwise();
cc.wire(20);
cc.save();
cc.wire(20);
cc.turnCounterClockwise();
cc.capacitor();
cc.turnCounterClockwise();
cc.wire(20);
cc.restore();
cc.turnClockwise();
cc.wire();
cc.turnCounterClockwise();
cc.wire(20);
cc.switch();
cc.wire(20);
cc.turnCounterClockwise();
cc.resistor();
cc.wire();
cc.trimmer();
cc.inductor();
cc.turnCounterClockwise();
cc.power();
cc.finish();
<canvas style="position:fixed;top:0;left:0;border:1px;" width="500" height="500" id="canvas">
Create a registry for your switches. It stores bounding boxes and states.
Calculate the position and size of each switch upon its creation (so that you can get x1,y1 & x2,y2, for a bounding box).
Enter each switch into the registry upon its creation via a "register" method.
Create a Click or MouseUp handler for the canvas. On Click or MouseUp, report the position of the mouse to the registry, via a "handleClick" method.
If the mouse location reported to the registry is within the bounding box of a switch, toggle that switch (both graphically and functionally).
Something like this:
class SwitchRegister {
var x1, x2, y1, y2; // float
var state; // boolean
constructor(x1, y1, x2, y2, state) {
this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2;
this.state = new Boolean(state);
}
}
class SwitchRegistry {
var registers; // array of SwitchRegister
register(x1, y1, x2, y2, state) {
this.registers[this.registers.length] = new SwitchRegister(x1, y1, x2, y2, state);
}
handleClick(x, y) {
for (i = 0; i < this.registers.length; i++) {
if (x >= this.registers[i].x1 && x <= this.registers[i].x2
&& y >= this.registers[i].y1 && y <= this.registers[i].y2) {
this.registers[i].state = !this.registers[i].state; // toggle state
// redraw the switch
// toggle its function within the sim
}
}
}
}

Event Listener only listening to two figures on the screen in Javascript and HTML Canvas

I have run into a problem with my program, which essentially moves 100 figures on a browser window and changes their direction if the user presses a key down. In order to determine if a user has pressed a key, I used an event listener, but the problem is that the event listener only works for two of the figures on the screen. I can only change the direction of two figures, while the other figures continue to move around the screen and not respond to user input. I have attached all of my code below, and I would really appreciate if someone could help me figure out the problem! Thanks!
let canvas = document.querySelector("canvas")
canvas.width = window.innerWidth
canvas.height = window.innerHeight
// console.log(innerWidth)
// console.log(innerHeight)
let c = canvas.getContext("2d")
let changeDirection = undefined
let repeatone = 0
let repeattwo = 0
window.addEventListener('keydown', function(event) {
repeatone = 0
repeattwo = 0
changeDirection = true
console.log(changeDirection)
})
window.addEventListener('keyup', function(event) {
changeDirection = false
console.log(changeDirection);
})
function random_rgba() {
var o = Math.round,
r = Math.random,
s = 255;
return 'rgba(' + o(r() * s) + ',' + o(r() * s) + ',' + o(r() * s) + ',' + r().toFixed(1) + ')';
}
// c.arc(xCircle, yCircle, radius, 0, Math.PI * 2, false)
function Circle(x, y, dx, dy, radius, color) {
this.x = x
this.y = y
this.dx = dx
this.dy = dy
this.radius = radius
this.color = color
this.draw = function() {
// c.strokeStyle = this.color
c.beginPath()
c.strokeStyle = this.color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
c.stroke()
}
this.update = function() {
repeatone += 1
if (changeDirection === true && repeatone <= 1) {
this.dx = -this.dx
this.dy = -this.dy
if (this.x >= innerWidth - this.radius) {
this.dx = -this.dx
} else if (this.x <= 0) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.radius) {
this.dy = -this.dy
} else if (this.y <= 0) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
} else if (changeDirection === false || repeatone > 1) {
if (this.x >= innerWidth - this.radius) {
this.dx = -this.dx
} else if (this.x <= 0) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.radius) {
this.dy = -this.dy
} else if (this.y <= 0) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
}
}
}
function Rectangle(x, y, dx, dy, height, width, color) {
this.x = x
this.y = y
this.dx = dx
this.dy = dy
this.height = height
this.width = width
this.color = color
this.draw = function() {
c.beginPath()
c.fillStyle = this.color
c.fillRect(this.x, this.y, this.width, this.height)
}
this.update = function() {
repeattwo += 1
if (changeDirection === true && repeattwo <= 1) {
this.dx = -this.dx
this.dy = -this.dy
if (this.x >= innerWidth - this.width) {
this.dx = -this.dx
} else if (this.x <= 0) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.height) {
this.dy = -this.dy
} else if (this.y <= 0) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
} else if (changeDirection === false || repeattwo > 1) {
if (this.x >= innerWidth - this.width) {
this.dx = -this.dx
} else if (this.x <= 0) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.height) {
this.dy = -this.dy
} else if (this.y <= 0) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
}
}
}
// let x = Math.floor((Math.random() * innerWidth) + 1)
// let dx = Math.floor((Math.random() * 10) + 1)
// let y = Math.floor((Math.random() * innerHeight) + 1)
// let dy = Math.floor((Math.random() * 10) + 1)
//
// console.log("X Value " + x)
// console.log("Y Value " + y)
// console.log("X Velocity Value " + dx)
// console.log("Y Velocity Value " + dy)
//
let rectangleArray = []
let circleArray = []
for (var i = 0; i < 50; i++) {
let xRect = Math.floor((Math.random() * innerWidth) + 1)
let dxRect = Math.floor((Math.random() * 10) + 1)
let yRect = Math.floor((Math.random() * innerHeight) + 1)
let dyRect = Math.floor((Math.random() * 10) + 1)
let heightRect = Math.floor((Math.random() * 250) + 1)
let widthRect = Math.floor((Math.random() * 250) + 1)
let colorRect = random_rgba()
let xCircle = Math.floor((Math.random() * innerWidth) + 1)
let dxCircle = Math.floor((Math.random() * 10) + 1)
let yCircle = Math.floor((Math.random() * innerHeight) + 1)
let dyCircle = Math.floor((Math.random() * 10) + 1)
let heightCircle = Math.floor((Math.random() * 250) + 1)
let widthCircle = Math.floor((Math.random() * 250) + 1)
let colorCircle = random_rgba()
let radiusCircle = Math.floor((Math.random() * 100) + 1)
rectangleArray.push(new Rectangle(xRect, yRect, dxRect, dyRect, heightRect, widthRect, colorRect))
circleArray.push(new Circle(xCircle, yCircle, dxCircle, dyCircle, radiusCircle, colorCircle))
}
console.log(circleArray)
console.log(rectangleArray)
function animate() {
requestAnimationFrame(animate)
c.clearRect(0, 0, innerWidth, innerHeight)
for (var i = 0; i < rectangleArray.length; i++) {
rectangleArray[i].draw()
rectangleArray[i].update()
}
for (var i = 0; i < circleArray.length; i++) {
circleArray[i].draw()
circleArray[i].update()
}
}
animate()
<canvas></canvas>
You had a lot of code, I remove a lot of it...
Take a look at the new logic under the addEventListener
Troubleshooting cases like this the first thing I do is reduce the scope:
you had 100 figures, I took it down to 6
your animation was too fast, I reduced the speed.
lot's of random stuff on the code that created the figures, I hard-coded some of that.
you had changeDirection, repeatone & repeattwo, I could not figure out what you needed those for so I remove them.
let canvas = document.querySelector("canvas")
canvas.width = canvas.height = innerWidth = innerHeight = 300
let c = canvas.getContext("2d")
window.addEventListener('keydown', function(event) {
for (var i = 0; i < rectangleArray.length; i++) {
rectangleArray[i].dx *= -1
rectangleArray[i].dy *= -1
}
for (var i = 0; i < circleArray.length; i++) {
circleArray[i].dx *= -1
circleArray[i].dy *= -1
}
})
function random_rgba() {
var o = Math.round,
r = Math.random,
s = 255;
return 'rgba(' + o(r() * s) + ',' + o(r() * s) + ',' + o(r() * s) + ',' + r().toFixed(1) + ')';
}
// c.arc(xCircle, yCircle, radius, 0, Math.PI * 2, false)
function Circle(x, y, dx, dy, radius, color) {
this.x = x
this.y = y
this.dx = dx
this.dy = dy
this.radius = radius
this.color = color
this.draw = function() {
// c.strokeStyle = this.color
c.beginPath()
c.strokeStyle = this.color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)
c.stroke()
}
this.update = function() {
if (this.x >= innerWidth - this.radius) {
this.dx = -this.dx
} else if (this.x <= this.radius) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.radius) {
this.dy = -this.dy
} else if (this.y <= this.radius) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
}
}
function Rectangle(x, y, dx, dy, height, width, color) {
this.x = x
this.y = y
this.dx = dx
this.dy = dy
this.height = height
this.width = width
this.color = color
this.draw = function() {
c.beginPath()
c.fillStyle = this.color
c.fillRect(this.x, this.y, this.width, this.height)
}
this.update = function() {
if (this.x >= innerWidth - this.width) {
this.dx = -this.dx
} else if (this.x <= 0) {
this.dx = -this.dx
}
if (this.y >= innerHeight - this.height) {
this.dy = -this.dy
} else if (this.y <= 0) {
this.dy = -this.dy
}
this.x += this.dx
this.y += this.dy
this.draw()
}
}
function randSpeed() {
return (Math.random() - 0.5) * 5
}
let rectangleArray = []
let circleArray = []
for (var i = 0; i < 3; i++) {
let heightRect = Math.floor((Math.random() * 100) + 1)
let widthRect = Math.floor((Math.random() * 100) + 1)
rectangleArray.push(new Rectangle(80, 80, randSpeed(), randSpeed(), heightRect, widthRect, random_rgba()))
let radiusCircle = Math.floor((Math.random() * 50) + 1)
circleArray.push(new Circle(80, 80, randSpeed(), randSpeed(), radiusCircle, random_rgba()))
}
function animate() {
requestAnimationFrame(animate)
c.clearRect(0, 0, innerWidth, innerHeight)
for (var i = 0; i < rectangleArray.length; i++) {
rectangleArray[i].draw()
rectangleArray[i].update()
}
for (var i = 0; i < circleArray.length; i++) {
circleArray[i].draw()
circleArray[i].update()
}
}
animate()
<canvas></canvas>

Html 5 Collision Between Points on an Arc

I'm working on a game that uses projectiles and a shielding system. The player would hold down 'Space' to use the shield. My plan is to get the projectiles to bounce of of the enemies shields (I've implemented speed so I already know how to do that). The problem I am having is with the collision, since the player rotates to follow the mouse I struggled with finding the best way to create the shield but I eventually settled on an arc, I used some trigonometry to get the left, leftHalf, mid, rightHalf, and right point of the arc/shield. The Player with Shield. The issue is I can't get the collision to work from just 5, x/y coordinates (the arc is just being drawn for show I'm only sending the points to the server). This is what I have for my collision so far:
p: Player object
self: bullet object
bot: a variable based on the direction the character is facing (bottom: true or false)
shieldLeft, sheildRight, etc: an array containing x and y coordinate 0 for x, 1 for y
if (self.getDistance(p) < 32 && self.parent !== p.id)
{
if (p.isShielding == true)
{
switch(self.bot)
{
case true:
if (self.x >= p.shieldRight[0] && self.x <= p.shieldLeft[0])
{
console.log("BOT X");
if ((self.y >= p.shieldLeft[1] || self.y >= p.shieldRight[1]) && self.y <= p.shieldMid[1])
{
console.log("BOT Y");
self.spdX = -self.spdX;
self.spdY = -self.spdY;
}
}
break;
case false:
if (self.x <= p.shieldRight[0] && self.x >= p.shieldLeft[0])
{
console.log("TOP X");
if ((self.y <= p.shieldLeft[1] || self.y <= p.shieldRight[1]) && self.y >= p.shieldMid[1])
{
console.log("TOP Y");
self.spdX = -self.spdX;
self.spdY = -self.spdY;
}
}
break;
}
}
}
I would really appreciate any help, I can't continue with the game features until there actually is a game. Thank you!
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
cursor: crosshair;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
// Anonymous closure
(function() {
// Enforce strict rules for JS code
"use strict";
// App variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var bounds = null;
var ctx = null;
var player = null;
var projectiles = [];
projectiles.length = 5;
// Classes
// Constructor function
function Player(x,y) {
this.x = x;
this.y = y;
this.dx = 0.0;
this.dy = 0.0;
this.rotation = 0.0;
this.targetX = 0.0;
this.targetY = 0.0;
this.isShieldUp = false;
this.isShieldRecharging = false;
this.shieldPower = this.shieldPowerMax;
this.left = false;
this.right = false;
this.up = false;
this.down = false;
window.addEventListener("keydown",this.onkeydown.bind(this));
window.addEventListener("keyup",this.onkeyup.bind(this));
window.addEventListener("mousemove",this.onmousemove.bind(this));
}
// shared properties/functions across all instances
Player.prototype = {
width: 10,
height: 10,
shieldRadius: 15.0,
shieldArcSize: 3.0, // In Radians
shieldPowerMax: 50.0,
shieldPowerCharge: 0.5,
shieldPowerDrain: 0.75,
onkeydown: function(e) {
switch(e.key) {
case " ": this.isShieldUp = true && !this.isShieldRecharging; break;
case "w": this.up = true; break;
case "s": this.down = true; break;
case "a": this.left = true; break;
case "d": this.right = true; break;
}
},
onkeyup: function(e) {
switch(e.key) {
case " ": this.isShieldUp = false; break;
case "w": this.up = false; break;
case "s": this.down = false; break;
case "a": this.left = false; break;
case "d": this.right = false; break;
}
},
onmousemove: function(e) {
this.targetX = e.clientX - bounds.left;
this.targetY = e.clientY - bounds.top;
},
tick: function() {
var x = (this.targetX - this.x);
var y = (this.targetY - this.y);
var l = Math.sqrt(x * x + y * y);
x = x / l;
y = y / l;
this.rotation = Math.acos(x) * (y < 0.0 ? -1.0 : 1.0);
if (this.isShieldUp) {
this.shieldPower = this.shieldPower - this.shieldPowerDrain;
if (this.shieldPower < 0.0) {
this.shieldPower = 0.0;
this.isShieldUp = false;
this.isShieldRecharging = true;
}
} else {
this.shieldPower = this.shieldPower + this.shieldPowerCharge;
if (this.shieldPower > this.shieldPowerMax) {
this.shieldPower = this.shieldPowerMax;
this.isShieldRecharging = false;
}
}
if (this.up) { --this.y; this.dy = -1; } else
if (this.down) { ++this.y; this.dy = 1; } else { this.dy = 0; }
if (this.left) { --this.x; this.dx = -1; } else
if (this.right) { ++this.x; this.dx = 1; } else { this.dx = 0; }
},
render: function() {
ctx.fillStyle = "darkred";
ctx.strokeStyle = "black";
ctx.translate(this.x,this.y);
ctx.rotate(this.rotation);
ctx.beginPath();
ctx.moveTo(0.5 * this.height,0.0);
ctx.lineTo(-0.5 * this.height,0.5 * this.width);
ctx.lineTo(-0.5 * this.height,-0.5 * this.width);
ctx.lineTo(0.5 * this.height,0.0);
ctx.fill();
ctx.stroke();
if (this.isShieldUp) {
ctx.strokeStyle = "cyan";
ctx.beginPath();
ctx.arc(0.0,0.0,this.shieldRadius,this.shieldArcSize * -0.5,this.shieldArcSize * 0.5,false);
ctx.stroke();
}
ctx.rotate(-this.rotation);
ctx.translate(-this.x,-this.y);
ctx.fillStyle = "black";
ctx.fillRect(canvasWidth - 80,canvasHeight - 20,75,15);
ctx.fillStyle = this.isShieldRecharging ? "red" : "cyan";
ctx.fillRect(canvasWidth - 75,canvasHeight - 15,65 * (this.shieldPower / this.shieldPowerMax),5);
}
};
function Projectile(x,y,dx,dy) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
}
Projectile.prototype = {
radius: 2.5,
tick: function(player) {
this.x = this.x + this.dx;
this.y = this.y + this.dy;
if (this.x + this.radius < 0.0) { this.x = canvasWidth + this.radius; }
if (this.x - this.radius > canvasWidth) { this.x = -this.radius; }
if (this.y + this.radius < 0.0) { this.y = canvasHeight + this.radius; }
if (this.y - this.radius > canvasHeight) { this.y = -this.radius; }
if (player.isShieldUp) {
var px = (player.x - this.x);
var py = (player.y - this.y);
var pl = Math.sqrt(px * px + py * py);
var ml = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
var mx = this.dx / ml;
var my = this.dy / ml;
px = px / pl;
py = py / pl;
if (Math.acos(px * mx + py * my) < player.shieldArcSize * 0.5 && pl < player.shieldRadius) {
px = -px;
py = -py;
this.dx = this.dx - 2.0 * px * (this.dx * px + this.dy * py) + player.dx;
this.dy = this.dy - 2.0 * py * (this.dx * px + this.dy * py) + player.dy;
}
}
},
render: function() {
ctx.moveTo(this.x + this.radius,this.y);
ctx.arc(this.x,this.y,this.radius,0.0,2.0 * Math.PI,false);
}
}
// Game loop
function loop() {
// Tick
player.tick();
for (var i = 0; i < projectiles.length; ++i) {
projectiles[i].tick(player);
}
// Render
ctx.fillStyle = "#555555";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
player.render();
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.beginPath();
for (var i = 0; i < projectiles.length; ++i) {
projectiles[i].render();
}
ctx.fill();
ctx.stroke();
//
requestAnimationFrame(loop); // Runs the loop at 60hz
}
// "Main Method", executes after the page loads
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
bounds = canvas.getBoundingClientRect();
ctx = canvas.getContext("2d");
player = new Player(90.0,80.0);
for (var i = 0; i < projectiles.length; ++i) {
projectiles[i] = new Projectile(
Math.random() * canvasWidth,
Math.random() * canvasHeight,
Math.random() * 2.0 - 1.0,
Math.random() * 2.0 - 1.0
);
}
loop();
}
})();
</script>
</body>
</html>

Categories