button animation error: Cannot read property 'requestAnimationFrame' of undefined (line 11) - javascript

I'm working on a custom button animation for my Wix website it is written in JavaScript and I get this error when I plug the code into an onclick event:
"cannot read property 'requestAnimationFrame' of undefined"
I've tried removing the return and I think the problem has to do with some sort of iframe issue because the original code was built to run in an html <iframe> element but that dident end up working out.
If someone could rewrite this code so that it dosent give this error that would be super helpful.
export function button7_click(event) {
$w.window.requestAnimFrame = (function() {
return $w.window.requestAnimationFrame ||
$w.window.webkitRequestAnimationFrame ||
$w.window.mozRequestAnimationFrame ||
$w.window.oRequestAnimationFrame ||
$w.window.msRequestAnimationFrame ||
function(callback) {
$w.window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function(min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function(x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function(x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function() {
var canvas = $w.document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
$w.document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = $w.document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
$w.window.setTimeout(buttonEffect, 100);
loop();
$w.window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for ($w.key in args) {
options[$w.key] = args[$w.key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs); // * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
$w.requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = $w.window.innerWidth;
height = canvas.height = $w.window.innerHeight;
};
})();
}
The button once clicked should run the JavaScript code and play the animation. Thanks for your help.

Related

Change color of Paticle(circle) when collision detected in canvas

// Initial Setup
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
// Canvas size
canvas.width = innerWidth;
canvas.height = innerHeight;
//Color
const colors = [
{r: 51, g: 99, b: 252}
//{r: 77, g: 57, b: 206},
// {r: 0, g: 189, b: 255},
];
// Utility Functions
function randomIntFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function randomColor(colors) {
return colors[Math.floor(Math.random() * colors.length)];
}
function distance(x1, y1, x2, y2) {
const xDist = x2 - x1;
const yDist = y2 - y1;
return Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
}
function rotateVelocities(velocity, theta) {
const rotatedVelocity = {
x: velocity.x * Math.cos(theta) - velocity.y * Math.sin(theta),
y: velocity.x * Math.sin(theta) + velocity.y * Math.cos(theta)
};
return rotatedVelocity;
}
// Objects
function Particle(x, y, radius, rgb) {
this.x = x;
this.y = y;
this.velocity = {
x: (Math.random() - 0.5) * 3,
y: (Math.random() - 0.5) * 3
};
this.radius = radius;
this.mass = 1;
this.opacity = 0;
this.r = rgb.r;
this.g = rgb.g;
this.b = rgb.b;
this.update = particles => {
this.draw();
for (let i = 0; i < particles.length; i++) {
const otherParticle = particles[i];
if (this.x === otherParticle.x) continue;
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0) {
const res = {
x: this.velocity.x - otherParticle.velocity.x,
y: this.velocity.y - otherParticle.velocity.y
};
if (res.x * (otherParticle.x - this.x) + res.y * (otherParticle.y - this.y) >= 0) {
const m1 = this.mass;
const m2 = otherParticle.mass;
const theta = -Math.atan2(otherParticle.y - this.y, otherParticle.x - this.x);
const rotatedVelocity1 = rotateVelocities(this.velocity, theta);
const rotatedVelocity2 = rotateVelocities(otherParticle.velocity, theta);
const swapVelocity1 = { x: rotatedVelocity1.x * (m1 - m2) / (m1 + m2) + rotatedVelocity2.x * 2 * m2 / (m1 + m2), y: rotatedVelocity1.y };
const swapVelocity2 = { x: rotatedVelocity2.x * (m1 - m2) / (m1 + m2) + rotatedVelocity1.x * 2 * m2 / (m1 + m2), y: rotatedVelocity2.y };
const u1 = rotateVelocities(swapVelocity1, -theta);
const u2 = rotateVelocities(swapVelocity2, -theta);
this.velocity.x = u1.x;
this.velocity.y = u1.y;
otherParticle.velocity.x = u2.x;
otherParticle.velocity.y = u2.y;
}
}
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0 ) {
this.opacity = 0.1;
}
}
if (this.x + this.radius >= canvas.width || this.x - this.radius <= 0)
this.velocity.x = -this.velocity.x;
if (this.y + this.radius >= canvas.height || this.y - this.radius <= 0)
this.velocity.y = -this.velocity.y;
this.x += this.velocity.x;
this.y += this.velocity.y;
};
this.draw = () => {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
c.strokeStyle = `rgba(${this.r}, ${this.g}, ${this.b}, 1)`;
c.stroke();
c.fillStyle = `rgba(${this.r}, ${this.g}, ${this.b}, ${this.opacity}`;
c.fill();
c.closePath();
};
}
// Implementation
let particles;
function init() {
particles = [];
let radius = 80
for (let i = 0; i < 10; i++) {
let x = randomIntFromRange(radius, innerWidth - radius);
let y = randomIntFromRange(radius, innerHeight - radius);
if (particles.length >= 1) {
for (let j = 0; j < particles.length; j++) {
if (distance(x, y, particles[j].x, particles[j].y) - radius * 2 < 0) {
x = randomIntFromRange(radius, innerWidth - radius);
y = randomIntFromRange(radius, innerHeight - radius);
j = -1;
continue;
}
}
}
particles.push(new Particle(x, y, radius, randomColor(colors)));
}
}
//I would like to initiate one circle out of all as red and whenever the red circle collide with other circle, other circle got red and at last all circle become red. but when two white circle collide it should not become red. basically one infected circle making other circle infected by touching.

Consistent way to draw ellipsis area

I'm trying to make a simple game in Processing. The canvas consist of two ellipsis, as in the following image:
This is my code:
var angle = Math.random()*360;
var diff = 1;
var region = {};
var first = true;
var o;
centerX = 250; centerY = 250; radiusX = 150; radiusY = 200;
var score = 0;
function setup() {
createCanvas(500, 500);
}
function draw() {
o = ellipseGetPoint(250,250,150,200,angle);
angle += diff;
background(220);
stroke("black");
fill("#333333");
ellipse(250,250,300,400);
stroke("white")
drawRegion(250,250,150,200);
stroke("red");
line(250,250,o.pointX, o.pointY);
fill("#999999");
stroke(0);
ellipse(250,250,200,300);
textSize(50);
text(str(score), 20, 490);
fill(0, 102, 153);
}
function ellipseGetPoint(centerX, centerY, radiusX, radiusY, angle) {
let o = {};
let pointX = centerX + radiusX * Math.cos(angle*Math.PI / 180);
let pointY = centerY + radiusY * Math.sin(angle*Math.PI / 180);
o.pointX = Math.floor(pointX);
o.pointY = Math.floor(pointY);
o.angle = angle;
return o;
}
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let currentX = region.pointX;
let currentY = region.pointY;
let t = 1;
for (let i = 0; i < 1000; i++) {
line(250,250, currentX, currentY);
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
}
}
function keyPressed() {
if (key == " ") {
diff*=-1;
}
let x = Math.floor(o.pointX);
let y = Math.floor(o.pointY);
let t = 1;
for (let i = 0; i < 1000; i++) {
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
if (Math.floor(currentX) == x) {
first = true
}
}
if (first) ++score;
else --score;
if (diff > 0 && diff < 3) diff += 0.1;
else if (diff > -3) diff -= 0.1;
}
The problem I'm facing is that, making the white area, I'm getting a different size of area depending of where it spawns.
I did it by getting a random point and adding a little offset, and drawing that 1000 times. I know this is not a good way to do it, but I don't know how to generate that region. Any way to do it?
Maybe you're looking for arc?
void draw() {
arc(50, 50, 80, 80, 0, QUARTER_PI, PIE);
}
Here's the documentation for more details. I think you'll love this.
Use arc() to draw an elliptical arc segment.
Compute the start and end angle in ellipseGetPoint and draw the arc:
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let t = 1;
let start = t*region.angle*Math.PI / 180;
t+= 0.15;
let end = t*region.angle*Math.PI / 180;
arc(centerX, centerY, radiusX*2, radiusY*2, start, end)
}
Note, you have to set the fill color before drawing the arc:
stroke("white")
drawRegion(250,250,150,200);
See the example:
var angle = Math.random()*360;
var diff = 1;
var region = {};
var first = true;
var o;
centerX = 250; centerY = 250; radiusX = 150; radiusY = 200;
var score = 0;
function setup() {
createCanvas(500, 500);
}
function draw() {
o = ellipseGetPoint(250,250,150,200,angle);
angle += diff;
background(220);
stroke("black");
fill("#333333");
ellipse(250,250,300,400);
fill("white")
stroke("white")
drawRegion(250,250,150,200);
stroke("red");
line(250,250,o.pointX, o.pointY);
fill("#999999");
stroke(0);
ellipse(250,250,200,300);
textSize(50);
text(str(score), 20, 490);
fill(0, 102, 153);
}
function ellipseGetPoint(centerX, centerY, radiusX, radiusY, angle) {
let o = {};
let pointX = centerX + radiusX * Math.cos(angle*Math.PI / 180);
let pointY = centerY + radiusY * Math.sin(angle*Math.PI / 180);
o.pointX = Math.floor(pointX);
o.pointY = Math.floor(pointY);
o.angle = angle;
return o;
}
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let t = 1;
let start = t*region.angle*Math.PI / 180;
t+= 0.15;
let end = t*region.angle*Math.PI / 180;
arc(centerX, centerY, radiusX*2, radiusY*2, start, end)
}
function keyPressed() {
if (key == " ") {
diff*=-1;
}
let x = Math.floor(o.pointX);
let y = Math.floor(o.pointY);
let t = 1;
for (let i = 0; i < 1000; i++) {
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
if (Math.floor(currentX) == x) {
first = true
}
}
if (first) ++score;
else --score;
if (diff > 0 && diff < 3) diff += 0.1;
else if (diff > -3) diff -= 0.1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>

how to use html canvas in between 2 <div>s

I tried to use canvas in middle of my html page.but it does't work fine. I want to use ribbon effect in div. it works fine when the there is no div and when there is div or other element it doesn't work. I want use canvas in between two div. I used ribbon pen in codepen and will post the code below. I want to how to use it in my html page.
var TWO_PI = Math.PI * 2;
var HALF_PI = Math.PI * 0.5;
var THICKNESS = 12;
var LENGTH = 10;
var STEP = 0.1;
var FPS = 1000 / 60;
function Particle(x, y, mass) {
this.x = x || 0;
this.y = y || 0;
this.ox = this.x;
this.oy = this.y;
this.mass = mass || 1.0;
this.massInv = 1.0 / this.mass;
this.fixed = false;
this.update = function (dt) {
if (!this.fixed) {
var fx = 0.0000;
var fy = 0.0000;
var tx = this.x,
ty = this.y;
this.x += (this.x - this.ox) + fx * this.massInv * dt * dt;
this.y += (this.y - this.oy) + fy * this.massInv * dt * dt;
this.ox = tx;
this.oy = ty;
}
};
};
function Spring(p1, p2, restLength, strength) {
this.p1 = p1;
this.p2 = p2;
this.restLength = restLength || 10;
this.strength = strength || 1.0;
this.update = function (dt) {
// Compute desired force
var dx = p2.x - p1.x,
dy = p2.y - p1.y,
dd = Math.sqrt(dx * dx + dy * dy) + 0.0001,
tf = (dd - this.restLength) / (dd * (p1.massInv + p2.massInv)) * this.strength,
f;
// Apply forces
if (!p1.fixed) {
f = tf * p1.massInv;
p1.x += dx * f;
p1.y += dy * f;
}
if (!p2.fixed) {
f = -tf * p2.massInv;
p2.x += dx * f;
p2.y += dy * f;
}
}
};
function Sim() {
this.particles = [];
this.springs = [];
this.tick = function (dt) {
var i, n;
for (i = 0, n = this.springs.length; i < n; ++i) {
this.springs[i].update(dt);
}
for (i = 0, n = this.particles.length; i < n; ++i) {
this.particles[i].update(dt);
}
}
};
// Create a new system
var sim = new Sim(),
old = new Date().getTime(),
canvas = document.getElementById('world'),
context = canvas.getContext('2d');
function init() {
var np,
op,
mouse,
anchor,
step = STEP,
length = LENGTH,
count = length / step;
var sx = canvas.width * 0.5;
var sy = canvas.height * 0.5;
for (var i = 0; i < count; ++i) {
//np = new Particle(i*8,i*8,0.1+Math.random()*0.01);
np = new Particle(sx + (Math.random() - 0.5) * 200, sy + (Math.random() - 0.5) * 200, 0.1 + Math.random() * 0.01);
sim.particles.push(np);
if (i > 0) {
s = new Spring(np, op, step, 0.95);
sim.springs.push(s);
}
op = np;
}
// Fix the first particle
anchor = sim.particles[0];
//anchor.fixed = true;
anchor.x = 50;
anchor.y = 50;
// Move last particle with mouse
mouse = sim.particles[count - 1];
mouse.fixed = true;
canvas.addEventListener('mousemove', function (event) {
mouse.x = event.clientX;
mouse.y = event.clientY;
});
};
function step() {
var now = new Date().getTime(),
delta = now - old;
sim.tick(delta);
// Clear canvas
canvas.width = canvas.width;
var points = []; // Midpoints
var angles = []; // Delta angles
var i, n, p1, p2, dx, dy, mx, my, sin, cos, theta;
// Compute midpoints and angles
for (i = 0, n = sim.particles.length - 1; i < n; ++i) {
p1 = sim.particles[i];
p2 = sim.particles[i + 1];
dx = p2.x - p1.x;
dy = p2.y - p1.y;
mx = p1.x + dx * 0.5;
my = p1.y + dy * 0.5;
points[i] = {
x: mx,
y: my
};
angles[i] = Math.atan2(dy, dx);
}
// Render
context.beginPath();
for (i = 0, n = points.length; i < n; ++i) {
p1 = sim.particles[i];
p2 = points[i];
theta = angles[i];
r = Math.sin((i / n) * Math.PI) * THICKNESS;
sin = Math.sin(theta - HALF_PI) * r;
cos = Math.cos(theta - HALF_PI) * r;
context.quadraticCurveTo(
p1.x + cos,
p1.y + sin,
p2.x + cos,
p2.y + sin);
}
for (i = points.length - 1; i >= 0; --i) {
p1 = sim.particles[i + 1];
p2 = points[i];
theta = angles[i];
r = Math.sin((i / n) * Math.PI) * THICKNESS;
sin = Math.sin(theta + HALF_PI) * r;
cos = Math.cos(theta + HALF_PI) * r;
context.quadraticCurveTo(
p1.x + cos,
p1.y + sin,
p2.x + cos,
p2.y + sin);
}
context.strokeStyle = 'rgba(255,255,255,0.1)';
context.lineWidth = 8;
context.stroke();
context.strokeStyle = 'rgba(0,0,0,0.8)';
context.lineWidth = 0.5;
context.stroke();
context.fillStyle = 'rgba(255,255,255,0.9)';
context.fill();
old = now;
setTimeout(step, FPS);
};
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener("resize", resize);
resize();
init();
step();
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
<canvas id='world' width='500' height='500'></canvas>
<header><h1>Wiggle your mouse...</h1></header>
Here is one way:
HTML:
<div class="top">
top
</div>
<div class="middle">
<canvas id='world' width='500' height='500'></canvas>
<header><h1>Wiggle your mouse...</h1></header>
</div>
<div class="bottom">
bottom
</div>
CSS:
div {
border: 1px solid black
}
.top, .bottom {
height: 200px
}
The js remains the same. The CSS gives the top and bottom divs some height. The canvas is in the middle div. Here is a jsfiddle: https://jsfiddle.net/av902pcs/

Why is camera's position not correctly calculated (canvas)

I am making a clone of agar.io and I am stuck in my code. I can't understand why my camera's position is not correctly calculated. I want my camera's position to half the vector between the farthest blob and the closest blob.
Below is a picture and my code:
<html>
<head>
<title>Play Agario Clone</title>
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="game">
kindly update your browser.
</canvas>
<script>
var
canvas,
ctx,
width = innerWidth,
height = innerHeight,
mouseX = 0,
mouseY = 0;
var
camera = {
x: 0,
y: 0,
// camera
update: function(obj) {
var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var x = farthestBlobX - closestBlobX;
var y = farthestBlobY - closestBlobY;
var length = Math.sqrt(x * x + y * y);
this.x = length/2 - width/2;
this.y = length/2 - height/2;
}
},
player = {
defaultMass: 54,
x: 0,
y: 0,
blobs: [],
update: function () {
for (var i = 0; i < this.blobs.length; i ++) {
var x = mouseX + camera.x - this.blobs[i].x;
var y = mouseY + camera.y - this.blobs[i].y;
var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var speed = 54/this.blobs[i].mass;
this.blobs[i].velX = x/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].velY = y/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].x += this.blobs[i].velX;
this.blobs[i].y += this.blobs[i].velY;
for (var j = 0; j < this.blobs.length; j ++) {
if (j != i && this.blobs[i] !== undefined) {
var blob1 = this.blobs[i];
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
if (dist < blob1.mass + blob2.mass) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
}
}
}
}
this.x += (mouseX - width/2)/(width/2) * 1;
this.y += (mouseY - height/2)/(height/2) * 1
},
split: function (cell) {
cell.mass /= 2;
this.blobs.push({
x: cell.x,
y: cell.y,
mass: cell.mass
});
},
draw: function () {
for (var i = 0; i < this.blobs.length; i ++) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(-camera.x + this.blobs[i].x, -camera.y + this.blobs[i].y, this.blobs[i].mass, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
}
};
function handleMouseMove (e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function setup () {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push({
x: 0,
y: 0,
mass: player.defaultMass
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass/2
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass*2
});
var loop = function () {
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
function update () {
camera.update(player);
player.update();
}
function draw () {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
player.draw();
}
setup();
</script>
</body>
</html>
Instead of computing everything relative to your camera, use your camera to set the global transformation matrix of your canvas, and only for this.
This way, your blobs' updates will be cleaner, and your camera easier to manage.
Now to get the middle position between two points, do (pt1 + pt2) / 2.
You were not clear in your question, if fartherstX and fartherstY should represent the same blob. In your code it wasn't, so I didn't change it.
Also, I didn't gone into all your logics, but beware NaN values, I got some while doing the edit.
function draw() {
var cw = ctx.canvas.width / 2;
var ch = ctx.canvas.height / 2;
// reset transform to clear the canvas
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
// here we really set the camera position
ctx.setTransform(1, 0, 0, 1, -camera.x + cw, -camera.y + ch);
ctx.strokeRect(0, 0, width, height); // just to show the original area
player.draw();
}
var
canvas,
ctx,
width = innerWidth,
height = innerHeight,
mouseX = 0,
mouseY = 0;
var camera = {
x: 0,
y: 0,
// camera
update: function(obj) {
var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) {
return cell.x
}));
var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) {
return cell.y
}));
var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) {
return cell.x
}));
var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) {
return cell.y
}));
this.x = (closestBlobX + farthestBlobX) / 2 || 0;
this.y = (closestBlobY + farthestBlobY) / 2 || 0;
}
},
player = {
defaultMass: 54,
x: 0,
y: 0,
blobs: [],
update: function() {
for (var i = 0; i < this.blobs.length; i++) {
var x = mouseX - this.blobs[i].x || 0;
var y = mouseY - this.blobs[i].y || 0;
var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var speed = 54 / this.blobs[i].mass;
this.blobs[i].velX = x / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].velY = y / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].x += this.blobs[i].velX;
this.blobs[i].y += this.blobs[i].velY;
for (var j = 0; j < this.blobs.length; j++) {
if (j != i && this.blobs[i] !== undefined) {
var blob1 = this.blobs[i];
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
if (dist < blob1.mass + blob2.mass) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
}
}
}
}
this.x += (mouseX - width / 2) / (width / 2) * 1;
this.y += (mouseY - height / 2) / (height / 2) * 1;
},
split: function(cell) {
cell.mass /= 2;
this.blobs.push({
x: cell.x,
y: cell.y,
mass: cell.mass
});
},
draw: function() {
for (var i = 0; i < this.blobs.length; i++) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(this.blobs[i].x, this.blobs[i].y, this.blobs[i].mass, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
}
}
};
function handleMouseMove(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function setup() {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push({
x: 10,
y: 10,
mass: player.defaultMass
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass / 2
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass * 2
});
var loop = function() {
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
function update() {
camera.update(player);
player.update();
}
setup();
body {
margin: 0;
padding: 0;
}
<canvas id="game">kindly update your browser.</canvas>
I see there is an answer already..
var canvas;
var ctx;
var width = innerWidth;
var height = innerHeight;
var mouseX = 0;
var mouseY = 0;
const camera = {
x : 0,
y : 0,
update(obj) { // camera
this.x = (obj.blobsExtent.minx + obj.blobsExtent.maxx) / 2;
this.y = (obj.blobsExtent.miny + obj.blobsExtent.maxy) / 2;
this.x -= width / 2;
this.y -= height / 2;
}
};
const player = {
defaultMass : 54,
blobs : [],
blobsExtent : { // get the extent while updating the blobs save you having to iterate all the objects a second time to get extent
minx :0,
miny : 0,
maxx : 0,
maxy : 0,
},
update () {
var be = this.blobsExtent; // be for Blob Extent alias to save typing and make code easier to read
for (var i = 0; i < this.blobs.length; i++) {
var blob1 = this.blobs[i];
var x = mouseX - blob1.x;
var y = mouseY - blob1.y;
// to stop the divide by zero propigating NaN set length to 1 if less than 1
var length = Math.max(1,Math.sqrt(x * x + y * y)); // x * x is quicker than Math.pow(x,2)
var speed = 54 / blob1.mass;
blob1.velX = x / length * speed * Math.min(1, Math.pow(x / blob1.mass, 2));
blob1.velY = y / length * speed * Math.min(1, Math.pow(x / blob1.mass, 2));
blob1.x += blob1.velX;
blob1.y += blob1.velY;
for (var j = 0; j < this.blobs.length; j++) {
if (j != i) {
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
var radTotal = blob1.mass + blob2.mass;
if (dist < radTotal) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * radTotal;
blob1.y = blob2.y - y * radTotal;
}
}
}
if(i === 0){ // use first blob to setup min max
be.maxx = be.minx = blob1.x;
be.maxy = be.miny = blob1.y;
}else{
be.maxx = Math.max(be.maxx, blob1.x);
be.maxy = Math.max(be.maxy, blob1.y);
be.minx = Math.min(be.minx, blob1.x);
be.miny = Math.min(be.miny, blob1.y);
}
}
},
split (cell) {
cell.mass /= 2;
this.blobs.push(createBlob(cell.x, cell.y, cell.mass));
},
draw () {
var b; // alias for blob
ctx.fillStyle = "red"; // all the same colour then can render as one path
ctx.setTransform(1,0,0,1,-camera.x,-camera.y);
ctx.beginPath();
for (var i = 0; i < this.blobs.length; i++) {
b = this.blobs[i];
ctx.arc( b.x, b.y, b.mass, 0, Math.PI * 2);
ctx.closePath();
}
ctx.fill();
ctx.setTransform(1,0,0,1,0,0); // restore default transform
}
};
function handleMouseMove(e) {
mouseX = e.clientX + camera.x;
mouseY = e.clientY + camera.y;
}
function createBlob(x,y,mass){ return {x,y,mass} }
function setup() {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push(createBlob(0,0,player.defaultMass));
player.blobs.push(createBlob(100,100,player.defaultMass / 2));
player.blobs.push(createBlob(100,100,player.defaultMass * 2));
}
function update() {
camera.update(player);
player.update();
}
function draw() {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
player.draw();
}
function loop() {
update();
draw();
requestAnimationFrame(loop);
}
setup();
requestAnimationFrame(loop);
body {
margin: 0;
padding: 0;
}
<canvas id="game"></canvas>

Js - calculate distance from point mapped to colour forms square?

I am working on a project where I visualise the effect of a magnetic dipole, on a range of vectors, I'm just testing with one pole at the moment and something doesn't work but I don't know why.
the force that a vector receives is mapped onto a color to check if I did it right, these are my results:
so this is the canvas I'm working with
and when I lower the size of each vector and increase the density you can see this forms diamonds rather than a circular pattern.
Does anybody know why this is or what could be causing it?
code below here:
function calcForce(magnet, vector){
return 1/distance(magnet.x,magnet.y,vector.centerx,vector.centery) * magnet.force;
}
function distance(cx, cy, ex, ey){
var dy = Math.abs(ey - cy);
var dx = Math.abs(ex - cx);
return Math.sqrt((dx^2) + (dy^2));
}
function mapRainbow(value) {
return 'hsl(' + value + ',100%,50%)';
}
function map_range(value, low1, high1, low2, high2) {
return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
}
function mapForce(force){
return map_range(force,10,1000,20,40);
}
function drawStroke(stroke){
ctx.beginPath();
ctx.moveTo(stroke.x1,stroke.y1);
ctx.lineTo(stroke.x2,stroke.y2);
stroke.color = mapRainbow(stroke.force);
ctx.strokeStyle = stroke.color;
ctx.stroke();
ctx.closePath();
}
*this is not all the code by far but I think this is enough, need to see more? just ask.
Use distance to generate gradient:
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 -= x1) * x2 + (y2 -= y1) * y2);
}
function angleBetweenPoints(x1, y1, x2, y2) {
return (Math.atan2(x2 - x1, y2 - y1) + 2 * Math.PI);
}
var center = { x: 250, y: 250 };
var vectorLength = 15;
function max(v, m) {
if (v > m) {
return m;
}
return v;
}
function draw() {
if (Math.random() > 0.5) {
center.x += (Math.random() - 0.5) * 10;
}
else {
center.y += (Math.random() - 0.5) * 10;
}
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var xIndex = 0; xIndex < canvas.width; xIndex += vectorLength) {
for (var yIndex = 0; yIndex < canvas.height; yIndex += vectorLength) {
var x = xIndex - (Math.random() * vectorLength * 0.0);
var y = yIndex - (Math.random() * vectorLength * 0.0);
var angle = angleBetweenPoints(center.x, center.y, x, y);
var dist = distance(x, y, center.x, center.y);
ctx.fillStyle = "rgb(" + Math.floor(max(dist, 255)) + "," + Math.floor((255 - max(dist, 255))) + ",0)";
ctx.translate((x + vectorLength * 0.5), (y + vectorLength * 0.5));
ctx.rotate(-angle);
ctx.fillRect(0 - vectorLength * 0.5, 0 - vectorLength * 0.5, vectorLength * 0.25, vectorLength * 0.75);
ctx.rotate(angle);
ctx.translate(0 - (x + vectorLength * 0.5), 0 - (y + vectorLength * 0.5));
}
}
ctx.fillRect(center.x + vectorLength / 2, center.y + vectorLength / 2, vectorLength, vectorLength);
requestAnimationFrame(function () {
setTimeout(draw, 1000 / 60);
});
}
draw();

Categories

Resources