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

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

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

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

Q&A

解決済

5回答

3272閲覧

インスタンスの消し方

nakamura-

総合スコア48

Java

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

0グッド

0クリップ

投稿2016/07/08 08:37

いまシューティングゲームみたいなものを作っています。
上から降ってくる桜の花びらをプレイヤーが弾で攻撃する感じです。
下のものがプログラムの一部になります。

コード public class Part01 extends JApplet{ /** * 初期メソッド */ public void init(){ setSize(1000, 700); //画面サイズ設定 MyPanel mp = new MyPanel(); //MyPanelインスタンス化 getContentPane().add(mp); //MyPanel追加 } }
コード public class MyPanel extends JPanel implements Runnable{ Player player; int gunCount = 0; Gun gun; ArrayList<Gun> gunList = new ArrayList<Gun>(); Sakura sakura; ArrayList<Sakura> sakuraList = new ArrayList<Sakura>(); Random rnd = new Random(); /** * MyPanelのコンストラクタ */ public MyPanel(){ setBackground(Color.BLACK); //背景色設定 /*再描画ループスレッド*/ Thread loopPaint = new Thread(this); loopPaint.start(); /*画像読み込み、切り取り*/ try{ player = new Player("jiki.gif", 0, 0, 32, 32); } catch(IOException ioe){ System.out.println("画像がありません"); } CreateThread ct = new CreateThread(); /*弾ループスレッド*/ ct.loopGunThread(this); /*桜作成ループスレッド*/ ct.loopCreateSakuraThread(this); /*桜ループスレッド*/ ct.loopSakuraThread(this); } /** * キー入力処理 */ @Override protected void processKeyEvent(KeyEvent ke){ /*何かキーが押された場合*/ if(ke.getID() == KeyEvent.KEY_PRESSED){ System.out.println("キー" + ke.getKeyCode() + "が押された"); /*押されたキーが左右だった場合*/ player.updata(ke.getKeyCode()); /*押されたキーがENTERだった場合*/ if(ke.getKeyCode() == KeyEvent.VK_ENTER){ gun = new Gun(10000, 10000); //Enter押されたらインスタンス生成 gunList.add(gun); //配列に追加 gunList.get(gunCount).startLine(player.m_x + 16, player.m_y); gunCount++; } } } /** * 描画メソッド */ @Override protected void paintComponent(Graphics g){ super.paintComponent(g); requestFocusInWindow(); //キー入力有効化 player.draw(g); if(gun != null){ //gunがインスタンス化されている場合(Enter押された場合) for(int i = 0; i < gunList.size(); i++){ //弾の数だけ繰り返し gunList.get(i).draw(g); } } if(sakura != null){ for(int i = 0; i < sakuraList.size(); i++){ sakuraList.get(i).draw(g); } } if(gun != null && sakura != null){ for(int i = 0; i < gunList.size(); i++){ for(int k = 0; k < sakuraList.size(); k++){ double x1 = (sakuraList.get(k).Screen_vData[0][0] + sakuraList.get(k).Screen_vData[1][0]) / 2; double y1 = (sakuraList.get(k).Screen_vData[0][1] + sakuraList.get(k).Screen_vData[1][1]) / 2; double x2 = gunList.get(i).m_x + 1; double y2 = gunList.get(i).m_y + 1; double length = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); if(length < sakuraList.get(k).scale){ System.out.println("-----衝突-----"); } } } } } /** * runメソッド(loopPaintスレッド) */ public void run(){ while(true){ repaint(); } } }
コード public class CreateThread{ Random rnd = new Random(); /** * 弾ループスレッド作成 */ public void loopGunThread(MyPanel mp){ Thread loopGun = new Thread(new Runnable(){ public void run(){ while(true){ try{ Thread.sleep(50); } catch(InterruptedException e){ } if(mp.gun != null){ //gunがインスタンス化されている場合(Enter押された場合) for(int i = 0; i < mp.gunList.size(); i++){ //弾の数だけ繰り返し if(mp.gunList.get(i).m_y > -10){ //画面内の場合(画面外になると終了) mp.gunList.get(i).updata(); } } } } } }); loopGun.start(); } /** * 桜作成ループスレッド作成 */ public void loopCreateSakuraThread(MyPanel mp){ Thread createSakura = new Thread(new Runnable(){ public void run(){ while(true){ try{ Thread.sleep((long)(Math.random() * 1000)); } catch(InterruptedException e){ } createSakura(mp); mp.sakuraList.add(mp.sakura); } } }); createSakura.start(); } /** * 桜ループスレッド作成 */ public void loopSakuraThread(MyPanel mp){ Thread loopSakura = new Thread(new Runnable(){ public void run(){ while(true){ try{ Thread.sleep(20); } catch(InterruptedException e){ } if(mp.sakura != null){ for(int i = 0; i < mp.sakuraList.size(); i++){ mp.sakuraList.get(i).updata(); } } } } }); loopSakura.start(); } /** * 桜インスタンス作成 */ public void createSakura(MyPanel mp){ mp.sakura = new Sakura( 1, 1, 0, -1, -1, 0, 1, 1, 0, 1, -1, 0, (Math.random() * 1000) - 200, -100, rnd.nextInt(6) + 5); } }

Sakura,Gun,Playerクラスは省略しています。
弾はEnterキーが押されるたびにインスタンスが生成され、gunListに格納されていきます
この弾を描画するときgunListに入っているだけ(弾の数だけ)繰り返して弾を全て描画しています。
if(ke.getKeyCode() == KeyEvent.VK_ENTER){
gun = new Gun(10000, 10000);//Enter押されたらインスタンス生成
gunList.add(gun);//配列に追加
}
このままだとEnterを押すたびにgunListが増えていき、描画するときにgunListの数だけ繰り返すので処理が重たくなると思います。
弾が画面外になったらgunListから取り除くような処理をしたいのですが、どのように記述すればいいのでしょうか?
よろしくお願いします。

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

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

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

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

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

guest

回答5

0

ベストアンサー

「次のように書けば良いよ」と言いたいところですが、

java

1for(int i = 0; i < mp.gunList.size(); i++){ 2 Gun gun = mp.gunList.get(i); 3 if(gunが画面外に出た){ 4 mp.gunList.remove(i); 5 }else{ 6 mp.gunList.get(i).updata(); 7 } 8}

キー入力のイベントが発生するスレッド(イベントディスパッチスレッド)と、
loopGunThreadのスレッドが同時に動作しているため、
gunListへGunを入れたり削除したりするには排他制御が必要です。

排他制御をどうするかはちょっと簡単じゃないので、今回は割愛で失礼します。

投稿2016/07/08 08:57

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nakamura-

2016/07/11 00:29

回答ありがとうございます。 排他制御というのを調べてみたいと思います。
guest

0

画面外に出たら消すという考え方ではなく、描写の前にその弾が画面内か否かを判定してから描写してみてはどうでしょう?
画面外のものは描写処理されなくなるので、少なくとも処理が軽くなることは期待できると思います。
ただし、Gunインスタンスが残る問題は解決しないので、定期的に画面外の弾を除去する(もちろん排他制御に気を遣って)必要があるかと思いますが。

投稿2016/07/10 04:53

編集2016/07/10 04:56
swordone

総合スコア20649

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

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

nakamura-

2016/07/11 00:37

回答ありがとうございます。 そういう考え方もありますね! 参考にさせていただきます。
guest

0

同期化処理(排他制御)にはいくつか方法があると思います

  • java.util.Collections.synchronizedList(List)を使用する

java

1//FQDN(完全修飾名) 2java.util.List<Gun> syncArray = java.util.Collections.synchronizedList(new java.util.ArrayList<Gun>());
  • スレッドを一つにまとめて処理する

java

1long c; 2int pup; 3boolean cgun; 4boolean loop=true; 5@Override 6public void run(){ 7 while(loop){ 8 frame(); 9 Thread.sleep(16); 10 } 11} 12 13private void frame(){ 14 c++; 15 player.updata(ke.getKeyCode()); 16 cgun(); 17 //1フレームごとの処理 18 //cにはloop回数が入ってます 19} 20private void cgun(){ 21 gun = new Gun(10000, 10000); //Enter押されたらインスタンス生成 22 gunList.add(gun); //配列に追加 23 gunList.get(gunCount).startLine(player.m_x + 16, player.m_y); 24 gunCount++; 25} 26 protected void processKeyEvent(KeyEvent ke){ 27 /*何かキーが押された場合*/ 28 if(ke.getID() == KeyEvent.KEY_PRESSED){ 29 System.out.println("キー" + ke.getKeyCode() + "が押された"); 30 31 /*押されたキーが左右だった場合*/ 32 pup=ke.getKeyCode(); 33 34 /*押されたキーがENTERだった場合*/ 35 if(ke.getKeyCode() == KeyEvent.VK_ENTER){ 36 cgun=true; 37 } 38 } 39 }

投稿2016/07/10 00:24

編集2016/07/11 07:25
tignear

総合スコア260

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

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

退会済みユーザー

退会済みユーザー

2016/07/10 09:19

プログラミング方法によっては、synchronizedListで簡単に解決できるかもしれません。 でも、イベントディスパッチのスレッドに処理をまとめるのは良くないと考えています。
nakamura-

2016/07/11 00:30

回答ありがとうございます。 synchronizedListというのがあるんですね。 調べてみたいと思います!
tignear

2016/07/11 11:45 編集

表現が悪すぎた イベントスレッドからはフラグを変更する処理だけをやらせてフラグの処理も含めて全体の処理は一つのスレッドでやらせるってことです (これをする場合最初のものは不要です)
guest

0

こんなふうに、List#removeを使えばListから該当のインスタンスを除去できます。

Java

1if(mp.gunList.get(i).m_y > -10){ //画面内の場合(画面外になると終了) 2 mp.gunList.get(i).updata(); 3} 4else { 5 // 画面外に出た時 6 mp.gunList.remove(i);// gunListからi番目を削除 7 i--; // iがずれるので補正 8}

投稿2016/07/08 08:43

masaya_ohashi

総合スコア9206

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

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

退会済みユーザー

退会済みユーザー

2016/07/08 08:58

排他制御の考慮が必要。
nakamura-

2016/07/11 00:21

回答ありがとうございます! 場合分けでremoveを使えばいいんですね! ありがとうございました。
guest

0

gunListからremoveすれば良いのでは?

投稿2016/07/08 08:42

PineMatsu

総合スコア3579

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

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

nakamura-

2016/07/11 00:20

回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問