1回顶部 谁说编写程序不是一项艺术?那些命令与符号正像一幅工笔画,一笔一画产生出多少变幻莫测的结果。不过,光有骨架的工笔画恐怕也无法成为绝世佳作,那么,今天就让我们来为自己的作品添上最初的绚丽色彩吧。 前言 今天我们会为游戏添加动画效果,这将会涉及到图形处理,还有线程的基本概念,这可是一项非常有意思的工作哦。本期源程序下载(点击下载, 2KB, winzip压缩)。 上一期我们完成了游戏界面的设计,可是游戏的功能却还十分单薄,比如说几个人同时玩一个游戏,我们怎么比较谁玩得比较好呢,就算是自己一个人在玩,也得知道自己每次的成绩啊。竞技是游戏的主要动力之一,为了提高游戏的可玩性,我们得加入计时和计分的功能才行。 关于游戏的计时和计分功能,因为与我们Swing的主题关系不大,这部分功能的实现我就不说了,如果大家感兴趣的话可以参考一下我的源程序,里面有详细的说明,在这里我们就只讨论一下如何将显示界面做得漂亮。 JLabel和Font 还记得最开始的主界面是如何设计的吗?我们将界面分成了三个部分:系统菜单、游戏区、用户交互区。用户交互区的作用就是放置用户的操作及反馈信息,计时和计分功能自然就是放在这里。 首先我们可以放置一个文本控件,然后将这个控件的背景设置为界面的背景色或透明色。那么这个控件应该是哪个呢?这个控件就是JLabel!JLabel的用法并不难,如果你能够熟练使用JButton的话,那么JLabel控件也会是小case了,让我们一起来试试吧: JLabel score = new JLabel("307"); // 假设用户当前的分数为307分 看看程序运行的结果,感觉如何?你也许会说:字太小了,而且颜色也太暗了,看不太清楚。没关系,这很容易解决: JLabel score = new JLabel("307"); 在上面的代码中,我们首先创建了一个字体对象font,Font构造函数中3个参数的意义依次为:使用字体的名称、字体的样式(普通、粗体、斜体等)以及字体的大小等;然后,我们使用setForeground来设计JLabel的前景色;最后,我们将JLabel的字体改为我们创建的字体。现在我们再来看看程序运行的结果,是不是效果好多了(见图1)? 在游戏的过程中,只要时间或者分数发生变化,我们就可以使用JLabel.setText(String s)来更新显示。 细心的朋友可能会发现,在我们显示时间和分数的过程中,如果将字体设置得很大,显示内容虽然更容易看清,但视觉效果却变得很差。这是因为字体越大,字体上的锯齿就会越明显,这是Swing控件显示文字的通病,遗憾的是暂时还没有很有效的解决方法(见图2)。 2回顶部 善用Graphics绘制图形 在前面所有的章节中,我们都是使用现成的控件来满足自己的需要,现成的控件虽然使用方便,却不能完全满足我们的要求。这时我们就需要了解一下如何不使用控件来绘制图形。 无论是Swing控件也好,AWT控件也好,他们都会有一个paint(Graphics g)方法,一般情况下我们不会去理它的,然而,当我们需要自己绘制图形的时候,我们就不得不对这个方法有所了解。 为了让大家能够接受自己绘制图形的方法,我们还是从paint(Graphics g)方法讲起吧:paint(Graphics g)方法将控件看作一张空白的纸,当我们需要绘制图形的时候,就可以使用Graphics提供的一些基本方法来进行绘制。为了方便大家理解,我们新建一个Clock类来完成用户时间的显示,代码如下: import javax.swing.*; 以上内容应该在我们新建的Clock.java文件中,代码并不难读懂,大家可以自己查看文档找到相关函数的使用说明。然后,我们将原来程序中显示时间的代码部分改为: Clock clock = new Clock(); 怎么样,运行结果是否相同?虽然此时我们仍然没有消除文字上的锯齿,不过已经对Swing中自己绘制图形有了一个大致的了解。 随心所欲的Graphics2D 对于追求最佳视觉效果的我们,文字上的锯齿显示是不能容忍的。那么如何解决这个问题呢?既然这是Swing控件显示字体的通病,并且就连Graphics也无能为力,看来,我们只有另辟蹊径了。 好在Sun也意识到了这一点,因此在Java中提供了Graphics2D类来解决这种问题。下面,我们将依然使用代码来说明问题: public void paint(Graphics g) { 在上述的代码中,我们将Graphics对象转换成Graphics2D对象后,只需使用简单的一句setRenderingHint()就完成了抗锯齿的功能。现在再来看看程序运行的效果,你还满意吗(见图3)? 3回顶部 让文字活起来 渴望无限,创造无限。如果能把计分和计时功能做成动画,一定会更加生动。最简单的做法就是让数字依次变化,比如说时间,我们可以每隔1秒钟就显示一次数值,比如说上面的代码,我们可以简单改为: for (int i = 1000; i < 2000; i++) { 当你执行以上代码以后便会知道,上面的代码实际上有问题!我们使用了Thread.sleep(1000)来让程序进行延时,每当执行Thread.sleep()的时候,程序会进入休眠状态,不响应其他任何操作,就连显示也不会更新,所以也就无从显示动画效果了。 线程(Thread)是惟一的解决方法,它可以让程序在同一个时刻完成两件或者两件以上的事情。想让你的程序支持线程,你可以选择以下两种方法的任意一种: ①public class Clock extends Thread 第一种方法要求你的程序继承Thread类,可是,如果继承Thread类之后,我们就没有办法再继承JPanel了,因为Java不支持多重继承,如果不能继承JPanel,那么paint(Graphics g)也没有用武之地了。而第二种方法只要求你实现Runnable接口,而Java允许一个类实现多个接口,所以我们应该选择第二种方法。 首先需要把Clock的声明改成public class Clock extends JPanel implements Runnable,然后添加public void run() { } 上面是实现Runnable接口的最基本的构架。有的时候,为了让线程能够具备开始和停止的功能,我们还得再扩充一下。首先是线程的开始: public void start() { 这里我们使用了System.currentTimeMillis()来获得开始时的系统时间,以便于以后计算用户的游戏时间。 然后是运行的过程: public void run() { 第一句话Thread currentThread = Thread.currentThread();获得系统当前的线程,然后在循环中进行判断是否为当前线程,这在在线程比较多而且线程之间的依赖性比较强的情况下非常有必要。repaint() 是AWT/Swing控件的方法,它会自动调用paint(Graphics g)方法以便重新绘制显示区域。最后,我们使用了thread.sleep(100)来让程序每隔0.1秒运行一次。由于thread.sleep()方法会抛出异常,所以我们还需要捕获异常。 由于paint(Graphics g)每次显示的内容都会不同,因此,我们需要使用一个全局全量usedTime来记录当前的时间,在输出的时候,我们应写成: g2.drawString("TimE:" + getTime(), 16, 40); 其实getTime()方法是我们自己写的,其作用是获得用户当前使用的时间,并将时间格式化后传出。最后,别忘记了在我们的主程序中调用start()方法,如: Clock clock = new Clock(); 小方糖 Thread的前世今生 最早的Thread提供了Thread.start() 、Thread.pause()/Thread.resume() 、Thread.stop() 这三个方法来完成线程的开始、暂停和结束功能,然而,在后来的JDK中,Sun却不推荐使用pause()/resume()和stop()方法,理由是pause()和stop()方法在某些场合会让程序进入死锁状态,因此,在你的程序中,假如你使用了Thread的以上几种方法,编译的时候编译器会告诉你 "xxx.java": stop() in java.lang.Thread has been deprecated at line xx, column xx 这时候你就要注意了! 小结 今天我们学习了使用Graphics/Graphics2D来满足自己特殊的需要,再也不需要看控件的脸色了。同时,我们也知道了如何使用线程来让程序同时进行多个操作,并且结合了以上两点来实现计时功能。但是我没有在这里完成计分功能,就把这当作留给大家的小小作业吧! |
闂傚倸鍊搁崐鎼佸磹瀹勬噴褰掑炊椤掆偓杩濋梺閫炲苯澧撮柡灞剧〒閳ь剨缍嗛崑鍛暦瀹€鍕厸鐎光偓閳ь剟宕伴弽顓溾偓浣糕槈濡嘲鐗氶梺鍛婂姉閸嬫挸袙婢跺绻嗛柣鎰典簻閳ь剚鍨垮畷鏇㈠蓟閵夈儱鐎梺绉嗗嫷娈旈柦鍐枛閺岋綁寮崶銉㈠亾閳ь剟鏌涚€n偅灏柍钘夘槸閳诲秹顢樿缁ㄥジ鏌熸笟鍨鐎规洘鍎奸ˇ顕€鏌¢埀顒勬嚍閵夛絼绨婚梺鍝勬川閸嬬偤藟閻愮儤鍊垫慨妯煎亾鐎氾拷闂傚倸鍊搁崐鎼佸磹妞嬪海鐭嗗〒姘e亾妤犵偞鐗犻、鏇㈠Χ閸℃ぞ绮℃俊鐐€栭崝褏绮婚幋鐘差棜闁秆勵殕閻撴洟鏌熼柇锕€鐏遍柛銈咁儔閺屻倝寮堕幐搴′淮闂佸搫鏈粙鎴﹀煡婢跺ň鏋庨柟閭﹀枤閳诲繒绱撻崒姘偓椋庢媼閺屻儱鐤鹃柣妯款嚙閽冪喖鏌i弮鍌楁嫛闁轰礁绉电换婵囩節閸屾碍鐏撻梺鍝勬-閸樺ジ鈥旈崘顔嘉ч柛鎰╁妼婵兘姊洪悷鏉挎闁瑰嚖鎷�>>
正在阅读:跟我学Java Swing之游戏设计(3)跟我学Java Swing之游戏设计(3)
2005-10-26 10:04
出处:
责任编辑:xietaoming