質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.10%

当たり判定の処理を一時的に止めるにはどうしたらいいですか?

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,829

score 27

//mysocoreが○○より高く、レベルが○ならレベルが上昇
if((Score.myscore > 160)&&(Level.level==0)){

Level.addLevel();

}

//myscoreが○○より高く、○○より低いか等しい場合、さらにレベルが○ならばクリアの文字を表示する
if((Score.myscore<=180)&&(Score.myscore> 160)&&(Level.level==1)){

title.drawGameclear(gBuf);

}
質問を変えます
上のプログラムは、クラスMyCanvasのプログラムの一部です。レベル上昇の条件と、クリアという文字を表示する処理をしています。

void gameMain()
{
//ゲームオーバーか?
if (objectpool.isGameover())
{
//ゲームオーバー文字を表示
title.drawGameover(gBuf);

これが、ゲームオーバーの文字を表示するプログラムです
ゲームオーバーかどうかを返すプログラムはObjectPoolというクラスにあります

ゲームオーバーになってSPACEキーを押すと、タイトル画面に戻る仕組みです

レベル上昇して、しばらく当たり判定のプログラムを停止させたいです
そうすれば、レベル上昇と同時にゲームオーバーになることは防げると思います

しかし、当たり判定はゲームオーバーと同じくObjectPoolで書かれていて、どうやってMyCanvasで当たり判定のプログラムを停止させる処理を作ればいいのかがわかりません。レベルが上がって、しばらく処理を停止させるにはどうしたらいいでしょうか?

それか、決められた時間の間だけ、文字を表示するにはどうしたらいいですか?

この下が、MyCanvasのすべてのプログラムです
なお、このプログラムはサンプルコードとして配布していたものを私が改造していっている段階です

もともと、このプログラムにはレベルが上がるためのクリア条件というものがありませんでした
500フレーム経過すると、自然とレベルが上がり、ひたすらhiscoreを競うものだったようです。
上記のものは、私がレベルを一つずつ上げるために追加したものです。

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;

/**
*描画先コンポーネントクラス(Canvasを継承)<p>
*メインループもここ
*/
public class MyCanvas extends Canvas implements Runnable{
    ObjectPool objectpool;
    KeyInput keyinput;
    Image imgBuf;
    Graphics gBuf;
    Random random;
    Title title;
    Score score;



    /**
     * シーン管理変数<p>
     * 0:タイトル画面 1:ゲームのメイン画面
     */
    public int scene;
    static final int SCENE_TITLE = 0;
    static final int SCENE_GAMEMAIN = 1;


    public boolean gameover;
    int counter;


    //押されている
    static final int SHOT_PRESSED = 1;
    //今押されたばかり
    static final int SHOT_DOWN = 2;
    int shotkey_state;


    /**
     * コンストラクタ
     */
    MyCanvas()
    {
        //キーリスナ実装
        keyinput = new KeyInput();
        addKeyListener(keyinput);
        setFocusable(true);                //フォーカスを取得できるようにする。
        random = new Random();            //乱数オブジェクト
        title = new Title();
        score = new Score();
    }

    /**
     * 初期化処理<p>
     * アプリケーションの開始時、またはリスタート時に呼ばれ、<br>
     * ゲーム内で使われる変数の初期化を行う。
     */
    public void init()
    {
        objectpool = new ObjectPool();
        Score.loadScore();

        //シーンはタイトル画面
        scene = SCENE_TITLE;
        gameover = false;
        //レベルの初期化
        Level.initLevel();
        //スコアの初期化
        Score.initScore();

        Title.initTitle();
    }

    /**
     * 外部からスレッドを初期化する。
     */
    public void initThread()
    {
        Thread thread = new Thread(this);
        thread.start();
    }

    /**
     * 描画処理<p>
     * repaint()の際に呼ばれて、
     * オフスクリーンバッファから画像をコピーし表示する。
     * @param g 描画先グラフィックハンドル
     */
    public void paint(Graphics g)
    {
        //オフスクリーンバッファの内容を自分にコピー
        g.drawImage(imgBuf, 0, 0, this);
    }

    /**
     * メインループ
     */
    public void run()
    {
        //オフスクリーンバッファ作成
        imgBuf = createImage(500, 500);
        gBuf = imgBuf.getGraphics();

        for(counter = 0; ; counter++)
        {
            shotkey_state = keyinput.checkShotKey();

            //バッファをクリア
            gBuf.setColor(Color.white);
            gBuf.fillRect(0, 0, 500, 500);

            //シーン遷移用の変数で分岐
            switch (scene)
            {
                //タイトル画面
                case 0:
                    title.drawTitle(gBuf);
                    score.drawScore(gBuf);
                    score.drawHiScore(gBuf);

                    //スペースキーが押された
                    if (shotkey_state == SHOT_DOWN)
                    {
                        //メイン画面に行く
                        scene = SCENE_GAMEMAIN;
                    }
                    break;

                //ゲームのメイン画面
                case 1:
                    gameMain();
                    break;
            }

            //再描画を要求
            repaint();

            try{
                Thread.sleep(20);                //ループのウェイト
            }
            catch(InterruptedException e)
            {}
        }
    }

    /**
     * 画面をいちいちクリアしないようにするため、
     * updateメソッドをオーバーライドする。
     * @param g 更新先グラフィックハンドル
     */
    public void update(Graphics g)
    {
        paint(g);
    }

    /**
     * ゲーム画面のメイン処理
     */
    void gameMain()
    {
        //ゲームオーバーか?
        if (objectpool.isGameover())
        {
            //ゲームオーバー文字を表示
            title.drawGameover(gBuf);

            if (shotkey_state == SHOT_DOWN)
            {
                //スコアをハイスコアに適用、必要があればセーブ
                Score.compareScore();

                //ゲームを再初期化
                init();
            }
        }        

        //衝突の判定
        objectpool.getColision();
        objectpool.movePlayer(keyinput);

        //敵出現間隔:レベルに応じて短くなる
        if (counter % (100 - Level.getLevel() * 10) == 0)
        {
            ObjectPool.newEnemy(100 + random.nextInt(300), 0);
        }

        //500フレーム経過するとレベルが上昇
        if ((Score.myscore >100)&&(Level.getLevel() == 0)){
            Level.addLevel();

        }
        if ((150>Score.myscore)&&(Score.myscore >100)&&(Level.getLevel() == 1)){

            title.drawGameclear(gBuf);


        }


        if ((Score.myscore >200)&&(Level.getLevel() == 1)){
            Level.addLevel();
        }

        if ((Score.myscore >300)&&(Level.getLevel() == 2)){
            Level.addLevel();
        }

        if ((Score.myscore >400)&&(Level.getLevel() == 3)){
            Level.addLevel();
        }

        if ((Score.myscore >500)&&(Level.getLevel() == 4)){
            Level.addLevel();
        }

        if((Score.myscore >600)&&(Level.getLevel() == 5)){
            Level.addLevel();
        }

        if((Score.myscore >700)&&(Level.getLevel() == 6)){
            Level.addLevel();
        }

        if((Score.myscore >800)&&(Level.getLevel() == 7)){
            Level.addLevel();
        }

        //スペースキーが押されており、かつカウンタが3の倍数なら弾を撃つ(等間隔に弾を撃てる)
        if ((shotkey_state == SHOT_PRESSED)&&(counter % 3 == 0))
        {
            objectpool.shotPlayer();
        }

        //ゲームオブジェクトの一括描画処理
        objectpool.drawAll(gBuf);
        //スコア描画
        score.drawScore(gBuf);
        score.drawHiScore(gBuf);

    }
}


`

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • coco_bauer

    2016/11/22 12:42

    「レベルが上昇」、「クリアと表示」、「ゲームオーバー」という順に起こる訳ですから、クリアを表示しないというのは無理(その時にはゲームオーバーになっていないので)。クリアの条件が整っていたらクリアの表示を削除して、その後にゲームオーバーの表示をするという方針が良さそうに思えます。

    キャンセル

  • ishi9

    2016/11/22 12:54 編集

    ゲームクリアの演出中にゲームオーバーになる事があるゲームって仕様的にどうなの?(普通のゲームは一旦ストップにしたり無敵にしたりしませんか?)とは思いますが、それが仕様だというのなら、ゲームクリアの演出を中断できるようにしておくのがいいかもしれませんね。でも一番に考えるべきはゲームの仕様ry

    キャンセル

  • Y.H.

    2016/12/06 12:18

    マルチポスト https://teratail.com/questions/57790

    キャンセル

  • 退会済みユーザー

    2016/12/06 12:28

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 3

checkベストアンサー

0

ざっくりですが、一例を書いてみます。
まずTitleにIsGameclearという関数を追加してください。
そしてこの関数はtitle.drawGameclearが呼ばれるとtrueになり、
title.drawGameclearが終わるとfalseが返るように実装してください。
(Title内にフラグ用のbool変数を用意しておけばそう難しくはないと思います)

後は下記のように書けばゲームクリア演出中かわかるようになるはずです。

if (title.IsGameclear())
{
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/25 11:29

    isGameoverと同じような感じというと、
    return player.active;と入力すると考えていいんでしょうか?

    それとも、レベルが上がる条件のようなものを書き込んだ方がいいのでしょうか?

    キャンセル

  • 2016/11/25 11:47 編集

    すいません、こちらが提案しているのがどういうものなのかちゃんと説明できていませんでした。

    まず質問文のタイトルの通り
    「当たり判定の処理を一時的に止めるにはどうしたらいいですか?」
    これがずっと当たり判定の処理を止めたいであれば

    if (false) // 絶対に通らない
    {
    objectpool.getColision();
    }

    と書けば多分実現できますよね?(まぁ中の処理を知らないので変なバグが出るのかもしれませんが)

    なので重要なのは「一時的に」の部分です。
    この「一時的に」を私は「ゲームクリアの演出中」と解釈しました。
    つまりゲームクリアの文字が描画されている間です。
    その区間がわかるようになるためにIsGameclear()という関数を作ってみては?という提案をしました。
    なのでIsGameclear()関数はゲームクリアの文字列が出ている間だけtrueを返すように作らないといけません。
    この中身を質問者様の言うとおり「return player.active;」と書いたらどうなるでしょうか?
    これは「ゲームクリアの文字列が出ている間だけ」という条件を満たしているでしょうか?

    そこで一つ前の私の返答に戻ってください。
    私がやってほしいと思っていたのは「ゲームクリアの文字が出ている間はtrue」になる処理です。

    ここまで見てちょっと何言ってんのかよくわかんないという場合は、
    すいません。多分、私のアプローチが間違っていたのだと思いますのでこの回答の事は忘れてください。

    キャンセル

  • 2016/11/25 11:58

    ・・・あ
    すいません、やっぱり私が完全に勘違いしていましたね。
    そもそも文字列を一定時間表示する方法自体も質問対象ですね。

    やっぱり一旦この回答の事は置いておいてください

    キャンセル

0

ソースコードが無いので想像ですが、おそらく、スレッドの中で
・判定1    ->    描画1
・判定2    ->    描画2
・判定3    ->    描画3

と繰り返してしているので、取消できないか?という質問に至っている?と想像しました。

ゆえに、順次描画しているところを、ちょっと我慢して、
・判定1    ->    描画1のフラグを立てる
・判定2    ->    描画2のフラグを立てる
・判定3    ->    描画3のフラグを立てる
・全ての判定が終わったら、描画1・2・3のフラグを判定し、優先して描きたい描画だけ行う。

ということではいかがですか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/06 13:14

    特に難しいことを述べているわけではありません。
    privateな変数、(仮名)levelupTimeを準備し、 Level.addLevel();の中で、
    levelupTime = counter;とすれば、LVが上がったタイミングがわかるので、
    if (levelupTime + 10 < counter) { //1スリープ20ms なので、200msは衝突しない
    objectpool.getColision();
    }
    といった具合です。ニューゲームの際にはlevelupTimeをクリアすることをお忘れなく。

    キャンセル

  • 2016/12/06 16:15

    //500フレーム経過するとレベルが上昇
    if ((Score.myscore >100)&&(Level.getLevel() == 0)){
    Level.addLevel();

    }
    if ((150>Score.myscore)&&(Score.myscore >100)&&(Level.getLevel() == 1)){

    title.drawGameclear(gBuf);

    こんな感じのプログラムですが、変更する必要はあるでしょうか。

    キャンセル

  • 2016/12/06 16:26

    >こんな感じのプログラムですが、変更する必要はあるでしょうか。

    ちょっと質問の意図がよく見えませんが、変更しなければ、
    「レベル上昇による一時的な判定の停止」が行えないだけです。
    そして、その必要性は製作者たる貴方にしか判断できません。

    今一度、じっくりと元サンプルソースを読み、一体どのような動作になっているのか、
    確認の上で、どのように改造するか、再検討することをお勧めします。

    キャンセル

0

まず皆さんも指摘しているとおりにクリアの最中にゲームオーバーになるというのがよくわかりませんが…
Javaの動きとして回答したいと思います。

まず前提として、処理を動いている途中に消す、というのは意図しないタイミングで処理が中断してしまう可能性があるのでおすすめしません。
また、スレッドの一時停止ブレークポイントのことでしょうか?
それでしたらこれはデバッグ時に使用するものであり、プログラムの動きではないので、結局動かすときに残ってしまうことになるかと思います。
途中で処理を抜ける、ならわかりますが。

ので、初期化処理を挟んであげるのがスタンダードかと思われます。
以下のように設計し直してみてください。

用意するクラス

  1. レベルアップクラス
  2. クリアと表示させるクラス
  3. ゲームオーバーと表示させるクラス
  4. 初期表示(クリアともゲームオーバーとも表示されない)クラス
  5. 実行メインクラス

※初期表示クラスの補足
表示されている文字が何であろうと、初期化し大元の表示に戻すクラス

処理を行うクラス(メインクラス){

  処理を行うメソッド{
    条件1(レベルアップしたか){
     レベルアップ処理の呼び出し
     クリア表示処理の呼び出し
     初期表示処理の呼び出し
   }
  条件2(ゲームオーバーになるか){
         ゲームオーバー処理の呼び出し
     (必要であれば初期表示処理)
     }
  }
}

実際どのようにコードを書いているかわかりませんので言葉での説明になりましたがこのような感じになるかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/06 16:09

    レベルアップしたかや、ゲームオーバーになるかというプログラムはどういう風に書けばいいのでしょうか。
    レベルアップの方は、何となくできなくもないですが、ゲームオーバーになるかという条件のプログラムはどうすればいいのかがわかりません。
    あと、私の作っているこのゲームは一発でも敵の攻撃を受けると死にます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る