package water;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WateWave extends JFrame implements Runnable, MouseMotionListener {
boolean m_isRunning = false;
// boolean m_isRain = false;
int m_width;
int m_height;
int length;
int[] arrWaveCurrent;// 当前波形
int[] arrWaveNext;// 下一帧的波形
int[] arrClrInfo;// 图片原始颜色信息
int[] arrClrBuff;// 图片新的颜色信息
private Thread runner;
private Random random;
private Image offImage;
private MemoryImageSource source;
private JPanel panel = null;
public WateWave() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(762, 502);
this.setLocationRelativeTo(null);
addMouseMotionListener(this);
random = new Random();
try {
offImage = ImageIO.read(getClass().getResource("backgroud.png"));// 你自己的图片目录
} catch (IOException e1) {
}
m_width = offImage.getWidth(this);
m_height = offImage.getHeight(this);
length = m_width * m_height;
arrWaveCurrent = new int[length];
arrWaveNext = new int[length];
arrClrInfo = new int[length];
arrClrBuff = new int[length];
PixelGrabber pg = new PixelGrabber(offImage, 0, 0, m_width, m_height,
arrClrInfo, 0, m_width);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
source = new MemoryImageSource(m_width, m_height, arrClrBuff, 0,
m_width);
source.setAnimated(true);
offImage.getGraphics();
offImage = createImage(source);
panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(offImage, 0, 0, this);
}
};
this.setContentPane(panel);
this.setVisible(true);
start();
}
public void start() {
m_isRunning = true;
runner = new Thread(this);
runner.start();
}
public void stop() {
m_isRunning = false;
}
public void destroy() {
stop();
runner.interrupt();
}
public void run() {
while (m_isRunning) {
source.newPixels();
dot();
rippleRender();
try {
Thread.sleep(30);
} catch (Exception e) {
e.printStackTrace();
}
}
}
void dot() {
int x = 10 + random.nextInt() % (m_width - 20);
int y = 10 + random.nextInt() % (m_height - 20);
dropStone(x, y, 3, 128);
}
/**
* * 某点下一时刻的波幅算法为:上下左右四点的波幅和的一半减去当前波幅, 即 X0' =(X1 + X2 + y1 + X4)/ 2 - X0
*
* <pre>
* +----x3----+
* + | +
* x1---x0----x2
* + | +
* +----x4----+
*
* <pre>
*/
void rippleRender() {
int index = m_width;
int indexPreX = index - 1;
int indexNextX = index + 1;
int indexPreY = index - m_width;
int indexNextY = index + m_width;
for (int y = 1; y < m_height - 1; y++) {
for (int x = 1; x < m_width - 1; x++, index++) {
int x1 = arrWaveCurrent[indexPreX++];
int x2 = arrWaveCurrent[indexNextX++];
int x3 = arrWaveCurrent[indexPreY++];
int x4 = arrWaveCurrent[indexNextY++];
// 波能扩散:上下左右四点的波幅和的一半减去当前波幅
// X0' =(X1 + X2 + X3 + X4)/ 2 - X0
arrWaveNext[index] = ((x1 + x2 + x3 + x4) >> 1)
- arrWaveNext[index];
// 波能衰减 1/32
arrWaveNext[index] -= arrWaveNext[index] >> 5;
// 计算出偏移象素和原始象素的内存地址偏移量 :
int xoffset = x1 - x2;
int yoffset = x3 - x4;
int offset = m_width * yoffset + xoffset;
// 判断坐标是否在窗口范围内
if (index + offset > 0 && index + offset < length) {
arrClrBuff[index] = arrClrInfo[index + offset];
} else {
arrClrBuff[index] = arrClrInfo[index];
}
}
}
// 交换波能数据缓冲区
int[] temp = arrWaveCurrent;
arrWaveCurrent = arrWaveNext;
arrWaveNext = temp;
}
/**
* 扔石头
*
* @param x
* @param y
* @param r
* 半径
* @param h
* 波源能量
*/
void dropStone(int x, int y, int r, int h) {
// 判断坐标是否在屏幕范围内
if ((x + r) > m_width || (y + r) > m_height || (x - r) < 0
|| (y - r) < 0) {
return;
}
int value = r * r;
for (int posx = x - r; posx < x + r; posx++) {
for (int posy = y - r; posy < y + r; posy++) {
if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < value) {
arrWaveCurrent[m_width * posy + posx] = -h;
}
}
}
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
int x = (int) (e.getX());
int y = (int) (e.getY());
dropStone(x, y, 4, 200);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new WateWave();
}
});
}
}
package water;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WaterApp extends JFrame implements Runnable, MouseListener,
MouseMotionListener {
int m_nBmpWidth;
int m_nBmpHeight;
int m_nBmpWidthBySize; // 图片每行占用字节数
int[] m_byArrClrInfo; // 图片原始颜色信息
int[] m_byArrClrBuff; // 图片新的颜色信息
int[] m_nArrWaveCurrent; // 当前波形
int[] m_nArrWaveNext; // 下一帧的波形
private MemoryImageSource source;
private Image offImage;
private Graphics offGraphics;
private Thread animatorThread;
private JPanel panel = null;
public WaterApp() {
super("Water");
init();
start();
}
void init() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(762, 502);
this.setLocationRelativeTo(null);
addMouseListener(this);
addMouseMotionListener(this);
try {
offImage = ImageIO.read(getClass().getResource("/images/0.jpg"));
} catch (IOException e1) {
}
m_nBmpWidth = offImage.getWidth(this);
m_nBmpHeight = offImage.getHeight(this);
m_nBmpWidthBySize = m_nBmpWidth * 4;
int len = m_nBmpWidthBySize * m_nBmpHeight;
m_byArrClrInfo = new int[len];
m_byArrClrBuff = new int[len];
m_nArrWaveCurrent = new int[m_nBmpWidth * m_nBmpHeight];
m_nArrWaveNext = new int[m_nBmpWidth * m_nBmpHeight];
PixelGrabber pg1 = new PixelGrabber(offImage, 0, 0, m_nBmpWidth,
m_nBmpHeight, m_byArrClrInfo, 0, m_nBmpWidth);
try {
pg1.grabPixels();
} catch (InterruptedException e) {
}
System.arraycopy(m_byArrClrInfo, 0, m_byArrClrBuff, 0, len);
offGraphics = offImage.getGraphics();
source = new MemoryImageSource(m_nBmpWidth, m_nBmpHeight,m_byArrClrBuff, 0, m_nBmpWidth);
source.setAnimated(true);
offImage = createImage(source);
panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(offImage, 0, 0, this);
System.out.println("paintComponent");
}
};
this.setContentPane(panel);
this.setVisible(true);
}
public void start() {
if (animatorThread == null) {
animatorThread = new Thread(this);
}
animatorThread.start();
}
public void stop() {
animatorThread = null;
}
public void destroy() {
removeMouseListener(this);
removeMouseMotionListener(this);
}
/**
* @param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new WaterApp();
}
});
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
setWavePoint(e.getX(), m_nBmpHeight - e.getY(),(int) Math.random() * 5 + 5, (int) Math.random() * 32 + 128);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void run() {
while (Thread.currentThread() == animatorThread) {
newframe();
source.newPixels();
offGraphics.drawImage(offImage, 0, 0, m_nBmpWidth, m_nBmpHeight,null);
panel.repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void newframe() {
int a, b, x, y, speed, fast, index, increment;
for (y = 1; y < m_nBmpHeight - 2; y++) {
index = y * m_nBmpWidth;
speed = y * m_nBmpWidthBySize;
for (x = 1; x < m_nBmpWidth - 2; x++) {
m_nArrWaveNext[index] = (m_nArrWaveCurrent[index - 1]+ m_nArrWaveCurrent[index + 1]
+ m_nArrWaveCurrent[index - m_nBmpWidth] + m_nArrWaveCurrent[index
+ m_nBmpWidth]) >> 1 - m_nArrWaveNext[index];
m_nArrWaveNext[index] = m_nArrWaveNext[index]- m_nArrWaveNext[index] >> 5; // '产生阻尼
a = m_nArrWaveNext[index + 1] - m_nArrWaveNext[index - 1] + x; // '右移越大// 折射变大
b = m_nArrWaveNext[index + m_nBmpWidth]- m_nArrWaveNext[index - m_nBmpWidth] + y; // '左移也可 折射变小
if (a == x && b == y) {
continue;
}
if (a < 0)
a = 0;
if (a >= m_nBmpWidth)
a = m_nBmpWidth - 1;
if (b < 0)
b = 0;
if (b >= m_nBmpHeight)
b = m_nBmpHeight - 1;
increment = m_nArrWaveNext[index]; // 用当前像素点的能量作为光线明暗度变化标志
increment >>= increment < 0 ? 5 : 3;
// 重置RGB值
fast = b * m_nBmpWidthBySize + a * 4;
int R = m_byArrClrInfo[fast] + increment;
int G = m_byArrClrInfo[fast + 1] + increment;
int B = m_byArrClrInfo[fast + 2] + increment;
// if (increment < 0) { // 如果是负数便是变暗 则不能让其越界 0 - 255
// R = R < 0 ? 0 : R;
// G = G < 0 ? 0 : G;
// B = B < 0 ? 0 : B;
// } else {
// R = R > 255 ? 255 : R;
// G = G > 255 ? 255 : G;
// B = B > 255 ? 255 : B;
// }
m_byArrClrBuff[speed] = R;
m_byArrClrBuff[speed + 1] = G;
m_byArrClrBuff[speed + 2] = B;
index = index + 1;
speed = speed + 4;
}
}
int[] temp = m_nArrWaveCurrent;
m_nArrWaveCurrent = m_nArrWaveNext;
m_nArrWaveNext = temp;
}
// 设置波源 x,y波源坐标 r波源半径 h波源的能量大小
public void setWavePoint(int x, int y, int r, int h) {
// 判断波源所在矩形位置是否越出图像 以便将越出部分坐标重置
int nXStart = x - r < 0 ? 0 : x - r; // 波源矩形位置x轴起点
int nYStart = y - r < 0 ? 0 : y - r; // 波源矩形位置y轴起点
int nXLen = x + r >= m_nBmpWidth ? m_nBmpWidth - 1 : x + r; // 波源x轴矩形长度
int nYlen = y + r >= m_nBmpHeight ? m_nBmpHeight - 1 : y + r; // 波源y轴矩形长度
for (int posX = nXStart; posX < nXLen; posX++) {
for (int posY = nYStart; posY < nYlen; posY++) { // 以点(x,y)半径为r内的点赋值一个能量
if ((posX - x) * (posX - x) + (posY - y) * (posY - y) < r * r)
m_nArrWaveCurrent[posY * m_nBmpWidth + posX] = -h;
}
}
}
}
java 这个有问题,放在这里请大家大家帮忙更正一下,让他正常运行。不喜欢的不要喷。
VERSION 5.00
Begin VB.Form FrmWater
BackColor = &H00C0FFC0&
Caption = "水波"
ClientHeight = 10170
ClientLeft = 120
ClientTop = 510
ClientWidth = 15525
FillColor = &H00FFFFFF&
BeginProperty Font
Name = "宋体"
Size = 12
Charset = 134
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Icon = "FrmWater.frx":0000
LinkTopic = "Form1"
ScaleHeight = 10170
ScaleWidth = 15525
StartUpPosition = 2 '屏幕中心
Begin VB.PictureBox PicWave
AutoSize = -1 'True
BorderStyle = 0 'None
Height = 10245
Left = -120
Picture = "FrmWater.frx":08CA
ScaleHeight = 683
ScaleMode = 3 'Pixel
ScaleWidth = 1024
TabIndex = 0
Top = -240
Width = 15360
End
Begin VB.Timer timerSetWave
Interval = 50
Left = 2520
Top = 4080
End
Begin VB.Timer timerDraw
Interval = 45
Left = 1920
Top = 4080
End
End
Attribute VB_Name = "FrmWater"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
'************************VB版本水波效果***********************
'**作者: laviewpbt
'**QQ: 33184777
'***********************************************************
Private Type BITMAPINFO '40 bytes
biSize As Long 'BITMAPINFOHEADER结构的大小
biWidth As Long
biHeight As Long
biPlanes As Integer '设备的为平面数,现在都是1
biBitCount As Integer '图像的颜色位图
biCompression As Long '压缩方式
biSizeImage As Long '实际的位图数据所占字节
biXPelsPerMeter As Long '目标设备的水平分辨率
biYPelsPerMeter As Long '目标设备的垂直分辨率
biClrUsed As Long '使用的颜色数
biClrImportant As Long '重要的颜色数。如果该项为0,表示所有颜色都是重要的
End Type
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function VarPtrArray Lib "msvbvm60" Alias "VarPtr" (Ptr() As Any) As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Const DIB_RGB_COLORS = 0&
Private Const BI_RGB = 0&
Private BmpInfo As BITMAPINFO
Private m_byArrClrInfo() As Byte '图片原始颜色信息
Private m_byArrClrBuff() As Byte '图片新的颜色信息
Private m_nArrWaveCurrent() As Long '当前波形
Private m_nArrWaveNext() As Long '下一帧的波形
Private m_nBmpWidth As Long '
Private m_nBmpHeight As Long '
Private m_nBmpWidthBySize As Long '图片每行占用字节数
Private SystemFrequency As Currency
Private Sub Form_DblClick()
Unload Me
End Sub
Private Sub Form_Load()
PicWave.Picture = LoadPicture(App.Path & "\123.jpg")
Me.Move Me.Left, Me.Top, PicWave.Width, PicWave.Height
m_nBmpWidth = PicWave.ScaleWidth
m_nBmpHeight = PicWave.ScaleHeight
m_nBmpWidthBySize = m_nBmpWidth * 4
With BmpInfo
.biSize = Len(BmpInfo)
.biWidth = m_nBmpWidth
.biHeight = m_nBmpHeight
.biPlanes = 1
.biBitCount = 32
.biCompression = BI_RGB
End With
ReDim m_byArrClrInfo(m_nBmpWidthBySize * m_nBmpHeight) As Byte
ReDim m_byArrClrBuff(m_nBmpWidthBySize * m_nBmpHeight) As Byte
ReDim m_nArrWaveNext(m_nBmpWidth * m_nBmpHeight) As Long
ReDim m_nArrWaveCurrent(m_nBmpWidth * m_nBmpHeight) As Long
timerDraw.Interval = 10 '绘制水波
timerDraw.Enabled = True
timerSetWave.Interval = 500 '随机产生波源
timerSetWave.Enabled = True
GetDIBits Me.hdc, PicWave.Image.Handle, 0, m_nBmpHeight, m_byArrClrInfo(0), BmpInfo, DIB_RGB_COLORS
CopyMemory m_byArrClrBuff(0), m_byArrClrInfo(0), m_nBmpWidthBySize * m_nBmpHeight
Randomize
End Sub
Private Sub timerDraw_Timer()
Dim nNewX As Long, nNewY As Long
Dim X As Long, Y As Long
Dim Speed As Long, Index As Long
Dim Fast As Long
Dim nIncrement As Long
Dim R As Long, G As Long
Dim B As Long
Dim T As Currency
T = GetCurrentTime
For Y = 1 To m_nBmpHeight - 2
Index = Y * m_nBmpWidth
Speed = Y * m_nBmpWidthBySize
For X = 1 To m_nBmpWidth - 2
m_nArrWaveNext(Index) = (m_nArrWaveCurrent(Index - 1) + m_nArrWaveCurrent(Index + 1) + _
m_nArrWaveCurrent(Index - m_nBmpWidth) + m_nArrWaveCurrent(Index + m_nBmpWidth)) \ 2 _
- m_nArrWaveNext(Index)
m_nArrWaveNext(Index) = m_nArrWaveNext(Index) - m_nArrWaveNext(Index) \ 32 '产生阻尼
nNewX = m_nArrWaveNext(Index + 1) - m_nArrWaveNext(Index - 1) + X '右移越大 折射变大
nNewY = m_nArrWaveNext(Index + m_nBmpWidth) - m_nArrWaveNext(Index - m_nBmpWidth) + Y '左移也可 折射变小
If nNewX = X And nNewY = Y Then
Else
If nNewX < 0 Then
nNewX = 0 '也可将其赋值为 0
ElseIf nNewX >= m_nBmpWidth Then
nNewX = m_nBmpWidth - 1
End If
If nNewY < 0 Then
nNewY = 0
ElseIf nNewY >= m_nBmpHeight Then
nNewY = m_nBmpHeight - 1
End If
nIncrement = m_nArrWaveNext(Index) '用当前像素点的能量作为光线明暗度变化标志
If nIncrement < 0 Then
nIncrement = nIncrement \ 32
Else
nIncrement = nIncrement \ 8
End If
'重置RGB值
Fast = nNewY * m_nBmpWidthBySize + nNewX * 4
B = m_byArrClrInfo(Fast) + nIncrement
G = m_byArrClrInfo(Fast + 1) + nIncrement
R = m_byArrClrInfo(Fast + 2) + nIncrement
' If nIncrement < 0 Then '如果是负数便是变暗 则不能让其越界 0 - 255
' If R < 0 Then R = 0
' If G < 0 Then G = 0
' If B < 0 Then B = 0
' Else
' If R > 255 Then R = 255
' If G > 255 Then G = 255
' If B > 255 Then B = 255
' End If
m_byArrClrBuff(Speed) = (B And (B >= 0) Or (B >= 256)) And &HFF
m_byArrClrBuff(Speed + 1) = (G And (G >= 0) Or (G >= 256)) And &HFF
m_byArrClrBuff(Speed + 2) = (R And (R >= 0) Or (R >= 256)) And &HFF
End If
Index = Index + 1
Speed = Speed + 4
Next
Next
SetDIBitsToDevice PicWave.hdc, 0, 0, m_nBmpWidth, m_nBmpHeight, 0, 0, 0, m_nBmpHeight, m_byArrClrBuff(0), BmpInfo, DIB_RGB_COLORS
Swap m_nArrWaveCurrent, m_nArrWaveNext '交换两个数组
Me.Caption = CLng(GetCurrentTime - T)
End Sub
Private Sub timerSetWave_Timer()
Dim i As Long
For i = 0 To 4
SetWavePoint (m_nBmpWidth - 1) * Rnd, (m_nBmpHeight - 1) * Rnd, Rnd * 5 + 5, Rnd * 32 + 128
Next
End Sub
Private Sub PicWave_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetWavePoint CLng(X), m_nBmpHeight - CLng(Y), Rnd * 5 + 5, Rnd * 32 + 128
End Sub
'设置波源 x,y波源坐标 r波源半径 h波源的能量大小
Public Sub SetWavePoint(X As Long, Y As Long, R As Long, h As Long)
Dim nXStart As Long, nYStart As Long
Dim nXLen As Long, nYlen As Long
Dim PosX As Long, PosY As Long
If X - R < 0 Then
nXStart = 0
Else
nXStart = X - R
End If
If Y - R < 0 Then
nYStart = 0
Else
nYStart = Y - R
End If
If X + R >= m_nBmpWidth Then
nXLen = m_nBmpWidth - 1
Else
nXLen = X + R
End If
If Y + R >= m_nBmpHeight Then
nYlen = m_nBmpHeight - 1
Else
nYlen = Y + R
End If
For PosX = nXStart To nXLen - 1
For PosY = nYStart To nYlen - 1 '以点(x,y)半径为r内的点赋值一个能量
If ((PosX - X) * (PosX - X) + (PosY - Y) * (PosY - Y) < R * R) Then
m_nArrWaveCurrent(PosY * m_nBmpWidth + PosX) = -h
End If
Next
Next
End Sub
Private Function GetCurrentTime() As Currency
If SystemFrequency = 0 Then '未初始化
If QueryPerformanceFrequency(SystemFrequency) = 0 Then
SystemFrequency = -1 '无高精度计数器
End If
End If
If SystemFrequency <> -1 Then
Dim CurCount As Currency
QueryPerformanceCounter CurCount
GetCurrentTime = CurCount * 1000@ / SystemFrequency
Else
GetCurrentTime = GetTickCount()
End If
End Function
Private Sub Swap(a() As Long, B() As Long)
Dim SafeA As Long, SafeB As Long
Dim AddressA As Long, AddressB As Long
CopyMemory SafeA, ByVal VarPtrArray(a), 4 '得到指向A数组SAFEARRAY指针的指针
CopyMemory SafeB, ByVal VarPtrArray(B), 4 '得到指向B数组SAFEARRAY指针的指针
SafeA = SafeA + 12 '偏移12个字节为指向真数组的指针
SafeB = SafeB + 12
CopyMemory AddressA, ByVal SafeA, 4 '得到A数组的“真数组”的内存首地址
CopyMemory ByVal SafeA, ByVal SafeB, 4 '交换B数组和A数组对应的真数组的内存首地址
CopyMemory ByVal SafeB, AddressA, 4
End Sub