4.前景树的制作
为增加动画的立体感,使得前景中的鱼跳跃时能在树间穿过,我们从背景图中切“割出”一颗树。我们没有使用特别的图像处理软件,也不用复杂的图像分割算法,而用在Windows2000/XP自带的“画图”软件进行比较粗的剪切获得一幅图,见图8。
图8 前景树制作(1)
然后对这幅图的背景进行像素改变,用类Java语言表示,算法如下:
if(red>=40&&red<=90&&green>=110&&
green<=130&&blue>=100&&blue<=180){
设置为白色且全透明;
}
else if(red==255&&green==255&&blue==255){
设置为全透明;
}
上述算法执行后,在内存中将形成如图9。在内存图9中,树是不透明的,其余白色区域是全透明的。
图9 前景树制作(2)
5.鱼的旋转
前景中的鱼在空中有一个旋转的动作,其代码解释如下。
(1) 先创建一个缓冲区图像
Image filtIm=new BufferedImage(width,height,
BufferedImage.TYPE_INT_ARGB);
(2) 绕图像中心逆时针旋转60度
AffineTransform transform=
AffineTransform.getRotateInstance(
Math.toRadians(-60),34,34);
(3) 创建仿射变换操作对像,用下面的方法
AffineTransformOp op=
new AffineTransformOp(transform,
AffineTransformOp.TYPE_BILINEAR);
其中transform为仿射变换对像,TYPE_ BILINEAR或TYPE_NEAREST_ NEIGHBOR是两个常量,与仿射变换中放大图像时有关。
(4) Java提供了许多过滤器执行常见的图像处理操作
op.filter(buff,filtIm);
关于仿射变换可参见文献[1, p.410]。
6. 双缓冲技术的使用
本程序使用双缓冲技术,首先定义空Image对像和空Graphcs对像:
Image offIm=createImage(256,256);
Graphics offGr=offIm.getGraphics();
所有画图动作先在空图形对像offGr上进行,待所有画图动作完成后,一次性地将图像在屏幕上画出。关于双缓冲技术可阅[3]。
7. 背景图像的层次
程序运行中几幅图像作画的先后次序是重要的,否则,将不会产生立体感。正确的次序如下:
(1) 画背景图像imBack
offGr.drawImage(imBack,0,0,this);
(2) 画出fish图imgA
offGr.drawImage(imgA,x,y,this);
或旋转后的fish图filtIm
offGr.drawImage(filtIm,x,y-80,null);
(3) 将已改变透明度的云层、海水和一棵树画出
offGr.drawImage(imBack1a,0,0,this);
offGr.drawImage(imBack2a,0,220,this);
offGr.drawImage(imTreea,0,0,this);
(4) 最后,一次性画出内存图像offIm
g.drawImage(offIm,0,0,this);
四、程序实例
下面是整个程序的代码。其中的HTML文件已作为注释加入到程序代码中。
/**
* @moveImage.java
* @Author Xie-Hua Sun, 2008.01.05
*/
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.awt.geom.*;
/*
*<html>
* <applet code=moveImage.class
* width=256 height=290>
* </applet>
*</html>
**/
public class moveImage extends Applet implements ActionListener, Runnable {
BufferedImage buff,filtIm; //缓冲图像
Image offIm,
img, //前景fish图
imgA, //背景全透明的fish图
imBack,imBack1a,
imBack2a,imTree,imTreea;
Graphics offGr,tempGr;
int iw,ih, //宽、高
width,height, //旋转fish图宽、高
pixels[]; //存储前景图像素
boolean tFlag=true; //动画运动标志
JButton bStart, bStop;
Thread thread;
AudioClip sound;
public void init() {
setLayout(new BorderLayout());
setBackground(Color.lightGray);
Panel panel=new Panel();
bStart=new JButton("开始");
bStop =new JButton("停止");
panel.add(bStart); panel.add(bStop);
this.add(panel,BorderLayout.SOUTH);
bStart.addActionListener(this);
bStop.addActionListener(this);
offIm=createImage(256,256);
offGr=offIm.getGraphics();
loadImage(); //装载图像
|