aardio 文档
aardio 范例: 动画天气卡片
/*
动画天气卡片:plus + GDI+ 自绘范例。
此示例采用小游戏/动画常用的绘图约定:
1. 场景状态统一使用 96-DPI 逻辑坐标。
2. 绘制时使用 save → scale(dpiX,dpiY) → restore 切换到逻辑坐标。
3. 所有速度都使用“逻辑像素/秒”或“角度/秒”,并按 deltaMs 更新。
4. 限制异常大的帧间隔,避免窗口阻塞后粒子瞬移。
5. 静态背景按当前像素尺寸与 DPI 缓存;画笔、画刷、字体等对象复用。
6. 绘图函数不改变动画状态,也不在绘图阶段生成随机数。
*/
import win.ui;
/*DSG{{*/
var winform = win.form(text="动画天气卡片";right=360;bottom=535;max=false;min=false)
winform.add(
btnRain={cls="plus";text="雨";left=121;top=485;right=166;bottom=525;bgcolor=0xD9904A;border={radius=8};color=0xFFFFFF;font=LOGFONT(h=-14;weight=600);notify=1;z=3};
btnSnow={cls="plus";text="雪";left=171;top=485;right=216;bottom=525;bgcolor=0xC37C8E;border={radius=8};color=0xFFFFFF;font=LOGFONT(h=-14;weight=600);notify=1;z=4};
btnSunny={cls="plus";text="晴";left=74;top=485;right=119;bottom=525;bgcolor=0x0095FF;border={radius=8};color=0xFFFFFF;font=LOGFONT(h=-14;weight=600);notify=1;z=2};
btnWind={cls="plus";text="风";left=221;top=485;right=266;bottom=525;bgcolor=0x9AA626;border={radius=8};color=0xFFFFFF;font=LOGFONT(h=-14;weight=600);notify=1;z=5};
plus={cls="plus";left=18;top=20;right=338;bottom=470;border={color=0xD0D0D0;radius=20;width=2};notify=1;z=1}
)
/*}}*/
import sys.midiOut;
var midiOut = sys.midiOut();
//场景数据始终使用 96-DPI 逻辑坐标。窗体不可缩放时初始值即为设计尺寸。
var sceneWidth,sceneHeight = 320,450;
var weatherState = "rain";
var animTime = 0;//秒
var rainDrops = [];
var snowFlakes = [];
var clouds = [];
var sunRays = [];
var windLines = [];
var trees = [];
var leaves = [];
var splashes = [];
var lightning = {
active=false;
flashOpacity=0;
bolts=[];
nextFlash=0.45;//秒
thunderDelay=0;
playThunder=false;
};
var labels = {
sunny="晴空万里";
rain="雷雨交加";
snow="雪花飘飘";
wind="清风徐来";
};
var leafColors = [0xFF8BC34A,0xFFCDDC39,0xFFFFA726];
var treeLayers = [
{offset=0;size=1;color=0xFF2E7D32},
{offset=-0.25;size=0.8;color=0xFF388E3C},
{offset=-0.45;size=0.6;color=0xFF43A047}
];
//动态对象共用可变画刷与画笔,避免每个粒子每帧创建 GDI+ 对象。
var sharedBrush = gdip.solidBrush(0xFFFFFFFF);
var sharedPen = gdip.pen(0xFFFFFFFF,1);
var labelFont = gdip.font("Microsoft YaHei UI",16,1/*_FontStyleBold*/,2/*_UnitPixel*/);
var labelFormat = gdip.stringFormat();
labelFormat.align = 1/*_StringAlignmentCenter*/;
labelFormat.lineAlign = 1/*_StringAlignmentCenter*/;
var labelBrush = gdip.solidBrush(0xFFFFFFFF);
var labelBackgroundBrush = gdip.solidBrush(0x60000000);
var clampByte = function(value){
return math.clamp(math.floor(value),0,255);
}
var withAlpha = function(alpha,rgb){
return (clampByte(alpha)<<24)|(rgb&0xFFFFFF);
}
var randomInt = function(minValue,maxValue){
minValue = math.floor(minValue);
maxValue = math.max(minValue,math.floor(maxValue));
return math.random(minValue,maxValue);
}
var randomSeconds = function(minMs,maxMs){
return math.random(minMs,maxMs)/1000;
}
var getLogicalSize = function(ctrl){
var rc = ctrl.getClientRect();
var dpiX,dpiY = winform.dpiScale(1,1);
return rc.width/dpiX,rc.height/dpiY,dpiX,dpiY,rc;
}
//静态背景使用当前 DPI 下的原尺寸位图缓存。
var backgroundLayer;
var backgroundWidth,backgroundHeight,backgroundDpiX,backgroundDpiY,backgroundWeather;
var invalidateBackground = function(){
if(backgroundLayer){
backgroundLayer.delete();
backgroundLayer = null;
}
backgroundWidth,backgroundHeight = null,null;
backgroundDpiX,backgroundDpiY = null,null;
backgroundWeather = null;
}
var ensureBackgroundLayer = function(pixelWidth,pixelHeight,dpiX,dpiY){
if(pixelWidth<=0 || pixelHeight<=0) return;
if(backgroundLayer
&& backgroundWidth==pixelWidth && backgroundHeight==pixelHeight
&& backgroundDpiX==dpiX && backgroundDpiY==dpiY
&& backgroundWeather==weatherState){
return;
}
invalidateBackground();
backgroundLayer = gdip.bitmap(pixelWidth,pixelHeight);
var graphics = gdip.graphics(backgroundLayer);
var saved = graphics.save();
graphics.smoothingMode = 4/*_SmoothingModeAntiAlias*/;
graphics.scale(dpiX,dpiY);
var width,height = pixelWidth/dpiX,pixelHeight/dpiY;
var topColor,bottomColor,groundColor;
if(weatherState=="sunny"){
topColor,bottomColor,groundColor = 0xFF4FC3F7,0xFF81C784,0xFF66BB6A;
}
elseif(weatherState=="rain"){
topColor,bottomColor,groundColor = 0xFF455A64,0xFF37474F,0xFF455A64;
}
elseif(weatherState=="snow"){
topColor,bottomColor,groundColor = 0xFF90A4AE,0xFFE8EAF6,0xFFFAFAFA;
}
else {
topColor,bottomColor,groundColor = 0xFF64B5F6,0xFFA5D6A7,0xFF66BB6A;
}
var skyBrush = gdip.lineBrush(
::POINTF(0,0),::POINTF(0,height),
topColor,bottomColor,0
);
graphics.fillRectangle(skyBrush,0,0,width,height);
skyBrush.delete();
var groundBrush = gdip.solidBrush(groundColor);
graphics.fillRectangle(groundBrush,0,height-60,width,60);
groundBrush.delete();
graphics.restore(saved);
graphics.delete();
backgroundWidth,backgroundHeight = pixelWidth,pixelHeight;
backgroundDpiX,backgroundDpiY = dpiX,dpiY;
backgroundWeather = weatherState;
}
var clearWeatherObjects = function(){
rainDrops = [];
snowFlakes = [];
clouds = [];
sunRays = [];
windLines = [];
trees = [];
leaves = [];
splashes = [];
}
var initClouds = function(count,dark){
clouds = [];
for(i=1;count){
var cloudWidth = randomInt(82,132);
table.push(clouds,{
x=randomInt(-cloudWidth,sceneWidth);
y=randomInt(58,math.max(70,sceneHeight*0.38));
width=cloudWidth;
height=randomInt(40,62);
speed=randomInt(10,28);//逻辑像素/秒
opacity=dark ? randomInt(200,238) : randomInt(178,225);
dark=dark;
});
}
}
var initSunRays = function(){
sunRays = [];
for(i=1;16){
table.push(sunRays,{
angle=(i-1)*22.5;
length=randomInt(62,105);
baseOpacity=randomInt(65,115);
phase=math.random(0,628)/100;
});
}
}
var initRain = function(){
rainDrops = [];
splashes = [];
var groundY = sceneHeight-60;
for(i=1;78){
table.push(rainDrops,{
x=randomInt(0,sceneWidth+24);
y=randomInt(-sceneHeight*0.45,groundY);
speed=randomInt(430,720);//逻辑像素/秒
drift=randomInt(35,55);
length=randomInt(12,25);
opacity=randomInt(105,205);
width=randomInt(1,2);
});
}
//溅水位置与相位只在初始化时随机,绘图阶段保持确定性。
for(i=1;10){
table.push(splashes,{
x=randomInt(14,sceneWidth-14);
phase=math.random(0,600)/1000;
period=randomInt(420,680)/1000;
});
}
}
var initSnow = function(){
snowFlakes = [];
var groundY = sceneHeight-60;
for(i=1;58){
table.push(snowFlakes,{
x=randomInt(0,sceneWidth);
y=randomInt(-100,groundY);
speed=randomInt(28,70);//逻辑像素/秒
size=randomInt(4,11);
swing=math.random(0,628)/100;
swingSpeed=randomInt(8,24)/10;//弧度/秒
driftSpeed=randomInt(12,25);//逻辑像素/秒
opacity=randomInt(180,255);
rotation=randomInt(0,360);
rotSpeed=randomInt(-110,110);//度/秒
});
}
}
var initWindLines = function(){
windLines = [];
for(i=1;12){
table.push(windLines,{
x=randomInt(-180,sceneWidth);
y=randomInt(75,sceneHeight-80);
length=randomInt(52,118);
speed=randomInt(240,430);//逻辑像素/秒
opacity=randomInt(75,155);
curve=randomInt(3,8);
phase=math.random(0,628)/100;
});
}
}
var initTrees = function(){
trees = [];
var positions = [0.14,0.39,0.65,0.87];
for(i,position in positions){
table.push(trees,{
x=sceneWidth*position;
y=sceneHeight-50;
height=randomInt(58,84);
swing=math.random(0,628)/100;
swingSpeed=randomInt(24,42)/10;//弧度/秒
});
}
}
var initLeaves = function(){
leaves = [];
for(i=1;12){
table.push(leaves,{
x=randomInt(-20,sceneWidth);
y=randomInt(90,sceneHeight-85);
speedX=randomInt(160,300);//逻辑像素/秒
speedY=randomInt(-15,25);
rotation=randomInt(0,360);
rotSpeed=randomInt(150,360);//度/秒
size=randomInt(7,13);
color=randomInt(1,#leafColors);
phase=math.random(0,628)/100;
});
}
}
var generateLightningBolt = function(startX,startY,endY){
var bolt = [];
bolt.branches = [];
var x,y = startX,startY;
var segments = randomInt(9,14);
var segmentHeight = (endY-startY)/segments;
table.push(bolt,{x=x;y=y});
for(i=1;segments){
y += segmentHeight;
x += randomInt(-17,17);
table.push(bolt,{x=x;y=y});
if(randomInt(1,100)>72 && i>2 && i<segments-2){
var branch = [{x=x;y=y}];
var bx,by = x,y;
var branchLength = randomInt(3,5);
var direction = randomInt(1,2)==1 ? -1 : 1;
for(j=1;branchLength){
bx += randomInt(8,18)*direction;
by += randomInt(10,22);
table.push(branch,{x=bx;y=by});
}
table.push(bolt.branches,branch);
}
}
return bolt;
}
var initLightning = function(){
lightning = {
active=false;
flashOpacity=0;
bolts=[];
nextFlash=0.45;
thunderDelay=0;
playThunder=false;
};
}
var triggerLightning = function(){
lightning.active = true;
lightning.flashOpacity = 210;
lightning.bolts = [];
var boltCount = randomInt(1,2);
for(i=1;boltCount){
var startX = randomInt(35,sceneWidth-35);
var endY = randomInt(sceneHeight*0.58,sceneHeight*0.82);
table.push(lightning.bolts,generateLightningBolt(startX,0,endY));
}
lightning.thunderDelay = randomSeconds(180,550);
lightning.playThunder = true;
}
var playThunder = function(){
if(midiOut){
//短促离散音效;sys.midiOut 默认 autoNoteOff 会在时值结束后释放音符。
midiOut.playAsync("changeInstrument(127),1____","C2",70);
}
}
var setSelectedButton = function(weather){
winform.btnSunny.disabled = weather=="sunny";
winform.btnRain.disabled = weather=="rain";
winform.btnSnow.disabled = weather=="snow";
winform.btnWind.disabled = weather=="wind";
}
var switchWeather = function(weather){
weatherState = weather;
animTime = 0;
clearWeatherObjects();
invalidateBackground();
setSelectedButton(weather);
if(midiOut) midiOut.reset();
if(weather=="sunny"){
initClouds(3,false);
initSunRays();
}
elseif(weather=="rain"){
initClouds(4,true);
initRain();
initLightning();
}
elseif(weather=="snow"){
initClouds(4,false);
initSnow();
}
else {
initClouds(3,false);
initWindLines();
initTrees();
initLeaves();
}
}
var drawCloud = function(graphics,cloud,opacity){
var rgb = cloud.dark ? 0x6E7B8B : 0xFFFFFF;
sharedBrush.color = withAlpha(opacity,rgb);
var x,y,w,h = cloud.x,cloud.y,cloud.width,cloud.height;
graphics.fillEllipse(sharedBrush,x,y+h*0.2,w*0.4,h*0.8);
graphics.fillEllipse(sharedBrush,x+w*0.2,y-h*0.1,w*0.45,h);
graphics.fillEllipse(sharedBrush,x+w*0.45,y+h*0.1,w*0.4,h*0.85);
graphics.fillEllipse(sharedBrush,x+w*0.15,y+h*0.3,w*0.55,h*0.6);
}
var drawTree = function(graphics,tree){
var swingOffset = math.sin(tree.swing)*14;
var x,y,height = tree.x,tree.y,tree.height;
sharedBrush.color = 0xFF5D4037;
graphics.fillPolygon(sharedBrush,[
::POINTF(x-9,y),
::POINTF(x+9,y),
::POINTF(x+5+swingOffset*0.3,y-height*0.5),
::POINTF(x-5+swingOffset*0.3,y-height*0.5)
]);
for(i,layer in treeLayers){
var layerY = y-height*0.4+layer.offset*height;
var layerWidth = 66*layer.size;
var layerHeight = 52*layer.size;
var offsetX = swingOffset*(0.48+i*0.18);
sharedBrush.color = layer.color;
graphics.fillEllipse(
sharedBrush,
x-layerWidth/2+offsetX,layerY-layerHeight/2,
layerWidth,layerHeight
);
}
}
var drawSnowflake = function(graphics,flake){
sharedBrush.color = withAlpha(flake.opacity,0xFFFFFF);
graphics.fillEllipse(
sharedBrush,
flake.x-flake.size/2,flake.y-flake.size/2,
flake.size,flake.size
);
if(flake.size>6){
sharedPen.color = withAlpha(flake.opacity*0.6,0xFFFFFF);
sharedPen.width = 1;
for(i=0;2){
var angle = math.rad(flake.rotation+i*60);
var dx = math.cos(angle)*flake.size*0.42;
var dy = math.sin(angle)*flake.size*0.42;
graphics.drawLine(sharedPen,flake.x-dx,flake.y-dy,flake.x+dx,flake.y+dy);
}
}
}
var drawLightning = function(graphics,bolt,opacity){
if(#bolt<2) return;
sharedPen.color = withAlpha(opacity*0.3,0xE1F5FE);
sharedPen.width = 12;
graphics.drawLines(sharedPen,bolt);
sharedPen.color = withAlpha(opacity*0.8,0xFFFFFF);
sharedPen.width = 4;
graphics.drawLines(sharedPen,bolt);
sharedPen.color = withAlpha(opacity,0xFFFFFF);
sharedPen.width = 2;
graphics.drawLines(sharedPen,bolt);
for(i,branch in bolt.branches){
sharedPen.color = withAlpha(opacity*0.22,0xE1F5FE);
sharedPen.width = 6;
graphics.drawLines(sharedPen,branch);
sharedPen.color = withAlpha(opacity*0.65,0xFFFFFF);
sharedPen.width = 2;
graphics.drawLines(sharedPen,branch);
}
}
var drawSunny = function(graphics,width,height){
var sunX,sunY = width*0.76,height*0.19;
var sunRadius = 42;
for(r=3;1;-1){
var glowOpacity = 18+r*14;
var glowSize = sunRadius+r*20;
sharedBrush.color = withAlpha(glowOpacity,0xFFD54F);
graphics.fillEllipse(
sharedBrush,
sunX-glowSize,sunY-glowSize,
glowSize*2,glowSize*2
);
}
for(i,ray in sunRays){
var angle = math.rad(ray.angle+animTime*20);//度/秒
var pulse = math.sin(animTime*2+ray.phase);
var currentLength = ray.length+pulse*14;
var opacity = ray.baseOpacity+pulse*32;
var x2 = sunX+math.cos(angle)*currentLength;
var y2 = sunY+math.sin(angle)*currentLength;
sharedPen.color = withAlpha(opacity,0xFFD54F);
sharedPen.width = 3;
graphics.drawLine(sharedPen,sunX,sunY,x2,y2);
}
sharedBrush.color = 0xFFFFD54F;
graphics.fillCircle(sharedBrush,sunX,sunY,sunRadius);
sharedBrush.color = 0x80FFFFFF;
graphics.fillEllipse(
sharedBrush,
sunX-sunRadius*0.62,sunY-sunRadius*0.62,
sunRadius*0.82,sunRadius*0.58
);
}
var drawRain = function(graphics,width,height,groundY){
if(lightning.active && lightning.flashOpacity>30){
for(i,bolt in lightning.bolts){
drawLightning(graphics,bolt,lightning.flashOpacity);
}
}
for(i,drop in rainDrops){
var opacity = drop.opacity;
if(lightning.flashOpacity>50){
opacity = math.min(255,opacity+lightning.flashOpacity/2);
}
sharedPen.color = withAlpha(opacity,0xB3E5FC);
sharedPen.width = drop.width;
graphics.drawLine(
sharedPen,
drop.x,drop.y,
drop.x-drop.length*0.2,drop.y+drop.length
);
}
//水洼位置根据当前逻辑宽度均匀分布,不使用旧范例中超出卡片的固定坐标。
for(i=1;4){
var puddleWidth = math.min(58,width*0.18);
var px = width*(i-0.5)/4-puddleWidth/2;
var rippleOffset = math.sin(animTime*4+i)*2.5;
var opacity = 0x60;
if(lightning.flashOpacity>50){
opacity = math.min(0xA0,opacity+lightning.flashOpacity/4);
}
sharedBrush.color = withAlpha(opacity,0x5C6BC0);
graphics.fillEllipse(sharedBrush,px,groundY+14,puddleWidth,15);
sharedPen.color = 0x407986CB;
sharedPen.width = 1;
graphics.drawEllipse(
sharedPen,
px+puddleWidth*0.22+rippleOffset,groundY+16,
puddleWidth*0.56+rippleOffset*2,9
);
}
for(i,splash in splashes){
var phase = (animTime+splash.phase)%splash.period;
var progress = phase/splash.period;
if(progress<0.42){
var localProgress = progress/0.42;
var radius = localProgress*8;
sharedPen.color = withAlpha(150*(1-localProgress),0xB3E5FC);
sharedPen.width = 1;
graphics.drawEllipse(
sharedPen,
splash.x-radius,groundY+5-radius*0.3,
radius*2,math.max(1,radius*0.65)
);
}
}
}
var drawSnow = function(graphics,width,height,groundY){
for(i,flake in snowFlakes){
drawSnowflake(graphics,flake);
}
var snowPoints = [::POINTF(0,height)];
for(x=0;width;24){
var snowHeight = 23+math.sin(x*0.035+animTime*0.8)*7;
table.push(snowPoints,::POINTF(x,groundY-snowHeight));
}
table.push(snowPoints,::POINTF(width,groundY-20));
table.push(snowPoints,::POINTF(width,height));
sharedBrush.color = 0xFFFAFAFA;
graphics.fillPolygon(sharedBrush,snowPoints);
sharedPen.color = 0x55FFFFFF;
sharedPen.width = 2;
for(x=16;width-20;68){
var highlightY = groundY-15+math.sin(x*0.05)*5;
graphics.drawCurve(sharedPen,[
x,highlightY,
x+24,highlightY-3,
x+50,highlightY+2
]);
}
}
var drawWind = function(graphics,width,height){
for(i,windLine in windLines){
var points = [];
for(j=0;5){
var x = windLine.x+j*windLine.length/5;
var y = windLine.y
+math.sin(j*0.8+animTime*4+windLine.phase)*windLine.curve;
table.push(points,x);
table.push(points,y);
}
sharedPen.color = withAlpha(windLine.opacity,0xFFFFFF);
sharedPen.width = 2;
graphics.drawCurve(sharedPen,points);
}
for(i,tree in trees){
drawTree(graphics,tree);
}
for(i,leaf in leaves){
var angle = math.rad(leaf.rotation);
var cosValue,sinValue = math.cos(angle),math.sin(angle);
var halfWidth,halfHeight = leaf.size*0.5,leaf.size*0.34;
var ux,uy = cosValue*halfWidth,sinValue*halfWidth;
var vx,vy = -sinValue*halfHeight,cosValue*halfHeight;
sharedBrush.color = leafColors[leaf.color];
graphics.fillPolygon(sharedBrush,[
::POINTF(leaf.x+ux,leaf.y+uy),
::POINTF(leaf.x+vx,leaf.y+vy),
::POINTF(leaf.x-ux,leaf.y-uy),
::POINTF(leaf.x-vx,leaf.y-vy)
]);
}
}
winform.plus.onDrawBackground = function(graphics,rc,backgroundColor,color){
var width,height,dpiX,dpiY = getLogicalSize(owner);
sceneWidth,sceneHeight = width,height;
ensureBackgroundLayer(rc.width,rc.height,dpiX,dpiY);
if(backgroundLayer) graphics.drawImage(backgroundLayer,rc.left,rc.top);
//闪光是动态层,不写入静态缓存。
if(weatherState=="rain" && lightning.flashOpacity>0){
sharedBrush.color = withAlpha(lightning.flashOpacity,0xFFFFFF);
graphics.fillRectangle(sharedBrush,rc);
}
return true;//阻止绘制默认背景色或背景图像。
}
winform.plus.onDrawForeground = function(graphics,rc,foregroundRect,foregroundColor,color,font){
var dpiX,dpiY = winform.dpiScale(1,1);
var width,height = rc.width/dpiX,rc.height/dpiY;
var groundY = height-60;
//完整隔离本次绘图的变换、剪切区与质量设置。
var saved = graphics.save();
graphics.smoothingMode = 4/*_SmoothingModeAntiAlias*/;
graphics.textRenderingHint = 4/*_TextRenderingHintAntiAlias*/;
graphics.scale(dpiX,dpiY);
if(weatherState=="sunny"){
drawSunny(graphics,width,height);
}
for(i,cloud in clouds){
var opacity = cloud.opacity;
if(weatherState=="rain" && lightning.flashOpacity>50){
opacity = math.min(255,opacity+lightning.flashOpacity/3);
}
drawCloud(graphics,cloud,opacity);
}
if(weatherState=="rain"){
drawRain(graphics,width,height,groundY);
}
elseif(weatherState=="snow"){
drawSnow(graphics,width,height,groundY);
}
elseif(weatherState=="wind"){
drawWind(graphics,width,height);
}
graphics.fillRectangle(labelBackgroundBrush,width/2-76,15,152,42);
graphics.drawString(
labels[weatherState],labelFont,
::RECTF(0,15,width,42),labelFormat,labelBrush
);
graphics.restore(saved);
return true;//阻止绘制默认前景色或前景图像。
}
//全部速度按秒计算;dt 最大只取 50ms,避免窗口阻塞后对象穿越整个画面。
winform.plus.onAnimation = function(state,beginning,change,timestamp,duration,deltaMs){
if(deltaMs===null) deltaMs = 16;
var dt = math.min(math.max(deltaMs,0),50)/1000;
animTime += dt;
var width,height = getLogicalSize(owner);
sceneWidth,sceneHeight = width,height;
var groundY = height-60;
for(i,cloud in clouds){
cloud.x += cloud.speed*dt;
if(cloud.x>width+20){
cloud.x = -cloud.width-20;
cloud.y = randomInt(58,math.max(70,height*0.38));
}
}
if(weatherState=="rain"){
for(i,drop in rainDrops){
drop.y += drop.speed*dt;
drop.x -= drop.drift*dt;
if(drop.y>groundY+12 || drop.x < -drop.length){
drop.y = randomInt(-110,-20);
drop.x = randomInt(0,width+40);
}
}
if(lightning.flashOpacity>0){
lightning.flashOpacity -= 520*dt;
if(lightning.flashOpacity<=0){
lightning.flashOpacity = 0;
lightning.active = false;
}
}
if(lightning.playThunder){
lightning.thunderDelay -= dt;
if(lightning.thunderDelay<=0){
playThunder();
lightning.playThunder = false;
}
}
lightning.nextFlash -= dt;
if(lightning.nextFlash<=0){
triggerLightning();
lightning.nextFlash = randomSeconds(2400,5200);
}
}
elseif(weatherState=="snow"){
for(i,flake in snowFlakes){
flake.y += flake.speed*dt;
flake.swing += flake.swingSpeed*dt;
flake.x += math.sin(flake.swing)*flake.driftSpeed*dt;
flake.rotation = (flake.rotation+flake.rotSpeed*dt)%360;
if(flake.y>groundY-4 || flake.x < -20 || flake.x > width+20){
flake.y = randomInt(-70,-10);
flake.x = randomInt(0,width);
}
}
}
elseif(weatherState=="wind"){
for(i,windLine in windLines){
windLine.x += windLine.speed*dt;
if(windLine.x>width+30){
windLine.x = -windLine.length-30;
windLine.y = randomInt(75,height-80);
}
}
for(i,tree in trees){
tree.swing = (tree.swing+tree.swingSpeed*dt)%(math.pi*2);
}
for(i,leaf in leaves){
leaf.x += leaf.speedX*dt;
leaf.y += (
leaf.speedY+math.sin(animTime*4+leaf.phase)*20
)*dt;
leaf.rotation = (leaf.rotation+leaf.rotSpeed*dt)%360;
if(leaf.x>width+20 || leaf.y<55 || leaf.y>groundY+10){
leaf.x = randomInt(-45,-12);
leaf.y = randomInt(90,groundY-20);
}
}
}
//startAnimation 自动刷新;只有返回恒等于 null(或无返回值)才停止。
return true;
}
winform.btnSunny.oncommand = function(){
switchWeather("sunny");
}
winform.btnRain.oncommand = function(){
switchWeather("rain");
}
winform.btnSnow.oncommand = function(){
switchWeather("snow");
}
winform.btnWind.oncommand = function(){
switchWeather("wind");
if(midiOut){
//切换时只播放一次短促阵风提示,不把持续音当背景音乐。
midiOut.playAsync("changeInstrument(122), 1____,5____,3____,6____","C3",100);
}
}
winform.btnSunny.skin({
background={default=0xFFFF9500;hover=0xFFFF7F00;active=0xFFE56900;disabled=0xFFC0C0C0};
color={default=0xFFFFFFFF};
});
winform.btnRain.skin({
background={default=0xFF4A90D9;hover=0xFF3A7FC8;active=0xFF2A6EB7;disabled=0xFFC0C0C0};
color={default=0xFFFFFFFF};
});
winform.btnSnow.skin({
background={default=0xFF8E7CC3;hover=0xFF7A68AF;active=0xFF66549B;disabled=0xFFC0C0C0};
color={default=0xFFFFFFFF};
});
winform.btnWind.skin({
background={default=0xFF26A69A;hover=0xFF1E958A;active=0xFF16847A;disabled=0xFFC0C0C0};
color={default=0xFFFFFFFF};
});
//统一释放缓存和原生资源;MIDI 设备关闭前先停止全部音符。
winform.onDestroy = function(){
invalidateBackground();
sharedBrush.delete();
sharedPen.delete();
labelFont.delete();
labelFormat.delete();
labelBrush.delete();
labelBackgroundBrush.delete();
if(midiOut){
midiOut.reset();
midiOut.close();
}
}
switchWeather("rain");
winform.plus.startAnimation(16);
winform.show();
win.loopMessage();
Markdown 格式