我的 JavaScript 粒子碰撞引擎无法渲染,“粒子不是构造函数”错误

问题描述 投票:0回答:1

我有以下代码,我尝试在其中创建基本粒子碰撞的引擎。但是,它无法渲染并留下一个空画布,并显示错误:“粒子不是构造函数”。请帮助解决这个问题,以及对引擎的建议。

我尝试将临时“Particle”变量更改为“p”。我的代码如下:

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()

以下为错误部分:

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();
    
}

感谢您的阅读。

javascript constructor html5-canvas
1个回答
1
投票

您似乎缺少函数调用(其中一些)的

()
,并且函数
Physics()
还不能很好地工作 - 这是因为错误的变量名称(
XVel
vs
Xvel
)。最后的奖励是,你不能与自己相撞,因此将这个条件添加到
isCollide

您可能遇到的其他问题是边界(更新:我对这种情况做了一些检查)和时间因素,您应该有变量

t
,它将根据经过的时间而不是根据超时的频率增加。

还可以考虑为此使用库,例如 matter.js

var Canvas = document.createElement('canvas');

Canvas.width = 400;
Canvas.height = 180;
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;

    // 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()

© www.soinside.com 2019 - 2024. All rights reserved.