Java游戏点滴 - 使用KeyListener控制图形移动

来源:互联网 发布:简单的c语言程序代码 编辑:程序博客网 时间:2024/06/05 06:12

 

乱侃

我上完了一个学期的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类。

事件监听在程序中用得十分常见,应该熟悉如何对各种组件添加不同的事件监听器。