JavaFX实现水波效果.docx

上传人:b****8 文档编号:9379632 上传时间:2023-02-04 格式:DOCX 页数:11 大小:30.66KB
下载 相关 举报
JavaFX实现水波效果.docx_第1页
第1页 / 共11页
JavaFX实现水波效果.docx_第2页
第2页 / 共11页
JavaFX实现水波效果.docx_第3页
第3页 / 共11页
JavaFX实现水波效果.docx_第4页
第4页 / 共11页
JavaFX实现水波效果.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

JavaFX实现水波效果.docx

《JavaFX实现水波效果.docx》由会员分享,可在线阅读,更多相关《JavaFX实现水波效果.docx(11页珍藏版)》请在冰豆网上搜索。

JavaFX实现水波效果.docx

JavaFX实现水波效果

JavaFX实现水波效果

publicclassJfxRipperextendsApplication{

privatefinaldoubleMAX_WIDTH=400.0;

privatefinaldoubleMAX_HEIGHT=400.0;

privatestaticAnimationTimertimer;

privatestaticAnimationTimerrainTimer;

privateFileChooserfc;

privatedoublescaleRate;

privateintmaxRainSize,maxRainPower,stoneSize,stonePower;

privateintimgWidth,imgHeight;

int[]arrWaveCurrent;//当前帧各点波动能量数据

int[]arrWaveNext;//下一帧各点波动能量数据

privateImageimg;

privateWritableImageimgRipper;

privateImageViewimgView;

@Override

publicvoidinit()throwsException{

fc=newFileChooser();

//添加文件类型过滤

fc.getExtensionFilters().add(

newFileChooser.ExtensionFilter("图片文件","*.jpg;*.png;*.jpeg;*.bmp"));

img=newImage(getClass().getClassLoader().getResourceAsStream("images/

红花.jpg"));

imgWidth=(int)img.getWidth();

imgHeight=(int)img.getHeight();

//波纹效果计算需要遍历图片每个像素,图片尺寸过大会导致运行速度极慢,故按比

例缩小

if(imgWidth>MAX_WIDTH||imgHeight>MAX_HEIGHT){

doublesx=MAX_WIDTH/imgWidth;

doublesy=MAX_HEIGHT/imgHeight;

scaleRate=sx>sy?

sy:

sx;

img=scaleImg(img,imgWidth,imgHeight,scaleRate);

imgWidth=(int)(scaleRate*(double)imgWidth);

imgHeight=(int)(scaleRate*(double)imgHeight);

maxRainSize=4;

maxRainPower=60;

stoneSize=5;

stonePower=128;

}else{//雨点和石子大小根据图片尺寸的大小稍作调整

maxRainSize=3;

maxRainPower=50;

stoneSize=4;

stonePower=108;

}

imgRipper=newWritableImage(imgWidth,imgHeight);

arrWaveCurrent=newint[imgWidth*imgHeight];

arrWaveNext=newint[imgWidth*imgHeight];

imgView=newImageView();

imgView.setOnMousePressed(newEventHandler(){

@Override

publicvoidhandle(Eventevent){

MouseEvente=(MouseEvent)event;

dropStone((int)e.getX(),(int)e.getY(),stoneSize,stonePower);

}

});

timer=newAnimationTimer(){

@Override

publicvoidhandle(longnow){

genRipper();

imgView.setImage(imgRipper);

}

};

rainTimer=newAnimationTimer(){

@Override

publicvoidhandle(longnow){

rain();

imgView.setImage(imgRipper);

}

};

}

/**

*模拟下雨,随机抛出不同大小和位置的石子

*/

protectedvoidrain(){

intx=(int)(Math.random()*imgWidth);

inty=(int)(Math.random()*imgHeight);

intrainSize=(int)(Math.random()*maxRainSize);

intpower=(int)(Math.random()*maxRainPower)+maxRainPower;

dropStone(x,y,rainSize,power);

}

@Override

publicvoidstart(StageprimaryStage)throwsException{

Grouproot=newGroup();

VBoxvb=newVBox(10);

root.getChildren().add(vb);

imgView.setImage(img);

Scenescene=newScene(root);

primaryStage.setScene(scene);

HBoxhb=newHBox(10);

ButtonrainControl=newButton("停止下雨");

rainControl.setOnAction((ActionEventevent)->{

if("开始下雨".equals(rainControl.getText())){

rainTimer.start();

rainControl.setText("停止下雨");

}else{

rainTimer.stop();

rainControl.setText("开始下雨");

}

});

ButtonchangePic=newButton("更换图片");

changePic.setOnAction((ActionEventevent)->{

Filef=fc.showOpenDialog(primaryStage);

if(null!

=f){

//将默认目录设置为上次访问过的目录

fc.setInitialDirectory(f.getParentFile());

//ImageimgTmp=null;

try{

img=newImage(newFileInputStream(f));

//Desktop.getDesktop().open(f);

}catch(Exceptione){

e.printStackTrace();

}

if(img!

=null){

imgWidth=(int)img.getWidth();

imgHeight=(int)img.getHeight();

if(imgWidth>MAX_WIDTH||imgHeight>MAX_HEIGHT){

doublesx=MAX_WIDTH/imgWidth;

doublesy=MAX_HEIGHT/imgHeight;

scaleRate=sx>sy?

sy:

sx;

img=scaleImg(img,imgWidth,imgHeight,scaleRate);

imgWidth=(int)(scaleRate*(double)imgWidth);

imgHeight=(int)(scaleRate*(double)imgHeight);

maxRainSize=4;

maxRainPower=60;

stoneSize=5;

stonePower=128;

}else{

maxRainSize=3;

maxRainPower=50;

stoneSize=4;

stonePower=108;

}

imgRipper=newWritableImage(imgWidth,imgHeight);

arrWaveCurrent=newint[imgWidth*imgHeight];

arrWaveNext=newint[imgWidth*imgHeight];

imgView.setFitHeight(imgHeight);

imgView.setFitWidth(imgWidth);

primaryStage.setWidth(imgWidth);

imgView.setImage(img);

primaryStage.setHeight(imgHeight+40);

}

}

});

Buttonexit=newButton("退出");

exit.setOnAction((ActionEventevent)->{

primaryStage.close();

});

hb.getChildren().addAll(rainControl,changePic,exit);

vb.getChildren().addAll(imgView,hb);

primaryStage.setWidth(imgWidth);

hb.setAlignment(Pos.CENTER);

scene.setFill(Color.BLUEVIOLET);

primaryStage.initStyle(StageStyle.TRANSPARENT);

timer.start();

rainTimer.start();

primaryStage.show();

}

/*

*水波算法,原作者Imagic

*/

publicvoidgenRipper(){

PixelReaderreadImg=img.getPixelReader();

PixelWriterwriteRipper=imgRipper.getPixelWriter();

intindex=imgWidth;

intindexPreX=index-1;

intindexNextX=index+1;

intindexPreY=index-imgWidth;

intindexNextY=index+imgWidth;

for(inty=1;y

for(intx=1;x

intx1=arrWaveCurrent[indexPreX++];

intx2=arrWaveCurrent[indexNextX++];

intx3=arrWaveCurrent[indexPreY++];

intx4=arrWaveCurrent[indexNextY++];

//波能扩散:

上下左右四点的波幅和的一半减去当前波幅

//X0'=,X1+X2+X3+X4,/2-X0

arrWaveNext[index]=((x1+x2+x3+x4)>>1)-arrWaveNext[index];

//波能衰减1/32

arrWaveNext[index]-=arrWaveNext[index]>>5;

//计算出偏移象素和原始象素的内存地址偏移量:

intxoffset=x2-x1;

intyoffset=x4-x3;

intoffset=imgWidth*yoffset+xoffset;

intposY=index/imgWidth;

intposX=index-posY*imgWidth;

intnewY=(index+offset)/imgWidth;

intnewX=(index+offset)-newY*imgWidth;

//判断坐标是否在窗口范围内

if(index+offset>0&&index+offset

writeRipper.setColor(posX,posY,readImg.getColor(newX,newY));

}else{

writeRipper.setColor(posX,posY,readImg.getColor(posX,posY));

}

}

}

//交换波能数据缓冲区

int[]temp=arrWaveCurrent;

arrWaveCurrent=arrWaveNext;

arrWaveNext=temp;

}

/**

*模拟向水中投石子

*

*@paramx:

石子位置X坐标

*@paramy:

石子位置y坐标

*@paramstoneSize:

石子半径

*@parampower:

波能大小

*/

privatevoiddropStone(intx,inty,intstoneSize,intpower){

intminPosX=x-stoneSize,maxPosX=x+stoneSize;

intminPosY=y-stoneSize,maxPosY=y+stoneSize;

minPosX=minPosX<0?

0:

minPosX;

minPosY=minPosY<0?

0:

minPosY;

maxPosX=maxPosX>imgWidth?

imgWidth:

maxPosX;

maxPosY=maxPosY>imgHeight?

imgHeight:

maxPosY;

intvalue=stoneSize*stoneSize;

for(intposx=minPosX;posx

for(intposy=minPosY;posy

if((posx-x)*(posx-x)+(posy-y)*(posy-y)

arrWaveCurrent[posy*imgWidth+posx]=-power;

}

}

}

}

/**

*按比例缩小图片

*缩小图片算法:

x0=x/sx,y0=y/sy。

x0,y0分别为原图水平和垂直索引,

*sx,sy分别为水平和垂直缩小比例

*@paramsrc:

原始图片

*@paramimgW:

原始图片宽度

*@paramimgH:

原始图片长度

*@paramrate:

缩小后的图片不原图片尺寸的比例

*@return缩小后的图片

*/

privateImagescaleImg(Imagesrc,intimgW,intimgH,doublerate){

intwidth=(int)((double)imgW*rate);

intheight=(int)((double)imgH*rate);

WritableImageimgScaled=newWritableImage(width,height);

PixelReaderreadSrc=src.getPixelReader();

PixelWriterwriteDest=imgScaled.getPixelWriter();

for(intx=0;x

for(inty=0;y

writeDest.setColor(x,y,

readSrc.getColor((int)(x/rate),(int)(y/rate)));

}

}

returnimgScaled;

}

publicstaticvoidmain(String[]args){

launch(args);

}

}

里面用到了行序优先一维数组存储二维数组时两个数组索引之间的算术关系公式。

设一维数组索引为index,二维数组行索引为x,列索引为y,均从0开始,每行存储元素个数为width,则:

y=int(index/width),int为取整函数,如int(1.1)和int(1.9)都等于1x=index-y*width

index=width*y+x

截图:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1