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

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

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

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

Swing

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

Q&A

解決済

2回答

1495閲覧

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

Alpa

総合スコア80

Java

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

Swing

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

0グッド

0クリップ

投稿2017/10/06 12:45

###前提・実現したいこと

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

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

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

###該当のソースコード

java

1import javax.swing.JF; 2 3import java.awt.*; 4import java.awt.event.*; 5 6public class MyGame extends JFrame implements ActionListener, MouseMotionListener{ 7 8 int zikiX = 750;//自機のX座標 9 int zikiY = 225;//自機のY座標 10 11 int zikidamaX = zikiX-30;//自機の弾のX座標 12 int zikidamaY = zikiY;//自機の弾のY座標 13 14 int count;//カウント感知用変数 15 16 ImageIcon icon1 = new ImageIcon 17 ("C:\Users\miyab\Desktop\シューティングゲーム\自機.png");//自機の画像ファイル指定;//ImageIconのicon1作成 18 ImageIcon icon2 = new ImageIcon 19 ("C:\Users\miyab\Desktop\シューティングゲーム\自機弾.png");//自機弾の画像ファイル指定;//ImageIconのicon2作成 20 21 JLabel ziki;//JLabelのziki作成 22 JLabel zikizahyou;//JLabelのzikizahyou作成 23 JLabel zikidamazahyou;////JLabelのzikidamazahyou作成 24 JLabel zikidama;//JLabelのzikidama作成 25 26 JPanel panel;//JPanelのpanel作成 27 28 Timer timer;//Timerのtimer作成 29 30 public static void main(String[] args){ 31 32 MyGame frame = new MyGame();//ウィンドウを内部的に作成 33 frame.setSize(900, 550);//ウィンドウサイズ設定 34 frame.setTitle("シューティングゲーム"); 35 frame.setLocationRelativeTo(null);//ウィンドウの位置を中央に設定 36 37 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 38 //ウィンドウを×で閉じるようにする設定 39 40 frame.setVisible(true);//ウィンドウを可視化 41 42 } 43 44 MyGame(){ 45 46 panel = new JPanel();//panel設定 47 panel.setLayout(null);//レイアウトマネージャー無効化 48 49 ziki = new JLabel(icon1);//JLabelに自機の画像ファイル設定 50 zikizahyou = new JLabel();//自機の座標を入れる 51 zikidamazahyou = new JLabel();//自機の弾の座標を入れる 52 zikidama = new JLabel(icon2);//JLabelに自機の弾の画像ファイル設定 53 54 ziki.setBounds(zikiX, zikiY, 80, 40);//zikiのサイズと座標設定 55 zikizahyou.setText("自機 "+"X座標:"+zikiX+" Y座標:"+zikiY);//自機の座標を設定 56 zikizahyou.setBounds(5, 5, 200, 15);//自機の座標の座標とサイズを設定 57 zikidamazahyou.setText("自機の弾 "+"X座標:"+zikidamaX+" Y座標:"+zikidamaY);//自機の座標を設定 58 zikidamazahyou.setBounds(5, 17, 200, 15);//自機の座標の座標とサイズを設定 59 60 timer = new Timer(10, this); 61 62 panel.add(ziki);//自機画像をpanelに追加 63 panel.add(zikizahyou);//自機の座標を画面に表示 64 panel.add(zikidamazahyou);//自機の弾の座標を画面に表示 65 66 pack(); 67 68 getContentPane().add(panel, BorderLayout.CENTER);//??? 69 70 enableEvents(java.awt.AWTEvent.KEY_EVENT_MASK);//キーイベントの有効化 71 72 addMouseMotionListener(this); 73 74 } 75 76 protected void processKeyEvent(java.awt.event.KeyEvent e){//キーイベントの関数 77 78 if(e.getID() == java.awt.event.KeyEvent.KEY_PRESSED){ 79 80 if(e.getKeyCode() == java.awt.event.KeyEvent.VK_A){ 81 82 zikidamaX = zikiX-30; 83 zikidamaY = zikiY; 84 85 zikidama.setBounds(zikidamaX, zikidamaY, 20, 20);//自機の弾のサイズと座標を設定 86 panel.add(zikidama);//panelにzikidamaを追加 87 88 if(zikidama.getParent() == panel){ 89 90 91 92 } 93 timer.start(); 94 95 } 96 } 97 } 98 99 public void actionPerformed(ActionEvent e){ 100 101 if(zikidamaX <= 0){ 102 103 timer.stop();//timerストップ 104 panel.remove(zikidama); 105 panel.repaint(); 106 107 zikidamaX = zikiX-30; 108 zikidamaY = zikiY; 109 zikidama.setBounds(zikidamaX, zikidamaY, 20, 20);//自機の弾のサイズと座標を設定 110 111 }else{ 112 113 zikidamaX -= 15;//zikidamaX[0]を-5 114 zikidama.setLocation(zikidamaX,zikidamaY);//座標を再設定 115 zikidamazahyou.setText("自機の弾 "+"X座標:"+zikidamaX+" Y座標:"+zikidamaY); 116 //座標表示を更新 117 118 } 119 120 } 121 122 public void mouseMoved(MouseEvent e){ 123 124 Point point = e.getPoint(); 125 zikiX = point.x-43; 126 zikiY = point.y-45; 127 128 if(zikiX <= 0){//座標が画面外に行ったら左端に戻す 129 130 zikiX = 0;//zikiのX座標を0に設定 131 132 } 133 134 if(zikiX >= 804){//座標が画面外に行ったら右端に戻す 135 136 zikiX = 804;//zikiのX座標を804に設定 137 138 } 139 140 if(zikiY <= 1){//座標が画面外に行ったら上端に戻す 141 142 zikiY = 1;//zikiのY座標を1に設定 143 144 } 145 146 if(zikiY >= 471){//座標が画面外に行ったら下端に戻す 147 148 zikiY = 471;//zikiのY座標を471に設定 149 150 } 151 152 ziki.setLocation(zikiX,zikiY);//座標を再設定 153 zikizahyou.setText("自機 "+"X座標:"+zikiX+" Y座標:"+zikiY);//座標表示を更新 154 155 } 156 157 public void mouseDragged(MouseEvent e){ 158 159 160 161 } 162 163}

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

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

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

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

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

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

guest

回答2

0

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

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

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

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

java

1public MyGame ... { 2 ... 3 // 表示中の弾を全て覚えておくためのリスト 4 List<JLabel> missileList = new JLabel<>(); 5 Icon missileIcon = new ImageIcon("弾画像.png"); 6 7 // 弾発射処理 8 protected void processKeyEvent(KeyEvent ev) { 9 ... 10 if (弾発射キーが押された) { 11 // インスタンスを新たに生成 12 JLabel missile = new JLabel(missileIcon); 13 // 自機の座標に基づき弾の最初の座標と大きさを設定 14 missile.setBounds(ziki.getX() - 30, ziki.getY(), 20, 20); 15 panel.add(missile); 16 missileList.add(missile); // リストへも追加 17 repaint(); 18 } 19 } 20 21 // タイマーハンドラー 22 public void actionPerformed(ActionEvent ev) { 23 // 表示中のそれぞれの弾についての処理 24 for (Missile missile : missileList) { 25 // まず左に移動 26 int x = missile.getX(); 27 int y = missile.getY(); 28 missle.setLocation(x - 30, y); 29 // もし画面左端に達していたらパネルと弾リストから外す 30 if (x < 0) { 31 panel.remove(missile); 32 missileList.remove(missile); 33 } 34 } 35 repaint(); 36 } 37}

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

投稿2017/10/06 15:37

KSwordOfHaste

総合スコア18394

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

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

0

ベストアンサー

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


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

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

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

Java

1enum Direction { 2 RIGHT, LEFT, UP, DOWN, 3} 4 5class Bullet extends JLabel implements Runnable { 6 static final Dimension bulletSize = new Dimension(20, 20); 7 8 private final JPanel field; 9 private final Direction forward; 10 11 private Point point; 12 13 Bullet(JPanel field, ImageIcon bulletImage, 14 Direction forward, Point shotPoint 15 ) { 16 super(ImageResizer.resize(bulletImage, bulletSize)); 17 18 this.field = field; 19 this.forward = forward; 20 this.point = new Point(shotPoint); 21 22 setBounds( 23 point.x, point.y, 24 getPreferredSize().width, getPreferredSize().height 25 ); 26 field.add(this); 27 } 28 29 @SuppressWarnings("InfiniteLoopStatement") 30 public void run() { 31 while(true) { 32 go(forward); 33 34 try { 35 Thread.sleep(10); 36 } catch(InterruptedException e) { 37 e.printStackTrace(); 38 } 39 40 if(!(0 < point.x && point.x < field.getWidth() )) break; 41 if(!(0 < point.y && point.y < field.getHeight())) break; 42 } 43 44 field.remove(this); 45 } 46 47 private void go(Direction direction) { 48 switch(direction) { 49 case RIGHT: point.x += 1; break; 50 case LEFT: point.x -= 1; break; 51 case DOWN: point.y += 1; break; 52 case UP: point.y -= 1; break; 53 } 54 55 setLocation(point.x, point.y); 56 } 57} 58 59class ImageResizer { 60 // https://stackoverflow.com/questions/6714045/how-to-resize-jlabel-imageicon 61 62 static ImageIcon resize(ImageIcon src, Dimension size) { 63 if(src.getIconWidth() == size.width && src.getIconHeight() == size.height) { 64 return src; 65 } 66 return new ImageIcon(resize(src.getImage(), size)); 67 } 68 69 static private Image resize(Image src, Dimension size) { 70 BufferedImage resizedImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); 71 Graphics2D g2 = resizedImage.createGraphics(); 72 73 g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 74 g2.drawImage(src, 0, 0, size.width, size.height, null); 75 g2.dispose(); 76 77 return resizedImage; 78 } 79}

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

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

投稿2017/10/06 13:03

編集2017/10/06 13:21
LouiS0616

総合スコア35660

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

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

Alpa

2017/10/06 14:21

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問