0 编程题
第一天的挑战是穿越星际效果。成果图如下图gif所示。
1 分析
1.1 需求分析
从需求来分析,我们需要什么:
- 建立黑色画布(或者自己设置星空背景)。
- “星星”类,要实现随机产生,布满画布。
- “星星”类,星星能够实现面向屏幕向前移动的效果
- “星星”类,星星到了临界自动消失,在其他地方重新产生另一批星星。
- “星星”类,有一根直线当成尾巴。
- 交互:鼠标从左往右滑动,速度变快。
1.2 重点难点
- 星星的移动与x,y轴无关,其靠近屏幕其实是沿着Z轴移动。
- 如何让“星星”消失后再次产生.
- 直线绘制问题。
编译过程链接:
请查看合辑的DAY1
请自己动手编译过后再看后文!
2 难点代码解析
2.1坐标轴变换
processing采用的屏幕坐标系如下图所示。
一开始,所有的变换都是沿着显示屏左上角(0,0,0)开始进行的。但是这样的画,会出现所有的星星从左上角散开的情况,我们需要调整坐标系,让星星从中心散开。
通过下面这句话解决从原点开始变换的问题,同时,将X,Y坐标延伸到负轴,以将星星布满整个屏幕
//移动坐标系
translate(width/2,height/2);
class Star{
float x;
float y;
float z;
float pz;
Star(){
//修改x,y取值范围
x = random(-width,width);
y= random(-height,height);
z = random(0,width);
pz = z;
}
void updata()
{
...}
void show()
{
...}
}
此时坐标轴形态如下图所示
2.2 星星复现
实现该功能核心是当Z降为0时,重设置(reset) Z值,用一个if判断语句就可以实现。
void updata()
{
//控制速度control the speed
...
if(z < 1)
{
z= width;
x = random(-width,width);
y= random(-height,height);
pz = z;
}
}
2.3 直线绘制问题
抓住一个要点:唯一产生变化的其实只有Z的取值,只要抓住Z这个变量就可以确定X,Y值,最后在平面上用仅含(x,y)的直线连接起始点和末尾点,。这个过程需要对X,Y做一个映射。
void show()
{
fill(255);
noStroke();
//绘制星星
float r = map(z,width,0,0,10);
float sx = map(x/z,0,1,0,width);
float sy = map(y/z,0,1,0,height);
ellipse(sx,sy,r,r);
float px = map(x/pz,0,1,0,width);
float py = map(y/pz,0,1,0,height);
stroke(255);
//始末点相连
line(px,py,sx,sy);
}
3 完整代码
主函数
// 创建数组
Star[] stars = new Star[800];
void setup()
{
size(800,800);
for(int i =0;i<stars.length;i++)
{
stars[i] = new Star();
}
}
void draw()
{
background(0);
translate(width/2,height/2);
for(int j = 0; j< stars.length;j++)
{
stars[j].updata();
stars[j].show();
}
}
星星类
class Star{
float x;
float y;
float z;
float pz;
Star(){
x = random(-width,width);
y= random(-height,height);
z = random(0,width);
pz = z;
}
void updata()
{
//控制速度control the speed
float move = map(mouseX,0,width,0,18);
z=z-move;
//print(move);
if(z < 1)
{
z= width;
x = random(-width,width);
y= random(-height,height);
pz = z;
}
}
void show()
{
fill(255);
noStroke();
float r = map(z,width,0,0,10);
float sx = map(x/z,0,1,0,width);
float sy = map(y/z,0,1,0,height);
ellipse(sx,sy,r,r);
float px = map(x/pz,0,1,0,width);
float py = map(y/pz,0,1,0,height);
stroke(255);
line(px,py,sx,sy);
}
}