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

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

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

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

Q&A

解決済

1回答

1857閲覧

敵と自機の当たり判定時におきるエラーを解決したい

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

1クリップ

投稿2017/08/17 15:04

前提・実現したいこと
javaで敵を複数体出すプログラムを作ったのですが
敵と自機が当たる部分で以下のエラーが出てしまいます。
###発生している問題・エラーメッセージ

エラーメッセージ

Exception

1 at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 2 at java.util.ArrayList$Itr.next(ArrayList.java:851) 3 at Rousakuten.runGameMain(Rousakuten.java:177) 4 at GameHoneGumi$MyTimerTask.run(GameHoneGumi.java:119) 5 at java.util.TimerThread.mainLoop(Timer.java:555) 6 at java.util.TimerThread.run(Timer.java:505)

言語
java

実行したソースコード(抜粋)

public void keyPressedGameMain(int keycode) { switch(keycode){ case KeyEvent.VK_UP : keyup = true;break; case KeyEvent.VK_DOWN : keydown= true; break; case KeyEvent.VK_LEFT : keyleft = true; break; case KeyEvent.VK_RIGHT : keyright = true; break; case KeyEvent.VK_SPACE: keySpace = true; break; case KeyEvent.VK_ENTER: keyEnter = true; break; } } @Override public void keyReleasedGameMain(int keycode) { switch(keycode){ case KeyEvent.VK_UP : keyup = false;break; case KeyEvent.VK_DOWN : keydown= false; break; case KeyEvent.VK_LEFT : keyleft = false; break; case KeyEvent.VK_RIGHT : keyright = false; break; case KeyEvent.VK_SPACE: keySpace = false; break; case KeyEvent.VK_ENTER: keyEnter = false; break; } } public void runStartGamen(Graphics g) { g.setColor(Color.BLUE); g.fillRect(0, 0, this.width, this.height); } @Override public void runStageStart(Graphics g) { // TODO 自動生成されたメソッド・スタブ } @Override public void runStageClear(Graphics g) { // TODO 自動生成されたメソッド・スタブ } @Override public void runGameMain(Graphics g) { // TODO 自動生成されたメソッド・スタ if(keyup){ y-=6; if(y<0) y = 0; } if(keydown){ y+=6; if(y>675) y=675; } if (keyleft) { x -= 6; if (x < 0) x = 0; } // 右移動 if (keyright) { x += 6; if (x >860) x = 860; } //弾発射 if (keySpace && rensya == 0) { jikitamas.add(new Jikitama(x+12, y)); rensya = 28; } if(rensya > 0) rensya--; //弾消滅 if (!jikitamas.isEmpty()) { Iterator<Jikitama> itr = jikitamas.iterator(); while(itr.hasNext()) { Jikitama jt = itr.next(); if (jt.y < 0) itr.remove(); else jt.y -= 8; } } //enemy delete, update if(!tekis.isEmpty()){ Iterator<Teki> itr = tekis.iterator(); while (itr.hasNext()) { Teki t = itr.next(); if (t.ey >= 675) itr.remove(); else t.ey += 3; } } // if(tekis.size() < 4 && tekideru <= 0){ int ex = (int)(Math.random()*420)+200; int ey = (int)(Math.random()*32); Teki t = new Teki(ex, ey); tekis.add(t); tekideru = 30; } if(tekideru > 0) tekideru--; if(!jikitamas.isEmpty()) { Iterator<Jikitama> itr = jikitamas.iterator(); boolean isHit = false; while (itr.hasNext()) { Jikitama jt = itr.next(); isHit = false; Iterator<Teki> itrE = tekis.iterator(); while (itrE.hasNext()) { Teki t= itrE.next(); if(jt.x +0> t.ex && jt.x< t.ex +40 && jt.y +8 > t.ey&& jt.y < t.ey + 32) { score+=50; itrE.remove(); tflag = false; score+=50; isHit = true; } } if (isHit) itr.remove(); } } //自分はこの部分に問題があると思っています if (!tekis.isEmpty()) { for (Teki t: tekis) { if (x +32 >t.ex && x < t.ex +32 && y +32 > t.ey && y < t.ey +32){ goGameOver(); } } } g.clearRect(0, 0, 900, 700); g.drawImage(back, 0, 0, frame1); g.drawImage(jiki, x, y, frame1); if (!jikitamas.isEmpty()) { Iterator<Jikitama> itr = jikitamas.iterator(); while(itr.hasNext()){ Jikitama jt = itr.next(); g.drawImage(tama, jt.x, jt.y, frame1); } } for(Teki t: tekis){ g.drawImage(teki, t.ex, t.ey, frame1); } g.setColor(Color.pink); g.drawString("SCORE:" + String.valueOf(score),50,50); bstrategy.show(); g.dispose(); } @Override public void runGameOver(Graphics g) { g.setColor(Color.RED); g.setFont(new Font("Sanserif" , Font.BOLD,80)); g.drawString("GAMEOVER", 230, 365); bstrategy.show(); g.dispose(); return; } @Override public void initStageStart() { // TODO 自動生成されたメソッド・スタブ } @Override public void initStageClear() { // TODO 自動生成されたメソッド・スタブ } @Override public void initGameOver() { x = 440; y = 660; rensya = 0; score = 0; jikitamas.clear(); keysClear(); tekis.clear(); } private void keysClear() { keyup = false; keydown = false; keyright = false; keyleft = false; keyEnter = false; keyP = false; } public static void main(String[] args) { Rousakuten r = new Rousakuten(900, 700, "test"); } }

試したこと
何を試せばよいのか分からず行っていません

補足情報(言語/FW/ツール等のバージョンなど)
このプログラムの完成形はシューティングゲームにしようと思っています。
上記のプログラムはスーパークラスから継承したものも含まれているので一応スーパークラスも載せておきます。
コードが長く申し訳ありません
回答よろしくお願いします。
また、この情報が足りないからほしいという意見がありましたら言ってくださると助かります。

import java.awt.Color; import java.awt.Graphics; import java.awt.Insets; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.image.BufferStrategy; import java.util.Timer; import java.util.TimerTask; import javax.swing.JFrame; public abstract class GameHoneGumi { public static final int GS_STARTGAMEN = 0; public static final int GS_STAGESTART = 1; public static final int GS_STAGECLEAR = 2; public static final int GS_GAMEOVER = 3; public static final int GS_GAMEMAIN = 4; private int gamestate; private int waittimer; JFrame frame1; BufferStrategy bstrategy; GameHoneGumi(int w, int h, String title){ frame1 = new JFrame(title); frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame1.setBackground(Color.WHITE); frame1.setResizable(false); frame1.setVisible(true); Insets insets = frame1.getInsets(); frame1.setSize(w + insets.left + insets.right, h + insets.top + insets.bottom); frame1.setLocationRelativeTo(null); frame1.createBufferStrategy(2); bstrategy = frame1.getBufferStrategy(); frame1.setIgnoreRepaint(true); frame1.addKeyListener(new MyKeyAdapter()); } public abstract void keyPressedGameMain(int keycode); public abstract void keyReleasedGameMain(int keycode); public abstract void runStartGamen(Graphics g); public abstract void runStageStart(Graphics g); public abstract void runStageClear(Graphics g); public abstract void runGameMain(Graphics g); public abstract void runGameOver(Graphics g); public abstract void initStageStart(); public abstract void initStageClear(); public abstract void initGameOver(); public void goStartGamen(){ gamestate = GS_STARTGAMEN; Timer t = new Timer(); t.schedule(new MyTimerTask(), 10, 10); } public void goStageStart(){ initStageStart(); waittimer = 100; gamestate = GS_STAGESTART; } public void goStageClear(){ initStageClear(); waittimer = 100; gamestate = GS_STAGECLEAR; } public void goGameMain(){ gamestate = GS_GAMEMAIN; } public void goGameOver(){ initGameOver(); gamestate = GS_GAMEOVER; } class MyKeyAdapter extends KeyAdapter{ public void keyPressed(KeyEvent ev){ if(gamestate == GS_GAMEMAIN){ keyPressedGameMain(ev.getKeyCode()); } } public void keyReleased(KeyEvent ev){ int keycode = ev.getKeyCode(); switch(gamestate){ case GS_GAMEMAIN: keyReleasedGameMain(keycode); break; case GS_STARTGAMEN: if(keycode== KeyEvent.VK_P) goStageStart(); break; case GS_GAMEOVER: if(keycode == KeyEvent.VK_R) goStageStart(); } } } class MyTimerTask extends TimerTask{ public void run(){ Graphics g = bstrategy.getDrawGraphics(); if(bstrategy.contentsLost() == false){ Insets insets = frame1.getInsets(); g.translate(insets.left, insets.top); switch(gamestate){ case GS_STARTGAMEN: runStartGamen(g); break; case GS_STAGESTART: runStageStart(g); waittimer = waittimer-1; if(waittimer<0) goGameMain(); break; case GS_STAGECLEAR: runStageClear(g); waittimer = waittimer-1; if(waittimer<0) goStageStart(); break; case GS_GAMEMAIN: runGameMain(g); break; case GS_GAMEOVER: runGameOver(g); break; } } } } }

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

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

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

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

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

LouiS0616

2017/08/17 15:16

エラーメッセージがちょん切れています。全体を再掲してください。
guest

回答1

0

ベストアンサー

ゲーム作り大変ですよね。苦労します。

さて、質問者様の予想は正しいです。
まさしく

Java

1 if (!tekis.isEmpty()) { 2 for (Teki t: tekis) { 3 if (x +32 >t.ex && x < t.ex +32 && y +32 > t.ey && y < t.ey +32){ 4 goGameOver(); 5 } 6 } 7 }

の部分が問題です。他にも問題があるかもしれませんが、同じエラーであれば、今回の回答を参考にして修正して頂ければ問題ないでしょう。

僕は質問者のコードを次のように修正致します。

Java

1 if (!tekis.isEmpty()) { 2 boolean flag = false; 3       for (Teki t: tekis) { 4 if (x +32 >t.ex && x < t.ex +32 && y +32 > t.ey && y < t.ey +32){ 5 flag = true; 6 break; 7 } 8   } 9 if(flag) goGameOver(); 10 } 11//イテレーターを使うやり方もあります。お好みでどうぞ。

変化したことは、
x +32 >t.ex && x < t.ex +32 && y +32 > t.ey && y < t.ey +32
trueとなったときにbreak;でforループを抜けてgoGameOver();を実行していることです。
どうしても、goGameOver();をforループの外に出したかったのです。
その理由は、このメソッドは'initGameOver()'を経由して'tekis.clear();'を実行しているからです。
つまり、
tekisがループされてる中、tekisの要素数が修正されたからです。
javaの仕様上、次の時ConcurrentModificationExceptionを出します。

この例外は、オブジェクトが別のスレッドによって並行して更新されていないことを必ずしも示しているわけではありません。単一のスレッドが、オブジェクトの規約に違反する一連のメソッドを発行した場合、オブジェクトはこの例外をスローします。たとえば、フェイルファストイテレータを持つコレクションの繰り返し処理を行いながら、スレッドがコレクションを直接修正する場合、イテレータはこの例外をスローします。

通常、非同期の並行変更がある場合、確かな保証を行うことは不可能なので、フェイルファストの動作を保証することはできません。フェイルファストオペレーションは最善努力原則に基づき、ConcurrentModificationException をスローします。したがって、正確を期すためにこの例外に依存するプログラムを書くことは誤りです。ConcurrentModificationException は、バグを検出するためにのみ使用してください。

「イテレータを持つコレクションの繰り返し処理を行いながら、スレッドがコレクションを直接修正する場合、イテレータはこの例外をスローします。」とあります。
この仕様を原因として、今回エラーがでました。

ゲーム作り諦めないでください。

投稿2017/08/17 23:39

編集2017/08/17 23:48
kirensunakawa

総合スコア24

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

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

退会済みユーザー

退会済みユーザー

2017/08/18 07:08

回答ありがとうございます! おかげで解決することができました! 自分はエラーを修正してプログラム上に表すことがまだまだ未熟なので、文章でエラーの直し方を書いてあって助かりました! ゲーム作り頑張ります!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問