#!/usr/bin/env ruby
# -*- coding: gb18030 -*-
# 2011-3
#ruby 1.8.7 (2011-02-18 patchlevel 334) [i386-mingw32]
#gem 1.6
#gem install win32-api windows-pr windows-api cstruct
#比如要使用 GetDC这个API时,搜索包含文字GetDC的文件在这个目录: D:\Ruby18\lib\ruby\gems\1.8\gems\, 比如我搜索出来是 windows-pr-1.1.3\lib\windows\gdi\device_context.rb , 打开看一下结构.
#则写 require 'windows/gdi/device_context'
#include Windows::GDI::DeviceContext
#同理: GetPixel 在文件 bitmap.rb, 可以打开它过目一下,看一下类结构.
#则写 require 'windows/gdi/bitmap'
#include Windows::GDI::Bitmap
#在Ruby中方便的调用Win32 API (使用windows-pr和CStruct) :
#
#不过代码在结束时,没有重画整个桌面,BUG..
require 'rubygems'
require 'windows/gdi/device_context'
require 'windows/gdi/bitmap'
require 'win32struct'
include Windows::GDI::DeviceContext
include Windows::GDI::Bitmap
module Windows
module GDI
module DeviceContext
API.new('InvalidateRect','LLL','L','user32')
end
end
end
class Snow
SnowNum = 500 #同一时间飘动的雪花数量
ScrnWidth = 1280 #屏幕宽度(单位:像素)
ScrnHight = 1024 #屏幕高度(单位:像素)
SnowColDown = 0xFFFFFF #积雪颜色
SnowColDuck = 0xFFDDDD #深色积雪颜色
SnowCol = 0xFEFfFE #雪花颜色
def initialize
`title 桌面飘雪` #设置窗口标题
print "\r按 ctrl + c 结束"
@hDC1 = GetDC(0)
#初始化整个屏幕
@vx=0
@vy=0
@px=[]
@py=[]
@pColor=[]
SnowNum.times{|j|
@px[j] = rand * ScrnWidth
@py[j] = rand * ScrnHight / 1.5
@pColor[j] = GetPixel(@hDC1, @px[j], @py[j])
}
end
def timerStart
#设置计时器,Timer1用于画单帧,Timer2用于风向变化
Thread.new{
loop do
sleep 0.015
#画出一帧
draw rescue(p $!.message + $@[0])
end
}
Thread.new{
loop do
#改变风向
@vx = rand * 4 - 2
@vy = rand + 2
sleep 1.4
end
}
end
#初始化雪花位置
def initP(i)
@px[i] = rand * ScrnWidth
@py[i] = rand * 3
@pColor[i] = GetPixel(@hDC1, @px[i], @py[i]) #取得屏幕原来的颜色值
end
#画出一帧,即重画所有雪花位置一次
def draw
SnowNum.times{|i|
if @pColor[i] != SnowCol
#还原上一个位置的颜色
SetPixel @hDC1, @px[i],@py[i], @pColor[i]
end
#设置新的位置,i Mod 3用于将雪花分为三类采用不同速度,以便形成层次感
@pvx = rand * 2 - 1 + @vx * (i%3)
@pvy = @vy * (i%3+1)
@px[i] =@px[i] + @pvx
@py[i] =@py[i] + @pvy
#取得新位置原始颜色值,用于下一步雪花飘过时恢复此处颜色
@pColor[i] = GetPixel(@hDC1,@px[i],@py[i])
#如果获取颜色失败,表明雪花已飘出屏幕,重新初始化
if @pColor[i] == 0xFFFFFFFF
initP i
else
#否则若雪花没有重叠
if @pColor[i] != SnowCol
#若对比度较小(即不能堆积),就画出雪花
#Rnd()>0.3用于防止某些连续而明显的边界截获所有雪花
if rand > 0.3 or getContrast(i) < 50
SetPixel @hDC1,@px[i],@py[i], SnowCol
#否则表明找到明显的边界,画出堆积的雪,并初始化以便画新的雪花
else
SetPixel @hDC1,@px[i],@py[i] - 1, SnowColDuck
SetPixel @hDC1,@px[i] - 1,@py[i], SnowColDuck
SetPixel @hDC1,@px[i] + 1,@py[i], SnowColDown
initP i
end
end
end
}
end