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

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

ただいまの
回答率

90.75%

  • Java

    13116questions

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

  • Swing

    213questions

    SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

2回目にJPanel内に追加したJLabelを消したい

解決済

回答 2

投稿

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

miyabi6184

score 25

前提・実現したいこと

キー入力で追加したzikidamaの次に追加したzikidamaを消したい

発生している問題・エラーメッセージ

二回目がzikidama発射された時にremoveすると最初のzikidamaも消える

該当のソースコード

import javax.swing.JF;

import java.awt.*;
import java.awt.event.*;

public class MyGame extends JFrame implements ActionListener, MouseMotionListener{

    int zikiX = 750;//自機のX座標
    int zikiY = 225;//自機のY座標

    int zikidamaX = zikiX-30;//自機の弾のX座標
    int zikidamaY = zikiY;//自機の弾のY座標

    int count;//カウント感知用変数

    ImageIcon icon1 = new ImageIcon
    ("C:\\Users\\miyab\\Desktop\\シューティングゲーム\\自機.png");//自機の画像ファイル指定;//ImageIconのicon1作成
    ImageIcon icon2 = new ImageIcon
    ("C:\\Users\\miyab\\Desktop\\シューティングゲーム\\自機弾.png");//自機弾の画像ファイル指定;//ImageIconのicon2作成

    JLabel ziki;//JLabelのziki作成
    JLabel zikizahyou;//JLabelのzikizahyou作成
    JLabel zikidamazahyou;////JLabelのzikidamazahyou作成
    JLabel zikidama;//JLabelのzikidama作成

    JPanel panel;//JPanelのpanel作成

    Timer timer;//Timerのtimer作成

    public static void main(String[] args){

        MyGame frame = new MyGame();//ウィンドウを内部的に作成
        frame.setSize(900, 550);//ウィンドウサイズ設定
        frame.setTitle("シューティングゲーム");
        frame.setLocationRelativeTo(null);//ウィンドウの位置を中央に設定

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //ウィンドウを×で閉じるようにする設定

        frame.setVisible(true);//ウィンドウを可視化

    }

    MyGame(){

        panel = new JPanel();//panel設定
        panel.setLayout(null);//レイアウトマネージャー無効化

        ziki = new JLabel(icon1);//JLabelに自機の画像ファイル設定
        zikizahyou = new JLabel();//自機の座標を入れる
        zikidamazahyou = new JLabel();//自機の弾の座標を入れる
        zikidama = new JLabel(icon2);//JLabelに自機の弾の画像ファイル設定

        ziki.setBounds(zikiX, zikiY, 80, 40);//zikiのサイズと座標設定
        zikizahyou.setText("自機 "+"X座標:"+zikiX+" Y座標:"+zikiY);//自機の座標を設定
        zikizahyou.setBounds(5, 5, 200, 15);//自機の座標の座標とサイズを設定
        zikidamazahyou.setText("自機の弾 "+"X座標:"+zikidamaX+" Y座標:"+zikidamaY);//自機の座標を設定
        zikidamazahyou.setBounds(5, 17, 200, 15);//自機の座標の座標とサイズを設定

        timer = new Timer(10, this);

        panel.add(ziki);//自機画像をpanelに追加
        panel.add(zikizahyou);//自機の座標を画面に表示
        panel.add(zikidamazahyou);//自機の弾の座標を画面に表示

        pack();

        getContentPane().add(panel, BorderLayout.CENTER);//???

        enableEvents(java.awt.AWTEvent.KEY_EVENT_MASK);//キーイベントの有効化

        addMouseMotionListener(this);

    }

    protected void processKeyEvent(java.awt.event.KeyEvent e){//キーイベントの関数

        if(e.getID() == java.awt.event.KeyEvent.KEY_PRESSED){

            if(e.getKeyCode() == java.awt.event.KeyEvent.VK_A){

                zikidamaX = zikiX-30;
                zikidamaY = zikiY;

                zikidama.setBounds(zikidamaX, zikidamaY, 20, 20);//自機の弾のサイズと座標を設定
                panel.add(zikidama);//panelにzikidamaを追加

                if(zikidama.getParent() == panel){



                }
                timer.start();

            }
        }
    }

    public void actionPerformed(ActionEvent e){

        if(zikidamaX <= 0){

            timer.stop();//timerストップ
            panel.remove(zikidama);
            panel.repaint();

            zikidamaX = zikiX-30;
            zikidamaY = zikiY;
            zikidama.setBounds(zikidamaX, zikidamaY, 20, 20);//自機の弾のサイズと座標を設定

        }else{

            zikidamaX -= 15;//zikidamaX[0]を-5
            zikidama.setLocation(zikidamaX,zikidamaY);//座標を再設定
            zikidamazahyou.setText("自機の弾 "+"X座標:"+zikidamaX+" Y座標:"+zikidamaY);
            //座標表示を更新

        }

    }

    public void mouseMoved(MouseEvent e){

        Point point = e.getPoint();
        zikiX = point.x-43;
        zikiY = point.y-45;

        if(zikiX <= 0){//座標が画面外に行ったら左端に戻す

            zikiX = 0;//zikiのX座標を0に設定

        }

        if(zikiX >= 804){//座標が画面外に行ったら右端に戻す

            zikiX = 804;//zikiのX座標を804に設定

        }

        if(zikiY <= 1){//座標が画面外に行ったら上端に戻す

            zikiY = 1;//zikiのY座標を1に設定

        }

        if(zikiY >= 471){//座標が画面外に行ったら下端に戻す

            zikiY = 471;//zikiのY座標を471に設定

        }

        ziki.setLocation(zikiX,zikiY);//座標を再設定
        zikizahyou.setText("自機 "+"X座標:"+zikiX+" Y座標:"+zikiY);//座標表示を更新

    }

    public void mouseDragged(MouseEvent e){



    }

}

試したこと

カウントの変数を使って一回目に+1して
画面にzikidamaがあってcountが1だったら
removeするとコードを書いた
結果:最初のzikidamaも消えた

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

実際に動かしてみましたが、自機弾がもろとも消えてしまうのは思い違いかと思います。
二発目を撃った時点で一発目は消えます。そういう設計じゃないからです。
jikidamaXなどが一つしかない時点で、二つ以上の自機弾を扱うことは出来ません。


註:以下、直接的な回答ではありません

以前から何度か質問を拝見していますが...
上手くいかないことが多発するのは、なんといっても設計の問題に思えます。
ある程度複雑な動作を手続的に書くのは大変でしょう?

せっかくJavaを使っているのですから、オブジェクト指向に慣れた方が良いです。
以下、適当に書いた『自機弾』のクラスです。

enum Direction {
    RIGHT, LEFT, UP, DOWN,
}

class Bullet extends JLabel implements Runnable {
    static final Dimension bulletSize = new Dimension(20, 20);

    private final JPanel field;
    private final Direction forward;

    private Point point;

    Bullet(JPanel field, ImageIcon bulletImage,
           Direction forward, Point shotPoint
    ) {
        super(ImageResizer.resize(bulletImage, bulletSize));

        this.field = field;
        this.forward = forward;
        this.point = new Point(shotPoint);

        setBounds(
            point.x, point.y,
            getPreferredSize().width, getPreferredSize().height
        );
        field.add(this);
    }

    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        while(true) {
            go(forward);

            try {
                Thread.sleep(10);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }

            if(!(0 < point.x && point.x < field.getWidth() )) break;
            if(!(0 < point.y && point.y < field.getHeight())) break;
        }

        field.remove(this);
    }

    private void go(Direction direction) {
        switch(direction) {
        case RIGHT: point.x += 1; break;
        case LEFT:  point.x -= 1; break;
        case DOWN:  point.y += 1; break;
        case UP:    point.y -= 1; break;
        }

        setLocation(point.x, point.y);
    }
}

class ImageResizer {
    // https://stackoverflow.com/questions/6714045/how-to-resize-jlabel-imageicon

    static ImageIcon resize(ImageIcon src, Dimension size) {
        if(src.getIconWidth() == size.width && src.getIconHeight() == size.height) {
            return src;
        }
        return new ImageIcon(resize(src.getImage(), size));
    }

    static private Image resize(Image src, Dimension size) {
        BufferedImage resizedImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = resizedImage.createGraphics();

        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.drawImage(src, 0, 0, size.width, size.height, null);
        g2.dispose();

        return resizedImage;
    }
}

座標をわざわざ配列で管理する必要はないです。
部品や機能は出来るだけ切り分けるべきです。クラスの設計を勉強してください。

上記のサンプルプログラムですが、あくまでも参考程度にお願いします。
Swingを日常的に利用していないので、よくないやり方もあるかもしれません。
個人的には、さらに抽象的なクラスFloatingDeviceが必要かと思っています。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/06 23:21

    わかりました
    もう少しいろんなことを勉強してからまた
    再挑戦したいと思います
    回答ありがとうございました

    キャンセル

+1

解決済みですが、途中まで回答を書いてたのでコメントしておきます。LouiS0616さん回答と重複した点がありますけど。

やりたいことは「画面上に2つ以上の弾を表示」なのですが、質問者さんは重要な点を見落として(あるいは勘違いして)おられるようです。

パネル上に2つのラベルを表示するには2つの異なるインスタンスが必要です。しかしコード上には弾のインスタンスは一つしかありません(LouiS0616さんが指摘しておられる通りです)。インスタンスはnewしたときに生成されるものです。多分質問者さんはインスタンスが画面に表示される一つ一つのもの(例えば複数の弾を表示するならそれぞれの弾)に1:1に対応して必要であるという点がピンと来てないように思えます。

さて、実際にアニメーションさせたい複数の弾をどうやって管理するかはいくつか考え方がありますが、素直に考えるなら表示中の全ての弾のインスタンスをListなどに全て覚えておけばよいです。

public MyGame ... {
  ...
  // 表示中の弾を全て覚えておくためのリスト
  List<JLabel> missileList = new JLabel<>();
  Icon missileIcon = new ImageIcon("弾画像.png");

  // 弾発射処理
  protected void processKeyEvent(KeyEvent ev) {
    ...
    if (弾発射キーが押された) {
      // インスタンスを新たに生成
      JLabel missile = new JLabel(missileIcon);
      // 自機の座標に基づき弾の最初の座標と大きさを設定
      missile.setBounds(ziki.getX() - 30, ziki.getY(), 20, 20);
      panel.add(missile);
      missileList.add(missile); // リストへも追加
      repaint();
    }
  }

  // タイマーハンドラー
  public void actionPerformed(ActionEvent ev) {
    // 表示中のそれぞれの弾についての処理
    for (Missile missile : missileList) {
      // まず左に移動
      int x = missile.getX();
      int y = missile.getY();
      missle.setLocation(x - 30, y);
      // もし画面左端に達していたらパネルと弾リストから外す
      if (x < 0) {
        panel.remove(missile);
        missileList.remove(missile);
      }
    }
    repaint();
  }
}


なお、2回ほど指摘しましたが、改めてTimerは動かしっぱなしにすることをお勧めします。例えば2つの弾を表示中に片方が画面左端に到達したからといってTimerを単純に止めるともう一つの弾が止まってしまいますよね?弾が全部なくなったらTimerを止め、弾がない状態で発射した場合のみまたTimerを動かすとやってもいいですが、そんなややこしいことをする必要はないと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • Java

    13116questions

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

  • Swing

    213questions

    SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。