- 論壇徽章:
- 0
|
有趣的小程序,轉(zhuǎn)給大家看看。
w-yong.com 作者:w-yong
[Ruby]代碼
#!/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這個(gè)API時(shí),搜索包含文字GetDC的文件在這個(gè)目錄: D:\Ruby18\lib\ruby\gems\1.8\gems\, 比如我搜索出來(lái)是 windows-pr-1.1.3\lib\windows\gdi\device_context.rb , 打開(kāi)看一下結(jié)構(gòu).
#則寫(xiě) require 'windows/gdi/device_context'
#include Windows::GDI::DeviceContext
#同理: GetPixel 在文件 bitmap.rb, 可以打開(kāi)它過(guò)目一下,看一下類結(jié)構(gòu).
#則寫(xiě) require 'windows/gdi/bitmap'
#include Windows::GDI::Bitmap
#在Ruby中方便的調(diào)用Win32 API (使用windows-pr和CStruct) :
#[url]http://www.w-yong.com/docs/ruby_win32_api.html[/url]
#不過(guò)代碼在結(jié)束時(shí),沒(méi)有重畫(huà)整個(gè)桌面,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 #同一時(shí)間飄動(dòng)的雪花數(shù)量
ScrnWidth = 1280 #屏幕寬度(單位:像素)
ScrnHight = 1024 #屏幕高度(單位:像素)
SnowColDown = 0xFFFFFF #積雪顏色
SnowColDuck = 0xFFDDDD #深色積雪顏色
SnowCol = 0xFEFfFE #雪花顏色
def initialize
`title 桌面飄雪` #設(shè)置窗口標(biāo)題
print "\r按 ctrl + c 結(jié)束"
@hDC1 = GetDC(0)
#初始化整個(gè)屏幕
@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
#設(shè)置計(jì)時(shí)器,Timer1用于畫(huà)單幀,Timer2用于風(fēng)向變化
Thread.new{
loop do
sleep 0.015
#畫(huà)出一幀
draw rescue(p $!.message + $@[0])
end
}
Thread.new{
loop do
#改變風(fēng)向
@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]) #取得屏幕原來(lái)的顏色值
end
#畫(huà)出一幀,即重畫(huà)所有雪花位置一次
def draw
SnowNum.times{|i|
if @pColor[i] != SnowCol
#還原上一個(gè)位置的顏色
SetPixel @hDC1, @px[i],@py[i], @pColor[i]
end
#設(shè)置新的位置,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
#取得新位置原始顏色值,用于下一步雪花飄過(guò)時(shí)恢復(fù)此處顏色
@pColor[i] = GetPixel(@hDC1,@px[i],@py[i])
#如果獲取顏色失敗,表明雪花已飄出屏幕,重新初始化
if @pColor[i] == 0xFFFFFFFF
initP i
else
#否則若雪花沒(méi)有重疊
if @pColor[i] != SnowCol
#若對(duì)比度較小(即不能堆積),就畫(huà)出雪花
#Rnd()>0.3用于防止某些連續(xù)而明顯的邊界截獲所有雪花
if rand > 0.3 or getContrast(i) < 50
SetPixel @hDC1,@px[i],@py[i], SnowCol
#否則表明找到明顯的邊界,畫(huà)出堆積的雪,并初始化以便畫(huà)新的雪花
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
#取得某一點(diǎn)與周圍點(diǎn)的對(duì)比度,確定是否在此位置堆積雪花
def getContrast(i)
#colorCmp = 0 #存儲(chǔ)用作對(duì)比的點(diǎn)的顏色值
#tempR = 0 #存儲(chǔ)CorlorCmp的紅色部分,下同
#tempG = 0
#tempB = 0
#slope=0 #存儲(chǔ)雪花飄落方向:Vx/Vy
#計(jì)算雪花飄落方向
if @pvy != 0
slope = @pvx / @pvy
else
slope = 2
end
#根據(jù)雪花飄落方向決定取哪一點(diǎn)作對(duì)比點(diǎn),
#若PVx/PVy在-1到1之間,即Slope=0,就取正下面的象素點(diǎn)
#若PVx/PVy>1,取右下方的點(diǎn),PVx/PVy<-1則取左下方
if slope == 0
colorCmp = GetPixel(@hDC1, @px[i], @py[i] + 1)
elsif slope > 1
colorCmp = GetPixel(@hDC1, @px[i] + 1, @py[i] + 1)
else
colorCmp = GetPixel(@hDC1, @px[i] - 1, @py[i] + 1)
end
#確定當(dāng)前位置沒(méi)有與另一個(gè)雪花重疊,否則返回0,用于防止由于不同雪花重疊造成雪花亂堆
if colorCmp == SnowCol
return 0
end
#分別獲取ColorCmp與對(duì)比點(diǎn)的藍(lán)、綠、紅部分的差值
tempB = ((colorCmp & 0xFF0000).abs - (@pColor[i] & 0xFF0000)) / 0x10000
tempG = ((colorCmp & 0xFF00).abs - (@pColor[i] & 0xFF00)) / 0x100
tempR = ((colorCmp & 0xFF).abs - (@pColor[i] & 0xFF))
##返回對(duì)比度值
(tempR + tempG + tempB) / 3
end
def cc
ReleaseDC 0, @hDC1 #釋放桌面窗口設(shè)備句柄
InvalidateRect 0, 0, 0 #清除所有雪花,恢復(fù)桌面
end
def run
trap(:INT){exit} #按 c-c 退出
timerStart #啟動(dòng)定時(shí)器
#等到所有進(jìn)程退出后,主進(jìn)程再退出
while(Thread.list.count != 1) do sleep 1 end
cc #結(jié)束運(yùn)行
end
end
Snow.new.run
110303171115591.jpg (153.42 KB, 下載次數(shù): 83)
下載附件
2011-03-04 08:27 上傳
|
|