清单 5 显示了用于移动实体的逻辑。这个过程在每个动画周期中执行一次。
清单 5. 移动所有实体
1 /** Move the entities around the pattern */
2 public void moveEntities() {
3 // update (move) the people
4 for (Iterator iter = people.iterator(); iter.hasNext();) {
5 Object next = iter.next();
6 if (next instanceof Person) {
7 ((Person)next).updateTick();
8 }
9 }
10 // update the other entities
11 for (Iterator iter = entities.iterator(); iter.hasNext();) {
12 Object next = iter.next();
13 if (next instanceof Entity) {
14 ((Entity)next).updateTick();
15 }
16 }
17 }
18
2 public void moveEntities() {
3 // update (move) the people
4 for (Iterator iter = people.iterator(); iter.hasNext();) {
5 Object next = iter.next();
6 if (next instanceof Person) {
7 ((Person)next).updateTick();
8 }
9 }
10 // update the other entities
11 for (Iterator iter = entities.iterator(); iter.hasNext();) {
12 Object next = iter.next();
13 if (next instanceof Entity) {
14 ((Entity)next).updateTick();
15 }
16 }
17 }
18
动画中的每个新帧(frame)都是由清单 6 所显示的过程创建的。注意实体将它们自己添加到帧中。
清单 6. 在当前位置添加实体
1 /** Advance the animation */
2 public void prepareNextFrame(boolean update, boolean shared) {
3 setBackground(Color.black);
4 if (update) {
5 manager.moveEntities();
6 }
7 mainPanel.setBounds(getBounds());
8 mainPanel.removeAll();
9 // add the people
10 for (Iterator iter = manager.getPeople().iterator();
11 iter.hasNext();) {
12 Person person = (Person)iter.next();
13 person.addToPanel(mainPanel, shared);
14 }
15 // add the entities
16 for (Iterator iter = manager.getEntities().iterator();
17 iter.hasNext();) {
18 Entity entity = (Entity)iter.next();
19 entity.addToPanel(mainPanel, shared);
20 }
21 }
22
2 public void prepareNextFrame(boolean update, boolean shared) {
3 setBackground(Color.black);
4 if (update) {
5 manager.moveEntities();
6 }
7 mainPanel.setBounds(getBounds());
8 mainPanel.removeAll();
9 // add the people
10 for (Iterator iter = manager.getPeople().iterator();
11 iter.hasNext();) {
12 Person person = (Person)iter.next();
13 person.addToPanel(mainPanel, shared);
14 }
15 // add the entities
16 for (Iterator iter = manager.getEntities().iterator();
17 iter.hasNext();) {
18 Entity entity = (Entity)iter.next();
19 entity.addToPanel(mainPanel, shared);
20 }
21 }
22
我们用清单 7 中的代码实现连续的动画。 delay 值控制动画运行的快慢以及它占用 CPU 时间的多少。
清单 7. 动画周期
1 public void runUpdates(int delay) {
2 TimerTask task = new TimerTask() {
3 public void run() {
4 SwingUtilities.invokeLater(new Runnable() {
5 public void run() {
6 prepareNextFrame();
7 repaint();
8 if (manager.getPeople().size() == 0) {
9 cancel();
10 }
11 }
12 });
13 }
14 };
15 (new Timer(true)).scheduleAtFixedRate(task, 0, delay);
16 }
17
2 TimerTask task = new TimerTask() {
3 public void run() {
4 SwingUtilities.invokeLater(new Runnable() {
5 public void run() {
6 prepareNextFrame();
7 repaint();
8 if (manager.getPeople().size() == 0) {
9 cancel();
10 }
11 }
12 });
13 }
14 };
15 (new Timer(true)).scheduleAtFixedRate(task, 0, delay);
16 }
17
下面是我们动画序列的几个屏幕快照。图 7 显示了在行动之前的逃生模拟(完成了全部过程的大约 10%)。
图 7. 刚开始时的逃生序列
图 8 显示在完成了大约 50% 时的动画序列。
图 8. 数次更新后的逃生序列
图 9 显示接近完成时的序列(尽管序列实际上是无限循环运行的)。
图 9. 接近完成时的逃生序列
在图 10 中可以看到实体是如何沿着控制路径移动的,它应当可以让您更好地理解运行是如何实现的。
图 10. 实体沿着控制路径移动