Water Wave Effect by skovron25th Sep 2003 18:25
|
---|
Summary Use your mouse and LMB to generate water waves... Description This code loads some image, than for each pixel position it calculates displacement. Displacement points to pixel which replaces current pixel. It could produce very chaotic bitmaps but displacement is calculatet with use of heightmaps. Each coord of heightmap holds wave amplitude at that position so calculationg difference between neighbor amplitudes (along each axis) we simply calculate displacement for pixel position Code ` This code was downloaded from The Game Creators ` It is reproduced here with full permission ` http://www.thegamecreators.com remstart Water Wave Effect by Mariusz Skowronski (2003) optimalized by D Man remend rem global vars rem bitmap size and color depth global g_bmpWidth as integer global g_bmpHeight as integer global g_bmpBpp as integer global g_bytesPerPixel as integer rem memblock pointers (for faster access) global g_srcMemPtr as dword global g_dstMemPtr as dword rem screen dimensions global g_scrWidth as integer global g_scrHeight as integer rem height array swap index (current and new) global g_ch as integer global g_nh as integer rem properties rem wave amplitude global g_waveForce as integer rem drop size global g_dropRadius as integer rem damping value (the smaller value the faster waves disappear) 1 - 100 global g_waveDamp as integer rem init vars g_scrWidth = 640 g_scrHeight = 480 g_waveForce = 300 g_dropRadius = 8 g_waveDamp = 20 : rem DON'T USE ZERO rem begin set display mode g_scrWidth, g_scrHeight, 16 sync rate 0: sync on rem load bitmap (remember the smaller bitmap the faster it runs) load bitmap "example1.jpg", 1 g_bmpWidth = bitmap width(1) g_bmpHeight = bitmap height(1) g_bmpBpp = bitmap depth(1) g_bytesPerPixel = g_bmpBpp/8 rem create 2 bitmap memblocks make memblock from bitmap 1, 1 make memblock from bitmap 2, 1 rem get memblock addresses g_srcMemPtr = get memblock ptr(2) g_dstMemPtr = get memblock ptr(1) rem dont need this bitmap anymore delete bitmap 1 rem allocate 2 height maps dim g_heightMap(1, g_bmpWidth-1, g_bmpHeight-1) as integer rem clear height maps ClearHeights() rem set current height map to 0 g_ch = 0: g_nh = 1 rem main loop set current bitmap 0 do rem update heights UpdateHeights() rem update bitmap UpdateBitmap() rem uncomment following lie and rem this above to see it in greyscale rem DrawHeights() rem create bitmap form memblock make bitmap from memblock 0, 1 sync if mouseclick()=1 rem make wave at point mx, my MakeWave(mousex(), mousey(), g_dropRadius, g_waveForce) endif loop delete memblock 1 delete memblock 2 rem that's all end rem this clears height maps function ClearHeights() local x, y for y=0 to g_bmpHeight-1 for x=0 to g_bmpWidth-1 g_heightMap(0, x, y) = 0 g_heightMap(1, x, y) = 0 next x next y endfunction rem this makes a new wave function MakeWave(x, y, radius, mul) local u, v, sqru, sqrv, sqrr sqrr = radius*radius rem check if not out of bitmap boundary if (x>radius) and (x<g_bmpWidth-1-radius) and (y>radius) and (y<g_bmpHeight-1-radius) for v=y-radius to y+radius sqrv = (v-y)*(v-y) for u=x-radius to x+radius sqru = (u-x)*(u-x) rem for speed reasons check (dx^2 + dy^2) <= r^2 rem instead of real formula: sqrt(dx^2 + dy^) < r if (sqru+sqrv)<=sqrr: g_heightMap(g_ch,u,v) = mul*int(radius - sqrt(sqru+sqrv)+1) endif next u next v endif endfunction rem this is only for debug (shows waves in grayscale) function DrawHeights() local x, y, height, color local dstAddr as dword rem for each height for y=0 to g_bmpHeight-1 for x=0 to g_bmpWidth-1 height = g_heightMap(g_ch, x, y)/10 rem prepare gray color color = rgb(height+128, height+128, height+128) rem dont need this if useing one color depth select g_bytesPerPixel case 2: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*2: endcase case 4: dstAddr = g_dstMemPtr +12+(y*g_bmpWidth+x)*4: endcase endselect *dstAddr = color next x next y endfunction rem the meat. this updates height map function UpdateHeights() local x, y, height, temp rem we need skip bitmap edges couse we're making kind of area sampling for y=2 to g_bmpHeight-3 for x=2 to g_bmpWidth-3 rem calculate height difference rem read 12 height values surrounding (x,y), divide by 6 so we've got twice as much as average value rem and then subtract current height at (x, y) height = g_heightMap(g_ch,x-1,y) height = height + g_heightMap(g_ch,x-2,y) height = height + g_heightMap(g_ch,x+1,y) height = height + g_heightMap(g_ch,x+2,y) height = height + g_heightMap(g_ch,x,y-1) height = height + g_heightMap(g_ch,x,y-2) height = height + g_heightMap(g_ch,x,y+1) height = height + g_heightMap(g_ch,x,y+2) height = height + g_heightMap(g_ch,x-1,y-1) height = height + g_heightMap(g_ch,x+1,y-1) height = height + g_heightMap(g_ch,x-1,y+1) height = height + g_heightMap(g_ch,x+1,y+1) height = int(height/6) - g_heightMap(g_nh,x,y) rem add some dampig reducing amplitudes height = height - int(height/g_waveDamp + 1) g_heightMap(g_nh, x, y) = height next x next y rem swap height maps temp = g_ch g_ch = g_nh g_nh = temp endfunction rem this creates waved bitmap function UpdateBitmap() local x, y, tx, ty, color local srcAddr, dstAddr as dword rem skip bitmap edges for y=1 to g_bmpHeight-1 for x=1 to g_bmpWidth-1 rem calculate pixel displacements based on height difference tx = x + (g_heightMap(g_ch, x-1, y) - g_heightMap(g_ch, x, y))/10: rem divide couse height values are too high ty = y + (g_heightMap(g_ch, x, y-1) - g_heightMap(g_ch, x, y))/10 rem if (tx, ty) still inside bitmap bounds if tx>=0 and tx<g_bmpWidth and ty>=0 and ty<g_bmpHeight rem read color from coords we've calculated select g_bytesPerPixel case 2: srcAddr = g_srcMemPtr+12+(ty*g_bmpWidth+tx)*2: endcase case 4: srcAddr = g_srcMemPtr+12+(ty*g_bmpWidth+tx)*4: endcase endselect color = *srcAddr else rem if out of bitmap bounds let the color be black color = 0 endif rem store this color at current position select g_bytesPerPixel case 2: dstAddr = g_dstMemPtr+12+(y*g_bmpWidth+x)*2: endcase case 4: dstAddr = g_dstMemPtr+12+(y*g_bmpWidth+x)*4: endcase endselect *dstAddr = color next x next y endfunction |