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

        罗云斌老师用汇编写了一个效果很赞的水波效果。一直想用在自己的工程中,可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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值