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

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

ただいまの
回答率

91.04%

  • Java

    11818questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1434questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

パッドの導入/制御/判定

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 207

eamons

score 4

Padクラスのmoveメソッド内でのパッドと壁およびボールとの衝突判定処理を追加し、以下2つのの条件のようにしたいのですが、ボールの衝突判定のif文はどのようにして、他をどのように変えたらいいでしょうか?
•パッドを3分割し,ボールが当たった位置で反射の仕方が変わる
•ボールが下の壁にあたったらゲームオーバーとするか,ボールの数を一つ減らしてボールの数がゼロになったらゲームオーバー

smileyball2.png
blockback.png

// BlockMain.java
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class BlockMain extends JFrame{
public static void main(String[] args) {
BlockMain w = new BlockMain();
w.setResizable(false);
w.setTitle("ブロック崩し?");
w.setSize(505, 540); //Window のサイズをセット
BlockCanvas bc = new BlockCanvas(500,500);
w.getContentPane().add(bc);
w.setVisible(true); //表示する
}

}
―――――――――――――――――――――――――――――――――――――――――――――
// BlockCanvas.java
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class BlockCanvas extends Canvas implements Runnable {
Ball ball = new Ball();
Pad pad = new Pad();
Image background = getToolkit().getImage("blockback.png");
Thread thread; // スレッドを使うためのインスタンスを宣言
Dimension dim; // 描画領域の大きさ

public BlockCanvas(int w, int h) {
dim = new Dimension(w, h);
setPreferredSize(dim);
// 描画領域の大きさを調べる
thread = new Thread(this); // スレッドを生成
thread.start(); // スレッドを開始 (run()が呼ばれる)
}

@Override
public void paint(Graphics g) {
super.paint(g);
// アンチエイリアス
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

Dimension dim = getSize(); // 描画領域の大きさを調べる
Image m_image = createImage(dim.width, dim.height);// 裏画面の画像イメージ
Graphics m_g = m_image.getGraphics(); // 裏画面に付随するグラフィックスオブジェクト
m_g.drawImage(background, 0, 0, dim.width, dim.height, null);

ball.draw(m_g, dim);

g.drawImage(m_image, 0, 0, this); // 裏画面を表画面にコピー
pad.draw(g, dim);
}
public void run() {
try {
while (true) {
Thread.sleep(50); 
// ballはEDTでの再描画時に参照する情報なので、
// 同期をとらずに更新するなら
// runLaterを通じてEDTで実行するようにするのが無難
SwingUtilities.invokeLater(() -> {
ball.move(dim);
pad.move(dim, ball);
repaint(); // 再描画要求
});
}
} catch (InterruptedException e) {
// sleep中に割り込まれたらこの例外が起きるので行儀よくループを終了する.
// 割り込まれているにもかかわらず強情にループを継続するのは良くない。
}
}
// ダブルバッファリング
public class Ball {
Image ballImage = getToolkit().getImage("smileyball2.png");
int x = 10, y = 100; // ボール中心の座標
int vx = 4, vy = 5; // ボールの速度ベクトル

static final double RADIUS = 0.02; // ボールの半径はウインドウの2%
int radius; // ボールの半径

public void draw(Graphics g, Dimension dim) {
radius = (int)(RADIUS * dim.width);
g.drawImage(ballImage, x - radius, y - radius, radius + radius, radius + radius, null);
}

public void move(Dimension dimension) {
x += vx;
if (x <  radius) {
x =  radius;
vx = -vx;
} else if (x > dimension.width-radius) {
// 左または右に当たったらx方向速度の符号を反転させる
x = dimension.width- radius;
vx = -vx;
}
y += vy;
if (y <  radius) {
y = radius;
vy = -vy;
} else if (y > dimension.height- radius) {
y = dimension.height- radius;
vy = -vy;
}
}
}
public class Pad implements MouseListener {
int x = 100, y = 380; // パッドの中心座標
int vx = 0; // パッドの速度ベクトル
static final double WIDTH = 0.25; // パッド幅のウインドウ幅に対する比率
static final double HEIGHT = 0.95; // パッド位置のy座標のウインドウ高さに対する比率
int width, height; // パッドの幅,高さ

public void draw(Graphics m_g, Dimension dim) {
width = (int)(WIDTH * dim.width);
height = width / 8;
y = (int)(HEIGHT * dim.height);
m_g.fillRect(x - width / 2, y - height / 2, width, height);
}

public void move(Dimension dim, Ball ball) {
x += vx; // パッドの移動
if (x <  width/2) {
x =  width/2;
vx = -vx;
} else if (x > dim.width-width/2) {
// 左または右に当たったらx方向速度の符号を反転させる
x = dim.width- width/2;
vx = -vx;
} // 左右の壁との衝突判定を行う.当たった場合は壁に接した位置で止める.
if() // ボールとの衝突判定 
}

@Override
public void mouseClicked(MouseEvent me) {        }

@Override
public void mouseEntered(MouseEvent me) {        }

@Override
public void mouseExited(MouseEvent me) {        }

@Override
public void mousePressed(MouseEvent me) {
int a = 8;
if (me.getButton() == MouseEvent.BUTTON1) {// 左ボタンクリック?
vx = -a; // 左向きに移動させる
} else {
vx =  a; // 右向きに移動させる
}
}

@Override
public void mouseReleased(MouseEvent me) {
vx = 0; // パッドを止める
}
}
}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+3

ボールの衝突判定のif文

コードを書いたら、丸投げになりそうなので、
衝突判定の考え方だけ言いますよ。


パッドを3分割し,ボールが当たった位置により反射の仕方が変わるようにせよ

この仕様分割してみます。

  1. パッドを3分割
  2. ボールが当たった位置
  3. 反射の仕方が変わる

さらに、具体化します。

  1. パッドが占めているX座標を三分割
  2. ボールがパッドとXY座標で衝突する位置
  3. ボールの(Xと)Y方向の速度を変える

そして、処理の順序を考慮して、並べ替えます。

  1. ボールとパッドのXY座標を(衝突)判定する
  2. パッドが占めているX座標によって三分岐する
  3. ボールの(Xと)Y方向の速度を三種に変える

後は、IF文などを使って、上記を実装するだけです。


ボールが下の壁にあたったらゲームオーバーとするか

これは、左右の壁の衝突判定を応用するだけです。
下の壁の衝突判定で、ゲームオーバーの処理に飛ばす(メソッドを呼ぶとか)。
または、ボールの数が減るなら、そういう処理を書きます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/15 22:53

    考え方を参考に、しっかり理解してできました。わかりやすいヒントをありがとうございました。

    キャンセル

+3

PadやBallはBlockCanvasの内部クラス(innter class)なので各々のメソッド内ではBlockCanvasの下記のインスタンスフィールドにアクセスできます。

Ball ball = new Ball();
Pad pad = new Pad();

Padのメソッド内からはballにもアクセスできる(つまりballの位置にもアクセスできる)のでそれにより衝突判定に必要な情報を得ることができます。同様にBallのメソッドからpadにアクセスできますので、衝突判定はBallのmoveでもできます。どちらがよいかは実際に書いてみてご自分で判断する方が学習効果が高いと思います。

なお衝突判定は「BallとPadの垂直方向の位置関係、水平方向の位置関係」で決まりますが、Ball, Padいずれも移動速度が1以上なので、ある程度の幅を持たせて判定する必要があることに注意してください。またBallは斜めに移動しているので、例えば

水平方向の位置(x):100、速度:5
垂直方向の位置(y):200、速度:4

だとすれば次の瞬間にはx=105,y=204になるわけですが、もしPadの垂直位置y=202だとしたらその位置でのBallの位置はx=102.5になるといったことも考慮する必要があろうかと思います。


余談ですが・・・
awtのコンポーネントCanvasはダブルバッファリング機構を持ってません。しかしswingのコンポーネントはデフォルトでダブルバッファんリングを持っています。おそらくWindowsでもMacintoshでもLinuxでもデフォルトでダブルバッファんリングが有効になっている気がします。このためBlockCanvasをCanvas(=awtコンポーネント)からJComponent(=swingコンポーネント)に変えるだけで、現在実装しているダブルバッファリングは必要なくなり単純にJComponent#paintComponentでそのまま描画しても画面のちらつきはなくなります。
課題の条件に「自前でダブルバッファリングせよ」というのが入っているなら今のままにする必要がありますが、そうでないならJComponentの派生クラスとした方がプログラムがすっきりします。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/15 22:56

    読んでしっかり理解を深めることができました。ありがとうございました。

    キャンセル

+3

質問文のコードをデバック実行して気づいた点を指摘します。

1,PadクラスはMouseListenerを実装してますが、BlockCanvasクラスのコンストラクタ内でリスナーの登録(addMouseListener)を行ってません。そのため、マウスクリックを行ってもマウスイベントが発火しないです。

2,MouseListenerの空実装(mouseClicked、mouseEntered、mouseExited)を行う場合は、
マウスアダプタークラスを使用する方が実装しているものが分かりやすくなります。

public class Pad implements MouseListener
public class Pad extends javax.swing.event.MouseInputAdapter


□参考情報
javax.swing.event.MouseInputAdapter

3,定期的に再描画をコンポーネントに伝えたい時は、javax.swing.Timerが使えます。

import javax.swing.Timer;

private final Timer paint_Timer;
public BlockCanvas(int w, int h) {
    dim = new Dimension(w, h);
    setPreferredSize(dim);
  // マウスイベントハンドラーを登録
    this.addMouseListener(pad);
    int delay = 50; // milliseconds
    paint_Timer = new Timer(delay, (evt) -> {
        ball.move(dim);
        pad.move(dim, ball);
        repaint();
    });
}
// startメソッドを追加
public void start() {
    paint_Timer.start();
}


BlockMain#mainメソッド

w.setVisible(true); //表示する
bc.start();

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/15 22:57

    読んでしっかり理解を深めることができました。ありがとうございました。

    キャンセル

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

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

関連した質問

  • 解決済

    コードの改良余地について。

    下記にあるコードは 四角形を9個作り、点が存在する四角形を青で塗り潰すコードなんですが、 一応これで思った通りに実行されます。 ですが、オブジェクト指向ではないような気がします。

  • 解決済

    java スクロールバーの配置について

    画像を傾けて表示させるプログラムを作成しました 続けてフレームの右と下にスクロールバーを配置させたいのですがどうすればよいのかがわかりません。よろしくお願いします。 impor

  • 受付中

    [JAVA Swing]キャプチャツールのキャプチャ範囲指定

    以下のツールを使って画面キャプチャツールをつくっていっるのですが、キャプチャするとフルスクリーンでキャプチャされてしまいます。 指定の範囲やマウスで範囲指定した時などのキャプチャ方

  • 解決済

    イメージを表示するタイミングを調整できません

    下記のソースコードで実行してみたところ、自分ではAの画像が最初に背景のように表示されてその1秒後にBの画像が出ることを想定していたのですが、実際に試すと最初に何も表示されていないウ

  • 受付中

    Java アイコンを取得するプログラム

    指定のファイルのアイコンをJavaのプログラムから取得したいのですが、どのようなプログラムを作成したらいいのでしょうか。 他のサイトでは、ドラッグを使用しているのですが、ドラッグ

  • 解決済

    国旗を表示させたい(続き)

    前提・実現したいこと btn [0][1][2]をクリックすると、それに対応した国旗が表示されるようにしたい。 ソースコード import java.awt.*;   

  • 解決済

    java eclipseについて

    java eclipseでスライドパズルを作成しています。 9枚の画像で作成しており、現在は9枚の画像を実行するたびにランダムで表示するところまでいきました。 その後ですが9枚

  • 受付中

    エラーの意味が分かりません

    import java.util.*; import java.awt.*; import java.awt.event.*; @SuppressWarnings("uncheck

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

  • Java

    11818questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Eclipse

    1434questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。