我正在编写一个游戏,以便当您按住 D 时角色向右移动,当您按住 S 时角色向左移动。该程序正常工作,但有一个异常(exception)。当我移动角色时(并且角色移动得非常好),java 不断抛出错误“java.util.ConcurrentModificationException”。我做了一些研究并了解到我不能添加到 ArrayList“键”并同时迭代它。话虽如此,我如何编辑代码才能让角色像现在一样无缝移动?据我所知,这是确保角色在按住按键时以相同稳定的速度移动的唯一方法,而不是快速移动、暂停,然后继续移动。
package LevelEditor;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Iterator;
public class LevelEditor extends Canvas implements KeyListener, Runnable, MouseListener, MouseMotionListener{
private Object[][] grid = new Object[50][50];
private Graphics bufferGraphics = null; //The graphics for the back buffer
private BufferStrategy bufferStrategy = null;
private Thread thread;
private boolean running;
private int selectedBlock = 0;
private int mouseX;
private int mouseY;
private int playerX;
private int playerY;
private ArrayList<Integer> keys = new ArrayList<Integer>();
Iterator itr;
Player player1;
public LevelEditor(Dimension size){
//Constructor
this.setPreferredSize(size);
this.addKeyListener(this);
this.thread = new Thread(this);
this.addMouseListener(this);
this.addMouseMotionListener(this);
running = true;
mouseX = 0;
mouseY = 0;
playerX = 0;
playerY = 0;
itr = keys.iterator();
}
public void paint(Graphics g){
if (bufferStrategy == null){
this.createBufferStrategy(2);
bufferStrategy = this.getBufferStrategy();
bufferGraphics = bufferStrategy.getDrawGraphics();
player1 = new Player(playerX, playerY);
this.thread.start();
}
}
@Override
public void run() {
//This is what runs when level editor is running
while (running){
//Program's logic
DoLogic();
Draw();
DrawBackbufferToScreen();
Thread.currentThread();
try{
Thread.sleep(10);
}
catch(Exception e){
e.printStackTrace();
}
}
}
public void DoLogic(){
}
public void Draw(){
//clear secondary screen
bufferGraphics = bufferStrategy.getDrawGraphics();
try{
bufferGraphics.clearRect(0, 0, this.getSize().width, this.getSize().height);
//this is where everything will be drawn to back buffer
for (int x = 0; x < grid.length; x++){
for(int y = 0; y < grid[x].length; y++){
Object o = grid[x][y];
if (o instanceof Block){
Block blocktoDraw = (Block)o;
blocktoDraw.draw(bufferGraphics);
}
}
}
Block.getBlock(selectedBlock, mouseX, mouseY).draw(bufferGraphics);
player1.draw(bufferGraphics);
for (Integer x : keys){
if(x == 68 && itr.hasNext()){
playerX += 5;
player1.updatePlayer(playerX, playerY);
player1.draw(bufferGraphics);
itr.next();
itr.remove();
}
if (x == 65 && itr.hasNext()){
playerX -= 5;
player1.updatePlayer(playerX, playerY);
player1.draw(bufferGraphics);
itr.next();
itr.remove();
}
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
bufferGraphics.dispose();
}
}
public void DrawBackbufferToScreen(){
bufferStrategy.show();
Toolkit.getDefaultToolkit().sync();
}
@Override
public void mouseReleased(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
mouseX = (mouseX / 25);
mouseY = (mouseY / 25);
if (e.getModifiers() == 16){
grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
}
else if (e.getModifiers() == 4){
grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
keys.clear();
}
@Override
public void keyPressed(KeyEvent e) {
keys.add(e.getKeyCode());
}
public void mouseMoved(MouseEvent e) {
this.mouseX = e.getX() / 25;
this.mouseY = e.getY() / 25;
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseDragged(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
mouseX = (mouseX / 25);
mouseY = (mouseY / 25);
if(e.MOUSE_DRAGGED == 506 && e.getModifiers() == 16){
grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
}
else if (e.MOUSE_DRAGGED == 506 && e.getModifiers() == 4){
grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
}
}
}
最佳答案
使用迭代器
在这里是错误的模型:您实际上并没有迭代列表,您只是查看是否有元素,然后在有元素时对其进行处理。
更好的选择是使用队列 - 特别是某种并发队列,例如java.util.concurrent.BlockingQueue
,因为您正在修改它并在不同的线程中读取它。
您可以使用 queue.add(e.getKeyCode())
添加关键代码,并使用 queue.poll()
(或 queue.peek()
),如果队列中没有任何内容,则返回 null 值(类似于 itr.hasNext()
为 false)。
关于java.util.ConcurrentModificationException 与迭代器(字符移动),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31465746/