Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 >  掲示板 >  掲示板(タイマーがよくわかりません。)
閲覧数:260
掲示板(タイマーがよくわかりません。)
名前
匿名
題名 タイマーがよくわかりません。
質問内容

質問を評価する
(0ポイント)
以前MFCでテトリスを作ったことがあります。
その時の構成は以下のようなものでした。

(一部省略)
CテトリスView.cpp
void CテトリスView::OnDraw(CDC* pDC)
{
    //画面の描画
}

// CテトリスView メッセージ ハンドラ

void CテトリスView::OnInitialUpdate()
{
    //起動時にタイマーの設定
}

void CテトリスView::start()
{
    //初期設定
}

void CテトリスView::OnTimer(UINT_PTR nIDEvent)
{
    /*メインループ
    ブロック落下用関数の呼び出しや
    そろってるかどうかの判定など*/
}
void CテトリスView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    /*キーが押されたときの処理
    各種ブロック処理用関数呼び出しや
    ブロックの回転処理*/
}

bool CテトリスView::block_down()
{
    //ブロック落下処理
}

void CテトリスView::block_move(int move,int wall)
{
    //ブロック左右移動処理
}

今度はそれをJavaに移植したいと思ったのですが、まずタイマーの知識がほとんどありません。
そこでタイマー処理についてネットで調べ、TimerTask等を使えばいいと思いました。
そこで、現状以下のように作っています。
(一部省略)
Tetris.java
public class Tetris extends Frame{
    public void paint(Graphics g){
        //画面の描画
    }
    
    public void start(){
        /*ゲームの初期化
        タイマー開始*/
    }
}

Game.java
public class Game  extends TimerTask {
    public void run() {
        /*メインループ
        ブロック落下用関数の呼び出しや
        そろってるかどうかの判定など*/
    }
}

Move.java
public class Move implements KeyListener {
    public boolean down(){
        //ブロックの落下処理
    }
}

ところが、ブロックの落下が思うようにいっていません。
たとえばブロックの形が違っていたり、一部取り残されてしまっていたり。
そこで、原因を調べるべくデバッグのために画面のデータを出力させてみました。
paintメソッドとdownメソッドのとこで出力をさせてみたところ、downメソッドでの出力の途中でpaintメソッドの出力が割り込んできてしまいました。
別スレッド構成のようで割り込まれたようです。
ブロックの落下は今の位置を配列から削除し、座標を1つずらして配列に記憶させるという方法で行っています。
今回の出力の割り込みはその間で起こった出来事で、うまくいかない原因はその処理中に新たな命令が割り込んでしまって思いもしない処理をしてしまっているんだと思いました。
そこで、メインループを用意し、waitやThead.sleepでスリープを入れるのを試してみました。
すると、ブロックが一番下まで着た後に次のブロックが出ることにならずにエラーになってしまうまで描画が更新されませんでした。
何が問題なのでしょうか?
質問日時 2014-02-03 23:28:31
名前
匿名
回答内容

回答を評価する
(0ポイント)
TimerTaskはスレッドだよ。

run()の中でメインスレッドへ描画を依頼しなければ、描
画は適当なタイミングでしか発生しないが、どうなって
る?
回答日時 2014-02-04 00:09:01
名前
匿名
回答内容

回答を評価する
(0ポイント)
MFCのOnTimerでInvalidate(false);(再描画命令)していたところでJavaのrunメソッドでもtetris.repaint();させてます。
たとえば
落下してそろってなかったとき
落下してそろって消した後
などです。
回答日時 2014-02-04 00:49:16
名前
匿名
回答内容

回答を評価する
(0ポイント)
Geme.javaの内容をすべて貼ってみます。

package tetris;

import java.awt.Point;
import java.util.Random;
import java.util.TimerTask;

public class Game  extends TimerTask {
    Tetris tetris;
    int top;
    Point[] block2={new Point(),new Point(),new Point()};
    Point pos;
    boolean comp;
    int count;
    Random rnd = new Random();
    
    Move move;
    
    Game(Tetris t){
        tetris=t;
        for(int r=0;r<25;r++){
            for(int c=0;c<10;c++){
                tetris.space[r][c]=-1;
            }
        }
        tetris.color[0]=rnd.nextInt(7);
        tetris.color[1]=rnd.nextInt(7);
        pos=new Point(4,0);
        top=24;
        tetris.space[pos.y][pos.x]=tetris.color[0]+7;
        for(int n=0;n<3;n++){
            block2[n].x=tetris.block[tetris.color[0]][n].x;
            block2[n].y=tetris.block[tetris.color[0]][n].y;
            if((pos.y+block2[n].y)>=0){
                tetris.space[pos.y+block2[n].y][pos.x+block2[n].x]=tetris.color[0]+7;
            }
        }
        comp=false;
        count=0;
        if(tetris.mode==0){
            tetris.timer=-1;
        }
        else if(tetris.mode==1){
            tetris.timer=300;
        }
        else if(tetris.mode==2){
            tetris.timer=60;
        }
        tetris.time_count=0;
        tetris.game_point=0;
        tetris.game_state=2;
        tetris.pause=false;
        
        move=new Move(this);
        
        tetris.repaint();
        System.out.println("Start");
        for(int r=0;r<25;r++){
            for(int c=0;c<10;c++){
                System.out.print(tetris.space[r][c]+" ");
            }
            System.out.println();
        }
        System.out.println();
    }

    @Override
    public void run() {
        if(tetris.game_state==2 && (tetris.mode==0 || tetris.timer>0 || comp==true) && tetris.pause==false){
            if(tetris.mode!=0){
                tetris.timer=tetris.timer-1;
            }
            tetris.time_count=tetris.time_count+1;
            boolean check=false;
            if(comp==false){
                check=move.down();
            }
            if(check==false){
                for(int n=0;n<3;n++){
                    if(top>(pos.y+block2[n].y)){
                        top=pos.y+block2[n].y;
                    }
                }
                if(top>pos.y){
                    top=pos.y;
                }
                if(comp==false){
                    tetris.space[pos.y][pos.x]=tetris.color[0];
                    for(int n=0;n<3;n++){
                        tetris.space[pos.y+block2[n].y][pos.x+block2[n].x]=tetris.color[0];
                    }
                    boolean full;
                    for(int r=24;r>0;r--){
                        full=true;
                        for(int c=0;c<10;c++){
                            if(tetris.space[r][c]==-1){
                                full=false;
                                break;
                            }
                        }
                        if(full==true){
                            comp=true;
                            for(int c=0;c<10;c++){
                                tetris.space[r][c]=-1;
                            }
                            tetris.game_point=tetris.game_point+100;
                            if(tetris.mode==2){
                                tetris.timer=tetris.timer+10;
                                if(tetris.timer>300){
                                    tetris.timer=300;
                                }
                            }
                        }
                    }
                    tetris.repaint();
                }
                else{
                    count=count+1;
                    if(count==2){
                        comp=false;
                        count=0;
                    }
                    else{
                        boolean full;
                        for(int r=24;r>0;r--){
                            full=true;
                            while(full!=false && r>=top){
                                for(int c=0;c<10;c++){
                                    if(tetris.space[r][c]>-1){
                                        full=false;
                                        break;
                                    }
                                }
                                if(full==true){
                                    top=top+1;
                                    for(int r2=r-1;r2>0;r2--){
                                        for(int c=0;c<10;c++){
                                            tetris.space[r2+1][c]=tetris.space[r2][c];
                                        }
                                    }
                                }
                            }
                        }
                        tetris.repaint();
                    }
                }
                if(comp==false && count==0){
                    tetris.color[0]=tetris.color[1];
                    tetris.color[1]=rnd.nextInt(7);
                    pos.x=4;
                    pos.y=0;
                    for(int n=0;n<3;n++){
                        block2[n].x=tetris.block[tetris.color[0]][n].x;
                        block2[n].y=tetris.block[tetris.color[0]][n].y;
                        if((pos.y+block2[n].y)>=0){
                            if(tetris.space[pos.y+block2[n].y+1][pos.x+block2[n].x]!=-1){
                                tetris.game_state=3;
                            }
                            tetris.space[pos.y+block2[n].y][pos.x+block2[n].x]=tetris.color[0]+7;
                        }
                    }
                    if(tetris.space[pos.y][pos.x]!=-1){
                        tetris.game_state=3;
                    }
                    tetris.space[pos.y][pos.x]=tetris.color[0]+7;
                    tetris.repaint();
                }
            }
        }
        else if(tetris.pause==true){
            tetris.repaint();
        }
        else if(tetris.game_state<=4 && tetris.mode>0 && tetris.timer>0){
            tetris.game_state=tetris.game_state+1;
            tetris.repaint();
        }
        else if(tetris.game_state<=6 && (tetris.timer==0 || tetris.mode==0)){
            if(tetris.game_state==2 || tetris.game_state==3){
                tetris.game_state=6;
            }
            tetris.game_state=tetris.game_state+1;
            tetris.repaint();
        }
    }
}
回答日時 2014-02-04 00:52:48
名前
回答内容

回答を評価する
(0ポイント)
頑張ってるようですが、AWT はあまりに古いので Swing を
学んだらいかがでしょう。
Swing にはこういうタイマーがあります。参考になるかな?
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Animation {
  public static void main(String args[]) throws Exception {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    AnimationPanel animation = new AnimationPanel();
    frame.add(animation);
    frame.pack();
    frame.setVisible(true);
    animation.start();
  }
  static class AnimationPanel extends JPanel implements ActionListener {
    private Timer timer;
    private int degree = 0;
    AnimationPanel() {
      timer = new Timer(100, this);
      setPreferredSize(new Dimension(300, 300));
    }
    void start() {
      timer.start();
    }
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      double rad = Math.toRadians(degree);
      int x = 100 + (int) (Math.sin(rad) * 50);
      int y = 100 - (int) (Math.cos(rad) * 50);
      g.fillOval(x, y, 50, 50);
    }
    public void actionPerformed(ActionEvent e) {
      degree = (degree + 10) % 360;
      repaint();
    }
  }
}
回答日時 2014-02-04 02:39:47
名前
匿名
回答内容

回答を評価する
(0ポイント)
>> 仙人

いまなら GUIプログラムつくるなら JavaFX じゃ?
回答日時 2014-02-04 12:36:40
名前
匿名
回答内容

回答を評価する
(0ポイント)
JavaFXって標準ランタイムに入ったっけ?
回答日時 2014-02-05 07:20:25
名前
匿名
回答内容

回答を評価する
(0ポイント)
Java7 から含まれている
回答日時 2014-02-05 17:20:23
名前
匿名
回答内容

回答を評価する
(0ポイント)
仙人さんのプログラムを参考にswingのTimerを使ってみました。
割り込みは感じませんでしたが、落下の書き方を間違えてるのかブロックの形がおかしなことになっていました。
とりあえずここからはまた自分で頑張ってみようと思います。
ありがとうございました。
回答日時 2014-02-05 17:58:28
名前
匿名
回答内容

回答を評価する
(0ポイント)
ブロックが変な形なのはブロックを削除・セットする座標を間違えているからでした。
回答日時 2014-02-05 18:29:43
回答内容を入力し、「確認」ボタンをクリックしてください。
ログインしていません。ログインしなくても回答はできますが、ログインすると、質問・回答の管理、更新があった場合のメールでの通知を受けることができます。 ユーザIDをお持ちでない方は「ID登録」からユーザIDの登録を行ってください。
氏名 匿名
回答内容
 



このページのトップへ
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道_CopyrightJavaの道