在做坦克大战的小程序,坦克无法被键盘控制,程序运行后,依然还是贴了第一张,想知道具体原因。
代码如下:
TankJFrame类:
import java.awt.*;
import javax.swing.*;
/**
* 坦克主体框架,继承JFrame类
*
* **/
public class TankFrame extends JFrame{
private static final long serialVersionUID = 1L;
//设置窗口的宽和高
public static int window_width = 1500;
public static int window_hight = 1000;
//新建tankPanel
TanksPanel t_panel = new TanksPanel();
//启动框架
public void lunchFrame() {
setTitle("坦克大战");
setSize(window_width, window_hight);
setLocation(200, 10);
//add各个组件
add(t_panel);
//添加键盘控制
addKeyListener(t_panel.p_tanks.k_contral);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
//窗口大小不可变
setResizable(false);
//启动线程
new Thread(t_panel).start();
}
//主函数
public static void main(String args[]) {
new TankFrame().lunchFrame();
}
}
TankPanel类:
import java.awt.*;
import javax.swing.*;
/**
* 坦克主面板函数,继承JPanel类
* **/
public class TanksPanel extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;
//新建玩家坦克
PlayerTanks p_tanks = new PlayerTanks(100, 100, false);
//重载paintComponent方法
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//绘制背景
g.fillRect(0, 0, TankFrame.window_width, TankFrame.window_hight);
//绘制玩家坦克
p_tanks.drawTanks();
g.drawImage(p_tanks.getTankImage(), p_tanks.getLocal_x(), p_tanks.getLocal_y(), p_tanks.getTanks_width(), p_tanks.getTanks_hight(), this);
p_tanks.move();
}
@Override
//实现Runnable接口抽象方法run
public void run() {
while(true) {
this.repaint();
//实现线程,使坦克每隔100毫秒重新绘制一次
try {
Thread.sleep(100);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Tanks类:
import java.awt.*;
/**
* 坦克抽象父类,定义敌方与玩家坦克的共有属性和抽象方法
*
* **/
public abstract class Tanks {
//坦克初始位置坐标,x值和y值
int local_x;
int local_y;
//坦克的大小,即贴图的宽高
int tanks_width = 300;
int tanks_hight = 300;
//坦克的速度
int speed = 100;
//坦克的移动方向
Orientation oriTanks;
//坦克炮塔的移动方向
Orientation oriTurret;
//声明坦克贴图
Image tankImage;
//判断坦克是否存活
boolean isAlive = true;
//判断坦克是否为玩家坦克
boolean isEnemy = false;
//将变量进行封装
public int getLocal_x() {
return local_x;
}
public void setLocal_x(int local_x) {
this.local_x = local_x;
}
public int getLocal_y() {
return local_y;
}
public void setLocal_y(int local_y) {
this.local_y = local_y;
}
public int getTanks_width() {
return tanks_width;
}
public void setTanks_width(int tanks_width) {
this.tanks_width = tanks_width;
}
public int getTanks_hight() {
return tanks_hight;
}
public void setTanks_hight(int tanks_hight) {
this.tanks_hight = tanks_hight;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Orientation getOriTanks() {
return oriTanks;
}
public void setOriTanks(Orientation oriTanks) {
this.oriTanks = oriTanks;
}
public Orientation getOriTurret() {
return oriTurret;
}
public void setOriTurret(Orientation oriTurret) {
this.oriTurret = oriTurret;
}
public Image getTankImage() {
return tankImage;
}
public void setTankImage(Image tankImage) {
this.tankImage = tankImage;
}
public boolean isAlive() {
return isAlive;
}
public void setAlive(boolean isAlive) {
this.isAlive = isAlive;
}
public boolean isEnemy() {
return isEnemy;
}
public void setEnemy(boolean isEnemy) {
this.isEnemy = isEnemy;
}
//构造方法
public Tanks(int local_x, int local_y, boolean isEnemy) {
super();
this.local_x = local_x;
this.local_y = local_y;
this.isEnemy = isEnemy;
}
//获取图片绘制坦克抽象函数
public abstract void drawTanks();
//移动函数
public abstract void move();
//获取当前位置,返回整张矩形(坦克)
public abstract Rectangle getRect();
//获取下一个矩形的位置,返回整个下一个矩形
public abstract Rectangle getNextRect();
}
PlayerTanks类:
import java.awt.*;
import java.awt.event.*;
/**
* 玩家坦克类,继承坦克父类Tanks
* **/
public class PlayerTanks extends Tanks{
//坦克移动方向
Orientation oriTanks = Orientation.Stop;
//坦克炮塔方向
Orientation oriTurret = Orientation.U;
public KeyContral k_contral = new KeyContral();
//构造函数
public PlayerTanks(int local_x, int local_y, boolean isEnemy) {
super(local_x, local_y, isEnemy);
}
@Override
//绘制坦克函数
public void drawTanks() {
switch(oriTurret) {
//炮塔向上图片
case U:
oriTurret = Orientation.U;
setTankImage(Toolkit.getDefaultToolkit().getImage("image/t1_shang.png"));
break;
//炮塔向左图片
case L:
oriTurret = Orientation.L;
setTankImage(Toolkit.getDefaultToolkit().getImage("image/t1_zuo.png"));
break;
//炮塔向下图片
case D:
oriTurret = Orientation.D;
setTankImage(Toolkit.getDefaultToolkit().getImage("image/t1_xia.png"));
break;
//炮塔向上图片
case R:
oriTurret = Orientation.R;
setTankImage(Toolkit.getDefaultToolkit().getImage("image/t1_you.png"));
break;
default:
setTankImage(Toolkit.getDefaultToolkit().getImage("image/t1_shang.png"));
break;
}
}
@Override
//判断坦克是否越界
public void move() {
//用户按“W”,坦克向上走时
if(oriTanks == Orientation.U) {
//坐标减每一次移动,每一次都大于0(不越界)
if(local_y - speed >= 0)
//向上移动,使用方法,更加安全
setLocal_y(local_y -= speed);
}else if(oriTanks == Orientation.L) {//用户按“A”, 坦克向左走
if(local_x - speed >= 0)
setLocal_x(local_y -= speed);
}else if(oriTanks == Orientation.D) {//用户按“S”, 坦克向下走
if(local_y + speed <= TankFrame.window_hight)
setLocal_y(local_y += speed);
}else if(oriTanks == Orientation.R) {//用户按“D”, 坦克向右走
if(local_x + speed <= TankFrame.window_width)
setLocal_x(local_x += speed);
}else {}
}
@Override
public Rectangle getRect() {
// TODO 自动生成的方法存根
return null;
}
@Override
public Rectangle getNextRect() {
// TODO 自动生成的方法存根
return null;
}
//内部类,继承KeyAdapter
public class KeyContral extends KeyAdapter{
//重写KeyPressed函数来实现对键盘按压事件的收集,做出坦克的移动
public void KeyPressed(KeyEvent e) {
super.keyPressed(e);
//判断用户按下的按键
if(e.getKeyCode() == KeyEvent.VK_W) {//用户按“W”,坦克向上走
oriTanks = oriTurret = Orientation.U;
}else if(e.getKeyCode() == KeyEvent.VK_A) {//用户按“A”, 坦克向左走
oriTanks = oriTurret = Orientation.D;
}else if(e.getKeyCode() == KeyEvent.VK_S) {//用户按“S”,坦克向下走
oriTanks = oriTurret = Orientation.L;
}else if(e.getKeyCode() == KeyEvent.VK_D) {//用户按“D”,坦克向右走
oriTanks = oriTurret = Orientation.R;
}else {//用户按其他按键,坦克不移动
oriTanks = oriTurret = Orientation.Stop;
}
}
//重写KeyReleased,判断用户松开KeyPressed定义的按键后,坦克停止移动
public void KeyReleased(KeyEvent e) {
super.keyReleased(e);
//判断用户释放的是否是所定义好的按键
if(e.getKeyCode() == KeyEvent.VK_W ||e.getKeyCode() == KeyEvent.VK_A || e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_D) {
oriTanks = Orientation.Stop;
}
}
}
}
枚举:
public enum Orientation {
U, D, L, R, Stop;
}
运行结果: