我是Processing的新手,我一直致力于模拟电子运动。 在我尝试为每个粒子添加渐变颜色之前,一切似乎都很好。帧速率大幅下降。
这是我到目前为止所尝试的内容:
float a=0;
float s;
void setup()
{
size(500,500);
smooth();
frameRate(500);
colorMode(HSB,360,100,100);
noStroke();
ellipseMode(RADIUS);
}
void draw()
{
background(200,0,100);
pushMatrix();
translate(width/2, height/2);
rotate(radians(-18));
for ( int r = width ; r >= 0; r = r - 1 )
{
s = 500*exp(-r);
fill(202, s, 100);
ellipse(100*cos(a), 50*sin(a), r, r);
}
a+=0.1;
popMatrix();
}
答案 0 :(得分:11)
您的问题不是关于模拟电子运动,而是关于在Processing中有效绘制渐变的问题。我看到你已经开始使用示例>基础知识>颜色> RadialGradient 样本。请注意,样本本身运行速度非常慢,可能是因为重点关注如何使用颜色(HSB)和绘图功能而不是性能。
你可以做的是使用PGraphics或PImage缓存渐变,这是你更熟悉的。
以下是使用PGraphics的示例,如果您不习惯使用像素,这可能会更简单:
PImage e;
void setup(){
size(500,500);
e = getElectronImg(30,30,0,100,100);//create a cached drawing
}
void draw(){
background(255);
translate(width * .5, height * .5);
float a = frameCount * .1;
image(e,100*cos(a), 50*sin(a));
}
PImage getElectronImg(int w,int h,int hue,int satMax,int brightness){
PGraphics electron = createGraphics(w+1,h+1);//create a PGraphics object
electron.beginDraw();//init drawing using the same Processing drawing functions
electron.colorMode(HSB,360,100,100);
electron.background(0,0);//transparent bg
electron.noStroke();
int cx = electron.width/2;
int cy = electron.height/2;
for (int r = w; r > 0; --r) {
electron.fill(hue,map(r,0,w,satMax,0),brightness);
electron.ellipse(cx, cy, r, r);
}
electron.endDraw();
return electron;
}
值得注意的是,PGraphics扩展了PImage,因此可以使用image()函数和其他PImage一起显示。
这是使用像素完成的相同缓存概念:
PImage e;
void setup(){
size(500,500);
e = getElectronImg(30,30,0,100,100);
}
void draw(){
background(255);
translate(width * .5, height * .5);
float a = frameCount * .1;
image(e,100*cos(a), 50*sin(a));
}
PImage getElectronImg(int w,int h,int hue,int satMax,int brightness){
pushStyle();//isolate drawing styles such as color Mode
colorMode(HSB,360,100,100);
PImage electron = createImage(w,h,ARGB);//create an image with an alpha channel
int np = w * h;//total number of pixels
int cx = electron.width/2;//center on x
int cy = electron.height/2;//center on y
for(int i = 0 ; i < np; i++){//for each pixel
int x = i%electron.width;//compute x from pixel index
int y = (int)(i/electron.width);//compute y from pixel index
float d = dist(x,y,cx,cy);//compute distance from centre to current pixel
electron.pixels[i] = color(hue,map(d,0,cx,satMax,0),brightness,map(d,0,cx,255,0));//map the saturation and transparency based on the distance to centre
}
electron.updatePixels();//finally update all the pixels
popStyle();
return electron;
}
当然,这样可以轻松使用更多的电子。 关于真实电子运动的主题,这里有一些有趣的测试,通过对draw()进行微调:
void draw(){
background(255);
translate(width * .5, height * .5);
for(int i = 0 ; i < 200 ; i++){
float a = (frameCount * .025 + (i*.1));
image(e,(100+i)*cos(a + i), (50+i)*sin(a + i));
}
}
void draw(){
background(255);
translate(width * .5, height * .5);
for(int i = 0 ; i < 1000 ; i++){
float a = (frameCount * .025 + (i*.1));
image(e,(100+(i * .25))*cos(a + i), (50+(i * .25))*sin(a + i));
}
}
void draw(){
background(255);
translate(width * .5, height * .5);
scale(.25);
for(int i = 0 ; i < 5000 ; i++){
float a = (frameCount * .025 + (i*.1));
image(e,sin(a) * (100+(i * .5))*cos(a + i), (50+(i * .25))*sin(a + i));
}
}
玩得开心!
现在你可以在这里实际运行代码(使用键1,2,3,4来改变演示):
var e,demo = 2;
function setup(){
createCanvas(500,500);
e = getGradientImg(30,30,0,100,100);
}
function draw(){
background(255);
translate(width * .5, height * .5);
if(demo == 1){
var a = frameCount * .1;
image(e,100*cos(a), 50*sin(a));
}
if(demo == 2){
for(var i = 0 ; i < 200 ; i++){
var a = (frameCount * .025 + (i*.1));
image(e,(100+i)*cos(a + i), (50+i)*sin(a + i));
}
}
if(demo == 3){
for(var i = 0 ; i < 1000 ; i++){
var a = (frameCount * .025 + (i*.1));
image(e,(100+(i * .25))*cos(a + i), (50+(i * .25))*sin(a + i));
}
}
if(demo == 4){
scale(.2);
for(var i = 0 ; i < 5000 ; i++){
var a = (frameCount * .025 + (i*.1));
image(e,sin(a) * (100+(i * .5))*cos(a + i), (50+(i * .25))*sin(a + i));
}
}
}
function keyReleased(){
if(key === '1') demo = 1;
if(key === '2') demo = 2;
if(key === '3') demo = 3;
if(key === '4') demo = 4;
}
function getGradientImg(w,h,hue,satMax,brightness){
push();//isolate drawing styles such as color Mode
colorMode(HSB,360,100,100);
var gradient = createImage(w,h);//create an image with an alpha channel
var np = w * h;//total number of pixels
var np4 = np*4;
var cx = floor(gradient.width * 0.5);//center on x
var cy = floor(gradient.height * 0.5);//center on y
gradient.loadPixels();
for(var i = 0 ; i < np4; i+=4){//for each pixel
var id4 = floor(i * .25);
var x = id4%gradient.width;//compute x from pixel index
var y = floor(id4/gradient.width);//compute y from pixel index
var d = dist(x,y,cx,cy);//compute distance from centre to current pixel
//map the saturation and transparency based on the distance to centre
gradient.pixels[i] = hue;
gradient.pixels[i+1] = map(d,0,cx,satMax,0);
gradient.pixels[i+2] = brightness;
gradient.pixels[i+3] = map(d,0,cx,255,0);
}
gradient.updatePixels();//finally update all the pixels
pop();
return gradient;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>