時間を測る

クリアまでの時間

解決策その2の続き。

クリアまでの時間を競うというのもゲームのよくあるパターンです。やってみましょう

moveDisk

System.currentTimeMillis()は現在時をミリ秒単位で知らせてくれます。戻り値はintでなくlongです。(実際には1970年1月1日からの現在までの経過時間を返します)

ゲームの最初に

long time0 = System.currentTimeMillis();

として時刻を記録し、ゲームの終わりに、

long time1 = System.currentTimeMillis();

として時刻を再度記録します。

time1-time0

は、かかった時間をミリ秒単位で計測したものになります。つまり16000となれば16秒ということです。

普通は1000で割って秒に直します。

(time1-time0)/1000

longとintの計算なので整数に切り捨てられます。

少数点以下も表現したいときは次のようにします。

(time1-time0)/1000.0

ボタンの表記

いまさらですが、green, blue は斜めの線にしておくと跳ね返りの方向が分かっていいでしょう。全角のバックスラッシュは「きごう」で変換すると出てきます。"/"は「すらっしゅ」を変換してもOKです。

rbtn = new JButton("start");
gbtn = new JButton("\");
bbtn = new JButton("/");

これまでの MoveDisk8

ファイル名 MoveDisk8.java

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;

public class MoveDisk8 extends JFrame implements ActionListener{
    JButton rbtn;
    JButton gbtn;
    JButton bbtn;
    MyPanel mypnl;
    JPanel  btnpnl;

    BufferedImage buffimg;
    Graphics bfg;

    int gctgrn = 0;
    int gctblu = 0;
    int clct = 0;
    int bnct = 0;
    int tmax = 2;
    Target[] ts = new Target[tmax];

    //constructor
    public MoveDisk8() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle("MoveDisk");
        mypnl = new MyPanel();
        rbtn = new JButton("start");
        gbtn = new JButton("\");
        bbtn = new JButton("/");
        btnpnl = new JPanel();
        btnpnl.setLayout(new GridLayout(1,3,0,0));
        btnpnl.add(rbtn);
        btnpnl.add(gbtn);
        btnpnl.add(bbtn);
        setLayout(new BorderLayout());
        add(mypnl, BorderLayout.CENTER);
        add(btnpnl,BorderLayout.SOUTH);
        rbtn.addActionListener(this);
        gbtn.addActionListener(this);
        bbtn.addActionListener(this);
        pack();
        setVisible(true);
        //BufferedImageを作るのはpaintComponentに移した
    }
    //イベント処理
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == rbtn) {
            clct=0;
            gctblu=0;
            gctgrn=0;
            bnct =0;
            rbtn.setEnabled(false);
            rbtn.setText("busy");
            Thread thread = new moveDisk(mypnl,buffimg);
            thread.start();
        }
        if (e.getSource() == gbtn) {
            gctgrn++;
        }
        if (e.getSource() == bbtn) {
            gctblu++;
        }
    }
    public static void main(String[] args){
        MoveDisk8 myframe = new MoveDisk8();
    }
    
    //内部クラス
    public class MyPanel extends JPanel{
        Color bc= new Color(255,255,191);  //背景の色
        Color c = new Color(0,0,0);  //楕円の色
        boolean firsttime = true; 
        public MyPanel(){
            setBackground(new Color(255,255,191));
            setPreferredSize(new Dimension(400,400));
                //panel側で大きさを指定する
        }
        @Override
        public void paintComponent(Graphics myg){
            super.paintComponent(myg);
            if (firsttime){  //1回目の描画でBufferedImageをつくる
                buffimg = new BufferedImage(
                  getSize().width,
                  getSize().height,
                  BufferedImage.TYPE_INT_RGB);
                bfg = buffimg.createGraphics();
                bfg.setColor(bc);
                bfg.fillRect(0, 0, getSize().width, getSize().height);
                firsttime = false;  //次回はやらない
            }
            myg.drawImage(buffimg, 0, 0
              ,getSize().width, getSize().height,this);
              //getSize().widthはMyPanelのインスタンスの幅
        }
        //円を動かすメソッド→下記内部クラスに

    }// end of class MyPanel

    //円を動かすクラス
    class moveDisk extends Thread{
        MyPanel pnl;
        BufferedImage image;
        int x ;
        int y ;
        int lx =0;
        int ly =0;
        int d = 10;
        int dx = 5;
        int dy = 0;
        int stime = 50; //sleeptime dx=10:stime=100
        int ctgrn;
        int ctblu;
        
        //constructor
        public moveDisk(MyPanel pn, BufferedImage im) {
            this.pnl   = pn;
            this.image = im;
            y = (int)(image.getHeight()*Math.random());
            int w = image.getWidth();
            int h = image.getHeight();
            for(int i=0 ; tmax>i ; i++){
                ts[i] = new Target(w,h);
            }
            ctgrn = gctgrn;
            ctblu = gctblu;
        }
        
        @Override
        public void run() {
            Graphics thg = image.createGraphics();
            Color bc= new Color(255,255,191);  //背景の色
            thg.setColor(bc);
            thg.fillRect(0,0,image.getWidth(),image.getHeight());

            thg.setColor(Color.blue);
            for(int i=0 ; tmax>i ; i++){
                if (ts[i].cleared) continue;
                thg.fillOval(ts[i].x-d/2,ts[i].y-d/2,d,d);            
            }
            while ( ! rbtn.isEnabled()  ){
                if (gctgrn != ctgrn) {
                    int tmp = dx;
                    dx = dy;
                    dy = tmp;
                    ctgrn = gctgrn;
                }
                if (gctblu != ctblu) {
                    int tmp = dy;
                    dy = -dx;
                    dx = -tmp;
                    ctblu = gctblu;
                }
                thg.setColor(bc);
                thg.fillOval(lx-d/2,ly-d/2,d,d);
                for(int i=0 ; tmax>i ; i++){
                    if (ts[i].cleared) continue;
                    if (d/2>Math.abs(ts[i].x-x)){
                        if (d/2>Math.abs(ts[i].y-y)){
                            ts[i].cleared = true;
                            thg.fillOval(ts[i].x-d/2,ts[i].y-d/2,d,d);
                            clct++;
                        }
                    }
                }
                thg.setColor(Color.red);
                thg.fillOval(x-d/2,y-d/2,d,d);            
                if (clct==tmax) {
                    int sx = x+8;
                    if (sx>image.getWidth()-60) sx=image.getWidth()-60;
                    int sy = y+16;
                    if (sy>image.getHeight()-60) sy=image.getHeight()-60;
                    thg.drawString("Cleared",sx,sy); 
                    thg.drawString("Click  "+(gctgrn+gctblu),sx,sy+16); 
                    thg.drawString("Bounce "+bnct,sx,sy+16*2); 
                    rbtn.setEnabled(true);
                    rbtn.setText("replay");
                }
                pnl.repaint();
                lx = x;
                ly = y;
                x += dx;
                y += dy;
                if (x >image.getWidth()){
                    x  = 2*image.getWidth()-x;
                    dx = -dx;
                }
                if (0 > x){
                    x  = -x;
                    dx = -dx;
                } 
                if (y >image.getHeight()){
                    y  = 2*image.getHeight()-y;
                    dy = -dy;
                }
                if (0 > y){
                    y  = -y;
                    dy = -dy;
                }
                //(stime÷1000 秒)停止
                try {
                    Thread.sleep(stime);
                }
                catch(InterruptedException ex) {
                    System.err.println(ex);
                }
            }//end of while
        }//end of run
    }//end of class moveDisk
    class Target{
        int x;   //x位置
        int y;   //y位置
        boolean cleared = false;   //クリアされたかどうか
        public Target(int w,int h){
            x = (int)(w*Math.random());
            y = (int)(h*Math.random());
        }
    }//end of class Target
}

主な変更点

課題

1.

MoveDisk8.javaに書き加えます。

1回のゲームが終わるたびに Click 3 などとクリック数が表示されています

その下の bouns 0 は壁の跳ね返り数を数えるためのものですが、これはまだ実装されていません。跳ね返り数は bnct という変数を使うように、宣言して初期値は入っています。跳ね返るところに bnct++ などと加えて正しい数が表示されるようにしなさい。

また、上記を参考にクリアにかかった秒数も表示するようにしなさい。

ファイル名 MoveDisk9.java

もくじ

聖愛高等学校
http://www.seiai.ed.jp/
Last Modified