您的位置:首页 > 编程语言 > C语言/C++

分享一个 C++ 水波效果静态库

2012-06-13 15:26 169 查看
罗云斌老师用汇编写了一个效果很赞的水波效果。一直想用在自己的工程中,可c++调用ASM的时候总出现稀奇古怪的问题。准备打算自己将汇编源代码改成C++的后来偶然看到博客园里已经有人做了这样的工作,就不重复发明轮子了。可惜的是原作者地址已经找不到了。深表歉意。

水波的效果:



水波分为好几种效果,有快艇划过的效果,有小雨的效果。等等。我这里能量值不大,所以看上去不是很明显。

静态库 下载地址 http://download.csdn.net/detail/witch_soya/4370709

附上罗老师asm源代码

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 水波效果公用子程序
; by 罗云彬,http://asm.yeah.net,luoyunbin@sina.com
; V 1.0.041019 --- 初始版本
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在源代码中只需要 include WaveObject.asm
; 然后按以下步骤调用即可:
;********************************************************************
; 1、创建水波对象:
;    要对一个窗口进行绘画,首先要创建一个水波对象(本函数申请一些缓冲区)
;    invoke _WaveInit,lpWaveObject,hWnd,hBmp,dwTime,dwType
;       lpWaveObject --> 指向一个空的 WAVE_OBJECT 结构
;       hWnd --> 要绘画水波效果的窗口,渲染后的图片将画到窗口的客户区中
;       hBmp --> 背景图片,绘画的范围大小同背景图片大小
;       dwTime --> 刷新的时间间隔(毫秒),建议值:10~30
;	dwType --> =0 表示圆形水波,=1表示椭圆型水波(用于透视效果)
;       返回值:eax = 0(成功,对象被初始化),eax = 1(失败)
;********************************************************************
; 2、如果 _WaveInit 函数返回成功,则对象被初始化,将对象传给下列各种函数
;    可以实现各种效果,下面函数中的 lpWaveObject 参数指向在 _WaveInit 函数
;    中初始化的 WAVE_OBJECT 结构
;
;    ◎ 在指定位置“扔石头”,激起水波
;       invoke _WaveDropStone,lpWaveObject,dwPosX,dwPosY,dwStoneSize,dwStoneWeight
;          dwPosX,dwPosY --> 扔下石头的位置
;          dwStoneSize --> 石头的大小,即初始点的大小,建议值:0~5
;          dwStoneWeight --> 石头的重量,决定了波最后扩散的范围大小,建议值:10~1000
;
;    ◎ 自动显示特效
;       invoke _WaveEffect,lpWaveObject,dwEffectType,dwParam1,dwParam2,dwParam3
;          dwParam1,dwParam2,dwParam3 --> 效果参数,对不同的特效类型参数含义不同
;          dwEffectType --> 特效类型
;             0 --> 关闭特效
;             1 --> 下雨,Param1=密集速度(0最密,越大越稀疏),建议值:0~30
;                         Param2=最大雨点直径,建议值:0~5
;                         Param3=最大雨点重量,建议值:50~250
;             2 --> 汽艇,Param1=速度(0最慢,越大越快),建议值:0~8
;                         Param2=船大小,建议值:0~4
;                         Param3=水波扩散的范围,建议值:100~500
;             3 --> 风浪,Param1=密度(越大越密),建议值:50~300
;                         Param2=大小,建议值:2~5
;                         Param3=能量,建议值:5~10
;
;    ◎ 窗口客户区强制更新(用于在窗口的WM_PAINT消息中强制更新客户端)
;       .if     uMsg == WM_PAINT
;               invoke  BeginPaint,hWnd,addr @stPs
;               mov     @hDc,eax
;               invoke  _WaveUpdateFrame,lpWaveObject,eax,TRUE
;               invoke  EndPaint,hWnd,addr @stPs
;               xor     eax,eax
;               ret
;********************************************************************
; 3、释放水波对象:
;    使用完毕后,必须将水波对象释放(本函数将释放申请的缓冲区内存等资源)
;       invoke  _WaveFree,lpWaveObject
;       lpWaveObject --> 指向 WAVE_OBJECT 结构
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 实现上的细节说明:
;
; 1、 水波的特征:
;   ◎ 扩散:每一点的波会扩散到其四周的位置中
;   ◎ 衰减:每次扩散会损失少量能量(否则水波会永不停止的震荡下去)
;
; 2、 为了保存两个时刻中的能量分步图,对象中定义2个缓冲区Wave1和Wave2
;  (保存在lpWave1和lpWave2指向的缓冲区内),Wave1为当前数据,Wave2为
;   上一帧的数据,每次渲染时将根据上面的2个特征,由Wave1的数据计算出新
;   能量分别图后,保存到Wave2中,然后调换Wave1和Wave2,这时Wave1仍是最
;   新的数据。
;      计算的方法为,某个点的能量=点四周的上次能量的平均值 * 衰减系数
;   取四周的平均值表现了扩展特征,乘以衰减系数表现了衰减特征。
;      这部分代码在 _WaveSpread 子程序中实现。
;
; 3、 对象在 lpDIBitsSource 中保存了原始位图的数据,每次渲染时,由原始
;   位图的数据根据Wave1中保存的能量分步数据产生新的位图。从视觉上看,
;   某个点的能量越大(水波越大),则光线折射出越远处的场景。
;      算法为:对于点(x,y),在Wave1中找出该点,计算出相邻点的波能差
;  (Dx和Dy两个数据),则新位图像素(x,y)=原始位图像素(x+Dx,y+Dy),
;   该算法表现了能量大小影响了像素折射的偏移大小。
;      这部分代码在 _WaveRender 子程序中实现。
;
; 4、 扔石头的算法很好理解,即将Wave1中的某个点的能量值置为非0值,数值
;   越大,表示扔下的石头的能量越大。石头比较大,则将该点四周的点全部
;   置为非0值。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ifndef		WAVEOBJ_INC
WAVEOBJ_INC	equ	1
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
F_WO_ACTIVE		equ	0001h
F_WO_NEED_UPDATE	equ	0002h
F_WO_EFFECT		equ	0004h
F_WO_ELLIPSE		equ	0008h

WAVE_OBJECT		struct
hWnd			dd	?
dwFlag			dd	?	; 见 F_WO_xxx 组合
;********************************************************************
hDcRender		dd	?
hBmpRender		dd	?
lpDIBitsSource		dd	?	; 原始像素数据
lpDIBitsRender		dd	?	; 用于显示到屏幕的像素数据
lpWave1		dd	?	; 水波能量数据缓冲1
lpWave2		dd	?	; 水波能量数据缓冲2
;********************************************************************
dwBmpWidth		dd	?
dwBmpHeight		dd	?
dwDIByteWidth		dd	?	; = (dwBmpWidth * 3 + 3) and ~3
dwWaveByteWidth	dd	?	; = dwBmpWidth * 4
dwRandom		dd	?
;********************************************************************
; 特效参数
;********************************************************************
dwEffectType		dd	?
dwEffectParam1		dd	?
dwEffectParam2		dd	?
dwEffectParam3		dd	?
;********************************************************************
; 用于行船特效
;********************************************************************
dwEff2X		dd	?
dwEff2Y		dd	?
dwEff2XAdd		dd	?
dwEff2YAdd		dd	?
dwEff2Flip		dd	?
;********************************************************************
stBmpInfo		BITMAPINFO <>
WAVE_OBJECT		ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 随机数产生子程序
; 输入:要产生的随机数的最大值,输出:随机数
; 根据:
; 1. 数学公式 Rnd=(Rnd*I+J) mod K 循环回带生成 K 次以内不重复的
;    伪随机数,但K,I,J必须为素数
; 2. 2^(2n-1)-1 必定为素数(即2的奇数次方减1)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveRandom16	proc	_lpWaveObject

mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
push	edx
push	ecx
mov	eax,[ebx].dwRandom
mov	ecx,32768-1	;2^15-1
mul	ecx
add	eax,2048-1	;2^11-1
adc	edx,0
mov	ecx,2147483647	;2^31-1
div	ecx
mov	eax,[ebx].dwRandom
mov	[ebx].dwRandom,edx
and	eax,0000ffffh
pop	ecx
pop	edx
ret

_WaveRandom16	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveRandom	proc	uses ebx ecx edx _lpWaveObject,_dwMax

invoke	_WaveRandom16,_lpWaveObject
mov	edx,eax
invoke	_WaveRandom16,_lpWaveObject
shl	eax,16
or	ax,dx
mov	ecx,_dwMax
or	ecx,ecx
jz	@F
xor	edx,edx
div	ecx
mov	eax,edx
@@:
ret

_WaveRandom	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 波能扩散
; 算法:
; Wave2(x,y) = (Wave1(x+1,y)+Wave1(x-1,y)+Wave1(x,y+1)+Wave1(x,y-1))/2-Wave2(x,y)
; Wave2(x,y) = Wave2(x,y) - Wave2(x,y) >> 5
; xchg Wave1,Wave2
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveSpread	proc	_lpWaveObject

pushad
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
;********************************************************************
test	[ebx].dwFlag,F_WO_ACTIVE
jz	_Ret

mov	esi,[ebx].lpWave1
mov	edi,[ebx].lpWave2
mov	ecx,[ebx].dwBmpWidth

mov	eax,[ebx].dwBmpHeight
dec	eax
mul	ecx
;********************************************************************
; ebx = width
; ecx = i,eax = max
;********************************************************************
.while	ecx < eax
push	eax
.if	[ebx].dwFlag & F_WO_ELLIPSE
mov	edx,[esi+ecx*4-1*4]
add	edx,[esi+ecx*4+1*4]
add	edx,[esi+ecx*4-2*4]
add	edx,[esi+ecx*4+2*4]
lea	edx,[edx+edx*2]
add	edx,[esi+ecx*4-3*4]
add	edx,[esi+ecx*4-3*4]
add	edx,[esi+ecx*4+3*4]
add	edx,[esi+ecx*4+3*4]

lea	eax,[esi+ecx*4]
sub	eax,[ebx].dwWaveByteWidth
mov	eax,[eax]
shl	eax,3
add	edx,eax

lea	eax,[esi+ecx*4]
add	eax,[ebx].dwWaveByteWidth
mov	eax,[eax]
shl	eax,3
add	edx,eax

sar	edx,4
sub	edx,[edi+ecx*4]

mov	eax,edx
sar	eax,5
sub	edx,eax

mov	[edi+ecx*4],edx
.else
mov	edx,[esi+ecx*4-1*4]
add	edx,[esi+ecx*4+1*4]

lea	eax,[esi+ecx*4]
sub	eax,[ebx].dwWaveByteWidth
add	edx,[eax]

lea	eax,[esi+ecx*4]
add	eax,[ebx].dwWaveByteWidth
add	edx,[eax]

sar	edx,1
sub	edx,[edi+ecx*4]

mov	eax,edx
sar	eax,5
sub	edx,eax

mov	[edi+ecx*4],edx
.endif
pop	eax
inc	ecx
.endw

mov	[ebx].lpWave1,edi
mov	[ebx].lpWave2,esi
_Ret:
;********************************************************************
assume	ebx:nothing
popad
ret

_WaveSpread	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; esi -> edi, ecx = line width
; return = (4*Pixel(x,y)+3*Pixel(x-1,y)+3*Pixel(x+1,y)+3*Pixel(x,y+1)+3*Pixel(x,y-1))/16
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveGetPixel:
movzx	eax,byte ptr [esi]
shl	eax,2
movzx	edx,byte ptr [esi+3]
lea	edx,[edx+2*edx]
add	eax,edx
movzx	edx,byte ptr [esi-3]
lea	edx,[edx+2*edx]
add	eax,edx
movzx	edx,byte ptr [esi+ecx]
lea	edx,[edx+2*edx]
add	eax,edx
mov	edx,esi
sub	edx,ecx
movzx	edx,byte ptr [edx]
lea	edx,[edx+2*edx]
add	eax,edx
shr	eax,4
mov	[edi],al
inc	esi
inc	edi
ret
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 渲染子程序,将新的帧数据渲染到 lpDIBitsRender 中
; 算法:
; posx = Wave1(x-1,y)-Wave1(x+1,y)+x
; posy = Wave1(x,y-1)-Wave1(x,y+1)+y
; SourceBmp(x,y) = DestBmp(posx,posy)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveRender	proc	_lpWaveObject
local	@dwPosX,@dwPosY,@dwPtrSource,@dwFlag

pushad
xor	eax,eax
mov	@dwFlag,eax
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT

test	[ebx].dwFlag,F_WO_ACTIVE
jz	_Ret

or	[ebx].dwFlag,F_WO_NEED_UPDATE
mov	esi,[ebx].lpWave1
mov	edi,[ebx].dwWaveByteWidth	; edi = 像素指针

xor	ecx,ecx
inc	ecx		; ecx=i  --  i=1; i<height; i++
_Loop1:
xor	edx,edx		; edx=j  --  j=0; j<width; j++
_Loop2:
push	edx
;********************************************************************
; PosY=i+像素上1能量-像素下1能量
; PosX=j+像素左1能量-像素右1能量
;********************************************************************
mov	eax,edi
sub	eax,[ebx].dwWaveByteWidth
mov	eax,[esi+eax]
mov	@dwPosY,eax

mov	eax,[ebx].dwWaveByteWidth
lea	eax,[edi+eax]
mov	eax,[esi+eax]
sub	@dwPosY,eax
add	@dwPosY,ecx

mov	eax,[esi+edi-4]
sub	eax,[esi+edi+4]
add	eax,edx			;@dwPosX = eax
mov	@dwPosX,eax

cmp	eax,0
jl	_Continue
cmp	eax,[ebx].dwBmpWidth
jge	_Continue
mov	eax,@dwPosY
cmp	eax,0
jl	_Continue
cmp	eax,[ebx].dwBmpHeight
jge	_Continue
;********************************************************************
; ptrSource = dwPosY * dwDIByteWidth + dwPosX * 3
; ptrDest = i * dwDIByteWidth + j * 3
;********************************************************************
mov	eax,@dwPosX
lea	eax,[eax+eax*2]
mov	@dwPosX,eax
push	edx
mov	eax,@dwPosY
mul	[ebx].dwDIByteWidth
add	eax,@dwPosX
mov	@dwPtrSource,eax

mov	eax,ecx
mul	[ebx].dwDIByteWidth
pop	edx
lea	edx,[edx+edx*2]
add	eax,edx			;@dwPtrDest = eax
;********************************************************************
; 渲染像素 [ptrDest] = 原始像素 [ptrSource]
;********************************************************************
pushad
mov	ecx,@dwPtrSource
mov	esi,[ebx].lpDIBitsSource
mov	edi,[ebx].lpDIBitsRender
lea	esi,[esi+ecx]
lea	edi,[edi+eax]
.if	ecx !=	eax
or	@dwFlag,1	;如果存在源像素和目标像素不同,则表示还在活动状态
mov	ecx,[ebx].dwDIByteWidth
call	_WaveGetPixel
call	_WaveGetPixel
call	_WaveGetPixel
.else
cld
movsw
movsb
.endif
popad
;********************************************************************
; 继续循环
;********************************************************************
_Continue:
pop	edx
inc	edx
add	edi,4		; 像素++
cmp	edx,[ebx].dwBmpWidth
jb	_Loop2

inc	ecx
mov	eax,[ebx].dwBmpHeight
dec	eax
cmp	ecx,eax
jb	_Loop1
;********************************************************************
; 将渲染的像素数据拷贝到 hDc 中
;********************************************************************
invoke	SetDIBits,[ebx].hDcRender,[ebx].hBmpRender,0,[ebx].dwBmpHeight,\
[ebx].lpDIBitsRender,addr [ebx].stBmpInfo,DIB_RGB_COLORS
.if	! @dwFlag
and	[ebx].dwFlag,not F_WO_ACTIVE
.endif
_Ret:
;********************************************************************
assume	ebx:nothing
popad
ret

_WaveRender	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveUpdateFrame	proc	_lpWaveObject,_hDc,_bIfForce

pushad
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT

cmp	_bIfForce,0
jnz	@F
.if	[ebx].dwFlag & F_WO_NEED_UPDATE
@@:
invoke	BitBlt,_hDc,0,0,[ebx].dwBmpWidth,[ebx].dwBmpHeight,\
[ebx].hDcRender,0,0,SRCCOPY
and	[ebx].dwFlag,not F_WO_NEED_UPDATE
.endif

assume	ebx:nothing
popad
ret

_WaveUpdateFrame	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 扔一块石头
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveDropStone	proc	_lpWaveObject,_dwX,_dwY,_dwSize,_dwWeight
local	@dwMaxX,@dwMaxY

pushad
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
;********************************************************************
; 计算范围
;********************************************************************
mov	edx,_dwSize
shr	edx,1

mov	eax,_dwX
mov	esi,_dwY

mov	ecx,eax
mov	edi,esi
add	eax,edx		; x + size
sub	ecx,edx		; x - size

push	edx
.if	[ebx].dwFlag & F_WO_ELLIPSE
shr	edx,1
.endif
add	esi,edx		; y + size
sub	edi,edx		; y - size
pop	edx

shl	edx,1
.if	! edx
inc	edx
.endif
mov	_dwSize,edx
;********************************************************************
; 判断范围的合法性
;********************************************************************
inc	eax
cmp	eax,[ebx].dwBmpWidth
jge	_Ret
cmp	ecx,1
jl	_Ret
inc	esi
cmp	esi,[ebx].dwBmpHeight
jge	_Ret
cmp	edi,1
jl	_Ret

dec	eax
dec	esi
;********************************************************************
; 将范围内的点的能量置为 _dwWeight
;********************************************************************
mov	@dwMaxX,eax
mov	@dwMaxY,esi
.while	ecx <=	@dwMaxX
push	edi
.while	edi <=	@dwMaxY
mov	eax,ecx
sub	eax,_dwX
imul	eax
push	eax
mov	eax,edi
sub	eax,_dwY
imul	eax
pop	edx
add	eax,edx
push	eax
mov	eax,_dwSize
imul	eax
pop	edx
.if	edx <=	eax
mov	eax,edi
mul	[ebx].dwBmpWidth
add	eax,ecx
shl	eax,2
add	eax,[ebx].lpWave1
push	_dwWeight
pop	[eax]
.endif
inc	edi
.endw
pop	edi
inc	ecx
.endw
or	[ebx].dwFlag,F_WO_ACTIVE
;********************************************************************
_Ret:
assume	ebx:nothing
popad
ret

_WaveDropStone	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算扩散数据、渲染位图、更新窗口、处理特效的定时器过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveTimerProc	proc	_hWnd,_uMsg,_idEvent,_dwTime

pushad
mov	ebx,_idEvent
assume	ebx:ptr WAVE_OBJECT

invoke	_WaveSpread,ebx
invoke	_WaveRender,ebx
.if	[ebx].dwFlag & F_WO_NEED_UPDATE
invoke	GetDC,[ebx].hWnd
invoke	_WaveUpdateFrame,ebx,eax,FALSE
invoke	ReleaseDC,[ebx].hWnd,eax
.endif
;********************************************************************
; 特效处理
;********************************************************************
test	[ebx].dwFlag,F_WO_EFFECT
jz	_Ret
mov	eax,[ebx].dwEffectType
;********************************************************************
; Type = 1 雨点,Param1=速度(0最快,越大越慢),Param2=雨点大小,Param3=能量
;********************************************************************
.if	eax ==	1
mov	eax,[ebx].dwEffectParam1
or	eax,eax
jz	@F
invoke	_WaveRandom,ebx,eax
.if	! eax
@@:
mov	eax,[ebx].dwBmpWidth
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	ecx,eax

mov	eax,[ebx].dwBmpHeight
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	edx,eax

invoke	_WaveRandom,ebx,[ebx].dwEffectParam2
inc	eax
mov	esi,eax
invoke	_WaveRandom,ebx,[ebx].dwEffectParam3
add	eax,50
invoke	_WaveDropStone,ebx,ecx,edx,esi,eax
.endif
;********************************************************************
; Type = 2 行船,Param1=速度(0最快,越大越快),Param2=大小,Param3=能量
;********************************************************************
.elseif	eax ==	2
inc	[ebx].dwEff2Flip
test	[ebx].dwEff2Flip,1
jnz	_Ret

mov	ecx,[ebx].dwEff2X
mov	edx,[ebx].dwEff2Y
add	ecx,[ebx].dwEff2XAdd
add	edx,[ebx].dwEff2YAdd

cmp	ecx,1
jge	@F
sub	ecx,1
neg	ecx
neg	[ebx].dwEff2XAdd
@@:
cmp	edx,1
jge	@F
sub	edx,1
neg	edx
neg	[ebx].dwEff2YAdd
@@:
mov	eax,[ebx].dwBmpWidth
dec	eax
cmp	ecx,eax
jl	@F
sub	ecx,eax
xchg	eax,ecx
sub	ecx,eax
neg	[ebx].dwEff2XAdd
@@:
mov	eax,[ebx].dwBmpHeight
dec	eax
cmp	edx,eax
jl	@F
sub	edx,eax
xchg	eax,edx
sub	edx,eax
neg	[ebx].dwEff2YAdd
@@:
mov	[ebx].dwEff2X,ecx
mov	[ebx].dwEff2Y,edx
invoke	_WaveDropStone,ebx,ecx,edx,[ebx].dwEffectParam2,[ebx].dwEffectParam3
;********************************************************************
; Type = 3 波浪,Param1=密度,Param2=大小,Param3=能量
;********************************************************************
.elseif	eax ==	3
xor	edi,edi
.while	edi <=	[ebx].dwEffectParam1
mov	eax,[ebx].dwBmpWidth
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	ecx,eax

mov	eax,[ebx].dwBmpHeight
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	edx,eax

invoke	_WaveRandom,ebx,[ebx].dwEffectParam2
inc	eax
mov	esi,eax
invoke	_WaveRandom,ebx,[ebx].dwEffectParam3
invoke	_WaveDropStone,ebx,ecx,edx,esi,eax
inc	edi
.endw
.endif
_Ret:
assume	ebx:nothing
popad
ret

_WaveTimerProc	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 释放对象
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveFree	proc	_lpWaveObject

pushad
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
;********************************************************************
.if	[ebx].hDcRender
invoke	DeleteDC,[ebx].hDcRender
.endif
.if	[ebx].hBmpRender
invoke	DeleteObject,[ebx].hBmpRender
.endif
.if	[ebx].lpDIBitsSource
invoke	GlobalFree,[ebx].lpDIBitsSource
.endif
.if	[ebx].lpDIBitsRender
invoke	GlobalFree,[ebx].lpDIBitsRender
.endif
.if	[ebx].lpWave1
invoke	GlobalFree,[ebx].lpWave1
.endif
.if	[ebx].lpWave2
invoke	GlobalFree,[ebx].lpWave2
.endif
invoke	KillTimer,[ebx].hWnd,ebx
invoke	RtlZeroMemory,ebx,sizeof WAVE_OBJECT
;********************************************************************
assume	ebx:nothing
popad
ret

_WaveFree	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 初始化对象
; 参数:_lpWaveObject = 指向 WAVE_OBJECT的指针
; 返回:eax = 0 成功、= 1 失败
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveInit	proc	_lpWaveObject,_hWnd,_hBmp,_dwSpeed,_dwType
local	@stBmp:BITMAP,@dwReturn

pushad
xor	eax,eax
mov	@dwReturn,eax
mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
invoke	RtlZeroMemory,ebx,sizeof WAVE_OBJECT

.if	_dwType
or	[ebx].dwFlag,F_WO_ELLIPSE
.endif
;********************************************************************
; 获取位图尺寸
;********************************************************************
push	_hWnd
pop	[ebx].hWnd
invoke	GetTickCount
mov	[ebx].dwRandom,eax

invoke	GetObject,_hBmp,sizeof BITMAP,addr @stBmp
.if	! eax
@@:
inc	@dwReturn
jmp	_Ret
.endif
mov	eax,@stBmp.bmHeight
mov	[ebx].dwBmpHeight,eax
cmp	eax,3
jle	@B
mov	eax,@stBmp.bmWidth
mov	[ebx].dwBmpWidth,eax
cmp	eax,3
jle	@B

push	eax
shl	eax,2
mov	[ebx].dwWaveByteWidth,eax
pop	eax
lea	eax,[eax+eax*2]
add	eax,3
and	eax,not 0011b
mov	[ebx].dwDIByteWidth,eax
;********************************************************************
; 创建用于渲染的位图
;********************************************************************
invoke	GetDC,_hWnd
mov	esi,eax
invoke	CreateCompatibleDC,esi
mov	[ebx].hDcRender,eax
invoke	CreateCompatibleBitmap,esi,[ebx].dwBmpWidth,[ebx].dwBmpHeight
mov	[ebx].hBmpRender,eax
invoke	SelectObject,[ebx].hDcRender,eax
;********************************************************************
; 分配波能缓冲区
;********************************************************************
mov	eax,[ebx].dwWaveByteWidth
mul	[ebx].dwBmpHeight
mov	edi,eax
invoke	GlobalAlloc,GPTR,edi
mov	[ebx].lpWave1,eax
invoke	GlobalAlloc,GPTR,edi
mov	[ebx].lpWave2,eax
;********************************************************************
; 分配像素缓冲区
;********************************************************************
mov	eax,[ebx].dwDIByteWidth
mul	[ebx].dwBmpHeight
mov	edi,eax
invoke	GlobalAlloc,GPTR,edi
mov	[ebx].lpDIBitsSource,eax
invoke	GlobalAlloc,GPTR,edi
mov	[ebx].lpDIBitsRender,eax
;********************************************************************
; 获取原始像素数据
;********************************************************************
mov	[ebx].stBmpInfo.bmiHeader.biSize,sizeof BITMAPINFOHEADER
push	[ebx].dwBmpWidth
pop	[ebx].stBmpInfo.bmiHeader.biWidth
mov	eax,[ebx].dwBmpHeight
neg	eax
mov	[ebx].stBmpInfo.bmiHeader.biHeight,eax
inc	[ebx].stBmpInfo.bmiHeader.biPlanes
mov	[ebx].stBmpInfo.bmiHeader.biBitCount,24
mov	[ebx].stBmpInfo.bmiHeader.biCompression,BI_RGB
mov	[ebx].stBmpInfo.bmiHeader.biSizeImage,0

invoke	CreateCompatibleDC,esi
push	eax
invoke	SelectObject,eax,_hBmp
invoke	ReleaseDC,_hWnd,esi
pop	eax
mov	esi,eax

invoke	GetDIBits,esi,_hBmp,0,[ebx].dwBmpHeight,[ebx].lpDIBitsSource,\
addr [ebx].stBmpInfo,DIB_RGB_COLORS
invoke	GetDIBits,esi,_hBmp,0,[ebx].dwBmpHeight,[ebx].lpDIBitsRender,\
addr [ebx].stBmpInfo,DIB_RGB_COLORS
invoke	DeleteDC,esi

.if	![ebx].lpWave1 || ![ebx].lpWave2 || ![ebx].lpDIBitsSource ||\
![ebx].lpDIBitsRender || ![ebx].hDcRender
invoke	_WaveFree,ebx
inc	@dwReturn
.endif

invoke	SetTimer,_hWnd,ebx,_dwSpeed,addr _WaveTimerProc

or	[ebx].dwFlag,F_WO_ACTIVE or F_WO_NEED_UPDATE
invoke	_WaveRender,ebx
invoke	GetDC,[ebx].hWnd
invoke	_WaveUpdateFrame,ebx,eax,TRUE
invoke	ReleaseDC,[ebx].hWnd,eax
;********************************************************************
_Ret:
assume	ebx:nothing
popad
mov	eax,@dwReturn
ret

_WaveInit	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 一些特效
; 输入:_dwType = 0	关闭特效
;	_dwType <> 0	开启特效,参数具体见上面
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaveEffect	proc	uses ebx eax _lpWaveObject,\
_dwType,_dwParam1,_dwParam2,_dwParam3
local	@dwMaxX,@dwMaxY

mov	ebx,_lpWaveObject
assume	ebx:ptr WAVE_OBJECT
;********************************************************************
mov	eax,_dwType
.if	eax ==	0
;********************************************************************
; 关闭特效
;********************************************************************
and	[ebx].dwFlag,not F_WO_EFFECT
mov	[ebx].dwEffectType,eax
.elseif	eax ==	2
;********************************************************************
; 行船特效
;********************************************************************
mov	eax,_dwParam1
mov	[ebx].dwEff2XAdd,eax
mov	[ebx].dwEff2YAdd,eax

mov	eax,[ebx].dwBmpWidth
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	[ebx].dwEff2X,eax

mov	eax,[ebx].dwBmpHeight
dec	eax
dec	eax
invoke	_WaveRandom,ebx,eax
inc	eax
mov	[ebx].dwEff2Y,eax

jmp	@F
.else
;********************************************************************
; 默认
;********************************************************************
@@:
push	_dwType
pop	[ebx].dwEffectType
push	_dwParam1
pop	[ebx].dwEffectParam1
push	_dwParam2
pop	[ebx].dwEffectParam2
push	_dwParam3
pop	[ebx].dwEffectParam3
or	[ebx].dwFlag,F_WO_EFFECT
.endif
;********************************************************************
assume	ebx:nothing
ret

_WaveEffect	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
endif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: