乱侃
我上完了一个学期的Java课程,想自己做一些Java小游戏来玩玩,才发现一个学期在课堂上学习的东西简直太少太少了。 即使期末考试拿到高分,但是实际应用起来,要做一个游戏程序,发现并不是那么容易……
本来想做一个超级玛丽的游戏,但是完全没有头绪……
后来去找CC老师指引人生方向,得知可以先试试做《推箱子》一类的游戏,即如何控制物体移动;接下来可以试试做《贪食蛇》,即在没有用户输入的时候物体仍然在自动移动;这两个任务完成了之后,再考虑《超级玛丽》的事情。
假设你和我一样刚刚学会了Java基本概念,但处于一个难以应用的境界。第一篇《Java游戏点滴》将介绍如何使用KeyListener来做一个简单的控制物体移动。
正文
我们要达到的目的,是在JFrame里画一个圆形,通过方向键控制圆形移动。
首先,我们新建一个类,这个类继承JFrame,我们的程序完全使用这一个类完成。接下来按照课堂上学的方法,覆盖掉JFrame的默认构造函数,将JFrame进行初始化,不再细说了。
要画一个圆形,很显然需要几个成员变量来记录圆形的位置和半径。
private int x,y;
private int r;
然后我们需要实现KeyListener接口,并且覆盖这个接口的三个抽象方法:
public void keyPressed ( KeyEvent e ) {}
public void keyReleased ( KeyEvent e ) {}
public void keyTyped ( KeyEvent e ) {}
别忘了给JFrame注册监听器,即在JFrame的构造函数当中加入addKeyListener(this);这句。
当按下方向键的时候,我们改变x,y的坐标值,使得圆形在面板上移动。(注意,我们这里只是设置了圆形的几个参数,并没有将圆形绘制到屏幕上去。关于绘制我们放在后面)实现这个功能的代码写在keyPressed方法中,即按下键盘时执行这些语句。
这里遇到一个很实际的问题:在keyPressed方法中如何得知按下的是那个键?
这个问题的答案就在keyPressed方法参数KeyEvent e当中,参数中就包含了所按下按键的信息。使用e.getKeyCode()方法会返回一个int型的值。单纯看这个值也一时不能判断哪个按键。
幸运的是KeyEvent类中定义了所有的键盘按键常量,用e.getKeyCode()方法获得的值与这些常量判等,就能知道按下的是什么键。下面给出常用的按钮的常量:
KeyEvent.VK_SPACE 空格
KeyEvent.VK_ENTER 回车
KeyEvent.VK_SHIFT shift
KeyEvent.VK_CONTROL ctrl
KeyEvent.VK_A ~ Z A ~ Z
KeyEvent.VK_0 ~ 9 0 ~ 9
KeyEvent.VK_UP 方向键 上
KeyEvent.VK_DOWN 下
KeyEvent.VK_LEFT 左
KeyEvent.VK_RIGHT 右
这样,我们的keyPressed方法可以这样写:
public void keyPressed(KeyEvent e){
int key = e.getKeyCode(); //获取按键码
switch(key){
case KeyEvent.VK_UP: //按下方向键 上
y-=10; break;
case KeyEvent.VK_DOWN: //按下方向键 下
y+=10; break;
case KeyEvent.VK_LEFT: //按下方向键 左
x-=10; break;
case KeyEvent.VK_RIGHT: //按下方向键 右
x+=10; break;
}
//在这里绘制图形
}
那么,这个程序的核心我们算是完成了,后面的工作仅仅是将圆形按照当前的坐标绘制到屏幕上。
要在JFrame中绘制图形,需要用到JFrame的getGraphics()方法,它可以获取这个组件的图形上下文,它返回一个Graphics类的对象,这个对象可以向组件中绘制各种图形图片文字等。
Graphics类提供了绘制椭圆的方法,g.fillOval(x, y, w, h);它将绘制一个以x,y为左上角w,h为宽高的矩形作为外框的椭圆。绘制圆形只需把这个矩形设置成正方形。
在keyPressed()方法的最后加上这样两句话:
Graphics g = this.getGraphics();
g.fillOval(x-r, y-r, 2*r, r*2);
目前为止,程序基本完成。在main()方法中new你的这个类就可以运行了。当然不要忘了在构造函数中写必要的设置和初始化x,y,r的值。
运行后你会发现一个问题,按下方向键虽然有一个圆形在移动,但是移动之前的图象仍然残留在屏幕上。其原因是使用Graphics类在组件中绘制图形时每次绘制都是在上一次绘制的基础上进行的,清除屏幕需要手动进行。
所以我们应该在画圆形之前清除屏幕上的图象:
g.clearRect(0, 0, 600, 400); //这里后两个参数是你设置JFrame的宽度和高度
这里给出整个程序的代码:
-----------------------------------------------------------------------------------------
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MoveItem extends JFrame implements KeyListener{
private int x,y;
private int r;
//默认构造函数
public MoveItem(){
x=300;
y=200;
r=50;
this.setSize(600, 400);
this.addKeyListener(this);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
//KeyListener方法
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode(); //获取按键码
switch(key){
case KeyEvent.VK_UP: //向上
y-=10; break;
case KeyEvent.VK_DOWN: //向下
y+=10; break;
case KeyEvent.VK_LEFT: //向左
x-=10; break;
case KeyEvent.VK_RIGHT: //向右
x+=10; break;
}
//绘制图形
Graphics g = this.getGraphics();
g.clearRect(0, 0, 600, 400);
g.fillOval(x-r, y-r, 2*r, r*2);
}
//main方法
public static void main(String args[]){
new MoveItem();
}
}
---------------------------------------------------------------------------------------
这个移动圆形的程序也就完成了。你会发现这个程序存在许多问题,而这些问题也就是我们以后需要解决的。粗略得列一下存在的问题:
1。初始时看不到图象,只有按下按键只有才显示出来。
2。你也许会发现圆形移动时,屏幕会出现严重的闪烁。
3。控制不够平缓,手感不好。
4。图形不能自动运动。
…… ……
小节
这个程序中,值得研究的东西一个是KeyEvent类,另一个是Graphics类。
事件监听在程序中用得十分常见,应该熟悉如何对各种组件添加不同的事件监听器。