画布仅针对某些粒子进行清除

时间:2017-05-24 16:45:45

标签: javascript canvas

我有这个代码,它在画面中叠加画布粒子,然后在一个画面已满时重置整个画布。

通过设置“particles = []”

来完成此操作

我想通过仅重置该特定通道的画布来修改此行为。有可能吗?

$(document).ready(function () {

"use strict";

var c = document.getElementById("c"),
    ctx = c.getContext("2d"),
    WIDTH = c.width = window.innerWidth,
    HEIGHT = c.height = window.innerHeight;

var particles = [],
    particle = null,
    particleCount = 3,
    radius = 0,
    numParticles = [0, 0, 0, 0, 0, 0],
    colors = ["#00FF6D", "E8D90C", "#FF5900", "#C00CE8", "#0D90FF"];

var Vector = function (x, y) {
    this.x = x || 0;
    this.y = y || 0;
};

Vector.prototype = {
    constructor: Vector,
    add: function (v) {
        this.x += v.x;
        this.y += v.y;
    },
    sub: function (v) {
        this.x -= v.x;
        this.y -= v.y;
    },
    mul: function (v) {
        this.x *= v.x;
        this.y *= v.y;
    }
};

var Particle = function (position, velocity, radius, lane, color) {
    this.position = position;
    this.velocity = velocity;
    this.radius = radius;
    this.baseRadius = radius;
    this.angle = 3;
    this.lane = lane;
    this.color = color;

};

Particle.prototype = {
    constructor: Particle,
    update: function (lane) {
        this.radius = 3;
        this.angle += 10;
        this.position.add(this.velocity);

        // CHECKS FIRST IF THERE'S ALREADY A PARTICLE IN THE LANE AND THEN SHORTENS THE STOP LENGTH
        if (this.position.x > WIDTH - (numParticles[this.lane] + 1) * 120) {

            // IF THERE IS ALREADY A PARTICLE ON A LANE THE NUMBER OF PARTICLES PER IS INCREASED
            if (this.velocity.x > 0) {
                console.log(numParticles[this.lane] + " particles in this lane")
                numParticles[this.lane]++;

                if (numParticles[this.lane] > 8) {
                    numParticles[this.lane] = 0;
                    particles = [];
                }
                // STOPS THE PARTICLE
                this.velocity.x = 0;
            }
        }
    },
    render: function (ctx) {
        for (var i = 0; i < 10; i++) {
            for (var j = 0; j < 5; j++) {
                ctx.beginPath()
                ctx.fillStyle = this.color;
                ctx.arc(this.position.x - i * 12, (this.position.y - 30) + j * 12, this.radius + 0.5, 0, Math.PI * 2);
                ctx.fill();
                ctx.closePath();
            }
        }
    }
};



function addParticle(lane) {
    radius = 3;
    particle = new Particle(
        new Vector(-radius, lane * (HEIGHT) / 5),
        new Vector(5),
        radius,
        lane,
        colors[Math.round(Math.random() * 4)]
    );
    particles.push(particle);
}

requestAnimationFrame(function loop() {
    requestAnimationFrame(loop);
    ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
    ctx.fillRect(0, 0, WIDTH, HEIGHT);

    for (var i = 0, len = particles.length; i < len; i++) {
        particle = particles[i];
        particle.update();
        particle.render(ctx);
    }
});

//
// ─── SOCKETIO CONNECTION TO NODE WEBSERVER RUNNING OPENCV ───────────────────────
//
var socket = io.connect('http://localhost:8000');

// SEND "CONNECTED" MESSAGE ONCE SUCCSEFULLY CONNECTED   
socket.on('connect', function () {
    console.log('connected');
});

socket.on('message', function (msg) {
    console.log(msg);

    // IF NUMBER OF CARS DETECTED IS MORE THAN 0, A PARTICLE WILL BE ADDED RANDOMLY TO ONE OF THE 4 LANES
    if (msg >= 0) {
        addParticle(Math.round((Math.random() * 3) + 1));
    }
});});

1 个答案:

答案 0 :(得分:0)

过滤数组

如果你有一个粒子数组,想要删除一些满足某些条件的项目,有几种方法可以做到。

Array.filter

使用Array.filter

创建一个新数组
var particles = []; // fill with particles
// remove particles in lane 3 using arrow function
particles = particles.filter(particle => particle.lane !== 3);
// or using via function
particles = particles.filter(function(particle){ return particle.lane !== 3});

此方法确实会创建一个新数组,因此会因GC(垃圾收集)和分配开销而受到一些惩罚。此外,如果您对阵列有多个参考,则需要更新所有参考文献。

var particles = [];
const obj = {
    particles : particles,  // referance to the array particles.
}


// remove particles in lane 3
particles = particles.filter(particle => particle.lane !== 3)
// the array referenced by obj.particles still has the unfiltered array
obj.particles = particles; // update reference

要过滤的Array.splice

当需要性能时,可以使用Array.splice从数组中删除项目。它还具有不创建必须传播的新参考的优点。

 for(var i = 0; i <particles.length; i++){  // must use particles.length
     if(particles[i].lane === 3){
         particles.splice(i--,1); // decrease i so you do not skip an item
                                  // as slice will move the index of all 
                                  // items above i down one
     }
  }

  // do not use a variable to store the length in the for loop
  var len = particles.length
  for(var i = 0; i < len; i++){  // will cause unexpected behaviors because
                                 // the array length will change 

标记有效

为获得最佳性能,您需要为所有粒子指定一个标志,以确定粒子是否已更新和渲染。

 for(var i = 0; i <particles.length; i++){  
     particles[i].active = ! particles[i].lane === 3;
 }

在更新和渲染之前,您将检查活动是否为真

 // in render and update loops
 for(var i = 0; i <particles.length; i++){  
      if(particles[i].active){
          particles[i].update(); // or render()  

      }
 }

当然,你有一个不断增长的阵列。要停止数组的无限制增长,请更改设置粒子属性的方式,将方法添加到粒子对象。

 function Particle(){}; // constructor
 Particle.prototype.set = function(pos,vel,foo,bar){
     this.active = true;
     this.velocity = vel;
     //... and the other properties

 }

当您添加粒子时,首先检查粒子数组中是否存在非活动粒子,并通过使用set函数设置其属性来使用它。如果没有非活动粒子,那么您只需创建一个新粒子并将其添加到粒子数组中,并使用set设置其属性。

 function addParticle(pos,vel,foo,bar){
    var i;
    for(i = 0; i < particles.length; i++){
         if(! particles[i].active){
             particles[i].set(pos,vel,foo,bar);
             return;
         }
     }
     // no inactive particles create a new one
     particles.push(
        new Particle().set(pos,vel,foo,bar);
     );
 }