Java Chaos Game噪聲游戲?qū)嵗a
[簡介]
最近一直在讀《深奧的簡潔》,里面有一章介紹了幾種使用噪聲產(chǎn)生分形圖的方法,感覺很有意思,于是嘗試使用計(jì)算機(jī)模擬了一下,效果還不錯(噪聲法比傳統(tǒng)迭代法在編程上好實(shí)現(xiàn)一些,后來發(fā)現(xiàn)這類算法還不少,搜索chaosgame可以找到更多)。
[Sierpinski三角形的噪聲產(chǎn)生法]

在這些噪聲游戲中,Sierpinski(謝爾賓斯基)三角形的生成規(guī)則可謂是最簡單的:
1.在平面上選取三個點(diǎn),標(biāo)記為1、2、3,作為大三角形的頂點(diǎn)。
2.選擇其中一點(diǎn),作為“當(dāng)前點(diǎn)”(比如選擇1號)。
3.產(chǎn)生1~3的隨機(jī)數(shù),在該數(shù)表達(dá)的頂點(diǎn)與“當(dāng)前點(diǎn)”的中點(diǎn)繪制一個新點(diǎn),并將新點(diǎn)作為“當(dāng)前點(diǎn)”。
4.重復(fù)步驟3,即可逼近圖案。
*.注意隨機(jī)數(shù)最好不要使用以時間作為種子的產(chǎn)生方式。
[模擬程序]
package com.geiv.chaos;
import java.awt.event.KeyEvent;
import com.thrblock.util.RandomSet;
import geivcore.DefaultFactor;
import geivcore.KeyFactor;
import geivcore.KeyListener;
import geivcore.R;
import geivcore.UESI;
import geivcore.enginedata.obj.Obj;
public class Sierpinski extends DefaultFactor implements KeyListener{
UESI UES;
Obj[] basePoint;
Obj crtPoint;
public Sierpinski(UESI UES,int times){
this.UES = UES;
basePoint = new Obj[3];
//創(chuàng)建三個基準(zhǔn)點(diǎn)
for (int i = 0;i < 3;i++){
basePoint[i] = UES.creatObj(UESI.BGIndex);
basePoint[i].addGLPoint("70DBDB",0,0);
basePoint[i].show();
}
basePoint[0].setCentralX(400);
//設(shè)置三點(diǎn)位置
basePoint[0].setCentralY(60);
basePoint[1].setCentralX(60);
basePoint[1].setCentralY(550);
basePoint[2].setCentralX(740);
basePoint[2].setCentralY(550);
crtPoint = basePoint[0];
//將0號點(diǎn)作為當(dāng)前點(diǎn)
this.setKeyListener(this);
UES.pushKeyBoardIO(this);
for (int i = 0;i < times;i++){
generateNew();
}
}
@Override
public void doKeyBord(KeyFactor whom, int keyCode, Boolean ispressed) {
//掛載回調(diào)
if(ispressed){
if(keyCode == KeyEvent.VK_SPACE){
//空格對應(yīng)創(chuàng)建一個新點(diǎn)
generateNew();
} else if(keyCode == KeyEvent.VK_A){
//A對應(yīng)創(chuàng)建100個新點(diǎn)
for (int i = 0;i < 100;i++){
generateNew();
}
} else if(keyCode == KeyEvent.VK_B){
//B對應(yīng)創(chuàng)建1000個新點(diǎn)
for (int i = 0;i < 1000;i++){
generateNew();
}
}
}
}
public void generateNew(){
Obj flagPoint = basePoint[RandomSet.getRandomNum(0, 2)];
//隨機(jī)選擇基準(zhǔn)點(diǎn)之一
float nx = (flagPoint.getCentralX() + crtPoint.getCentralX())/2f;
//計(jì)算中點(diǎn)
float ny = (flagPoint.getCentralY() + crtPoint.getCentralY())/2f;
Obj newPoint = UES.creatObj(UESI.BGIndex);
//創(chuàng)建新點(diǎn)
newPoint.addGLPoint("70DBDB",0,0);
newPoint.setColor(RandomSet.getRandomColdColor());
newPoint.setCentralX(nx);
//設(shè)置坐標(biāo)
newPoint.setCentralY(ny);
newPoint.show();
crtPoint = newPoint;
//置為當(dāng)前點(diǎn)
}
public static void main(String[] args) {
UESI ues = new R();
new Sierpinski(ues,0);
//后面的構(gòu)造參數(shù)可以設(shè)置初始點(diǎn)數(shù)。
}
}
[模擬結(jié)果]
在B鍵按下時



[Barnsleyfern的噪聲產(chǎn)生法]

相比于Sierpinski三角的簡單規(guī)則性,Barnsleyfern(分形羊齒草)給人以更加復(fù)雜的印象,出于它的復(fù)雜性,混沌學(xué)科經(jīng)常拿出它來證明“簡單規(guī)則也可產(chǎn)生復(fù)雜對象”的結(jié)論。
它的產(chǎn)生規(guī)則也不是很復(fù)雜:
1.首先給定”當(dāng)前點(diǎn)”(0,0),我們用ox,oy表示橫縱坐標(biāo)。
2.計(jì)算下一點(diǎn)(nx,ny)需要以一定隨機(jī)規(guī)則選擇下列四種迭代公式之一:
1)以%1的概率選擇此迭代公式:
nx=0;
ny=0.16f*oy;
2)以%85的概率選擇此迭代公式:
nx=0.85*ox+0.04*oy;
ny=-0.04*ox+0.85*oy+1.6;
3)以%7的概率選擇此迭代公式:
nx=0.2*ox-0.26*oy;
ny=0.23*ox+0.22*oy+1.6;
4)以%7的概率選擇此迭代公式:
nx=-0.15*ox+0.28*oy;
ny=0.26*ox+0.24*oy+0.44;
3.繪制(nx,ny),并將其設(shè)為當(dāng)前點(diǎn),重復(fù)2,即可無限逼近結(jié)果。
↑以上公式摘自Wiki:http://en.wikipedia.org/wiki/Barnsley_fern。在編程時,我發(fā)現(xiàn)一個問題,Wiki并未指明這個坐標(biāo)的決對值與屏幕大小的關(guān)系,也并未說明x、y軸的方向,在我自己定義的坐標(biāo)系下繪制總是不成功,后來我按照公式搜索,找到了這個面:http://people.sc.fsu.edu/~jburkardt/cpp_src/fern_opengl/fern.cpp。這是一個C++下的OPENGL程序,而里面用了與Wiki相同的公式,也就是說,這組公式是以O(shè)pengl的坐標(biāo)系為基準(zhǔn)的,在做了對應(yīng)變換后終于成功繪制。
[模擬程序]
package com.geiv.chaos;
import geivcore.DefaultFactor;
import geivcore.KeyFactor;
import geivcore.KeyListener;
import geivcore.R;
import geivcore.UESI;
import geivcore.enginedata.obj.Obj;
import java.awt.Color;
import java.awt.event.KeyEvent;
import com.thrblock.util.RandomSet;
public class Barnsleyfern extends DefaultFactor implements KeyListener{
UESI UES;
Obj crtPoint;
public Barnsleyfern(UESI UES,int times){
this.UES = UES;
crtPoint = UES.creatObj(UESI.BGIndex);
crtPoint.addGLPoint("70DBDB",0,0);
crtPoint.show();
crtPoint.setCentralX(0);
crtPoint.setCentralY(0);
UES.setViewOffsetX(90);
this.setKeyListener(this);
UES.pushKeyBoardIO(this);
for (int i = 0;i < times;i++){
generateNew();
}
}
@Override
public void doKeyBord(KeyFactor whom, int keyCode, Boolean ispressed) {
//鍵盤IO的方式同上例
if(ispressed){
if(keyCode == KeyEvent.VK_SPACE){
generateNew();
} else if(keyCode == KeyEvent.VK_A){
for (int i = 0;i < 100;i++){
generateNew();
}
} else if(keyCode == KeyEvent.VK_B){
for (int i = 0;i < 1000;i++){
generateNew();
}
}
}
}
public void generateNew(){
float nx,ny;
float ox = crtPoint.getCentralX()/150f,oy = (600 - crtPoint.getCentralY())/60f;
//這里做了OPENGL坐標(biāo)轉(zhuǎn)換,在設(shè)置新點(diǎn)位置時對應(yīng)反轉(zhuǎn)。
double code = 100.0 * RandomSet.getRandomFloatIn_1();
//隨機(jī)浮點(diǎn)數(shù)數(shù)0~100
if(code >= 0&&code <= 1){
nx = 0;
ny = 0.00f * ox + 0.16f * oy;
} else if(code > 1&& code <= 86){
nx = 0.85f*ox + 0.04f*oy;
ny = -0.04f*ox + 0.85f*oy + 1.6f;
} else if(code > 86&& code <= 93){
nx = 0.2f*ox - 0.26f*oy;
ny = 0.23f*ox + 0.22f*oy + 1.6f;
} else{
nx = -0.15f*ox + 0.28f*oy;
ny = 0.26f*ox + 0.24f*oy + 0.44f;
}
Obj newPoint = UES.creatObj(UESI.BGIndex);
newPoint.addGLPoint("70DBDB",0,0);
newPoint.setColor(Color.GREEN);
newPoint.setCentralX(nx*150f);
//將之前的坐標(biāo)變換抵消
newPoint.setCentralY(600 - ny*60f);
newPoint.show();
crtPoint = newPoint;
//設(shè)置新點(diǎn)為當(dāng)前點(diǎn)。
}
public static void main(String[] args) {
UESI ues = new R();
new Barnsleyfern(ues,0);
}
}
[模擬結(jié)果]



總結(jié)
以上就是本文關(guān)于Java Chaos Game噪聲游戲?qū)嵗a的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關(guān)文章
SpringCloud解決Feign異步回調(diào)問題(SpringBoot+Async+Future實(shí)現(xiàn))
這篇文章主要介紹了SpringCloud解決Feign異步回調(diào)問題(SpringBoot+Async+Future實(shí)現(xiàn)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
Spring中的@EnableWebSecurity注解詳解
這篇文章主要介紹了Spring中的@EnableWebSecurity注解詳解,EnableWebSecurity注解是個組合注解,它的注解中,又使用了@EnableGlobalAuthentication注解,需要的朋友可以參考下2023-12-12
Java單表實(shí)現(xiàn)評論回復(fù)功能(多種實(shí)現(xiàn)方式)
這篇文章主要介紹了Java單表實(shí)現(xiàn)評論回復(fù)功能,大家都知道評論功能有多種實(shí)現(xiàn)方式,本文逐一給大家詳細(xì)講解,需要的朋友可以參考下2023-03-03
Dubbo擴(kuò)展點(diǎn)SPI實(shí)踐示例解析
這篇文章主要為大家介紹了Dubbo擴(kuò)展點(diǎn)SPI實(shí)踐示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10

