I have the following code in which I attempt to create an engine for basic particle collisions. However, it is failing to render and leaves an empty canvas with the error: "Particle is not a constructor". Please aid in solving this problem, as well as suggestions for the engine.
I have tried changing the temporary 'Particle' variable to 'p'. My code is as follows:
var Canvas = document.createElement('canvas');
Canvas.width = 300;
Canvas.height = 300;
Canvas.style = 'border: 1px solid black';
document.body.appendChild(Canvas);
var CTX = Canvas.getContext('2d');
var ParticleIndex = [];
function Particle(X, Y, Xvel, Yvel, Size, Xfric, Yfric, Xacc, Yacc, Bounce){
this.X = X;
this.Y = Y;
this.XVel = Xvel;
this.YVel = Yvel;
this.Size = Size;
this.Xfric = Xfric;
this.Yfric = Yfric;
this.Xacc = Xacc;
this.Yacc = Yacc;
this.Bounce = Bounce
this.appendToIndex = function(){
ParticleIndex.push(this);
}
this.Render = function(){
CTX.fillRect(this.X, this.Y, this.Size, this.Size);
};
this.Physics = function(){
this.X += this.Xvel;
for(var i = 0; i < ParticleIndex.length; i++){
if(isCollide(this, ParticleIndex[i])){
this.X -= this.Xvel
this.Xvel *= this.Bounce * -1;
}
}
this.Y += this.Yvel;
for(var i = 0; i < ParticleIndex.length; i++){
if(isCollide(this, ParticleIndex[i])){
this.Y -= this.Yvel
this.Yvel *= this.Bounce * -1;
}
}
this.Xvel *= this.Xfric;
this.Yvel *= this.Yfric;
}
}
function isCollide(a, b) {
return !(
((a.Y + a.Size) < (b.Y)) ||
(a.Y > (b.Y + b.Size)) ||
((a.X + a.Size) < b.X) ||
(a.X > (b.X + b.Size))
);
}
function Render(){
CTX.clearRect(0, 0, Canvas.width, Canvas.height);
for(var k = 0; k < ParticleIndex.length; k++){
ParticleIndex[k].Physics;
ParticleIndex[k].Render;
}
}
for(var j = 0; j < 100; j++){
var p = new Particle(
Math.round(Math.random() * Canvas.width),
Math.round(Math.random() * Canvas.height),
(Math.random * 10) - 5,
(Math.random * 10) - 5,
5,
0.9,
0.9,
0,
0,
0.8
)
p.appendToIndex();
p.Render();
}
alert('Rendering...');
Render()
The following part gives the error:
for(var j = 0; j < 100; j++){
var p = new Particle(
Math.round(Math.random() * Canvas.width),
Math.round(Math.random() * Canvas.height),
(Math.random * 10) - 5,
(Math.random * 10) - 5,
5,
0.9,
0.9,
0,
0,
0.8
)
p.appendToIndex();
p.Render();
}
Thank you for reading.
You seem to be missing ()
for the function calls ( a few of them), and the function Physics()
doesn't work well, yet – it is because bad variable names (XVel
vs Xvel
). And the final bonus, you can't collide with yourself therefore added that condition to isCollide
.
Other Issues you might have are the boundaries (update: I did some checking for this case), and time factor, you should have variable t
which will increase according to time passed, not according to frequency of timeout.
Also consider using a library for this, such as matter.js
var Canvas = document.createElement('canvas');
Canvas.width = 400;
Canvas.height = 180;
Canvas.style = 'border: 1px solid black; background: white;';
document.body.appendChild(Canvas);
var CTX = Canvas.getContext('2d');
var ParticleIndex = [];
function Particle(X, Y, Xvel, Yvel, Size, Xfric, Yfric, Xacc, Yacc, Bounce) {
this.X = X;
this.Y = Y;
this.Xvel = Xvel;
this.Yvel = Yvel;
this.Size = Size;
this.Xfric = Xfric;
this.Yfric = Yfric;
this.Xacc = Xacc;
this.Yacc = Yacc;
this.Bounce = Bounce
this.appendToIndex = function() {
ParticleIndex.push(this);
}
this.Render = function() {
CTX.fillRect(this.X, this.Y, this.Size, this.Size);
};
this.Physics = function() {
this.X += this.Xvel;
for (var i = 0; i < ParticleIndex.length; i++) {
if (isCollide(this, ParticleIndex[i])) {
this.X -= this.Xvel
this.Xvel *= this.Bounce * -1;
}
}
this.Y += this.Yvel;
for (var i = 0; i < ParticleIndex.length; i++) {
if (isCollide(this, ParticleIndex[i])) {
this.Y -= this.Yvel
this.Yvel *= this.Bounce * -1;
}
}
this.Xvel *= this.Xfric;
this.Yvel *= this.Yfric;
// boundaries
if (this.X < 0) {
this.X = 0
this.Xvel *= this.Bounce * -1;
}
if (this.Y < 0) {
this.Y = 0
this.Yvel *= this.Bounce * -1;
}
if (this.X + this.Size > Canvas.width - 1) {
this.X = Canvas.width - this.Size - 1
this.Xvel *= this.Bounce * -1;
}
if (this.Y + this.Size > Canvas.height - 1) {
this.Y = Canvas.height - this.Size - 1
this.Yvel *= this.Bounce * -1;
}
}
}
function isCollide(a, b) {
if (a == b) {
return false
}
return !(
((a.Y + a.Size) < (b.Y)) ||
(a.Y > (b.Y + b.Size)) ||
((a.X + a.Size) < b.X) ||
(a.X > (b.X + b.Size))
);
}
function Render() {
CTX.clearRect(0, 0, Canvas.width, Canvas.height);
for (var k = 0; k < ParticleIndex.length; k++) {
ParticleIndex[k].Physics();
ParticleIndex[k].Render();
}
requestAnimationFrame(Render)
}
for (var j = 0; j < 10; j++) {
var Size = 12;
var p = new Particle(
Math.round(Math.random() * (Canvas.width - Size)),
Math.round(Math.random() * (Canvas.height - Size)),
(Math.random() * 10) - 5,
(Math.random() * 10) - 5,
Size,
0.999,
0.999,
0,
0,
1
)
p.appendToIndex();
// p.Render();
}
Render()