最近在绘制山脉,先来看看效果:
虽然不是很好看,但至少从远方望去,山脉的那种感觉出来了,下面来看看是怎么做的:
绘制画图板很简单,这里就不多作叙述了。我们直接来看看山脉是怎么画的。
首先,我们需要确定一条长直线的起点和终点坐标,然后取这条直线的中点坐标,横坐标直接起点和终点的横坐标相加再除以二即可。至于纵坐标,为了实现山脉的效果,我们需要先确定某个值,然后以这个值为中心确定一个范围,纵坐标应该在这个范围内随机取值。然后,再分别取起点和这一点的中点以及这一点和终点的中点,再分别用递归来完成。
然后要注意,这个范围每次递归的时候都要按照一定的比例减小。
等到递归结束的时候,再画直线,同时填充颜色。这样一来,绘制山脉的方法基本思路就确定了。
下面是绘制山脉的方法:
1 public void drawMountains(int x1,int y1,int x2,int y2,double k,int times,Graphics g,Color c){
2 Random rand = new Random();
3 int range=0;
4 if(times > 0){
5 range = (int)((rand.nextInt(400)-200)*k); //纵坐标取值的范围
6 k*=0.5; //缩小的比例
7 int middleX = (x1+x2)/2; //中点横坐标
8 int middleY = (y1+y2)/2 + range; //中点纵坐标
9 drawMountains(x1,y1,middleX,middleY,k,times-1,g,c); //这里开始就是递归
10 drawMountains(middleX,middleY,x2,y2,k,times-1,g,c);
11 }else{
12 g.drawLine(x1,y1,x2,y2); //递归结束,画直线
13 g.setColor(c); //同时设置颜色
14 Polygon p1 = new Polygon(); //使用这个类来填充颜色
15 p1.addPoint(x1, 800);
16 p1.addPoint(x1, y1);
17 p1.addPoint(x2, y2);
18 p1.addPoint(x2, 800);
19 Graphics2D g2 = (Graphics2D)g;
20 g2.fillPolygon(p1);
21 }
22 }
至于天空的颜色,我们可以在绘制画图板的时候就设置背景颜色。
下面来看完整代码:
Board.java:
1 package Practice;
2
3 import java.awt.Graphics;
4 import javax.swing.JFrame;
5
6 public class Board extends JFrame{
7 public void paint(Graphics g){
8 super.paint(g);
9 }
10 }
Mountains.java:
1 package Practice;
2
3 import java.awt.Color;
4 import java.awt.Graphics;
5 import java.awt.Graphics2D;
6 import java.awt.Polygon;
7 import java.util.Random;
8 import javax.swing.JFrame;
9
10 public class Mountains{
11
12 public static void main(String[] args) {
13 Mountains m = new Mountains();
14 m.show();
15 }
16
17 public void show(){
18 Board board = new Board();
19 board.setTitle("绘制山脉");
20 board.setSize(1200,800);
21 board.setLocationRelativeTo(null);
22 board.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
23 board.setVisible(true);
24 try {
25 Thread.sleep(100); //画图板也是绘制的,这里是为了等画图板全部绘制完成后再画山脉
26 } catch (InterruptedException e) {
27 // TODO Auto-generated catch block
28 e.printStackTrace();
29 }
30 Graphics g = board.getGraphics();
31 Color c1 = new Color(12,62,88);
32 Color c2 = new Color(14,70,101);
33 Color c3 = new Color(7,38,54);
34 g.setColor(new Color(109,191,235));
35 g.fillRect(0, 0, 1200, 800);
36 g.drawArc(100,40,90,50,0,180); //这里画个太阳
37 g.setColor(Color.yellow); g.fillArc(100,100,40,40,0,-360);
38 drawMountains(0, 580, 1200, 580, 2,10,g,c3);
39 drawMountains(0, 580, 1200, 580, 2,10,g,c2);
40 drawMountains(0, 580, 1200, 580, 2,10,g,c1);
41 }
42
43 public void drawMountains(int x1,int y1,int x2,int y2,double k,int times,Graphics g,Color c){
44 Random rand = new Random();
45 int range=0;
46 if(times > 0){
47 range = (int)((rand.nextInt(400)-200)*k); //纵坐标取值的范围
48 k*=0.5; //缩小的比例
49 int middleX = (x1+x2)/2; //中点横坐标
50 int middleY = (y1+y2)/2 + range; //中点纵坐标
51 drawMountains(x1,y1,middleX,middleY,k,times-1,g,c); //这里开始就是递归
52 drawMountains(middleX,middleY,x2,y2,k,times-1,g,c);
53 }else{
54 g.drawLine(x1,y1,x2,y2); //递归结束,画直线
55 g.setColor(c); //同时设置颜色
56 Polygon p1 = new Polygon(); //使用这个类来填充颜色
57 p1.addPoint(x1, 800);
58 p1.addPoint(x1, y1);
59 p1.addPoint(x2, y2);
60 p1.addPoint(x2, 800);
61 Graphics2D g2 = (Graphics2D)g;
62 g2.fillPolygon(p1);
63 }
64 }
65 }
这样就可以啦!
关于遇到的Bug:
首先,就是范围缩小的问题,特别注意这里k值一定要是double型!一开始我定义的k是整型的,但是这样一来,每次k×0.5的话,取整就变成0了,这样一来画出来不是山脉的效果,而是一条直线。
其次,是关于颜色的问题。因为这里在show方法里面调用了三次绘制山脉的方法,因此画出来有三条山脉,这里没有问题,但是天空的颜色,我刚开始是想画山脉的时候顺便就把天空颜色给画了。这样的话绘制山脉的方法里面我又添加了一个Color类型的参数,代表画天空的颜色。在画山脉颜色的时候,同时也利用Polygon这个类把山脉上方填充为天空的天蓝色。但是,因为有三座山,高度又是随机取值,一旦有一座山在横坐标相同情况下纵坐标取值比另一座山低,那么它的上面就会被填充成天蓝色,这样一来,上面那座山脉的颜色就被覆盖了,所以画出来只有一座山。然鹅解决方法很简单,只需要在最开始给整个绘图板画上天蓝色即可。
最后是一个不怎么算bug的bug,就是range取值,不要太大了。-400到400的范围就很好。