一、引入
先来看一下最终效果。游戏在刚开始启动的时候,图片是随机打乱的。
但是在玩游戏的过程中我想看一下游戏完整的图片,该这么做呢?
我可以给这个游戏去安排一个快捷键,例如 A
,当我按住 A
不松的时候,它就会显示完整图片。
当松开 A
的时候,再去显示打乱的图片即可。
首先来思考:在什么时候,来执行的这段代码?
是不是我在整个窗体上玩游戏的时候,按键盘上的 A
触发的效果?
因此我们应该给整个窗体去绑定一个 键盘监听事件
。
当事件被触发之后,再去执行对应的代码即可。
在书写代码之前需要带着大家先去看一下我们导入的图片。
还是以 animal
下的 animal3
为例,双击打开:在每组图片中,除了给大家提供了 1 ~ 15
这样的小图片之外,额外的还有一个叫做:all.jpg
。
双击打开,这个其实就是游戏的完整图片。
它的大小看右上角:高和宽都是 420个像素
每一组图片都会有一个 all.jpg
,因此我们要做的其实就是按住 A
不松的时候,把 all.jpg
显示出来。
二、代码实现
找到 GameJFrame类
,首先第一个你要来想:我是在整个窗体上玩游戏的时候触发的键盘监听事件,因此我需要给整个窗体添加一个键盘监听。
但是不需要我们再去额外写代码了,因为在我们之前写 上下左右移动
的时候已经绑定过了,因此这一点我们可以忽略。
接下来继续,找一下重写 KeyListener接口
的方法:当键盘按键按下不松的时候,就会反复调用 keyPressed()
方法;当你松开的时候,就会调用 keyReleased()
方法,因此这两个方法我们都需要用到。
先来写 keyPressed()
重写方法。
通过形参的 e
获取到当前所对应到的 code
值。
然后就是对 按键a
做一个 if判断
。
这里一样要注意,在将完整图片添加到界面时,依旧需要先清空界面的图片,然后再来加载两张图片(完整图片、背景图片)。
图片的位置在之前也调试过了:(83, 134)
,宽高就是图片原来的大小:(420, 420)
。
添加背景图片的代码直接从 initImage()
中拷贝过来即可。
最后不要忘记 刷新界面
!
// 按下不松时会调用这个方法
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65) {
// 把界面中所有的图片全部删除
this.getContentPane().removeAll();
// 加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon("puzzlegame\\image\\animal\\animal3\\all.jpg"));
all.setBounds(83, 134, 420, 420);
this.getContentPane().add(all);
// 添加背景图片
JLabel background = new JLabel(new ImageIcon("puzzlegame\\image\\background.png"));
background.setBounds(40, 40, 508, 560);
// 把背景图片添加到界面当中
this.getContentPane().add(background);
// 刷新界面
this.getContentPane().repaint();
}
}
但此时还没结束,这个只是按下 a
的业务逻辑,我们还有松开,将图片变回去的代码没写!
因此在 keyReleased()
方法中,我们还要再来加一个判断。
松开的代码很简单:再次调用 initImage()
再来加载一下图片就行了。
在 initImage()
方法中,它还是会来清空图片,然后按照二维数组的顺序来加载 15
张小图片,最后加载背景图片。
因此我们直接调用 initImage()
方法即可。
//松开按键的时候会调用这个方法
@Override
public void keyReleased(KeyEvent e) {
//对上,下,左,右进行判断
//左:37 上:38 右:39 下:40
int code = e.getKeyCode();
System.out.println(code);
if (code == 37) {
.....
} else if (code == 38) {
.....
} else if (code == 39) {
.....
} else if (code == 40) {
.....
} else if (code == 65) {
initImage();
}
}
代码写完后,打开 App
右键运行,分别 按下
、松开
a键
,查看效果。
代码写完后,我们还需要做最后一步优化。
三、优化
现在不管是在 initImage()
方法中:animal
下的 animal3
下的 jpg图片
还是在展示完整图片的时候,路径都是写死的:animal
下的 animal3
下的 all.jpg
这么写的话它其实是有一个小弊端的:我们后面是不是要去写 更换游戏图片
,如果这里直接将路径写死的话,那么以后想要更换游戏图片,就会非常麻烦!
因此我们需要将这里的路径去改写一下,改写的方式也非常简单。
在成员位置去定义一个变量:用来记录当前展示图片的路径。
然后将重复的这一堆,可以直接粘贴过去 "puzzlegame\\image\\animal\\animal3\\"
// 定义一个变量,记录当前展示图片的路径
String path = "puzzlegame\\image\\animal\\animal3\\";
下面用到这个路径的时候,就不要去用后面的值了,直接使用 path
就行了。
private void initImage() {
this.getContentPane().removeAll();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
// 创建一个 JLabel对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon( path + num + ".jpg"));
}
}
}
背景图片就不需要使用这种方式了,因为背景图片它是固定的。
再往下,我们去展示完整图片的时候,也可以改写一下
// 按下不松时会调用这个方法
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65) {
// 加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
....
}
}
这样以后,如果我需要更换图片,那我就只需要更改 path变量
所记录的值就行了。