Java 水面倒影

概要:

水面倒影在生活中可以见到,就是在水中呈现出一个物体的倒影。本实例是一个Java小应用程序(Applet)的例子。使用线程技术,运行小程序就会显示一个水面倒影的特效。

| |目录

技术要点

水面倒影的技术要点如下:

  • 类Math的使用。

  • 类MediaTracket的使用。

  • 类Graphics的使用。

  • 水波特效。

代码实现

package net.xsoftlab.baike;

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;

public class Reflection extends Applet implements Runnable {

	private static final long serialVersionUID = 4148367580239511427L;

	Thread thread = null;// 声明线程
	private Graphics g, inv_g;// 定义绘制正常图像和倒立后图像的Graphics对象
	private Image image, invimage;// image用于载入正常图像,invimage用于载入倒立后图像
	private int inv;// 应用于形成倒立影象的变量
	private int image_W = 0, image_H = 0;// 定义装载图片宽和高的变量
	private boolean load_Flag = false;// 定义标志,其作用是标志加载图片是否完毕
	private final int fre = 14;// 定义水纹波动的频率,数值越大,波动越慢。
	private String picture_name = "";// 定义图片名字

	@Override
	public void init() {// 初始化applet
		picture_name = "flaw.jpg";
	}

	@Override
	public void paint(Graphics g) {
		if (!load_Flag)// 如果已经载入图片,则返回
			return;
		if (invimage != null) {// 输出倒影图片
			g.drawImage(invimage, (-inv * image_W), image_H, this);
			g.drawImage(invimage, ((fre - inv) * image_W), image_H, this);
		}
		g.drawImage(image, 0, -1, this);// 输出正向图片
	}

	@Override
	public void start() {// 启动applet,创建并启动线程
		if (thread == null) {
			thread = new Thread(this);
			thread.start();
		}
	}

	public void run() {// 启动线程
		// 加载图片
		inv = 0;
		g = getGraphics();
		MediaTracker imageTracker = new MediaTracker(this);
		image = getImage(this.getCodeBase(), picture_name);
		imageTracker.addImage(image, 0);
		try {
			imageTracker.waitForAll();
			load_Flag = !imageTracker.isErrorAny();// 检查媒体跟踪器跟踪的所有图像的错误状态
		} catch (InterruptedException e) {
		}
		// 图片宽度、图片高度
		image_W = image.getWidth(this);
		image_H = image.getHeight(this);
		this.setSize(image_W, image_H * 2 - 20);
		System.out.println(image_W + "  " + image_H);
		creatWater();// 生成倒影
		repaint();// 重新输出applet
		while (true) {
			try {
				if (!load_Flag)
					return;
				if (invimage != null) {
					g.drawImage(invimage, (-inv * image_W), image_H, this);
					g.drawImage(invimage, ((fre - inv) * image_W), image_H, this);
				}
				g.drawImage(image, 0, -1, this);
				if (++inv == fre)
					inv = 0;
				Thread.sleep(50);
			} catch (InterruptedException e) {
				stop();
			}
		}
	}

	public void creatWater() {// 产生水波特效
		Image back = createImage(image_W, image_H + 1);
		Graphics graphics = back.getGraphics();
		int phase = 0;
		int x, y;
		double p1;
		graphics.drawImage(image, 0, 1, this);
		for (int i = 0; i < (image_H >> 1); i++) {
			graphics.copyArea(0, i, image_W, 1, 0, image_H - i);
			graphics.copyArea(0, image_H - 1 - i, image_W, 1, 0, -image_H + 1 + (i << 1));
			graphics.copyArea(0, image_H, image_W, 1, 0, -1 - i);
		}
		invimage = createImage((fre + 1) * image_W, image_H);
		inv_g = invimage.getGraphics();
		inv_g.drawImage(back, fre * image_W, 0, this);
		for (phase = 0; phase < fre; phase++) {
			p1 = 2 * Math.PI * phase / fre;
			x = (fre - phase) * image_W;
			for (int i = 0; i < image_H; i++) {
				y = (int) ((image_H / 14) * (i + 28.0)
						* Math.sin((double) ((image_H / 14) * (image_H - i)) / (double) (i + 1) + p1) / image_H);
				if (i < -y)
					inv_g.copyArea(fre * image_W, i, image_W, 1, -x, 0);
				else
					inv_g.copyArea(fre * image_W, i + y, image_W, 1, -x, -y);
			}
		}
		graphics.drawImage(image, 0, 1, this);
		image = back;
	}
}

程序解读

  1. 先定义一个正常的图片和一个倒立的图片,初始化变量。

  2. 启动线程,同时检查媒体跟踪器跟踪的所有图像的错误状态,如果有错误状态就会抛出异常,如果没有则程序就会向下进行,将上面的图片加载到程序中,再对线程进行控制,将图片生成倒影效果。最后关闭线程。

  3. 实现水波特效。通过public void creatWater()方法可以产生倒影中的水波特效。


评论关闭
评论 还能输入200
评论关闭
评论 还能输入200
资料加载中...
已关注 , 取消