关于在Java游戏中实现暂停的讨论

最近写了一个Swing版本的Snake程序,可是不太清楚怎么样来实现游戏中常见的暂停操作,所以我列出自己的一些方案,大家来讨论下什么样的方式会好些,还有就是如何更好的实现暂停这种方法。

方案1,直接利用状态变量,如果处于暂停状态,则什么也不做(空循环)
public void keyPressed(KeyEvent e) {
		int keyCode = e.getKeyCode();
		int mDirection = sv.getMoveDirection();

		// KEY_START
		//如果是开始键,就设置程序状态为开始
		if (keyCode == SnakeKey.START) {
			gameState == RUNNING;
			return;
		}
		// KEY_PAUSE
		//如果是暂停键,就设置程序状态为开始
		if (keyCode == SnakeKey.PAUSE) {
			gameState == PAUSE;
			return;
		}
		//设置方向
		//省略其它按键的操作
		//...
		return;
	}

更新画面的线程

private Thread mRedrawHandler = new Thread() {
		@Override
		public void run() {
			try {
				while (true) {
					// if pause mode, do nothing
					if (mMode == PAUSE) {
						continue;
					}

					if (mMode == RUNNING) {
						// 进行更新操作
						// 省略部分代码
					}

					Thread.sleep(mMoveDelay);
				}

				if (mMode == LOSE) {
					// TODO sss
					// 重置 mScore
					// 重置 mMoveDelay
					// 记录当前得分,如果有排行榜的话
				}
			} catch (InterruptedException ex) {
			}
		}
	};

觉得这样的话 while 循环会占用大量的 CPU 时间 , 所以在 continue 前加了一个 Thread.sleep(1000); 先让程序停止 1s 钟。虽然不知道系统的原理是什么,但感觉自己写的空循环占用的资源要比 Thread.sleep() 要多吧。
if (mMode == PAUSE) {
        Thread.sleep(1000);
        continue; 
	}

可是觉得这样也不好,会影响程序的响应速度。

后来学习了线程的同步,就想着改成同步,在系统中加入一个锁,平时这个锁可以由画面线程获得,可是当按下 pause 时,就让另外的线程取得锁,这样的话,画面线程取得不到锁,就会自已停下来了。

接收键盘事件的函数

public void keyPressed(KeyEvent e) {
		int keyCode = e.getKeyCode();
		int mDirection = sv.getMoveDirection();
		// KEY_START
		if (keyCode == SnakeKey.START) {
			pauseOrResume();
			return;
		}
		// KEY_PAUSE
		if (keyCode == SnakeKey.PAUSE) {
			pauseOrResume();
			return;
		}

		//设置方向
		//省略其它按键的操作
		//...

		return;
	}

更新画面的线程

	private Thread mRedrawHandler = new Thread() {
		@Override
		public void run() {
			try {
				while (true) {
					synchronized (pauseLock) {
						// if pause mode, wait the lock.
						if (mMode == PAUSE) {
							pauseLock.wait();
						}
						pauseLock.notifyAll();
					}

					if (mMode == RUNNING) {
						// 进行更新操作
						// 省略部分代码
					}

					Thread.sleep(mMoveDelay);
				}
				if (mMode == LOSE) {
					// TODO sss
					// 重置 mScore
					// 重置 mMoveDelay
					// 记录当前得分,如果有排行榜的话
				}
			} catch (InterruptedException ex) {
			}
		}
	};

另外加了一个方法来控制锁:

	private Object pauseLock = new Object();
     /**
	 * Pause or resume the game
	 */
	private void pauseOrResume() {
		while (true)
			synchronized (pauseLock) {
				if (mMode == RUNNING) {
					mMode = PAUSE;
					break;
				}
				if (mMode == PAUSE || mMode == LOSE) {
					mMode = RUNNING;
					 // Tell the screen to run. 
					pauseLock.notifyAll();
					break;
				}
			}
	}

但是不知道在这种情况下会有什么不好,欢迎大家讨论。

附件是一个小的示例程序,大家可以看一下,可以是因为代码贴多了,不好容易看,可以下载附件看看示例。
=================================================
2009-05-23
1.更新了代码,删除了无用的部分代码
2.更新了TrafficLightsDemo.jar代码,修正原来的代码,使用在暂停时的响应时间减少。
3.贪吃蛇的程序已经放到论坛上,可以去下载看全部代码 http://www.iteye.com/topic/393669

你可能感兴趣的:(java,设计模式,多线程,thread,游戏)