赞
踩
思路总体分为几点:
一、如何实现一列字符向下滑动的效果?其实就是把字符序列逐个字符地输出在屏幕上,保持x轴不变,随时间改变y轴坐标= =
二、如何展现多列字符向下滑动?其实就是上例的推广,作一个循环来处理不同的列。
为了保证效果,可以先为每列定义一个随机化初始位置,还可以加一个不同的速度和加速度= =
实现中,我先把屏幕进行了划分,计算出所需要的字符序列行列数,随机生成。
之后就只是从里面取字符,加速度啥的没有去做= =
当然也可以作一个改变,由自己输入多行不同的字符串之类,可能效果看着更有新鲜感= =
三、如何实现颜色效果?仔细看下Matrix中的字符雨,大概上就是一个从黑到绿的颜色过渡。
实现这种过渡也就是改变RGB值中的G分量大小,很容易= =
import java.awt.*;
import java.util.Random;
import javax.swing.JFrame;
class RainCanvas extends Canvas implements Runnable {
private int width, height;
private Image offScreen; //缓冲图片
private char[][] charset; //随机字符集合
private int[] pos; //列的起始位置
private Color[] colors = new Color[30]; //列的渐变颜色
public RainCanvas(int width, int height) {
this.width = width;
this.height = height;
//生成ASCII可见字符集合
Random rand = new Random();
charset = new char[width / 10][height / 10];
for (int i = 0; i < charset.length; i++) {
for (int j = 0; j < charset.length; j++) {
charset[j] = (char) (rand.nextInt(96) + 33);
}
}
//随机化列起始位置
pos = new int[charset.length];
for (int i = 0; i < pos.length; i++) {
pos = rand.nextInt(pos.length);
}
//生成从黑色到绿色的渐变颜色,最后一个保持为白色
for (int i = 0; i < colors.length - 1; i++) {
colors = new Color(0, 255 / colors.length * (i + 1), 0);
}
colors[colors.length - 1] = new Color(255, 255, 255);
setBackground(Color.BLACK);
setSize(width, height);
setVisible(true);
}
public void startRain() {
new Thread(this).start();
}
public void drawRain() {
if (offScreen == null) {
return;
}
Random rand = new Random();
Graphics g = offScreen.getGraphics();
g.clearRect(0, 0, width, height);
g.setFont(new Font("Arial", Font.BOLD, 12));
//
for (int i = 0; i < charset.length; i++) {
int speed = rand.nextInt(2);
for (int j = 0; j < colors.length; j++) {
int index = (pos + j) % charset.length;
g.setColor(colors[j]);
g.drawChars(charset, index, 1, i * 10, index * 10);
}
pos = (pos + 1) % charset.length;
}
}
@Override
public void update(Graphics g) {
paint(g);
}
public void run() {
while (true) {
drawRain();
repaint();
try {
Thread.sleep(50); //可改变睡眠时间以调节速度
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
@Override
public void paint(Graphics g) {
//当组件显示时检测是否要创建缓冲图片,在组件还不可见时调用createImage将返回null
if (offScreen == null) {
offScreen = createImage(width, height);
}
g.drawImage(offScreen, 0, 0, this);
}
}
public class Test extends JFrame {
private RainCanvas canvas = new RainCanvas(860, 480);
public Test() {
super("Test");
getContentPane().add(canvas);
setSize(860, 480);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Test test = new Test();
test.canvas.startRain();
}
}
补充:如果需要全屏显示,可以在Test类的构造函数中再加上
setUndecorated(true);
setExtendedState(JFrame.MAXIMIZED_BOTH);
这两句来设置无边框和最大化,修改后如下
public class Test extends JFrame {
private RainCanvas canvas;
public Test() {
super("Test");
setUndecorated(true);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);
canvas = new RainCanvas(this.getWidth(), this.getHeight());
getContentPane().add(canvas);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
Test test = new Test();
test.canvas.startRain();
}
}
如果需要修改屏幕上的字符序列个数,可以修改new charset[widht/10][height/10]这里的widht/10的值,
对应的g.drawChars(charset, index, 1, i * 10, index * 10);这里的坐标值也要进行修改。
要重新设定Font的大小,直接修改new Font("Arial", Font.BOLD, 15)这处
这些最好是定义成一个字面常量或抽取出方法来进行设置= =
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。