java画图板之平面山水画(一):https://blog.csdn.net/qq_43348021/article/details/104346805
上次的博客中已经将山脉的轮廓画出来了,这次我们对它进行修饰。
填充
刚开始,我以为将区域填充需要将其中每个点都画到,其实不然。我们知道画出的山脉轮廓其实是有若干个点连线组成的,我们只需要从这些点开始,垂直向下划线即可,当点的数量足够多的时候,显示的就是全部被填充的情况。
public void showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter) {
double midx, midy;
//计算中点坐标
midx = (startx + endx) / 2;
midy = (starty + endy) / 2 + (Math.random() * 2 - 1) * range;
if (timescounter++ == times) {
//画山脉轮廓
g.drawLine((int) startx, (int) starty, (int) midx, (int) midy);
g.drawLine((int) midx, (int) midy, (int) endx, (int) endy);
//填充山脉
g.setColor(mtcolor);
g.drawLine((int) midx, (int) midy, (int) midx, (int) 600/*画布底部*/);
} else {
//随着相邻两个点的横坐标距离减少,纵坐标随机起伏范围也要减小
range *= rate;
//递归
showmt(startx, starty, midx, midy, mtcolor, range, timescounter);
showmt(midx, midy, endx, endy, mtcolor, range, timescounter);
}
}
- 这是递归次数(times)为10时画出的效果:
- 这是递归次数(times)为11时画出的效果:
群山
只有一座山肯定是不够的,我们用循环来画多做山脉,同时对远近山脉的高低、颜色进行调整,这部分放在监听器中。
for (int i = 0; i < 4; i++) {
int distance = 100;// 每座山脉间距离
mountain mountain = new mountain();
mountain.setGraphics(bufferg);// 先在缓存中绘制
Color mtcolor = new Color(i * 50, i * 50, i * 50);// 设置每座山脉颜色
mountain.showmt(0, 50 + i * distance, 800, 50 + i * distance, mtcolor, 100, 1);// showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter)
}
提速
实际运行过上面的代码就会知道,递归11次会使得画出图像需要1秒左右的过程,有没有什么办法能使图像在运行的瞬间就显示出来呢?这就需要用到计算机的缓存了,我们可以事先在缓存中画出图形并保存,然后将缓存中的图像显示出来(CPU与缓存间传输信息的速度要大于CPU与输入输出设备的)。
这样做还有一个好处,由于我们的图像绘制时使用了随机函数,导致我们每次调用函数都会改变图像,当其他构件发生变化时,山脉的图像也在跟着变化。运用缓存后,当其他构件发生变化影响到山脉的图像时,我们只需要将缓存中保存的图片重新显示出来就行了,而不需要重新绘制。
java提供了BufferedImage类供我们使用。
//绘制山脉
// 设置缓存
BufferedImage buffer = new BufferedImage(800, 400, BufferedImage.TYPE_INT_RGB);
// 设置缓存画布
Graphics bufferg = buffer.getGraphics();
// 设置画布背景颜色
Color bufferbgcolor = new Color(255,255,255);
bufferg.setColor(bufferbgcolor);
bufferg