【プログラムc:\MyJava\BlueJ\nsa12\nsa12.java】**************************


import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;



class MovingCharacter{
    Point p;
    Point ps;
    int mode;
    final int STAY=0;
    final int MOVE=1;
    final int ARRIVE=2;
    int r;

    double speed;
    double dx,dy,tx,ty,count;
    Color color;
    int clw,clh;
    int rw,rh;
    BufferedImage image;
    
    MovingCharacter(){
        ps=new Point();
        mode=STAY;
        dx=0;dy=0;tx=0;ty=0;
    }
    
    void makeImage(Color backgroundcolor){
        image= new BufferedImage(r*2,r*2,BufferedImage.TYPE_INT_BGR);
        Graphics gb = image.getGraphics();
        gb.setColor(backgroundcolor);
        gb.fillRect(0,0,r*2,r*2);
        gb.setColor(color);
        gb.fillOval(0,0,r*2,r*2);
    }
        

    void move(double speed,int x2,int y2){
        Point p2=new Point(x2,y2);
        move(speed,p2);
    }
    
    void move(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(mode==STAY){
            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;
            mode=MOVE;
        }
        else if(count<=0){
            dx=0;dy=0;
            mode=ARRIVE;
        }
        else if(mode==MOVE){    
            tx+=dx;
            ty+=dy;
            count-=1;
            p.setLocation(tx,ty);
            
        }
    }

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

class Ball extends MovingCharacter{
    Ball(Color backgroundcolor){
        p=new Point();
        r=4;
        speed=4.0;
        color=Color.white;
        clw=6*r;
        clh=6*r;
        //mode=0;
        mode=STAY;
        makeImage(backgroundcolor);
    }
    
}

class Player extends MovingCharacter{
    boolean pass;
    BitSet reach;
    Player(Color co){
        reach=new BitSet(4);
        pass=false;
        p=new Point();
        mode=STAY;
        r=5;
        speed=2;
        color=co;
        clw=60*r;
        clh=10*r;
        rw=35;
        rh=35;
    }
    Player(Color co,Color backgroundcolor){
        this(co);
        makeImage(backgroundcolor);
    }
    

    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);
    }
    
    void drible(Ball bl,int x,int y){
        bl.move(x,y);
        if(bl.mode==bl.ARRIVE)move(x,y-8);
    }
                
    
    
    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;
    final BasicStroke lineStroke = new BasicStroke((float)w);
    
    void drawArcLine2(Graphics g,int x,int y,int width,int height,int startAngle,int arcAngle){
         Graphics2D g2 = (Graphics2D)g;
         g2.setStroke(lineStroke);
         g2.draw(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN));
    }
}


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);//遅すぎる   
        
    }
        //オフサイドポジション:ボールおよび後方から2人目の相手競技者より相手ゴールラインに近い位置 
        //ボールが味方競技者によって触れられるかプレーされた瞬間にオフサイドポジションにいるとオフサイド

}


public class nsa12 extends JApplet implements MouseMotionListener,MouseListener,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 Color GC=new Color(50,125,50);
    final Color SC=Color.white;
    
    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+4,ps.y+4);
    final Point pre=new Point(pe.x-4,pe.y-4);
    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 pglt=new Point(pccc.x-gw/2,ps.y);//ゴール、上、左
    final Point pgrt=new Point(pccc.x+gw/2,ps.y);//ゴール、上、右
    
    final Point pgelb=new Point(pglb.x-55,pe.y);//ゴールエリア下
    final Point pgerb=new Point(pgrb.x+55,pe.y);
    
    final Point pgelt=new Point(pglb.x-55,ps.y);//ゴールエリア上
    final Point pgert=new Point(pgrb.x+55,ps.y);
    
    final Point ppelb=new Point(pglb.x-165,pe.y);//ペナルティーエリア下
    final Point pperb=new Point(pgrb.x+165,pe.y);
    
    final Point ppelt=new Point(pglt.x-165,ps.y);//ペナルティーエリア上
    final Point ppert=new Point(pgrt.x+165,ps.y);
    
    final Point ppm=new Point(pccc.x,pe.y-110);//ペナルティーマーク上
    final Point ppmt=new Point(pccc.x,ps.y+110);//ペナルティーマーク下
    

    final JViewport view = new JViewport();
    final Point[]vp=new Point[3];
    final Rectangle[]vr=new Rectangle[3];
    final Dimension vd=new Dimension(800,400);
    Rectangle r;
    Point vp2=new Point();
    //final Dimension vd=new Dimension(10,10);

    Ground ground;
    int vy;
    
    final Ball ball=new Ball(GC);
    final Color BC=ball.color;
        
    Player gk1=new Player(Color.yellow,GC);
    Player gk2=new Player(Color.yellow,GC);
    final Color GKC=gk1.color;
    
    Player cf1=new Player(Color.blue,GC);
    Player cf2=new Player(Color.red,GC);
    final Color C1=cf1.color;
    final Color C2=cf2.color;
    
    Player cb2=new Player(C2,GC);
    Player cb3=new Player(C2,GC);
    
    final Point cfsp=new Point(pccc.x,pccc.y+300);//センターフォワードの最初の位置
    final Point sb2sp=new Point(pccc.x+80,pccc.y+330);//サイドバック2の最初の位置
    
    String[] cw={"ナイスパンチ!","もっと左! ","もっと右! ","早すぎる!","遅すぎる!"};
    String sk="";
    Staff coach=new Staff(cw);
    
    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=15;
    
    int mode=0;
    boolean mstart=false;
    
    final int STAY=ball.STAY;
    final int MOVE=ball.MOVE;
    final int ARRIVE=ball.ARRIVE;
    
    //TimeCheck ti=new TimeCheck();

    public void init() {
        setBackground(GC);

        ground = new Ground();
        view.setView(ground);
        view.addMouseListener(this);
        view.addMouseMotionListener(this);
        view.setBackground(GC);
        getContentPane().add(view);
        view.setViewPosition(vp[1]);//********************************************
        vp2.setLocation(vp[1].x,vp[1].y);
        
        
        cf2.rw=15;
        cf2.rh=15;
        
        pks=new Point(pglb.x,pglb.y);
        pke=new Point(pgrb.x,pgrb.y);
        gk1.p.setLocation(pccc.x,pe.y);
        gk2.p.setLocation(pccc.x,ps.y);
        
        
        cf1.rw=15;
        cf1.rh=15;
        
        
        
    }
    
    public void start(){
        view.setViewPosition(vp[1]);
        if (t_game != null) t_game.start();
    }
    
    
    
    
    public void run() {
        Thread ct = Thread.currentThread();
        
        while (t_game == ct) {
            switch(mode){
            case 0:    
                r=vr[1];
                if(!mstart){
                    ball.p.setLocation(pccc.x,pccc.y-10);
                    
                    cf1.p.setLocation(pccc.x+10,pccc.y+ccr+8);
                    cf2.p.setLocation(ball.p.x,ball.p.y-4);
                    cb2.p.setLocation(cf2.p.x,cf2.p.y-50);
                    cb3.p.setLocation(cf2.p.x+70,cf2.p.y);
                    
                    view.setViewPosition(vp[1]);
                    try{
                    Thread.sleep (1500);
                    }
                    catch(InterruptedException e){
                    }
                    mstart=true;
                }
                
                ball.move(cb2.p.x,cb2.p.y+8);
                cf2.move(pccc.x-150,pccc.y);
                cb3.move(pccc.x+150,pccc.y);
                cf1.move(cb2.p);
                if(ball.mode==ARRIVE && cb3.mode==ARRIVE){  
                    
                    if(Math.random()>0.5)mode++;
                    mstart=false;
                    nextMode();
                }
                break;
            case 1:
                ball.move(cb3.p.x,cb3.p.y+8);
                cf1.move(cb3.p.x-8,cb3.p.y);
                cb2.move(cb3.p.x-8,cb2.p.y);
                if(ball.mode==ARRIVE){
                    nextMode();
                    
                }
                break;
            case 2:
                ball.move(cf2.p.x,cf2.p.y+100);
                cf2.move(cf2.p.x,cf2.p.y+95);
                cb3.move(cb3.p.x,cf2.p.y+95);
                
                if((cb3.mode+ball.mode+cf2.mode)==(3*ARRIVE)){
                    mode=3;
                }
                break;
            case 3:
                
                for(int i=vp[1].y;i<=vp[2].y;i+=15){
                    if(i>vp[2].y)i=vp[2].y;
                    try{
                    Thread.sleep (0,1);
                    }
                    catch(InterruptedException e){
                    }
                    
                    vp2.setLocation(vp[1].x,i);
                    view.setViewPosition(vp2);
                }

                nextMode();
                break;
            case 4:
                r=vr[2];
                
                int i=cb3.p.x;
                if(Math.random()>0.5)i=cf2.p.x;
                int j=(int)(Math.random()*3);
                int k=(int)(Math.random()*5);
                
                ball.move(i,cb3.p.y+100);
                cf2.move(cf2.p.x+j,cf2.p.y+95);
                cb3.move(cb3.p.x-k,cf2.p.y+95);
                cf1.move(pccc.x,vp[1].y+40);
                cb2.move(pccc.x,vp[1].y+20);
                
                if(cf2.p.y<ppelb.y-150){
                    if(ball.mode+cf2.mode+cb3.mode==3*ARRIVE){
                        ball.mode=STAY;
                        cf2.mode=STAY;
                        cb3.mode=STAY;
                    }
                }
                else if(ball.mode+cf2.mode+cb3.mode==3*ARRIVE){
                    nextMode();
                }
                break;
            case 5:
                if(ball.mode==STAY){//************************************
                    int x=(int)(1 + Math.random() * gw);
                    x+=(pccc.x-gw/2);
                    pbe.setLocation(x,pe.y+18);
                }
                ball.move(pbe);
                if(ball.mode==ARRIVE){
                    try{
                    Thread.sleep (1500);
                    }
                    catch(InterruptedException e){
                    }
                    nextMode(0);
                }
                break;
            case 6:
                if(ball.mode==STAY){//************************************
                    int x=(int)(1 + Math.random() * w);
                    x+=ps.x;
                    pbe.setLocation(x,ps.y);
                }
                ball.move(pbe);
                if(ball.p.y<vp[2].y){
                    nextMode(7);
                    //mode=7;
                    mstart=false;
                }
                break;
            case 7:
                nextMode(0);
                break;
              /*
                if(!mstart){
                    view.setViewPosition(vp[1]);
                    r=vr[1];
                    mstart=true;
                }
                ball.move(ball.speed/3,pbe);
                cb2.move(cb2.speed*2,pbe);
                if(ball.p.y<vp[1].y){
                    mstart=false;
                    nextMode(0);
                }
                break;
                
            case 8:
                ball.move(ball.speed/3,pbe);
                
                break;
                */
            }
            
            
            
                
        
            //repaint();
            ground.repaint(r);
            
            if(mode!=3){
                try {
                    Thread.sleep (STOP_TIME);
                }
                catch (InterruptedException e) {
                }       
            }
        }
    }
    
    void nextMode(){
        ball.mode=STAY;
        cf1.mode=STAY;
        cf2.mode=STAY;
        cb2.mode=STAY;
        cb3.mode=STAY;
        mode++;
    }
    
    void nextMode(int i){
        nextMode();
        mode=i;
    }
    
    public void update(Graphics g) {//**********************************************************
        paint(g);
    }   
    

    public void mouseClicked(MouseEvent e) {
        //vy++;
        //if(vy>2)vy=0;
        //view.setViewPosition(vp[vy]);
        
        //view.scrollRectToVisible(vr[vy]);
        //view.scrollRectToVisible(vr[0]);
        //view.scrollRectToVisible(vr[1]);
        //view.scrollRectToVisible(vr[2]);
    
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mousePressed(MouseEvent e) { 
        
        if(mode==7){
            if(cf1.reach.cardinality()==0){
                nextMode();
            }
            
        }
        else if(mode==8){
            if(cf1.reach.cardinality()==0){
                switch(e.getButton()){
                case MouseEvent.BUTTON1:
                    //ball.p.setLocation(ball.p.x-10,ball.p.y);
                    pbe.setLocation(100,100);
                    break;
                case MouseEvent.BUTTON2:
                    pbe.setLocation(10,10);
                    //ball.p.x++;
                    break;
                case MouseEvent.BUTTON3:
                    pbe.setLocation(500,10);
                    //ball.p.y--;
                    break;  
                }
            
                /*  
                public int getButton()状態が変更されたマウスボタンがある場合、そのマウスボタンを返します。 

                戻り値:
                定数 NOBUTTON、BUTTON1、BUTTON2、またはBUTTON3 のいずれか
*/
                nextMode();
            }
            
        }
        else if(mode>3){
            sk=coach.speakWords(gk1.getReach(ball));
        
            if(gk1.reach.cardinality()==0){
                gk1.p.setLocation(ball.p.x,gk1.p.y);
                nextMode(6);
            }
        }
        ground.repaint(pgelb.x-20,pgelb.y+20,540,520);
    //  vy = e.getPoint().y;
    //  ground.repaint();
    
    }
        
    public void mouseReleased(MouseEvent e) {}
    public void mouseDragged(MouseEvent e) {}
    
    public void mouseMoved(MouseEvent e) {
        if(mode==7){
            cf1.p.x=e.getX()-vp[1].x;
            cf1.p.y=e.getY()+vp[1].y;
            if(e.getX()<ps.x){
                cf1.p.x=ps.x;
            }
            else if(e.getX()>pe.x){
                cf1.p.x=pe.x;
            }
            
        }
        
        else if(mode>3){
            gk1.p.x=e.getX()+50;
            if(gk1.p.x<pgelb.x){
                gk1.p.x=pgelb.x;
            }
            else if(gk1.p.x>pgerb.x){
                gk1.p.x=pgerb.x;
            }
            
            //repaint();
        }
        
    //  int offset = (e.getPoint().y -vy)*2 ;
    //  vy = e.getPoint().y;
    //  view.setViewPosition(new Point(view.getViewPosition().x ,view.getViewPosition().y + offset));
    }

    class Ground extends JLabel{
        final int wg=900;
        final int hg=1300;
        final Dimension dg=new Dimension(wg,hg);
        final Line li=new Line();
        final Color LC=li.lcolor;
        
        //BufferedImage ibuff; /* 裏画面用Image          */
        Image ibuff; /* 裏画面用Image          */
        Image ib2;
        Graphics gb;    /* 裏イメージの描画領域用 */
        Graphics g2;
        
        Ground(){
            super();
            setPreferredSize(dg);
            
            vp[0]=new Point(50,0);
            vp[1]=new Point(50,400);
            vp[2]=new Point(50,800);
            
            for(int i=0;i<vp.length;i++){
                vr[i]=new Rectangle(vp[i],vd);
            }

            //ibuff= createImage(900,1300);  
            ibuff= new BufferedImage(wg,hg,BufferedImage.TYPE_INT_BGR);     /* 横900×縦1300でImage生成 */
            gb = ibuff.getGraphics();
            //gb.setFont(new Font("SansSerif",Font.BOLD,20));
            
            ib2= new BufferedImage(wg,hg,BufferedImage.TYPE_INT_BGR);
            g2 = ib2.getGraphics();
            g2.setFont(new Font("SansSerif",Font.BOLD,20));
            
            gb.setColor(GC);
            gb.fillRect(0,0,wg,hg);
            gb.setColor(LC);
            
            li.drawArcLine2(gb,prs.x-car/2-li.w,pre.y-car/2+li.w,car+li.w,car+li.w,0,90);
            li.drawArcLine2(gb,prs.x-car/2-li.w,prs.y-car/2-li.w,car+li.w,car+li.w,270,90);
            li.drawArcLine2(gb,pre.x-car/2+li.w,prs.y-car/2-li.w,car+li.w,car+li.w,180,90);
            li.drawArcLine2(gb,pre.x-car/2+li.w,pre.y-car/2+li.w,car+li.w,car+li.w,90,90);
            
            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.drawArcLine2(gb,ppm.x-ccr,ppm.y-ccr,ccr*2,ccr*2,36,108);//コーナーアーク
            li.drawArcLine2(gb,ppmt.x-ccr,ppmt.y-ccr,ccr*2,ccr*2,219,103);
            
            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(pccc.x-gw/2,ps.y-gd,li.w,gd);
            gb.fillRect(pccc.x+gw/2,ps.y-gd,li.w,gd);
            gb.fillRect(pccc.x-gw/2,ps.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(pgelt.x,pgelt.y,li.w,55);
            gb.fillRect(pgert.x,pgelt.y,li.w,55);
            gb.fillRect(pgelt.x,pgelt.y+55,pgert.x-pgelt.x+li.w,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.fillRect(ppelt.x,ppelt.y,li.w,165);
            gb.fillRect(ppert.x,ppert.y,li.w,165);
            gb.fillRect(ppelt.x,pgelt.y+165,ppert.x-ppelt.x+li.w,li.w);
            
            gb.fillOval(ppm.x-cpr,ppm.y-cpr,pmr*2,pmr*2);//ペナルティーマーク
            gb.fillOval(ppmt.x-cpr,ppmt.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);
        }
                
        public void paint(Graphics g){
            g2.drawImage(ibuff,0,0,this);
            
            //g2.drawImage(ball.image,vp2.x,vp2.y,this);
            //g2.drawString("sss",vp2.x,vp2.y);
            g2.drawString(sk,pgelb.x-20,pe.y-10);
            moveCopy(g2,ball);
            moveCopy(g2,cf1);
            moveCopy(g2,cf2);
            moveCopy(g2,cb2);
            moveCopy(g2,cb3);
            moveCopy(g2,gk1);
            moveCopy(g2,gk2);
            //gb.setColor(SC);
            //gb.drawString("幅:"+ view.getExtentSize().getWidth(),pccc.x,pccc.y-100);
            //gb.drawString("高さ:"+ view.getExtentSize().getHeight(),pccc.x,pccc.y-150);
            //gb.setColor(GC);
            //gb.fillRect(pccc.x-10,pccc.y-300,100,100);
            //gb.setColor(SC);
            //gb.drawString("y:"+ view.getViewPosition().y,pccc.x,pccc.y-250);
            //gb.drawString("x:"+ view.getViewPosition().x,pccc.x,pccc.y-200);

            //movePaint(g2,ball);
            /*
            movePaint(g2,cf1);
            movePaint(g2,cf2);
            movePaint(g2,cb2);
            movePaint(g2,cb3);
            movePaint(g2,gk1);
            movePaint(g2,gk2);
            */
            g.drawImage(ib2,0,0,this);
        }
        
        void movePaint(Graphics g,MovingCharacter mc){
            g.setColor(mc.color);
            g.fillOval(mc.p.x-mc.r,mc.p.y-mc.r,mc.r*2,mc.r*2);
        }
        void moveCopy(Graphics g,MovingCharacter mc){
            g.drawImage(mc.image,mc.p.x-mc.r,mc.p.y-mc.r,this);
        }
        
    }
}