// 名前 : 高井 佳基
// 学生証番号 : 350526C
// 説明 : AWTにより月と雪だるまを描画するプログラム・改3
//          1.月及び雪だるまをドラッグにより移動させる
//          2.なにもないところでドラッグすると, ランダムに3色の星を書き込む
//          3.Delete ボタンを押すと星が一つ消える
//          4.Clear ボタンを押すと星がすべて消える
//          5.Checkbox により, 夜と昼を切り替える
//          6.昼は月の変わりに太陽が動くが, 固定された月の影に太陽が入ると
//              日食が起こる。元に戻すには隠れた太陽を月の外に出す
//          7.以上の機能をアプレットとしてブラウザで動くようにした


// アプレットを使うため
import java.applet.*;
// AWTを使うので java.awt.*を import する
import java.awt.*;
// イベント駆動関係のクラスを用いるため
import java.awt.event.*;
// Randomクラス, Vectorクラスを用いるために必要
import java.util.*;

// "星"のクラスを定義する//
class Star{
    // x座標, y座標を int で保持する
    public int st_x,st_y,st_color;
    // Star のコンストラクタ
    // Star(x座標,y座標,星の色)と指定する
    public Star(int sx1,int sy1,int sc1){
	st_x = sx1; st_y = sy1;
	st_color = sc1;
    }
}

public class Kadai1209 extends Applet implements ActionListener, ItemListener{
    // Star の配列を保持する Vector クラスの変数 starArray の宣言
    Vector starArray;
    // 月や雪だるまのないところでドラッグ中ならば dragging = true
    // 月の上にマウスカーソルがあれば moon = true
    // 雪だるまの上にマウスカーソルがあれば snowman = true
    boolean dragging, moon, snowman;
    // (x1,y1)が月, (x2,y2)が雪だるまの座標を表す
    int x1 = 55, y1 = 40, x2 = 230, y2 = 190;
    // Random に雪を降らせたり, 星の色を決めたりするための
    // 乱数の元となるオブジェクトを作成
    Random r = new Random();
    // マウスで月や雪だるまをドラッグする際の相対的な座標を int で保持する
    int dx, dy;
    // night = true で夜, false で昼, eclipse = true で日食
    boolean night = true, eclipse = false;

    Image offScreenImage;
    Graphics offScreenGraphics;
    public void update(Graphics g){
	if(offScreenImage == null){
	    // offScreenImage に値を入れるので, 次回はif文は成立しない
	    offScreenImage = createImage(400, 400);
	    offScreenGraphics = offScreenImage.getGraphics();
	}
	paint(offScreenGraphics);
	g.drawImage(offScreenImage, 0, 0, this);
    }

    public void paint(Graphics g){
	int i;
	// 遠いものや大きいものから配置する
	// night = true (夜)のとき
	if(night){
	    // 夜の空
	    g.setColor(new Color(25, 25, 112));
	    g.fillRect(0, 0, 400, 400);

	    // 星
	    int size = starArray.size();
	    if(dragging) size--;
	    for(i = 0; i < size; i++){
		Star s = (Star)starArray.elementAt(i);
		g.drawImage(star[s.st_color], s.st_x-8, s.st_y-8, this);   
	    }
	    if(dragging){
		Star s = (Star)starArray.elementAt(size);
		g.drawImage(star[s.st_color], s.st_x-8, s.st_y-8, this);
	    }

	    // 三日月
	    g.setColor(new Color(255, 255, 204));
	    g.fillOval(x1, y1, 46, 46);
	    g.setColor(new Color(25, 25, 112));
	    g.fillOval(x1-29, y1-29, 69, 69);

	    // 一面の雪にやや丸い地平線
	    g.setColor(new Color(245, 255, 250));
	    g.fillOval(-600, 210, 1600, 360);

	    // 雪だるまの影
	    g.setColor(new Color(245, 245, 245));
	    g.fillOval(x2+37, y2+75, 100, 50);

	    // 雪だるま(下)
	    g.setColor(new Color(255, 250, 250));
	    g.fillOval(x2, y2, 100, 100);

	    // 雪だるま(上)
	    g.fillOval(x2+10, y2-65, 80, 80);

	    // "口"
	    g.setColor(Color.black);
	    g.fillRect(x2+32, y2-18, 19, 3);

	    // "鼻(小枝)"
	    g.setColor(new Color(128, 0, 0));
	    int[] xs0 = {x2+15, x2+15, x2+40, x2+40};
	    int[] ys0 = {y2-28, y2-25, y2-25, y2-31};
	    g.fillPolygon(xs0, ys0, 4);
 
	    // "帽子(バケツ)"
	    g.setColor(Color.red);
	    int[] xs1 = {x2+35, x2+85, x2+83, x2+53};
	    int[] ys1 = {y2-63, y2-45, y2-74, y2-84};
	    g.fillPolygon(xs1, ys1, 4);

	    // Randomに雪を降らせる
	    // (sx, sy) = ((雪のx座標)+10, (雪のy座標)+10)
	    // 10 ずらしているのは左端も自然に描画するため
	    // s_size は雪の大きさを表す
	    for(i = 0; i < 300; i++){
		int sx = r.nextInt(420);
		int sy = r.nextInt(420);
		int s_size = r.nextInt(5)+3;
		g.setColor(Color.white);
		g.fillOval(sx-10, sy-10, s_size, s_size);
		g.setColor(new Color(230, 230, 250));
		g.drawOval(sx-10, sy-10, s_size, s_size);
	    }

	    // 雪だるまの"目"
	    g.setColor(Color.black);
	    g.fillOval(x2+30, y2-45, 6, 6);
	    g.fillOval(x2+50, y2-45, 6, 6);

	    // 説明
	    g.setFont(new Font("Serif", Font.ITALIC, 11));
	    g.drawString("You can move the moon or the snowman", 180, 320);
	    g.drawString("by dragging it.", 320, 335);
	    g.drawString("You can create a new star", 180, 350);
	    g.drawString("by dragging any other area.", 255, 365);
	}
	// night = false (昼)のとき(通常時)
	else if(!eclipse){
	    // 昼の空
	    g.setColor(new Color(135, 206, 250));
	    g.fillRect(0, 0, 400, 400);

	    // 太陽
	    g.drawImage(sun, x1, y1, this);

	    // 昼の月
	    g.setColor(new Color(240, 248, 255));
	    g.fillOval(20, 10, 46, 46);
	    g.setColor(new Color(135, 206, 250));
	    g.fillOval(-9, -19, 69, 69);

	    // 一面の雪にやや丸い地平線
	    g.setColor(new Color(255, 250, 250));
	    g.fillOval(-600, 210, 1600, 360);

	    // 雪だるまの影
	    g.setColor(new Color(230, 230, 250));
	    g.fillOval(x2+37, y2+75, 100, 50);

	    // 雪だるま(下)
	    g.setColor(new Color(255, 250, 240));
	    g.fillOval(x2, y2, 100, 100);

	    // 雪だるま(上)
	    g.fillOval(x2+10, y2-65, 80, 80);
	    g.drawImage(sweat, x2+60, y2-40, 15, 20, this);

	    // "口"
	    g.setColor(Color.black);
	    g.fillRect(x2+32, y2-10, 19, 3);

	    // "鼻(小枝)"
	    g.setColor(new Color(128, 0, 0));
	    int[] xs0 = {x2+15, x2+15, x2+40, x2+40};
	    int[] ys0 = {y2-20, y2-17, y2-17, y2-23};
	    g.fillPolygon(xs0, ys0, 4);
 
	    // "帽子(バケツ)"
	    g.setColor(Color.red);
	    int[] xs1 = {x2+80, x2+140, x2+130, x2+90};
	    int[] ys1 = {y2+120, y2+120, y2+90, y2+90};
	    g.fillPolygon(xs1, ys1, 4);

	    // 雪だるまの"目"
	    g.setColor(Color.black);
	    g.fillOval(x2+30, y2-37, 6, 6);
	    int[] xs2 = {x2+25, x2+39, x2+37, x2+23};
	    int[] ys2 = {y2-40, y2-47, y2-49, y2-42};
	    g.fillPolygon(xs2, ys2, 4);
	    g.fillOval(x2+50, y2-37, 6, 6);
	    int[] xs3 = {x2+62, x2+48, x2+50, x2+64};
	    int[] ys3 = {y2-40, y2-47, y2-49, y2-42};
	    g.fillPolygon(xs3, ys3, 4);

	    // 説明
	    g.setFont(new Font("Serif", Font.ITALIC, 11));
	    g.drawString("You can move the sun by dragging it.", 220, 365);
	}
	// 日食
	else{
	    // 夜の空
	    g.setColor(new Color(25, 25, 112));
	    g.fillRect(0, 0, 400, 400);

	    // 星
	    int size = starArray.size();
	    if(dragging) size--;
	    for(i = 0; i < size; i++){
		Star s = (Star)starArray.elementAt(i);
		g.drawImage(star[s.st_color], s.st_x-8, s.st_y-8, this);   
	    }
	    if(dragging){
		Star s = (Star)starArray.elementAt(size);
		g.drawImage(star[s.st_color], s.st_x-8, s.st_y-8, this);
	    }

	    // 月と太陽
	    g.setColor(new Color(255, 215, 0));
	    g.fillOval(x1-2, y1-2, 50, 50);
	    g.setColor(new Color(255, 255, 204));
	    g.fillOval(20, 10, 46, 46);

	    // 一面の雪にやや丸い地平線
	    g.setColor(new Color(245, 255, 250));
	    g.fillOval(-600, 210, 1600, 360);

	    // 雪だるまの影
	    g.setColor(new Color(245, 245, 245));
	    g.fillOval(x2+37, y2+75, 100, 50);

	    // 雪だるま(下)
	    g.setColor(new Color(255, 250, 250));
	    g.fillOval(x2, y2, 100, 100);

	    // 雪だるま(上)
	    g.fillOval(x2+10, y2-65, 80, 80);

	    // "口"
	    g.setColor(Color.black);
	    g.fillRect(x2+32, y2-10, 19, 3);

	    // "鼻(小枝)"
	    g.setColor(new Color(128, 0, 0));
	    int[] xs0 = {x2+15, x2+15, x2+40, x2+40};
	    int[] ys0 = {y2-20, y2-17, y2-17, y2-23};
	    g.fillPolygon(xs0, ys0, 4);
 
	    // "帽子(バケツ)"
	    g.setColor(Color.red);
	    int[] xs1 = {x2+35, x2+85, x2+83, x2+53};
	    int[] ys1 = {y2-63, y2-45, y2-74, y2-84};
	    g.fillPolygon(xs1, ys1, 4);

	    // 雪だるまの"目"
	    g.setColor(Color.black);
	    g.fillOval(x2+30, y2-37, 6, 6);
	    int[] xs2 = {x2+37, x2+23, x2+25, x2+39};
	    int[] ys2 = {y2-40, y2-47, y2-49, y2-42};
	    g.fillPolygon(xs2, ys2, 4);
	    g.fillOval(x2+50, y2-37, 6, 6);
	    int[] xs3 = {x2+50, x2+64, x2+62, x2+48};
	    int[] ys3 = {y2-40, y2-47, y2-49, y2-42};
	    g.fillPolygon(xs3, ys3, 4);

	    // 説明
	    g.setFont(new Font("Serif", Font.ITALIC, 40));
	    g.drawString("eclipse!!!", 130, 275);
	    g.setFont(new Font("Serif", Font.ITALIC, 11));
	    g.drawString("You can move the sun by dragging it.", 220, 365);
	}
    }
    // 星を1つ消すメソッド
    public void deleteStar(){
	int size;
	if((size = starArray.size())>0 & (night | eclipse)){
	    starArray.removeElementAt(size-1);
	    repaint();
	}
    }
    // 星をすべて消すメソッド
    public void clearStar(){
	if(night | eclipse){
	    starArray.removeAllElements();
	    repaint();
	}
    }

    Button deleteButton, clearButton, exitButton;
    CheckboxGroup cbg = new CheckboxGroup();
    Checkbox nightChkbox, dayChkbox;
    Image sun, sweat;
    Image star[] = new Image[3];
    // コンストラクタは書かない
    public void init(){
	starArray = new Vector();
	dragging = false;
	setSize(400, 400);
	int i;	
	for(i = 0; i < 3; i++){
	    star[i] = getImage(getCodeBase(), "star"+i+".png");
	}
      	sun = getImage(getCodeBase(), "sun1.png");
	sweat = getImage(getCodeBase(), "sweat.png");
	// レイアウトを GridBagLayout に設定し, Button や Checkbox を配置する
	Panel panel = new Panel();
	panel.setLayout(new GridBagLayout());
	panel.add(deleteButton = new Button("Delete"));
	deleteButton.addActionListener(this);
	panel.add(clearButton = new Button("Clear"));
	clearButton.addActionListener(this);
	panel.add(exitButton = new Button("Exit"));
	exitButton.addActionListener(this);
	panel.add(nightChkbox = new Checkbox("night", cbg, true));
	nightChkbox.addItemListener(this);
	panel.add(dayChkbox = new Checkbox("day", cbg, false));
	dayChkbox.addItemListener(this);
	setLayout(new BorderLayout());
	add(panel,"South");   
	// サイズを400x400に設定
	setSize(400,400);
	// 表示する.
	setVisible(true);
	addMouseListener(new MouseAdapter(){
		public void mousePressed(MouseEvent e){
		    int mx = e.getX(), my = e.getY();
		    // なにもないところでマウスボタンが押されたら星を一つ追加
		    // その際, Random に星の色を決める
		    //   mc=0,1,2 がそれぞれ黄色, 青色, 赤色に対応
		    // 月(太陽)や雪だるまの上でマウスボタンが押されたら,
		    // 月や雪だるまに対する相対的な座標を記録する
		    if(night){
			if(!moon & !snowman){
			    int mc = r.nextInt(3);
			    starArray.addElement(new Star(mx, my, mc));
			    dragging = true;
			}
			else if(moon){
			    dx = mx-x1; dy = my-y1;
			}
			else if(snowman){
			    dx = mx-x2; dy = my-y2;
			}
		    }
		    else{
			if(moon){
			    dx = mx-x1; dy = my-y1;
			}
		    }
		    // 再表示をおこなう
		    repaint();
		}
		public void mouseReleased(MouseEvent e){
		    int mx = e.getX(), my = e.getY();
		    // マウスボタンが離されたら星の座標及び色を固定する
		    if(night){
			if(!moon & !snowman){
			    Star s = (Star)starArray.elementAt(starArray.size()-1);
			    s.st_x = mx; s.st_y = my;
			    dragging = false;
			}
			repaint();
		    }
		}
	    });
	addMouseMotionListener(new MouseMotionAdapter(){
		public void mouseDragged(MouseEvent e){
		    int mx = e.getX(),my = e.getY();
		    // マウスのドラッグに合わせて星, 月, 雪だるまを動かす
		    // ドラッグ中は星の色は変えない
		    if(night){
			if(!moon & !snowman){
			    Star s = (Star)starArray.elementAt(starArray.size()-1);
			    s.st_x = mx; s.st_y = my;
			}
			else if(moon){
			    x1 = mx-dx; y1 = my-dy;
			}
			else if(snowman){
			    x2 = mx-dx;
			    // 雪だるまの下の部分が地平線から
			    // はみ出さないようにする
			    if (my > 157+dy) y2 = my-dy;
			    else y2 = 158;
			}
			eclipse = false;
		    }
		    else if(moon){
			x1 = mx-dx; y1 = my-dy;
			if(x1 < 21 & y1 < 11){
			    eclipse = true;
			}
			if(eclipse & (x1 > 40 | y1 > 30)){
			    eclipse = false;
			}
		    }
		    repaint();
		}
		public void mouseMoved(MouseEvent e){
		    int mx = e.getX(), my = e.getY();
		    // マウスカーソルが月の上に入ったら moon = true
		    // 雪だるまの上に入ったら snowman = true
		    if(night){
			if(mx > x2 & mx < x2+100 & my > y2-80 & my < y2+100){
			    moon = false; snowman = true;
			}
			else if(mx > x1 & mx < x1+46 & my > y1 & my < y1+46){
			    moon = true; snowman = false;
			}
			else{
			    moon = false; snowman = false;
			}
		    }
		    else{
			if(mx > x1 & mx < x1+46 & my > y1 & my < y1+46){
			    moon = true; snowman = false;
			}
			else{
			    moon = false; snowman = false;
			}
		    }
		}
	    });
    }
    public void actionPerformed(ActionEvent e){
	System.out.println(e);
	Object source = e.getSource();
	if(source.equals(deleteButton)){
	    deleteStar();
	}
	else if(source.equals(clearButton)){
	    clearStar();
	}
	else if(source.equals(exitButton)){
	    // 見かけ上終了
	    setVisible(false);
	}
    }
    public void itemStateChanged(ItemEvent e){
	if(nightChkbox.getState()){
	    night = true;
	}
	else{
	    night = false;
	}
	repaint();
    }
}