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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

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

Eclipse

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

Q&A

解決済

3回答

681閲覧

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

eamons

総合スコア12

Java

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

Eclipse

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

1グッド

0クリップ

投稿2017/12/08 13:57

編集2017/12/09 05:52

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; // パッドを止める } }

}

A-pZ👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

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

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

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

Java

1public class Pad implements MouseListener

Java

1public class Pad extends javax.swing.event.MouseInputAdapter

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

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

Java

1import javax.swing.Timer; 2 3private final Timer paint_Timer; 4public BlockCanvas(int w, int h) { 5 dim = new Dimension(w, h); 6 setPreferredSize(dim); 7  // マウスイベントハンドラーを登録 8 this.addMouseListener(pad); 9 int delay = 50; // milliseconds 10 paint_Timer = new Timer(delay, (evt) -> { 11 ball.move(dim); 12 pad.move(dim, ball); 13 repaint(); 14 }); 15} 16// startメソッドを追加 17public void start() { 18 paint_Timer.start(); 19}

BlockMain#mainメソッド

Java

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

投稿2017/12/09 00:30

編集2017/12/09 00:40
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eamons

2017/12/15 13:57

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

0

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

Java

1Ball ball = new Ball(); 2Pad 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/08 18:38

編集2017/12/08 18:39
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eamons

2017/12/15 13:56

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

0

ベストアンサー

ボールの衝突判定のif文

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


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

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

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

さらに、具体化します。

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

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

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

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


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

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

投稿2017/12/08 18:08

LLman

総合スコア5592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eamons

2017/12/15 13:53

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問