- PR -

四角い画像を円として認識させる

投稿者投稿内容
ゴールデン
常連さん
会議室デビュー日: 2004/08/22
投稿数: 46
投稿日時: 2004-09-01 21:54
あいつーさん、びしばしさん、H2さん、a-sanさん、アドバイスありがとうございます。
とりあえずシンプルな円のみにして、試しています。いいところまでいっています。バブルの動きは、落下して跳ねるという運動です。ただし、collision()メソッドについて、新たな問題が出てきました。それは、初めのうちは、2つのバブル間での距離の問題なので、うまく跳ねていますが、途中から、3つ以上のバブルが重なり、たくさんのバブル間での問題になってきてしまいます。そんなとき、まず2つのバブル間で反発しもう一つとのバブル間で反発し、で、よって、重なりができるように動いてしまうのです。これを回避する方法を考えたのですが、おそろしいループしか頭に浮かびません。(でも最高いくつまで重なるのかなあ)
ですので、みなさんのアドバイスに頼るしかなさそうです。お忙しい中かもしれませんが、何とかお願いします。(そんなに急いではいないので、時間があるときで結構です。)
でも、跳ねるところまではきました。すごく嬉しいです。

コード:

import java.awt.*;
import java.applet.Applet;
/*
<applet code="BubbleWorld2" width=200 height=240>
</applet>
*/
public class BubbleWorld2 extends Applet implements Runnable{
Bubble bubble[];//バブル大,中、小
Image offs;
Graphics og;
Thread th;
boolean is_on;//スレッドのスイッチ
int k;
public void init(){
th=null;
offs=createImage(200,240);
bubble=new Bubble[30];
for(int i=0;i<6;i++){
for(int j=0;j<5;j++){
bubble[i*5+j]=new Bubble(40*(j+1)-20,40*(i+1)-20,10);
}
}
}
public void start(){
if(th==null){
th=new Thread(this);
th.start();
}
}
public void stop(){
th=null;
}
public void run(){
Thread thisThread=Thread.currentThread();
while(thisThread==th){
is_on=true;
for(int i=0;i<30;i++){
bubble[i].move();
}
collision();
repaint();
try{
th.sleep(50);
}catch(InterruptedException e){}
}
}
public void update(Graphics g){
paint(g);
}
public void paint(Graphics g){
og=offs.getGraphics();
if(og!=null){
try{
og.setColor(Color.blue);
og.fillRect(0,0,200,240);
og.setColor(Color.white);
for(int i=0;i<30;i++){
bubble[i].draw(og);
}
g.drawImage(offs,0,0,this);
}catch(Exception e){}
finally{og.dispose();}
}
}
public void collision(){
for(int i=0;i<29;i++){
for(int j=i+1;j<30;j++){
//互いの中心点から中心点までの距離が互いの半径の和より小さいとき衝突
if(Math.sqrt(Math.pow((bubble[i].x-bubble[j].x),2)+Math.pow((bubble[i].y-bubble[j].y),2))<bubble[i].radias+bubble[j].radias){
if(bubble[i].b*bubble[j].b==-1){
//互いの動きの方向が逆の場合、向きを変える
bubble[i].b=-bubble[i].b;
bubble[j].b=-bubble[j].b;
}
if(bubble[i].y==240-20){bubble[j].b=-bubble[j].b;}//片方が底にたまっている場合ぶつかったの方が向きを変える
if(bubble[j].y==240-20){bubble[i].b=-bubble[i].b;}
//速度ベクトルを交換
double tmp=bubble[j].dk;
bubble[j].dk=bubble[i].dk;
bubble[i].dk=tmp;
}
}
}
}
}
class Bubble{
double x;
double y;
double radias;
int b;//上下のスイッチ(1…下向き、−1…上向き)
double r;//縦方向速度ベクトルの元
double dk;//縦方向速度ベクトル
Bubble(double x,double y,double radias){
this.x=x;
this.y=y;
this.radias=radias;
b=1;
r=0.0;
}
void move(){
dk=Math.pow(r,2);
if(b==-1){
r=r-0.03;
if(r<1){b=1;}
if(y<0){b=1;}
dk=-dk;
}
else if(b==1){
r=r+0.02;
if(y>240-10){b=-1;}
}
y+=dk;
if(r==0&&y>=240-20){b=0;}
}
void draw(Graphics g){
g.drawOval((int)(x-radias),(int)(y-radias),(int)radias*2,(int)radias*2);
}
}



[ メッセージ編集済み 編集者: ゴールデン 編集日時 2004-09-01 21:58 ]

[ メッセージ編集済み 編集者: ゴールデン 編集日時 2004-09-01 22:22 ]
a-san
ベテラン
会議室デビュー日: 2004/06/01
投稿数: 53
投稿日時: 2004-09-01 23:27
collision()はすごく雑な計算しかしてません。(速度を入れ替えているだけ)
実際にはもっと厳密な計算をしなければいけないです。
前回のコマから今回のコマの間でぶつかっているので、
ぶつかった時刻を計算し、衝突後の速度だけではなく、位置も計算する必要が
あります。
また、最初にぶつかるバブルがどれなのかも特定する必要があります。
最初にぶつかったバブルから順番に1つづつ処理していけば、
かなりイイ線までできるのではないかと思います。
衝突が多くなると恐ろしく動きが鈍くなるでしょうが。

その前に、速度を遅くしたり、時間間隔を短くすれば、多少はマシになると思います。

こーいうシミュレーションの応用って色々考えられます。
3次元にするとか、大きさや質量を変えるとか、回転も考えるとか、
衝突計数を考慮するとか、風を吹かすとか。
他に、衝突のたびに音を出したり、色を変えたり、2つのバブルを結合して
1つのバブルにするのも面白いかもしれません。
他に、バブルを太陽や惑星としてみるとか、ビリヤードの球にするとか・・・。
ゴールデン
常連さん
会議室デビュー日: 2004/08/22
投稿数: 46
投稿日時: 2004-09-02 00:11
今日はわりと時間があったので、3〜4時間たっぷりパソコンができました。ただし、行き詰まってからは空回りですが…。これからの方向としては、@バブルを当初のとおり、ぼかしを入れて立体感のあるものにする。Aバブルばかりでは面白くないので、バブル30個の中にイラストをいつだけ入れ込み、そのイラストの輪郭線とバブルとの接触を考えようと思っています。
本日はこれにて終了します。またよろしくお願いします。
ゴールデン
常連さん
会議室デビュー日: 2004/08/22
投稿数: 46
投稿日時: 2004-09-02 20:39
バブルを軽く跳ねるように動かすことからちょっと離れて、次の段階に進もうと思います。バブルをただの円ではなく、立体的なバブルにするために、Alfa値を操作して透明感のあるバブルにしたいのですが、setColor()メソッドでは、RGBしか操作できないのですね。何か良い方法はあるでしょうか。それとも、そういうことをするよりも、今回のアプレットのバックは単一色なので、バブルの画像を画像ソフトで透明感があるように作って、教えていただいたcollision()メソッドで、輪郭線を計算して、バブルが跳ねるようにした方が早いのでしょうか。(画像を作るのが面倒そうなので、できればプログラム内で作りたいと思っていますが…)よろしくお願いします。
コード:
int v=(int)(200/(radias-1));//v=Alfa値を(radias-1)分割した値
		for(int h=0;h<(int)(radias-1);h++ ){
			//この行にAlfa値を200からvずつ減らして、色指定をしていくコードを書きたい
			g.drawOval((int)(x-(radias-h)),(int)(y-(radias-h)),(int)(radias-h)*2),(int)(radias-h)*2));
		}

a-san
ベテラン
会議室デビュー日: 2004/06/01
投稿数: 53
投稿日時: 2004-09-07 02:13
BufferedImageを作り、それを描画してはどうでしょう?

スキルアップ/キャリアアップ(JOB@IT)