噴水のエフェクト
をテンプレートにして作成
home
>
サイトマップ
開始行:
RIGHT:寄稿:東條遼平
* 簡単な物理法則とぼかし [#ac1358b6]
実際の噴水とは随分違いますが、それなりに動いていると思い...
色の選び方や、残像を作ってぼかしているあたりが少々面倒で...
炎と同じく水滴の動きの理論自体は大変簡単です。
#ref(img1.png,nolink)
#ref(img2.png,nolink)
高校物理で習う上記の式を使います。これで初速度と噴出角度...
水滴の座標を知ることができ、実装することができそうです。
ただし、初速度、経過時間はそれぞれ単位がメートル/秒と秒で...
それを画面上でどう置き換えるかにもよるのですが、
得られた値を座標にし、経過時間をループ回数などとすれば、
重力加速度gが9.8では恐らく残念な結果になると思います。
市販のゲームですらジャンプした直後は重力と逆向きに加速し...
自分の納得のいく見え方になるように柔軟に値を変更する事も...
それでは噴水において水滴のそれぞれの動きを考えてみます。
物理法則は上記の式で良いのですが、初速度や噴出角度が同じ...
初速度に関しては最大の初速度を決めておき、その範囲内でラ...
初速度を決め、角度についても一定の範囲内でランダムに決め...
また、水滴の座標に点をプロットするだけでは余りに御粗末で...
そのため残像を付けたり、炎のときのようにぼかしてみました。
これに色を付けることでライトアップされたような噴水ができ...
それではソースコードを見ていきます。今回メインのFountain...
それぞれの水滴を扱うDropofwaterクラス、色情報を扱うPallet...
作成しました。
public double getX(){
return -velocity*Math.cos(Math.toRadians((double)degre...
}
public double getY(){
return -velocity*Math.sin(Math.toRadians((double)degre...
*time + 0.8*time...
}
これはDropofwaterクラスのメソッドの一部です。
それぞれの座標を得るために上記の式を計算しているだけです。
注意点としてはcosやsinの関数は引数としてラジアンを取るた...
度数をラジアンに変更しています。また、画面上の左上が原点...
した方向にY軸をとりますので符号に気を付けてください。
public void setisonscreen(boolean isonscreen){
this.isonscreen = isonscreen;
}
public boolean isOnscreen(){
return isonscreen;
}
これらのメソッドは、水滴が画面より外にでた事を調べるため...
水滴を無限に作成することはできないので、画面から外れたも...
発射し直す必要があります。isOnscreenの返り値の真偽によっ...
public void timeInc(){
time++;
}
経過時間もそれぞれのインスタンス毎に管理すべき値です。
メソッドを作成しておきます。
public Palletcolor(int colornum, int gradationnum){
this.colornum = colornum;
this.gradationnum = gradationnum;
nowcolor = (int)(colornum*Math.random());
color = new Color[colornum][];
for(int i=0; i<colornum; i++){
color[i] = new Color[gradationnum];
for(int j=0; j<gradationnum; j++){
color[i][j] = Color.getHSBColor((float)i/colornum,
1-(float)j/gradati...
(float)j/gradation...
}
}
}
これはPalletcolorクラスのコンストラクタです。今回も色の決...
RGBではなくHSBのパラメータで色を決定しています。
colornumは扱う色相の種類の数、gradationnumはそれぞれの色...
どれだけのグラデーションを持つかという変数です。nowcolor...
噴水の色で最初はランダムに設定します。
それではいよいよメインのクラスです。
int image[]; //RGB情報をもった配列
int pallet[]; //対応するピクセルが使っているパレットのイ...
int position[][]; //水滴の位置
imageの配列の情報を用いて画面のイメージを作成しています。
palletはPalletcolorクラスで作成したグラデーションの番号を...
そのためこの値が変化しなくても色相が変化すれば色はかわり...
positionは各水滴の位置を保持しています。多次元配列となっ...
過去数回分の水滴の位置を保持しておきます。
if(System.currentTimeMillis() - timerstart > 5000){
palletcolor.setnextColor();
nowmaxvelocity = (int)(maxvelocity * Math.random());
timerstart = System.currentTimeMillis();
}
run内での処理です。毎回同じ色や初速度では面白くないので
指定した時間が経過する度色相を次のものにし、各々の水滴が...
最大の初速度をランダムでnowmaxvelocityに保持しています。
//残像の作成
for(int i=0; i<AFTERIMAGENUM; i++){
for(int j=0; j<width*height; j++){
position[AFTERIMAGENUM-i][j] =
(int)(position[AFTERIMAGENUM-1-i][j]*4...
}
}
//水滴の現在位置のクリア
for(int i=0; i<width*height; i++) position[0][i] = 0;
時間的に新しいものを1つずつ古い方に送り、次の位置を保持す...
クリアします。古い方に送る際に4/5倍しているのは残像ははっ...
考えです。
//画面の上部と左右の端は値が変化しないためクリアする
for(int i=0; i<width; i++) pallet[i] = 0;
for(int i=0; i<height; i++) pallet[i*width] = 0;
for(int i=0; i<height; i++) pallet[i*width + width-1]...
画面の端は値が無くならないので、うまくぴったり端の座標を...
それでは都合が悪いのでクリアしています。下部は水を張って...
//前回描画された情報の上に新しい水滴を残像から順に描画
for(int i=0; i<AFTERIMAGENUM+1; i++){
for(int j=0; j<width*(height-1); j++){
if(position[AFTERIMAGENUM-i][j]!=0)
pallet[j] = position[AFTERIMAGENUM-i][j];
}
}
古い残像から順に書き込んでいます。if文で分岐させているの...
値が無い部分は書き込んではいけません。というのはpalletに...
ピクセルに対応させてカラーパレットの番号を保持しています。
また毎回周りのピクセルの値と平均を取りながらぼかしている...
palletの値はクリアされず、前の状態を保ちながら新しい値を...
そのため値がない部分も書き込んでしまうとせっかくぼけさせ...
//ぼやけさせる
for(int i=1; i<height-1; i++){
for(int j=1; j<width-1; j++){
pallet[i*width + j] = (pallet[i*width + j] +
pallet[(i-1)*width + j] +
pallet[i*width + j-1] +
pallet[i*width + j+1] +
pallet[(i+1)*width + j])/5;
}
}
値を平均化しています。といってもここで値を混ぜているわけ...
Palletcolorクラスにてパレット番号の小さいもの程明度や彩度を
低くしています。
- &ref(Fountain.java);
- &ref(Dropofwater.java);
- &ref(Palletcolor.java);
終了行:
RIGHT:寄稿:東條遼平
* 簡単な物理法則とぼかし [#ac1358b6]
実際の噴水とは随分違いますが、それなりに動いていると思い...
色の選び方や、残像を作ってぼかしているあたりが少々面倒で...
炎と同じく水滴の動きの理論自体は大変簡単です。
#ref(img1.png,nolink)
#ref(img2.png,nolink)
高校物理で習う上記の式を使います。これで初速度と噴出角度...
水滴の座標を知ることができ、実装することができそうです。
ただし、初速度、経過時間はそれぞれ単位がメートル/秒と秒で...
それを画面上でどう置き換えるかにもよるのですが、
得られた値を座標にし、経過時間をループ回数などとすれば、
重力加速度gが9.8では恐らく残念な結果になると思います。
市販のゲームですらジャンプした直後は重力と逆向きに加速し...
自分の納得のいく見え方になるように柔軟に値を変更する事も...
それでは噴水において水滴のそれぞれの動きを考えてみます。
物理法則は上記の式で良いのですが、初速度や噴出角度が同じ...
初速度に関しては最大の初速度を決めておき、その範囲内でラ...
初速度を決め、角度についても一定の範囲内でランダムに決め...
また、水滴の座標に点をプロットするだけでは余りに御粗末で...
そのため残像を付けたり、炎のときのようにぼかしてみました。
これに色を付けることでライトアップされたような噴水ができ...
それではソースコードを見ていきます。今回メインのFountain...
それぞれの水滴を扱うDropofwaterクラス、色情報を扱うPallet...
作成しました。
public double getX(){
return -velocity*Math.cos(Math.toRadians((double)degre...
}
public double getY(){
return -velocity*Math.sin(Math.toRadians((double)degre...
*time + 0.8*time...
}
これはDropofwaterクラスのメソッドの一部です。
それぞれの座標を得るために上記の式を計算しているだけです。
注意点としてはcosやsinの関数は引数としてラジアンを取るた...
度数をラジアンに変更しています。また、画面上の左上が原点...
した方向にY軸をとりますので符号に気を付けてください。
public void setisonscreen(boolean isonscreen){
this.isonscreen = isonscreen;
}
public boolean isOnscreen(){
return isonscreen;
}
これらのメソッドは、水滴が画面より外にでた事を調べるため...
水滴を無限に作成することはできないので、画面から外れたも...
発射し直す必要があります。isOnscreenの返り値の真偽によっ...
public void timeInc(){
time++;
}
経過時間もそれぞれのインスタンス毎に管理すべき値です。
メソッドを作成しておきます。
public Palletcolor(int colornum, int gradationnum){
this.colornum = colornum;
this.gradationnum = gradationnum;
nowcolor = (int)(colornum*Math.random());
color = new Color[colornum][];
for(int i=0; i<colornum; i++){
color[i] = new Color[gradationnum];
for(int j=0; j<gradationnum; j++){
color[i][j] = Color.getHSBColor((float)i/colornum,
1-(float)j/gradati...
(float)j/gradation...
}
}
}
これはPalletcolorクラスのコンストラクタです。今回も色の決...
RGBではなくHSBのパラメータで色を決定しています。
colornumは扱う色相の種類の数、gradationnumはそれぞれの色...
どれだけのグラデーションを持つかという変数です。nowcolor...
噴水の色で最初はランダムに設定します。
それではいよいよメインのクラスです。
int image[]; //RGB情報をもった配列
int pallet[]; //対応するピクセルが使っているパレットのイ...
int position[][]; //水滴の位置
imageの配列の情報を用いて画面のイメージを作成しています。
palletはPalletcolorクラスで作成したグラデーションの番号を...
そのためこの値が変化しなくても色相が変化すれば色はかわり...
positionは各水滴の位置を保持しています。多次元配列となっ...
過去数回分の水滴の位置を保持しておきます。
if(System.currentTimeMillis() - timerstart > 5000){
palletcolor.setnextColor();
nowmaxvelocity = (int)(maxvelocity * Math.random());
timerstart = System.currentTimeMillis();
}
run内での処理です。毎回同じ色や初速度では面白くないので
指定した時間が経過する度色相を次のものにし、各々の水滴が...
最大の初速度をランダムでnowmaxvelocityに保持しています。
//残像の作成
for(int i=0; i<AFTERIMAGENUM; i++){
for(int j=0; j<width*height; j++){
position[AFTERIMAGENUM-i][j] =
(int)(position[AFTERIMAGENUM-1-i][j]*4...
}
}
//水滴の現在位置のクリア
for(int i=0; i<width*height; i++) position[0][i] = 0;
時間的に新しいものを1つずつ古い方に送り、次の位置を保持す...
クリアします。古い方に送る際に4/5倍しているのは残像ははっ...
考えです。
//画面の上部と左右の端は値が変化しないためクリアする
for(int i=0; i<width; i++) pallet[i] = 0;
for(int i=0; i<height; i++) pallet[i*width] = 0;
for(int i=0; i<height; i++) pallet[i*width + width-1]...
画面の端は値が無くならないので、うまくぴったり端の座標を...
それでは都合が悪いのでクリアしています。下部は水を張って...
//前回描画された情報の上に新しい水滴を残像から順に描画
for(int i=0; i<AFTERIMAGENUM+1; i++){
for(int j=0; j<width*(height-1); j++){
if(position[AFTERIMAGENUM-i][j]!=0)
pallet[j] = position[AFTERIMAGENUM-i][j];
}
}
古い残像から順に書き込んでいます。if文で分岐させているの...
値が無い部分は書き込んではいけません。というのはpalletに...
ピクセルに対応させてカラーパレットの番号を保持しています。
また毎回周りのピクセルの値と平均を取りながらぼかしている...
palletの値はクリアされず、前の状態を保ちながら新しい値を...
そのため値がない部分も書き込んでしまうとせっかくぼけさせ...
//ぼやけさせる
for(int i=1; i<height-1; i++){
for(int j=1; j<width-1; j++){
pallet[i*width + j] = (pallet[i*width + j] +
pallet[(i-1)*width + j] +
pallet[i*width + j-1] +
pallet[i*width + j+1] +
pallet[(i+1)*width + j])/5;
}
}
値を平均化しています。といってもここで値を混ぜているわけ...
Palletcolorクラスにてパレット番号の小さいもの程明度や彩度を
低くしています。
- &ref(Fountain.java);
- &ref(Dropofwater.java);
- &ref(Palletcolor.java);
ページ名:
home
>
Modified by
物理のかぎプロジェクト
PukiWiki 1.4.5_1
Copyright © 2001-2005
PukiWiki Developers Team
. License is
GPL
.
Based on "PukiWiki" 1.3 by
yu-ji
Powered by PHP 5.3.29HTML convert time to 0.004 sec.