Processing绘制星空-2-绘制流星

Processing绘制星空-2-绘制流星

工具:processing3.5
静态星星的绘制原理参考上篇

  • 最终效果
  • 参考示例
  • 绘制流星
  • 总结与体会
  • 笔者的话

前言

就这个项目而言不要再求源代码到邮箱了,认真看看博文吧,我有将项目完整代码都贴在文章末尾,可是还是有很多人直接要项目源码,问的人多了有些不开心,我不想断言你这样直接要代码的用途,但是希望看官尊重文章内容,不做伸手党,谢谢~

最终效果

请调到电脑最大亮度观看

在这里插入图片描述
局部:
在这里插入图片描述
最后的效果这里放上了动图,但是实际上的效果与这里有所不同,比如星星的颜色并不是白色,总之实际效果比动图美很多,如果你也能在电脑上跑一下源程序就能体会到。
截图如下:

在这里插入图片描述
参考示例汇总

参考示例来自《代码本色》的第1章,也就是向量的应用。(不感兴趣这些示例可以跳过这一块)

示例一
本示例主要展示了给物体添加速度以及简单运动模糊的实现。本项目参考其实现流星的运动和流星的运动模糊。

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

// Example 1-2: Bouncing Ball, with PVector!
PVector position;
PVector velocity;

void setup() {
  size(200,200);
  background(255);
  position = new PVector(100,100);
  velocity = new PVector(2.5,5);
}

void draw() {
  noStroke();
  fill(255,20);
  rect(0,0,width,height);
  
  // Add the current speed to the position.
  position.add(velocity);

  if ((position.x > width) || (position.x < 0)) {
    velocity.x = velocity.x * -1;
  }
  if ((position.y > height) || (position.y < 0)) {
    velocity.y = velocity.y * -1;
  }

  // Display circle at x position
  stroke(0);
  fill(175);
  ellipse(position.x,position.y,16,16);
}

运行效果:
在这里插入图片描述
示例二

本示例主要参考向量的更新,也就是从一边屏幕消失,从另一边屏幕中出现。在本程序中不断对物体的位置进行更新、判断,当物体的位置超出了画布范围,就将物体的挪动到画布的另一边,具体就是初始化坐标为0,或者为画布长宽。

绘制流星时也用到这个思想。

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

Mover mover;

void setup() {
  size(640,360);
  mover = new Mover(); 
}

void draw() {
  background(255);
  
  mover.update();
  mover.checkEdges();
  mover.display(); 
}
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

class Mover {

  PVector position;
  PVector velocity;

  Mover() {
    position = new PVector(random(width), random(height));
    velocity = new PVector(random(-2, 2), random(-2, 2));
  }

  void update() {
    position.add(velocity);
  }

  void display() {
    stroke(0);
    strokeWeight(2);
    fill(127);
    ellipse(position.x, position.y, 48, 48);
  }

  void checkEdges() {

    if (position.x > width) {
      position.x = 0;
    } 
    else if (position.x < 0) {
      position.x = width;
    }

    if (position.y > height) {
      position.y = 0;
    } 
    else if (position.y < 0) {
      position.y = height;
    }
  }
}

运行效果:
注:黄色圆圈为录屏软件所自带,并不是程序运行的效果。
在这里插入图片描述

绘制流星

1.绘制普通星星
绘制静态的星星是一件很简单的事情,用点来代表星星,只需要随机地在画布上画上规定数目的点即可。
为了使代码可复用性高,最好将星星封装成一个类。

class Stars
{
  int starsNum;//静态星星的数量
  int maxX;//星星的分布范围
  int maxY;
  
  Stars(int num,int maxX,int maxY)
  {
    meteorNum=num;
     starsNum=5000;
     
   //初始化星空,随机生成星星
    int x,y;
    for (int i=0;i<starsNum;i++)
    {    
       x=int(random(maxX));//产生0-maxX范围内的整数
       y=int(random(maxY));
       point(x,y);//在(x,y)处画点
    }
  }
}

2.绘制流星
流星=星星+速度+“尾巴”
分析:
流星的速度以及方向:
每次在draw函数绘制星星时将星星的坐标加上一个固定的值使得(x,y)变成(x+tx,y+ty),便可以使得星星运动起来。
代码如下,position数组存放流星的位置和方向(x,y),velocity数组就是控制方向和速度的向量(tx,ty)

     for (int i=0;i<meteorNum;i++)
     {
      position[i].add(velocity[i]);//向量相加
     }

流星的拖尾:
星星走过的路线本来是全亮的,在画面上展示出来就是一条白色的直线,但是我们可以通过使得星星先走过的路线先变黑来形成拖尾的效果。在每一帧刷新的时候画上一个大小为画布尺寸的矩形,用有透明度的黑色填充矩形。效果可由下面一张图片来表示:在这里插入图片描述
是不是看起来像一条向右边运动的流星?
代码如下,写在draw函数里面。

  fill(0,18);//颜色为黑色,透明度为18
  rect(0,0,width,height);

边界判断:
流星超出画布范围的时候应该把流星的位置初始化。
代码如下,position数组存放的是流星的位置。

void checkEdges()
{
  for (int i=0;i<meteorNum;i++)
  {
    if (position[i].x > width) 
    {
        position[i].x = 0;
    } else if (position[i].x < 0)
    {
        position[i].x = width;
    }
  
    if (position[i].y > height)
    {
        position[i].y = 0;
    } else if (position[i].y < 0) 
    {
        position[i].y = height;
    }
  }
}

  • 最后加上一些简单的细节,比如星星们的大小不同,但是以小的星星为主,流星的大小也是不一样的,这些基本上都是随机数的应用。下面放上整个项目的完整代码:
    两个文件
    1.drawStars.pde
Stars myStars;

void setup()
{
  size(1920,1080);
  //流星数量30颗,普通星星5000颗,画布大小1920*1080
  myStars=new Stars(30,5000,1920,1080);

}

void draw()
{
  fill(0,18);//颜色为黑色,透明度为18
  rect(0,0,width,height);
  myStars.update();
  myStars.checkEdges();
  myStars.display();

}

2.Stars.pde

class Stars
{
  int starsNum;//静态星星的数量
  int maxX;//星星的分布范围
  int maxY;
  PVector []starsp;//星星的位置
  int meteorNum;//流星的数量
  PVector []position;//流星的位置
  PVector []velocity;//流星的速度
 
  Stars(int num1,int num2,int maxX,int maxY)
  {
    meteorNum=num1;
    starsNum=num2;
    starsp=new PVector[starsNum];
    position=new PVector[meteorNum];//流星的位置
    velocity=new PVector[meteorNum];//控制流星的向量
   
   //初始化星空,随机生成星星
    int x,y;
    float xoff=0.0,yoff=10500.0;
    for (int i=0;i<starsNum;i++)
    {    
       x=int(map(noise(xoff),0,1,0,maxX+200));
       y=int(map(noise(yoff),0,1,0,maxY+0));
       point(x,y);
       starsp[i]= new PVector(x, y);
       yoff+=30;
       xoff+=0.5;
    }
   //随机生成流星初始位置

    for (int i=0;i<meteorNum;i++)
    {
     x=int(random(maxX));
     y=int(random(maxY));
     position[i]=new PVector(x,y);
     
     x=int(random(1.0,2.0));
     y=int(random(1.0,2.0));
     velocity[i]= new PVector(x, y);
    }
  }

  void display()
  {
    //画流星
    stroke(#edccf7);
   for (int i=0;i<meteorNum;i++)
   {
   
    if (i>meteorNum/2)
    {
     point(position[i].x, position[i].y);
    }
    else
    {
       float size=random(0.5);
       ellipse(position[i].x, position[i].y,size, size);    
    }
    
   }
   //画普通星星
   for (int i=0;i<starsNum;i++)
   {
    
     if (i%20==0)//每隔20颗,画一个大小随机的星星
     {
        stroke(#edccf7);
        int flag=int(random(50));
        float size=random(1);
        if(flag>48)
        {
          stroke(#edccf7);
        }
        ellipse(starsp[i].x,starsp[i].y,size, size);
     }
     else//画大小为一个点的星星
     {
         //随机闪烁
        stroke(#888deb);
        int flag=int(random(50));
        if(flag>48)
        {
          stroke(#edccf7);
        }
        
        point(starsp[i].x,starsp[i].y);
     }
  }
  
  }
  void update()
  {
     for (int i=0;i<meteorNum;i++)
     {
      position[i].add(velocity[i]);
     }
  }

void checkEdges()
{  //检查边界
  for (int i=0;i<meteorNum;i++)
  {
    if (position[i].x > width) 
    {
        position[i].x = 0;
    } else if (position[i].x < 0)
    {
        position[i].x = width;
    }
  
    if (position[i].y > height)
    {
        position[i].y = 0;
    } else if (position[i].y < 0) 
    {
        position[i].y = height;
    }
  }
}
}

总结与体会

画一个简单的星空并不难,而且通过画星空的方式将一些看似枯燥的数学原理变的生动了起来。在这个项目中我其实有试过给流星添加加速度,流星就会变的有点像雨滴,这也是很有意思的变化,也许以后可以拓展。


笔者的话:
我个人还是非常喜欢这个画星空的小项目的,喜欢天空,也很喜欢星星
。(//▽//)。

  • 36
    点赞
  • 167
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值