【プログラムC:\MyJava\cn\nsa8.java】**************************

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;


class MovingCharacter{
	Point p;
	Point ps;
    int mode;
	int r;
	boolean start;
	boolean arrive;
	double speed;
	double dx,dy,tx,ty,count;
	Color color;
	int clw,clh;
	int rw,rh;
	
	MovingCharacter(){
		ps=new Point();
		start=false;
		arrive=false;
		mode=0;
		dx=0;dy=0;tx=0;ty=0;
	}

	void move(double speed,int x2,int y2){
		Point p2=new Point(x2,y2);
		move(speed,p2);
	}
	
	
	void move(Point p2){
		move(speed,p2);
	}
	
	void move(double speed,Point p2){//*****************************
		if(!start){
			arrive=false;
			tx=p.x;
			ty=p.y;
			count=p.distance(p2)/speed;
			dx=(p2.x-p.x)/count;
			dy=(p2.y-p.y)/count;
			start=true;
		}
		else if(count<=0){
			dx=0;dy=0;
			arrive=true;
		}
		else if(!arrive){
			tx+=dx;
			ty+=dy;
			count-=1;
			p.setLocation(tx,ty);
			
		}
	}

	Point action(Point p1,Point p2){
		return p;	
	}
	
}
	

class Ball extends MovingCharacter{
	Ball(){
		p=new Point();
		start=false;
		arrive=false;
    	r=4;
		speed=2.5;
		color=Color.white;
		clw=6*r;
		clh=6*r;
		mode=0;
	}
	
}

class Player extends MovingCharacter{
	boolean pass;
	BitSet reach;
	Player(Color co){
		reach=new BitSet(4);
		pass=false;
		p=new Point();
		start=false;
		arrive=false;
		r=5;
		speed=1;
		color=co;
		clw=60*r;
		clh=10*r;
		rw=35;
		rh=35;
		
	}

	void ballTrace4(double speed,int xp,int yp,int xsb,int ysb,int xeb,int yeb){
		double d1=(ysb-yeb)*(xp-xeb)/(xeb-xsb);
		
		int y=(int)(yeb-d1);
		move(speed,xp,y);
	}
	
	BitSet getReach(Ball b1){	
		reach.clear();
		if(b1.p.x<(p.x-rw/2))reach.set(0);
		if(b1.p.x>(p.x+rw/2))reach.set(1);
		if(b1.p.y<(p.y-rh/2))reach.set(2);
		if(b1.p.y>(p.y+rh/2))reach.set(3);	
		return reach;
	}
}	


class Line{
	final int w=3;	
	final Color lcolor=Color.white;
	/*
	パラメータ:
	x - 描画される孤の左上隅の x 座標
	y - 描画される孤の左上隅の y 座標
	width - 描画される孤の幅
	height - 描画される孤の高さ
	startAngle - 開始角度
	arcAngle - 開始角度に対する弧の展開角度の大きさ
	*/
	
	void drawArcLine(Graphics g,int x,int y,int width,int height,int startAngle,int arcAngle){
		for(int i=0;i<w;i++){
			g.drawArc(x+i,y+i,width-i*2,height-i*2,startAngle,arcAngle);//***
		}
	}
}


class Staff{
	String[] words;
	BitSet bs;
	
	Staff(String[] words){
		this.words=words;
		bs=new BitSet(words.length);
	}

	String speakWords(BitSet bs){
		String s=" ";
		if(bs.cardinality()==0){
			s+=words[0];
			return s;
		}
		else{
			for(int i=0;i<bs.length();i++){
				if(bs.get(i))s+=words[i+1];
			}
			return s;
		}

	}
	
	//*  ********************************************  mc1,Ball  mc2,Keeper
	void checkPlay(MovingCharacter mc1,MovingCharacter mc2){
		

		bs.clear();
		
		if(mc1.p.x<(mc2.p.x-mc2.rw/2))bs.set(0);//もっと左
		if((mc2.p.x+mc2.rw/2)<mc1.p.x)bs.set(1);//もっと右
		if(mc1.p.y<(mc2.p.y-mc2.rh/2))bs.set(2);//早すぎる
		if((mc2.p.y)<mc1.p.y)bs.set(3);//遅すぎる	
		
	}
		
}



public class nsa8 extends java.applet.Applet implements Runnable{
	
	final int w=680;
	final int d=1050;//グランド、縦105m×横68m
	
	final int gw=74;//ゴールポストの内側が7.32m
	final int gd=15;
	final int ccr=92;//センターサークルの半径9.15m
	final int cpr=5;//センターマークの半径
	final int pmr=1;//ペナルティーマークの半径
	final int car=10;//コーナーアークの半径1m
	//final int car=100;//コーナーアークの半径1m
	
	
	final Color GC=new Color(50,125,50);
	final Color SC=Color.white;
	
	Line li=new Line();
	final Color LC=li.lcolor;
	
	Ball ball=new Ball();
	final Color BC=ball.color;
		
	Player gk=new Player(Color.red);
	final Color GKC=gk.color;
	
	Player sb=new Player(Color.yellow);
	final Color SBC=sb.color;
	
	Player cf=new Player(SBC);
	
	Player sb2=new Player(SBC);
	
	
	String[] cw={"ナイスパンチ!","もっと左! ","もっと右! ","早すぎる!","遅すぎる!"};
	Staff coach=new Staff(cw);

	int i5=100;
	
	String sk;
	
	
	final Point ps=new Point(100,100);          //グランド上のラインの起点
    final Point pe=new Point(ps.x+w,ps.y+d);
	final Point prs=new Point(ps.x+ball.r,ps.y+ball.r);
    final Point pre=new Point(pe.x-ball.r,pe.y-ball.r);
	final Point pce=new Point(ps.x,(prs.y+pre.y)/2);//センターライン
	final Point pccc=new Point(pce.x+w/2,pce.y);//センターマーク
	final Point pglb=new Point(pccc.x-gw/2,pe.y);//ゴール、下、左
	final Point pgrb=new Point(pccc.x+gw/2,pe.y);//ゴール、下、右
	final Point pgelb=new Point(pglb.x-55,pe.y);//ゴールエリア
	final Point pgerb=new Point(pgrb.x+55,pe.y);//ゴールエリア
	final Point ppelb=new Point(pglb.x-165,pe.y);//ペナルティーエリア
	final Point pperb=new Point(pgrb.x+165,pe.y);//ペナルティーエリア
	final Point ppm=new Point(pccc.x,pe.y-110);//ペナルティーマーク
	
	final Point cfsp=new Point(pccc.x,pccc.y+300);//センターフォワードの最初の位置
	final Point sb2sp=new Point(pccc.x+80,pccc.y+330);//サイドバック2の最初の位置
	
	Point pks;
	Point pke;
	

	Point pbs=new Point(pccc.x,pccc.y);
	Point pbe=new Point(pccc.x+31,pe.y+10);
	Point pbe2=new Point(500,pccc.y);
	
	Point sbs=new Point(ps.x-50,pe.y-20);
	Point sbe=new Point(ps.x,pe.y);
	
	Thread t_game=new Thread(this);
	
	final int STOP_TIME= 10;

	Image ibuff;    /* 裏画面用Image          */
  	Graphics gb;    /* 裏イメージの描画領域用 */
	
	int mode=0;
	
	
    public void init() {
    		
    	addMouseListener(new MA(this));
    	addMouseMotionListener(new MMA(this));

    	setBackground(GC);
   		ibuff= createImage(900,1300);     /* 横900×縦1300でImage生成 */
    	gb = ibuff.getGraphics();          /* 裏イメージの描画領域 */
    	gb.setFont(new Font("SansSerif",Font.BOLD,20));
    	
    	pks=new Point(pglb.x,pglb.y);
		pke=new Point(pgrb.x,pgrb.y);
    	gk.p.setLocation(pks);
    	
    	sb.p.setLocation(sbe.x,sbe.y);
    	
    	cf.p.setLocation(cfsp.x,cfsp.y);
    	cf.rw=15;
		cf.rh=15;
    	
    	sb2.p.setLocation(sb2sp.x,sb2sp.y);
    	sb2.rw=25;
		sb2.rh=25;
    	
    	ball.p.setLocation(ps.x,pe.y);
    }
	
	public void start(){
    	if (t_game != null) t_game.start();
	}
	
	public void run() {
    	Thread ct = Thread.currentThread();
		
		while (t_game == ct) {
			switch(mode){
			case 0:                     //外からコーナーにボールが帰る。
				if(!ball.start){
					ball.p.setLocation(ps.x-60,pe.y+150);
    				try{
    					t_game.sleep(2000);
    				}
    				catch(InterruptedException ie){
    				}
    			}
				
				cf.move(cf.speed-0.5,cfsp);
				sb2.move(sb2.speed-0.5,sb2sp);
				
    			ball.move(ball.speed-1.0,ps.x,pe.y);
				//ball.move(ball.speed-1.0,ps.x-60,pe.y+150,ps.x,pe.y);
    			if(ball.arrive && cf.arrive && sb2.arrive){
    				ball.start=false;
    				sb.start=false;
    				sb.arrive=false;
    				cf.start=false;
    				sb2.start=false;
    				mode=1;
    			}
    			break;	
			case 1:
				if(!sb.start){
					try{
						t_game.sleep(500);
					}
					catch(InterruptedException ie){
						
					}
				}
				sb.move(sb.speed-0.5,sbs);
				if(sb.arrive){
					mode=2;
					sb.start=false;
					sb.arrive=false;
					ball.start=false;
					ball.arrive=false;
				}
				break;
			case 2:
				if(!sb.start){
					try{
						t_game.sleep(400);
					}
					catch(InterruptedException ie){
						
					}
				}
				sb.move(sb.speed+0.5,sbe);
				if(sb.arrive){
					ball.start=false;
					ball.arrive=false;
					mode=3;
				}
				break;
			case 3:
				if(!ball.start){
    				int y=(int)(1 + Math.random() * d/3);
    				y+=(pccc.y+d/6);
    				pbe.setLocation(pe.x,y);
    				pbs.setLocation(ps.x,pe.y);
    			}
				ball.move(pbe);
				
				cf.ballTrace4(cf.speed+0.1,cf.p.x,cf.p.y,pbs.x,pbs.y,pbe.x,pbe.y);
				if(cf.getReach(ball).cardinality()==0){
					cf.p.setLocation(ball.p.x,ball.p.y);
					cf.start=false;
					sb2.start=false;
					sb2.arrive=true;
					ball.start=false;
					ball.arrive=false;
					mode=4;
				}
				if(cf.getReach(ball).get(1)|cf.getReach(ball).get(2))cf.arrive=true;
				
				sb2.ballTrace4(sb2.speed-0.1,sb2.p.x,sb2.p.y,pbs.x,pbs.y,pbe.x,pbe.y);
				if(sb2.getReach(ball).cardinality()==0){
					sb2.p.setLocation(ball.p.x,ball.p.y);
					sb2.start=false;
					cf.start=false;
					ball.start=false;
					ball.arrive=false;
					mode=4;
				}
				if(sb2.getReach(ball).get(1)|sb2.getReach(ball).get(2))sb2.arrive=true;
    			
				if(ball.arrive){
					cf.start=false;
    				sb2.start=false;
    				ball.start=false;
    				ball.arrive=false;
    				mode=0;
    			}
				break;
			case 4:
				if(!ball.start){//************************************
    				int x=(int)(1 + Math.random() * gw);
    				x+=(pccc.x-gw/2);
    				pbe.setLocation(x,pe.y+18);
					pbs.setLocation(ball.p.x,ball.p.y);
    			}
    			
    			ball.move(ball.speed+0.5,pbe);
				if(ball.arrive){
					ball.start=false;
    				ball.arrive=false;
					sb2.start=false;
					mode=0;
				}
				break;
			case 5:
				if(!ball.start){//************************************
    				pbe.setLocation(ps.x,pccc.y);
					pbs.setLocation(ball.p.x,ball.p.y);
    			}
				ball.move(pbe);
				if(ball.arrive){
					ball.start=false;
    				ball.arrive=false;
					cf.start=false;
					sb2.start=false;
					mode=0;
				}
				break;
				
			}
			repaint();
			try {
        		Thread.sleep (STOP_TIME);
      		}
    		catch (InterruptedException e) {
    		}	
		}
		
		
	}

	public void update(Graphics g) {//**********************************************************
		paint(g);
  	}	
	
    public void paint(Graphics g) {
    	
    	gb.setColor(GC);
    	gb.fillRect(0,0,900,1300);
    	gb.setColor(LC);
    	
    	//li.drawArcLine(gb,prs.x-car/2-li.w,pre.y-car/2+li.w,car+li.w,car+li.w,0,90);
    	gb.fillArc(prs.x-car/2-li.w,pre.y-car/2+li.w,car+li.w,car+li.w,0,90);
    	gb.setColor(GC);
    	gb.fillArc(prs.x-car/2-li.w,pre.y-car/2+2*li.w,car,car,0,90);
    	gb.setColor(LC);

    	gb.fillRect(ps.x,ps.y,li.w,d);
    	gb.fillRect(ps.x+w,ps.y,li.w,d+li.w);
    	gb.fillRect(ps.x,ps.y,w,li.w);
    	gb.fillRect(ps.x,ps.y+d,w,li.w);
    	
    	li.drawArcLine(gb,ppm.x-ccr,ppm.y-ccr,ccr*2,ccr*2,36,108);//
    	
    	
    	gb.setColor(LC);
    	gb.fillRect(pccc.x-gw/2,pe.y,li.w,gd);//ゴール
    	gb.fillRect(pccc.x+gw/2,pe.y,li.w,gd);//ゴール
    	gb.fillRect(pccc.x-gw/2,pe.y+gd,gw+li.w,li.w);//ゴール
    	
    	gb.fillRect(pgelb.x,pgelb.y-55,li.w,55);//ゴールエリア
    	gb.fillRect(pgerb.x,pgelb.y-55,li.w,55);//ゴールエリア
    	gb.fillRect(pgelb.x,pgelb.y-55,pgerb.x-pgelb.x,li.w);//ゴールエリア
    	
    	gb.fillRect(ppelb.x,ppelb.y-165,li.w,165);//ペナルティーエリア
    	gb.fillRect(pperb.x,pperb.y-165,li.w,165);//ペナルティーエリア
    	gb.fillRect(ppelb.x,pgelb.y-165,pperb.x-ppelb.x,li.w);//ペナルティーエリア
    	
    	gb.fillOval(ppm.x-cpr,ppm.y-cpr,pmr*2,pmr*2);
    	
    	gb.fillOval(pccc.x-ccr,pccc.y-ccr,ccr*2,ccr*2);
    	
    	gb.setColor(GC);
    	gb.fillOval(pccc.x-ccr+li.w,pccc.y-ccr+li.w,(ccr-li.w)*2,(ccr-li.w)*2);
    	
    	
    	gb.setColor(LC);
    	gb.fillOval(pccc.x-cpr,pccc.y-cpr,cpr*2,cpr*2);
    	gb.fillRect(pce.x,pce.y,w,li.w);
       
    	gb.setColor(BC);
    	gb.fillOval(ball.p.x-ball.r,ball.p.y-ball.r,ball.r*2,ball.r*2);
    	
    	gb.setColor(GKC);
    	gb.fillOval(gk.p.x-gk.r,gk.p.y-gk.r,gk.r*2,gk.r*2);
    	//gb.drawRect(gk.p.x-gk.rw/2,gk.p.y-gk.rh/2,gk.rw,gk.rh);
    	
    	gb.setColor(SBC);
    	gb.fillOval(sb.p.x-sb.r,sb.p.y-sb.r,sb.r*2,sb.r*2);
    	gb.fillOval(cf.p.x-cf.r,cf.p.y-cf.r,cf.r*2,cf.r*2);
    	gb.fillOval(sb2.p.x-sb2.r,sb2.p.y-sb2.r,sb2.r*2,sb2.r*2);
    	//gb.drawRect(cf.p.x-cf.rw/2,cf.p.y-cf.rh/2,cf.rw,cf.rh);
    	
    	gb.setColor(SC);
    	gb.drawString("ball.p.x:"+ball.p.x,200,200);
    	gb.drawString("ball.p.y:"+ball.p.y,200,230);
    	gb.drawString("ball.dx:"+ball.dx,200,260);
    	gb.drawString("ps.x>ball.p.x:"+(ps.x>ball.p.x),200,290);
    	
    	gb.drawString("peb.y:"+pbe.y,pglb.x,pglb.y+90);
    	gb.drawString("ball.arrive:"+ball.arrive,200,320);
    	gb.drawString("mode:"+mode,200,360);
    	gb.drawString("sb.mode:"+sb.mode,200,400);
    	gb.drawString("cf.start:"+cf.start,200,440);
    	gb.drawString("cf.arrive:"+cf.arrive,200,480);
    	gb.drawString("cfsp.y:"+cfsp.y,200,520);
    	
    	gb.drawString("Punch! : "+sk,pgelb.x,pgelb.y+50);
    	
    	g.drawImage(ibuff,0,0,this);
    	
    }

 	 public void stop(){
 	 	if(t_game != null) t_game = null;
  	}
	
}

class MA extends MouseAdapter{
	nsa8 ap;
	Player gk;

	MA(nsa8 ap) {
		this.ap = ap;
		this.gk=ap.gk;
	}

	public void mousePressed(MouseEvent e){//******************************
		
		ap.sk=ap.coach.speakWords(gk.getReach(ap.ball));
		
		if(gk.reach.cardinality()==0){
			gk.p.setLocation(ap.ball.p.x,gk.p.y);
			ap.mode=5;
			ap.ball.arrive=true;
			ap.ball.start=false;
		}
		ap.repaint(ap.pgelb.x-20,ap.pgelb.y-10,540,520);
	}
	
}

class MMA extends MouseMotionAdapter{
	nsa8 ap;
	
	MMA(nsa8 ap) {
		this.ap = ap;
	}
	
	public void mouseMoved(MouseEvent e){
		
		if(e.getX()<ap.pgelb.x){
			ap.gk.p.x=ap.pgelb.x;
		}
		else if(e.getX()>ap.pgerb.x){
			ap.gk.p.x=ap.pgerb.x;
		}
		else{
			ap.gk.p.x=e.getX();
		}
	}
}