利用递归实现山脉效果,填充山脉以及山脉颜色渐变

利用递归实现山脉效果,填充山脉以及山脉颜色渐变

递归山脉要求:

  • 初始定义两个点AB
  • 取AB的中点P,让中点的Y坐标在[-range,range]范围内随机取值,得到P点
  • 要求每次迭代后range按比例rate缩小
  • 分别取AP和PB,重复上述过程
  • 递归结束,连线
    —————————————————————————————————————
public void mountain(Graphics g,int x1,int y1,int x2,int y2,int range,double rate){//定义山脉方法
		if(Math.abs(x2-x1)<20){  //迭代退出条件
			g.drawLine(x1,y1,x2,y2);  //※【迭代结束,连接当前两个点】
		}else{
			int x = (int)((x1+x2)/2);  //P点横坐标
			int y = (int)((y1+y2)/2);  //P点线性纵坐标
			int Rnumber = (int)(Math.random()*(2*range)-range);  //从-range到range随机取值
			int Nrange = (int)(range*rate);  //每次迭代改变range的范围
			mountain(g,x1,y1,x,y+Rnumber,Nrange,rate);
			mountain(g,x,y+Rnumber,x2,y2,Nrange,rate);
		}

mountain(gr,0,500,1000,500,200,0.5);
效果如下:在这里插入图片描述
如何填充山脉呢?要用到fillPolygon方法,我们来看下该方法的描述:
public void fillPolygon(Polygon p)
作用是填充一个多边形,需要指定 Polygon 对象定义这个多边形。
需要用到的方法是addPoint(int x;int y);
作用是将指定的坐标追加到此 Polygon对象。

public void mountain(Graphics g,int x1,int y1,int x2,int y2,int range,double rate){
		if(Math.abs(x2-x1)<20){
			g.drawLine(x1,y1,x2,y2);  //在连线操作结束后填充
			Polygon p = new Polygon();  //创建一个Polygon()类的对象,调用addPoint方法
			p.addPoint(x1, y1);
			p.addPoint(x1,1000);
			p.addPoint(x2, 1000);
			p.addPoint(x2, y2);  //这里注意坐标的追加要逆时针
			g.fillPolygon(p);  //填充,g是画笔对象
		}else{
			int x = (int)((x1+x2)/2);
			int y = (int)((y1+y2)/2);
			int Rnumber = (int)(Math.random()*(2*range)-range);  
			int Nrange = (int)(range*rate);
			mountain(g,x1,y1,x,y+Rnumber,Nrange,rate);
			mountain(g,x,y+Rnumber,x2,y2,Nrange,rate);
		}

效果如下
由于此时还没有定义颜色,所以填充是纯黑效果
下一步我们要实现山脉的渐变,有两种方式,一是每次画完一个山脉后改变RGB的值,二是每次画完一个山脉后改变透明度A的值,我们分别试下

  • 改变R、G、B三值
public void mouseClicked(MouseEvent e) {  //点击方法
		if ("递归山脉".equals(type)){
			Color c = new Color(r,g,b);  //r,g,b我定义在全局变量,初始值均为20
			gr.setColor(c);  //给画笔设置颜色
			mountain(gr,0,500,1000,500,200,0.5); 
			r+=20;  //迭代结束后改变r,g,b的值
			g+=20;
			b+=20;
		}

效果如下在这里插入图片描述
这种效果本质上还是纯色填充,会重叠覆盖,于是我们可以去修改透明度的值

public void mouseClicked(MouseEvent e) {  //点击方法
	if("递归山脉".equals(type)){
			Color c = new Color(r,g,b,a);  //r、g、b、a均定义在全局变量,初值均为0。r、g、b三值为0时是纯黑,a为0时全透明,为255时不透明
			gr.setColor(c);
			mountain(gr,0,500,1000,500,200,0.5);
			a+=30;
		}

效果如下在这里插入图片描述
是不是有透视的感觉?
但是还有一个问题,第二种方法(改变透明度的操作)的响应速度比较慢,往往是鼠标点击后几秒,才开始“慢悠悠”绘制山脉与填充,而且填充过程也是逐渐的,像动画一样。
如何解决呢?java缓存!!!
介绍一个简易的缓存
BufferedImage类是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片),原理是系统在尚未执行画的操作/代码前,已经把图像画在缓冲区,随时调用。
步骤:

  • 创建一个BufferedImage对象
  • 获取缓冲区的画笔
  • 将实现画图的代码中的原画笔对象改为缓冲区画笔
  • 用原画笔对象调用drawImage方法
if("递归山脉".equals(type)){
			BufferedImage buffImage = new BufferedImage(1000,1000,BufferedImage.TYPE_INT_ARGB);  //创建BufferedImage对象,前两个参数为窗体大小
			Graphics buffG = buffImage.getGraphics();  //获取缓冲区画笔对象
			Color c = new Color(r,g,b,a);
			buffG.setColor(c);   //将原画笔对象改为缓冲区画笔
			mountain(buffG,0,500,1000,500,200,0.5);  //将实现画图的代码中的原画笔对象改为缓冲区画笔
			a+=30;
			gr.drawImage(buffImage, 0, 0,null);  //用原画笔画出缓冲区图片,中间两个int值代表画图的起始点
			
		}

效果就不展示了,确实可以瞬间画出图片。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值