
import win.ui;
/*DSG{{*/
var winform = win.form(text="烟花特效 (By: Mr_MAO)";right=991;bottom=679;border="dialog frame";edge=1)
winform.add(
plus={cls="plus";left=0;top=0;right=992;bottom=680;bgcolor=0x000000;db=1;dl=1;dr=1;dt=1;notify=1;z=1}
)
/*}}*/
// 烟花粒子类
class FireworkParticle {
ctor(x, y, vx, vy, color, size, life, generation) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = color;
this.size = size;
this.life = life;
this.maxLife = life;
this.alpha = 255;
this.generation = generation || 1;
this.canExplode = (generation == 1) && (..math.random() < 0.35);
this.explodeTime = ..math.random(10, 30);
this.hasExploded = false;
}
update = function() {
this.x += this.vx;
this.y += this.vy;
this.vy += 0.12; // 重力
this.vx *= 0.98; // 阻力
this.vy *= 0.98;
this.life--;
this.alpha = (this.life / this.maxLife) * 255;
this.size *= 0.97;
}
// 检查是否需要二次爆炸
shouldExplode = function() {
if(this.canExplode && !this.hasExploded) {
var elapsed = this.maxLife - this.life;
if(elapsed >= this.explodeTime) {
this.hasExploded = true;
return true;
}
}
return false;
}
isDead = function() {
return this.life <= 0 || this.alpha <= 0 || this.size < 0.5;
}
}
// 上升火花类
class RisingFirework {
ctor(x, startY, targetY) {
this.x = x;
this.y = startY;
this.targetY = targetY;
this.trail = {};
this.exploded = false;
}
update = function() {
// 添加尾迹
..table.push(this.trail, {
x = this.x + ..math.random(-2, 2);
y = this.y;
alpha = 200;
size = 3
});
// 限制尾迹长度
while(#this.trail > 12) {
..table.remove(this.trail, 1);
}
// 更新尾迹
for(i = #this.trail; 1; -1) {
var t = this.trail[i];
t.alpha -= 20;
t.size *= 0.85;
if(t.alpha <= 0) {
..table.remove(this.trail, i);
}
}
// 计算上升速度
var distance = this.y - this.targetY;
var speed = distance * 0.15;
if(speed < 5) speed = 5;
if(speed > 25) speed = 25;
// 上升
this.y -= speed;
// 到达目标位置即爆炸
if(this.y <= this.targetY) {
this.y = this.targetY;
this.exploded = true;
}
}
}
// 烟花管理器
var particles = {};
var risingFireworks = {};
// 预定义的烟花颜色
var fireworkColors = {
0xFFFF0000; // 红
0xFFFF6600; // 橙
0xFFFFFF00; // 黄
0xFF00FF00; // 绿
0xFF00FFFF; // 青
0xFF0066FF; // 蓝
0xFFFF00FF; // 紫
0xFFFF69B4; // 粉红
0xFFFFD700; // 金色
0xFF00FF7F; // 春绿
}
// 创建主爆炸粒子(第一代)
var createExplosion = function(x, y) {
var particleCount = 100;
var baseColor = fireworkColors[math.random(1, #fireworkColors)];
for(i = 1; particleCount) {
var angle = (i / particleCount) * math.pi * 2 + math.random() * 0.5;
var speed = math.random() * 6 + 3;
var vx = math.cos(angle) * speed;
var vy = math.sin(angle) * speed;
var color;
if(math.random() > 0.3) {
color = baseColor;
} else {
color = fireworkColors[math.random(1, #fireworkColors)];
}
var size = math.random() * 3 + 2;
var life = math.random(50, 90);
// 第一代粒子,可能会二次爆炸
table.push(particles, FireworkParticle(x, y, vx, vy, color, size, life, 1));
}
// 添加闪光中心粒子
for(i = 1; 30) {
var angle = math.random() * math.pi * 2;
var speed = math.random() * 2;
var vx = math.cos(angle) * speed;
var vy = math.sin(angle) * speed;
table.push(particles, FireworkParticle(x, y, vx, vy, 0xFFFFFFFF, 4, 20, 3));
}
}
// 创建二次爆炸粒子(第二代)
var createSecondaryExplosion = function(x, y, parentColor) {
var particleCount = math.random(15, 25); // 小型爆炸
for(i = 1; particleCount) {
var angle = (i / particleCount) * math.pi * 2 + math.random() * 0.8;
var speed = math.random() * 3 + 1.5; // 速度较小
var vx = math.cos(angle) * speed;
var vy = math.sin(angle) * speed;
// 继承父粒子颜色或随机新颜色
var color;
if(math.random() > 0.4) {
color = parentColor;
} else {
color = fireworkColors[math.random(1, #fireworkColors)];
}
var size = math.random() * 2 + 1;
var life = math.random(25, 45); // 寿命较短
// 第二代粒子,不会再次爆炸
table.push(particles, FireworkParticle(x, y, vx, vy, color, size, life, 2));
}
// 小型闪光
for(i = 1; 8) {
var angle = math.random() * math.pi * 2;
var speed = math.random() * 1.5;
var vx = math.cos(angle) * speed;
var vy = math.sin(angle) * speed;
table.push(particles, FireworkParticle(x, y, vx, vy, 0xFFFFFFFF, 2, 12, 3));
}
}
// 鼠标点击事件
winform.plus.onMouseDown = function(wParam, lParam) {
var x = lParam & 0xFFFF;
var y = (lParam >> 16) & 0xFFFF;
var rc = winform.plus.getClientRect();
var startY = rc.bottom;
table.push(risingFireworks, RisingFirework(x, startY, y));
}
// 自绘制函数
winform.plus.onDrawForegroundEnd = function(graphics,rc,rcContent){
graphics.clear(0xFF000000);
// 绘制上升的烟花
for(i = 1; #risingFireworks) {
var rf = risingFireworks[i];
// 绘制尾迹
for(j = 1; #rf.trail) {
var t = rf.trail[j];
var alpha = t.alpha;
if(alpha > 255) alpha = 255;
if(alpha < 0) alpha = 0;
var trailColor = (alpha << 24) | 0xFFFF00;
var trailBrush = gdip.solidBrush(trailColor);
graphics.fillEllipse(trailBrush, t.x - t.size, t.y - t.size, t.size * 2, t.size * 2);
trailBrush.delete();
}
// 绘制火花头部
var headBrush = gdip.solidBrush(0xFFFFFFFF);
graphics.fillEllipse(headBrush, rf.x - 4, rf.y - 4, 8, 8);
headBrush.delete();
var glowBrush = gdip.solidBrush(0x80FFFF00);
graphics.fillEllipse(glowBrush, rf.x - 6, rf.y - 6, 12, 12);
glowBrush.delete();
}
// 绘制爆炸粒子
for(i = 1; #particles) {
var p = particles[i];
var alpha = p.alpha;
if(alpha > 255) alpha = 255;
if(alpha < 0) alpha = 0;
var rgb = p.color & 0x00FFFFFF;
var color = (alpha << 24) | rgb;
var particleBrush = gdip.solidBrush(color);
graphics.fillEllipse(particleBrush, p.x - p.size, p.y - p.size, p.size * 2, p.size * 2);
particleBrush.delete();
// 光晕效果
if(p.size > 1.5) {
var glowAlpha = alpha * 0.3;
if(glowAlpha > 255) glowAlpha = 255;
var glowColor = (glowAlpha << 24) | rgb;
var glowBrush = gdip.solidBrush(glowColor);
var glowSize = p.size * 1.5;
graphics.fillEllipse(glowBrush, p.x - glowSize, p.y - glowSize, glowSize * 2, glowSize * 2);
glowBrush.delete();
}
}
}
// 更新函数
var updateFireworks = function() {
var needRedraw = false;
// 更新上升的烟花
for(i = #risingFireworks; 1; -1) {
var rf = risingFireworks[i];
rf.update();
needRedraw = true;
if(rf.exploded) {
createExplosion(rf.x, rf.y);
table.remove(risingFireworks, i);
}
}
// 收集需要二次爆炸的粒子信息
var secondaryExplosions = {};
// 更新粒子
for(i = #particles; 1; -1) {
var p = particles[i];
p.update();
needRedraw = true;
// 检查是否需要二次爆炸
if(p.shouldExplode()) {
table.push(secondaryExplosions, {
x = p.x;
y = p.y;
color = p.color
});
// 二次爆炸后原粒子消失
table.remove(particles, i);
} elseif(p.isDead()) {
table.remove(particles, i);
}
}
// 执行二次爆炸
for(i = 1; #secondaryExplosions) {
var e = secondaryExplosions[i];
createSecondaryExplosion(e.x, e.y, e.color);
}
// 刷新显示
if(needRedraw || #particles > 0 || #risingFireworks > 0) {
winform.plus.redraw();
}
}
// 启动定时器
winform.setInterval(updateFireworks, 16);
winform.enableDpiScaling(false);
winform.show();
win.loopMessage();