我有一个类Handler,用于在gameview类中绘制塔的arraylist
public class Handler {
public static int Scale=50;
public static ArrayList<Tower> towers=new ArrayList<Tower>();
public static void draw(Canvas c){
for(Tower t:towers){
t.draw(c);
}
}
public static void update(){
for(Tower t:towers){
t.update();
}
}
}
GameView类,用于扩展surfaceview和implments surfaceholder.callback
public class GameView extends SurfaceView implements
SurfaceHolder.Callback {
public int ScreenWidth,ScreenHeight;
TouchInput touchinput;
TableLayout table;
///////////////////////////////////////
//these variables used for adding new tower
boolean addingnewtower=false;
Bitmap Tempbitmap;
public float x,y;
//////////////////////////////////////
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
table=(TableLayout) findViewById(R.id.tablelayout1);
Sprite sprite=new Sprite(context.getResources());
touchinput=new TouchInput(this);
Tempbitmap=sprite.bitmap;
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
setFocusable(true);//
}
private static final String TAG = GameView.class.getSimpleName();
private MainThread thread;
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
//if(!thread.isAlive()){
setOnTouchListener(touchinput);
thread = new MainThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
public void Draw(Canvas c) {
Paint paint=new Paint();//paint used to set color,text font,text size...
paint.setColor(Color.RED);
paint.setTextSize(paint.getTextSize()*3);
c.drawRect(100,100,200,200,paint);
c.drawText("touch is" + x + " "+ y,200,200, paint);
Handler.draw(c);
if(addingnewtower){
c.drawBitmap(Tempbitmap,x,y, paint);
}
}
public void update(){
Handler.update();
}
类mainthread,它包含方法run()
中的游戏循环 public class MainThread extends Thread {
private static final String TAG = MainThread.class.getSimpleName();
// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private GameView gameview;
// flag to hold game state
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder,GameView gameview) {
super();
this.surfaceHolder = surfaceHolder;
this.gameview = gameview;
}
@Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
if(canvas!=null){
canvas.drawColor(Color.BLACK);
gameview.Draw(canvas);}
gameview.update();
}
} finally {
// in case of an exception the surface is not left in
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
}
最后是实现ontouchlistesnser的MainActivity
public class MainActivity extends Activity implements OnTouchListener {
private ImageView tower1,tower2,tower3,tower4,tower5,tower6;
private TableLayout layout;
private GameView gameview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//hide the action bar
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//make it full screen
setContentView(R.layout.activity_main);
gameview=(GameView) findViewById(R.id.gameview1);
tower1=(ImageView) findViewById(R.id.tower1);
layout=(TableLayout) findViewById(R.id.tablelayout1);
tower1.setOnTouchListener(this);
gameview.setOnTouchListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
gameview.onpause();
}
@Override
protected void onResume() {
super.onResume();
gameview.onresume();
}
//this is called whenever an imageview is touched for adding a new tower on the map
@Override
public boolean onTouch(View v, MotionEvent m) {
int location[]=new int[2];
tower1.getLocationOnScreen(location);//get the location of imageview with respect to screen since the touch area will be with respect to the view v width and height
switch(m.getAction()){
case MotionEvent.ACTION_DOWN:
if(v.getId()==tower1.getId()){//if tower1 is touched
layout.setVisibility(View.INVISIBLE);//make them invisible
}
break;
case MotionEvent.ACTION_MOVE:
gameview.handle_imageView_TouchEvent(location,m.getX(),m.getY(),false);//false meaning in touch move
break;
case MotionEvent.ACTION_UP:
gameview.handle_imageView_TouchEvent(location,m.getX(),m.getY(),true);//this will be called only once for adding the new tower
layout.setVisibility(View.VISIBLE);
gameview.addingnewtower=false;
break;
}
return true;
}
}
当这个代码做的时候,每当我触摸一个imageview并将它拖过屏幕时,一个新的对象机器人将延伸塔添加到处理程序类的arraylist塔中 但是几次将新的机器人添加到arraylist后我在处理程序的draw方法中出现错误
01-20 18:16:13.261: E/AndroidRuntime(1339): FATAL EXCEPTION: Thread-114
01-20 18:16:13.261: E/AndroidRuntime(1339): java.util.ConcurrentModificationException
01-20 18:16:13.261: E/AndroidRuntime(1339): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
01-20 18:16:13.261: E/AndroidRuntime(1339): at com.example.test1.Handler.draw(Handler.java:15)
01-20 18:16:13.261: E/AndroidRuntime(1339): at com.example.test1.GameView.Draw(GameView.java:97)
01-20 18:16:13.261: E/AndroidRuntime(1339): at com.example.test1.MainThread.run(MainThread.java:44)
是否有任何帮助?
答案 0 :(得分:2)
问题似乎是你在使用draw()方法迭代它的同时添加到ArrayList。迭代时不能修改集合(除了使用迭代器删除项目)。
你没有显示'gameview.handle_imageView_TouchEvent()'的方法,但我认为你需要使用与draw()和update()相同的Handler来添加到ArrayList。然后,这两个进程应该在同一个线程上排队,不会发生冲突。