看~流星
processing吧
全部回复
仅看楼主
level 4
qof3990 楼主
float x1, x2, x3, y1, y2, y3, l1, l2, angle;
float[] v3, v4;
float epsilon = 25; // 定义一个很小的容差值
void setup() {
size(600, 600);
background(0);
stroke(255);
strokeWeight(1);
noFill();
x1 = 500;
y1 = 100;
angle = radians(235);
}
float l=400;//总轨迹长度
float t=200;//持续时间
float t1=2;//间隔时间(持续时间的倍数)
float l3=200;//线段长度
Transition transition1 = new Transition(0, l, t, t1); // 3秒的过渡
Transition transition2 = new Transition(0, l, t, t1);
void draw() {
background(0);
// 计算终点坐标
//l1 = transitionValue(0, l3, t);//线段长度
v4 = transition2.getValue();//总轨迹长度
l2 = v4[0];
//不要用ifelse,会导致跳过某个if。
if (l2 < l3) {
l1 = 0;
}
if (abs(l2 - l3) < epsilon) { // 使用容差值进行比较
transition1.reset();
v3 = transition1.getValue();
l1 = v3[0];
}
if (l2 > l3) {
v3 = transition1.getValue();
l1 = v3[0];
}
x2 = x1 + l1 * cos(angle);
y2 = y1 - l1 * sin(angle);
x3 = x1 + l2 * cos(angle);
y3 = y1 - l2 * sin(angle);
if (v3 != null && v3.length > 1 && v3[1] < 1 || v4[1]<1) {
line(x2, y2, x3, y3);
}
}
class Transition {
private long startTime = -1;
private float startValue;
private float endValue;
private float duration;
private float tt;
// 构造函数初始化起始值、结束值和持续时间,间隔时间(是持续时间的几倍就输入几)
Transition(float startValue, float endValue, float duration, float tt) {
this.startValue = startValue;
this.endValue = endValue;
this.duration = duration;
this.tt = tt;
}
// 开始或重置计时器的方法
void reset() {
startTime = millis();
}
// 获取当前插值的方法
float[] getValue() {
if (startTime == -1) {
reset(); // 第一次调用时设置开始时间
}
float t = (millis() - startTime) / duration;
float v1, v2;
if (t <= 1) {
v1= lerp(startValue, endValue, t);
v2=t;
} else if ((t>1) && (t<1+tt)) {
v1= endValue;
v2=t;
} else {
startTime = -1; // 重置开始时间以便下次调用时重新开始计时
v1= endValue;
v2=t;
}
// 返回包含两个值的数组
return new float[]{v1, v2};
}
}
很简单的效果,不知为何居然写了这么长的代码。应该还有更简单的方法吧。感谢ai教我用类。这是我第一次用类。用ps做的gif不知为何很慢。找了个在线工具ezgif做了一下速度才正常。
接下来挑战流星雨![太开心]
2024年12月06日 12点12分 1
level 4
qof3990 楼主
流星雨也做好啦[哈哈]
ArrayList<Meteor> meteors = new ArrayList<Meteor>();
void setup() {
size(600, 600);
background(0);
stroke(255);
strokeWeight(1);
noFill();
for (int i=0;i<20;i++){
addOneMeteor();
}
}
void draw() {
background(0); // 清除背景以避免重叠绘图
for (Meteor meteor : meteors) {
meteor.update();
}
}
void addOneMeteor() {
float startX = random(width/3, width);
float startY = random(height/5, height);
float angle = radians(235);
float totalLength = random(50, 500); // 总轨迹长度
float duration = random(100,500); // 持续时间
float interval = random(3,9); // 间隔时间(持续时间的倍数)
float segmentLength = totalLength * pow(random(0.1,0.999),3); // 线段长度
Meteor newMeteor = new Meteor(startX, startY, angle, totalLength, duration, interval, segmentLength);
meteors.add(newMeteor);
}
class Meteor {
Transition transition1, transition2;
float[] values1, values2;
float segLen1, segLen2;
float startX, startY, angle;
float totalLength, duration, segmentLength, epsilon;
// 构造函数初始化起始位置、角度、总长度、持续时间、间隔时间和线段长度
Meteor(float startX, float startY, float angle, float totalLength, float duration,
float interval, float segmentLength) {
this.startX = startX;
this.startY = startY;
this.angle = angle;
this.segmentLength = segmentLength;
this.totalLength = totalLength;
this.duration = duration;
transition1 = new Transition(0, totalLength, duration, interval); // 初始化第一个过渡
transition2 = new Transition(0, totalLength, duration, interval); // 初始化第二个过渡
}
void update() {
// 计算终点坐标
values2 = transition2.getValue(); // 总轨迹长度
segLen2 = values2[0];
epsilon = 700 * totalLength / frameRate / duration; // 定义一个容差值0.7是让间隔缩为0.7
if (abs(segLen2 - segmentLength) < epsilon) { // 使用容差值进行比较
transition1.reset();
}
values1 = transition1.getValue();
// 根据segLen2的值更新segLen1
if (segLen2 < segmentLength) {
segLen1 = 0;
} else {
segLen1 = values1[0];
}
float endX1 = startX + segLen1 * cos(angle);
float endY1 = startY - segLen1 * sin(angle);
float endX2 = startX + segLen2 * cos(angle);
float endY2 = startY - segLen2 * sin(angle);
// 这个if是为了让线条在该消失的时候消失
if (values1 != null && values1.length > 1 && values1[1] < 1 || values2[1] < 1) {
line(endX1, endY1, endX2, endY2);
}
}
}
class Transition {
private long startTime = -1;
private float startValue;
private float endValue;
private float duration;
private float interval;
// 构造函数初始化起始值、结束值和持续时间,间隔时间(是持续时间的几倍就输入几)
Transition(float startValue, float endValue, float duration, float interval) {
this.startValue = startValue;
this.endValue = endValue;
this.duration = duration;
this.interval = interval;
}
// 开始或重置计时器的方法
void reset() {
startTime = millis();
}
// 获取当前插值的方法
float[] getValue() {
if (startTime == -1) {
reset(); // 第一次调用时设置开始时间
}
float elapsed = millis() - startTime;
float timeFraction = elapsed / duration;
float currentValue, timeProgress;
if (timeFraction <= 1) {
currentValue = lerp(startValue, endValue, timeFraction);
timeProgress = timeFraction;
} else if ((timeFraction > 1) && (timeFraction < 1 + interval)) {
currentValue = endValue;
timeProgress = timeFraction;
} else {
startTime = -1; // 重置开始时间以便下次调用时重新开始计时
currentValue = endValue;
timeProgress = timeFraction;
}
// 返回包含两个值的数组
return new float[]{currentValue, timeProgress};
}
}
=======================================================
ai真好用。虽然也经常出错。参数名也用ai改进了真方便。
2024年12月07日 08点12分 2
1