【问题标题】:How do I fill a rectangle or ellipse with a gradient in Processing?如何在处理中用渐变填充矩形或椭圆?
【发布时间】:2021-03-03 20:35:49
【问题描述】:

我试图让我的桨从白色变为渐变(线性)并且球具有径向渐变。感谢您的帮助!您可以在 void drawPaddle 中找到桨的代码。

这是我的目标:

这是我的代码: //球 国际球X = 500; 国际球Y = 350; 国际球高度 = 35; int ballWidth = 35; 诠释速度X = 4; int speedY = 4; int 方向X = 1;
int方向Y = 1;

//Paddles
int player1X = 30;
int player2X = 830;
int player1Y = 350;
int player2Y = 350;

//Healthbars
int bar1X = 100;
int bar1Y = 20;
int player1health = 100;
int bar1colour = #22E515;
int bar2X = 700;
int bar2Y = 20;
int player2health = 100;
int bar2colour = #22E515;

//Movements
boolean upX = false;
boolean downX = false;
boolean upY = false;
boolean downY = false;

void setup() {
  size(900, 700);
}

void draw() {
  background(55, 68, 120);

drawPaddle();

  //EmptySpace**
  fill(55, 68, 120);
  noStroke();
  rect(player1X, player1Y, 40, 140);
  rect(player2X, player2Y, 40, 140);
  
  //Healthbars
  fill(bar1colour);
  rect(bar1X, bar1Y, player1health, 15);
  fill(bar2colour);
  rect(bar2X, bar2Y, player2health, 15);

  //Ball
  fill(194, 16, 0);
  ellipse(ballX, ballY, ballHeight, ballWidth);
  

  moveCircle();
  movePaddle();
  moveCollisions();
}

void drawPaddle() {  
  fill(255);
  noStroke();
  rect(30, 0, 40, 1000);
  rect(830, 0, 40, 1000);
}

void moveCircle() {  
  ballX = ballX + speedX * 1;
  ballY = ballY + speedY * 1;

  if (ballX > width- ballWidth +20 || ballX < ballWidth) {
    speedX *= -1;
  }
  if (ballY > height- ballHeight +20 || ballY < ballHeight) {
    speedY *= -1;
  }
}

void movePaddle() {
  //key movements
  if (upX == true) {
    player1Y = player1Y - 5;
  }
  if (downX == true) {
    player1Y = player1Y + 5;
  }
  if (upY == true) {
    player2Y = player2Y - 5;
  }
  if (downY == true) {
    player2Y = player2Y + 5;
  } 

  //Wrap around
  if (player1Y > 700) {
    player1Y = 0;
  } else if (player1Y + 140 < 0) {
    player1Y = 700;
  }
  if (player2Y > 700) {
    player2Y = 0;
  } else if (player2Y + 140 < 0) {
    player2Y = 700;
  }
}

void moveCollisions() {
  //Collisions
  if ((ballX - ballWidth / 2 < player1X + 40) && ((ballY - ballHeight / 2 > player1Y + 140) || (ballY + ballHeight / 2 < player1Y))) {
    if (speedX < 0) {
      player1health -= 20;
      speedX = -speedX*1;
      if (player1health == 20) {
        bar1colour = #F51911;
      }
    }
  } else if ((ballX + ballWidth / 2 > player2X) && ((ballY - ballHeight / 2 > player2Y + 140) || (ballY + ballHeight/2 < player2Y))) {
    if (speedX > 0) {
      player2health -= 20;
      bar2X += 20;
      speedX = -speedX*1;
      if (player2health == 20) {
        bar2colour = #F51911;
      }
    }
  }
}

void keyPressed() {
  if (key == 'w' || key == 'W') {
    upX = true;
  } else if (key == 's' || key == 'S') {
    downX = true;
  } else if (keyCode == UP) {
    upY = true;
  } else if (keyCode == DOWN) {
    downY = true;
  }
}

void keyReleased() {
  if (key == 'w' || key == 'W') {
    upX = false;
  } else if (key == 's' || key == 'S') {
    downX = false;
  } else if (keyCode == UP) {
    upY = false;
  } else if (keyCode == DOWN) {
    downY = false;
  }
}

【问题讨论】:

    标签: processing gradient


    【解决方案1】:

    我为这种目的(在处理中绘制颜色渐变)编写了一个名为 PeasyGradients 的库 — 从 Github 版本下载 .jar 并将其拖放到您的草图上.它将 1D 渐变作为 2D 光谱渲染到您的草图或给定的PGraphics 对象中。

    以下是使用所需渐变绘制线性和径向光谱的示例:

    PeasyGradients renderer;
    PGraphics rectangle, circle, circleMask;
    
    final Gradient pinkToYellow = new Gradient(color(227, 140, 185), color(255, 241, 166));
    
    void setup() {
      size(800, 800);
    
      renderer = new PeasyGradients(this);
    
      rectangle = createGraphics(100, 400);
      renderer.setRenderTarget(rectangle); // render into rectangle PGraphics
      renderer.linearGradient(pinkToYellow, PI/2); // gradient, angle
    
      circle = createGraphics(400, 400);
      renderer.setRenderTarget(circle);  // render into circle PGraphics
      renderer.radialGradient(pinkToYellow, new PVector(200, 200), 0.5); // gradient, midpoint, zoom
    
      // circle is currently a square image of a radial gradient, so needs masking to be circular  
      circleMask = createGraphics(400, 400);
      circleMask.beginDraw();
      circleMask.fill(255); // keep white pixels
      circleMask.circle(200, 200, 400);
      circleMask.endDraw();
    
      circle.mask(circleMask);
    }
    
    void draw() {
      background(255);
    
      image(rectangle, 50, 50);
    
      image(circle, 250, 250);
    }
    

    【讨论】:

    【解决方案2】:

    您可以尝试为您正在绘制的每个矩形创建一个PGraphics 对象,使用linear interpolation 填充渐变色,然后在drawPaddle() 中使用image(pgraphic, x, y) 而不是使用rect(x1, y1, x2, y2)

    以下是在处理中使用lerpColor() 创建渐变效果的方法:

    • 将渐变的起点设为(x1, y1),终点设为(x2, y2)
    • 将开始和结束颜色设为c1c2
    • 现在对于点 P (x, y),计算起点和 P 之间的距离,然后将其除以起点和终点之间的距离。这将是从开始颜色和结束颜色开始的“数量”。 float t = dist(x1, y1, x, y) / dist(x1, x2, y1, y2)
    • 将此值作为lerpColor(c1, c2, value) 放入lerpColor()。这将为您提供点 P 的颜色。
    • 对要计算梯度的每个点重复相同的操作。

    这是一个例子: 注意:在这里,我将t 计算为 渐变起点之间的距离除以渐变起点和终点之间的距离,因为它总是是介于 0 和 1 之间的值。

    PGraphics g = createGraphics(50, 200); // set these values to the size(width, height) of paddle you want 
        color startColor = color(255, 25, 25); // color of start of the gradient
        color endColor   = color(25, 25, 255); // color of end of the gradient
        
        g.beginDraw(); //start drawing in this as you would draw in the screen
        g.loadPixels();//load pixels, as we are going to set the color of this, pixel-by-pixel
        
        int x1 = g.width/2;
        int y1 = 0;
        int x2 = g.width/2;
        int y2 = g.height;
        
        // (x1, y1) is the start point of gradient
        // (x2, y2) is the end point of gradient
        
        // loop through all the pixels
        for (int x=0; x<g.width; x++) {
            for (int y=0; y<g.height; y++) {
                
                //amout to lerp, the closer this is to (x2, y2) it will get closer to endColor
                float t = dist(x1, y1, x, y) / dist(x1, y1, x2, y2);
                
                // you need to convert 2D indices to 1D, as pixels[] is an 1D array
                int index = x + y * g.width;
                g.pixels[index] = lerpColor(startColor, endColor, t);
            }
        }
        g.updatePixels(); // update the pixels
        g.endDraw(); // we are done drawing into this
        
        // Now, you can draw this using image(g, x, y);
    

    这是我在全局范围内创建它然后使用image(g, width/2 ,height/2)draw() 中绘制它时的结果:

    现在,您可以根据自己的喜好修改所有内容。
    如果对您有任何帮助,请将其标记为答案。

    【讨论】:

    • 我也喜欢这个解决方案的外观,但我无法让它发挥作用。发布完整的工作草图而不是部分代码非常容易 - 你能发布完整的工作草图吗?
    • @RichJohnstone 当然,here 是完整的代码
    【解决方案3】:

    很好的问题和很棒的 mycycle 和 void main 的答案已经很棒了。 PeasyGradients library 看起来很棒!

    我想提供一个小解决方法:使用P2D 渲染器通过形状处理渐变:

    size(100,100,P2D);// render via OpenGL
    noStroke();
    // draw the rect by manually setting vertices
    beginShape();
    // gradient start
    fill(#fef1a6);
    vertex(0  ,  0); // TL  
    vertex(100,  0); // TR
    // gradient end
    fill(#e28ab9);
    vertex(100,100); // BR
    vertex(  0,100); // BL
    
    endShape();
    

    对于更复杂的形状,这可以与mask() 结合使用。不仅PImage可以被屏蔽,PGraphics也可以被屏蔽,因为它们继承自PImage

    PGraphics gradient;
    PGraphics mask;
    
    void setup() {
      size(640, 360, P2D);
      
      gradient = getGradientRect(width, height, #fef1a6, #e28ab9);
      mask = getMaskRect(width, height);
    }
    
    void draw() {
      background(#483b6c);
      drawPongShapes();
      // apply pong shapes mask to gradient
      gradient.mask(mask);
      // render masked gradient
      image(gradient, 0, 0);
    }
    // draw white shapes (masks) on black background
    void drawPongShapes(){
      mask.beginDraw();
      mask.background(0);
      mask.ellipse(width * 0.5, height * 0.5, 60, 60);
      mask.rect(width * .25, mouseY, 30, 150);
      mask.rect(width * .75, height-mouseY, 30, 150);
      mask.endDraw();
    }
    
    PGraphics getMaskRect(int w, int h) {
      PGraphics layer = createGraphics(w, h, P2D);
      layer.beginDraw();
      layer.background(0);
      layer.noStroke();
      layer.fill(255);
      layer.ellipseMode(CENTER);
      layer.rectMode(CENTER);
      layer.endDraw();
      return layer;
    }
    
    PGraphics getGradientRect(int w, int h, color grad1, color grad2) {
      PGraphics layer = createGraphics(w, h, P2D);
      layer.beginDraw();
      layer.noStroke();
      // draw rect as shape quad
      layer.beginShape();
      
      // gradient start
      layer.fill(grad1);
      layer.vertex(0, 0); // TL  
      layer.vertex(w, 0); // TR
      // gradient end
      layer.fill(grad2);
      layer.vertex(w, h); // BR
      layer.vertex(0, h); // BL
      
      layer.endShape();
      layer.endDraw();
      return layer;
    }
    

    【讨论】:

    • 我喜欢你的解决方案的外观,但是当我运行你的代码时,所有的乒乓球形状都是黑色的
    猜你喜欢
    • 1970-01-01
    • 2011-06-05
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多