积极地在p5.js中的“半透明”区域下面画画

时间:2016-09-22 03:11:55

标签: p5.js

当我开发一个更大的p5.js草图时,我遇到了一个令人费解的问题,而我的解决方案并不适合我。所以,我把它归结为这个(公认的蹩脚)草图。

这个p5.js草图每帧绘制几个随机大小和彩色的点。在画布的中心是一个半透明的蓝色填充矩形,看起来在观察者和点之间。这是半透明的蓝色区域是问题所在。草图有效,但我不禁想到有更好的方法来实现半透明度。

var cells;
var cellsz = 10;
var wid, hgt;

function setup()
{
  wid = floor(windowWidth / cellsz);
  hgt = floor(windowHeight / cellsz);
  createCanvas(windowWidth, windowHeight);
  frameRate(15);

  cells = new Array(wid);

  for (x = 0; x < wid; x++) {
    cells[x] = new Array(hgt);
    for (y = 0; y < hgt; y++) {
      cells[x][y] = false;
    }
  }
}

function cell_draw(c)
{
  strokeWeight(1);
  stroke(c.r, c.g, c.b);
  fill(c.r, c.g, c.b);
  ellipse(c.x, c.y, c.w, c.w);
}

function cell_new()
{
  var x = int(floor(random(wid)));
  var y = int(floor(random(hgt)));

  var c = {
    x: x * cellsz,
    y: y * cellsz,
    w: random(cellsz * 2),
    r: floor(random(256)),
    g: floor(random(256)),
    b: floor(random(256))
  };

  cells[x][y] = c;
  cell_draw(c);
}

// draw a translucent blue filled rectangle in the center of the window
function overlay()
{
  strokeWeight(1);
  stroke(0, 0, 255, 75);
  fill(0, 0, 255, 75);
  var w = windowWidth / 4;
  var h = windowHeight / 4;
  rect(w, h, w * 2, h * 2);
}

// erase what's in the center of the window, then redraw the underlying cells
function underlay()
{
  strokeWeight(1);
  stroke(255);
  fill(255);
  var w = windowWidth / 4;
  var h = windowHeight / 4;
  rect(w, h, w * 2, h * 2);

  var x0 = floor((w / cellsz) - 2);
  var y0 = floor((h / cellsz) - 2);
  var x1 = floor(x0 + 3 + ((w * 2) / cellsz));
  var y1 = ceil(y0 + 3 + ((h * 2) / cellsz));

  for (x = x0; x <= x1; x++) {
    for (y = y0; y <= y1; y++) {
      if (cells[x][y]) {
        cell_draw(cells[x][y]);
      }
    }
  }
}

function draw()
{
  underlay();

  for (i = 0; i < 5; i++) {
    cell_new();
  }

  overlay();
}
body {padding: 0; margin: 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.js"></script>

代码背后的基本思想是将画布量化为固定大小的cells。每个单元格保存零个或一个点对象(其位置,直径和颜色)。当选择每个新的随机点时,它将被保存到适当的单元格中。这用作画布中的内容的逻辑内存。 (但这并不完美,因为它不能处理绘制点的顺序。但是,无论如何,我们都是这里的朋友。)

我在解决半透明区域的基本问题。最初,我每次都重绘整个框架,似乎是处理方式...但是有太多的对象。画每一帧花了太长时间。最后,我最终吹走半透明矩形下面的区域,重新绘制受影响的物体,然后在顶部铺设一个新的半透明矩形。

我可以在这里应用哪种技术表现更好,或者使用更少的代码,或者......(喘气)两种技术?

1 个答案:

答案 0 :(得分:2)

您的方法非常合理,但您可以通过基本上使用缓冲区图像来存储底衬而不是2D数组来简化它。画出你的点,然后每个帧简单地将整个缓冲区绘制到屏幕上,然后在其上绘制矩形叠加层。这样做的好处是不会限制自己的数组位置,并且它将来会对类似的分层问题起作用。

有关详细信息,请参阅我的回答here,但基本方法可能是这样的:

var buffer;

function setup() {
  createCanvas(windowWidth, windowHeight);
  frameRate(15);

  buffer = createGraphics(width, height);
  
  //start with white background
  buffer.background(255);
}

function drawRandomCircleToBuffer() {
  buffer.noStroke();
  buffer.fill(random(255), random(255), random(255));
  var diameter = random(5, 20);
  buffer.ellipse(random(buffer.width), random(buffer.height), diameter, diameter);
}

function overlay() {
  strokeWeight(1);
  stroke(0, 0, 255, 75);
  fill(0, 0, 255, 75);
  rect(mouseX, mouseY, 200, 200);
}

function draw() {
  
  drawRandomCircleToBuffer();

  image(buffer, 0, 0);
  overlay();
}
body {padding: 0; margin: 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.js"></script>