通过前面学习了java事件处理机制和java绘图技术,请试试看如何让自己的坦克可以通过按键控制上右下左(wdsa表示)的移动。
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
//2. 为了监听键盘事件,实现KeyListener
public class MyPanel extends JPanel implements KeyListener {
//定义我的坦克
Hero hero = null;
public MyPanel() {
hero = new Hero(100, 100);//初始化自己坦克
// hero.setSpeed(5); 可以在构造器中修改速度
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色
//画出坦克-封装方法
drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
}
//编写方法,画出坦克
/**
*
* @param x 坦克的左上角x坐标
* @param y 坦克的左上角y坐标
* @param g 画笔
* @param direct 坦克方向,上下左右
* @param type 坦克类型
*/
public void drawTank(int x, int y, Graphics g, int direct,int type) {
switch (type) {
case 0: //敌人坦克
g.setColor(Color.cyan);
break;
case 1: //我们坦克
g.setColor(Color.yellow);
break;
}
//1. 根据坦克的方向来绘制对应形状的坦克
//1.1 direct 表示方向(0:向上,1:向右,2:向下,3:向左)
switch (direct) {
case 0: //表示向上
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克主体
g.fillOval(x + 10, y + 20, 20,20);//画出坦克盖子
g.drawLine(x + 20, y + 30, x + 20, y);
break;
case 1: //表示向右
g.fill3DRect(x, y, 60, 10, false);//画出坦克左边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克主体
g.fillOval(x + 20, y + 10, 20,20);//画出坦克盖子
g.drawLine(x + 30, y + 20, x + 60 , y + 20);//炮筒
break;
case 2: //表示向下
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克主体
g.fillOval(x + 10, y + 20, 20,20);//画出坦克盖子
g.drawLine(x + 20, y + 30, x + 20, y + 60);
break;
case 3: //表示向左
g.fill3DRect(x, y, 60, 10, false);//画出坦克左边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克主体
g.fillOval(x + 20, y + 10, 20,20);//画出坦克盖子
g.drawLine(x + 30, y + 20, x , y + 20);//炮筒
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
//2.1 处理 wdsa 键按下的情况
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) { //按下w键
//2.2 改变坦克方向
hero.setDirect(0);
//3 修改坦克的坐标,让坦克动起来
//在此处修改坦克的坐标会使问题变得麻烦
//我们可以采用封装的方式,在Tank类中编写一个move方法,在此处调用来实现坦克的移动
hero.moveUp();
} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键
hero.setDirect(1);
hero.moveRight();
} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键
hero.setDirect(2);
hero.moveDown();
} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键
hero.setDirect(3);
hero.moveLeft();
}
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
}
这个类的主要修改是: 首先在drawTank中Switch新增了坦克在不同方向上的绘画. 然后是实现了KeyListener接口, 来监听键盘事件, wdsa按下的时候 改变方向加移动. 切记:当你的坦克不显示移动时,可能是忘了添加repaint()方法, repaint()方法会重绘画板。
public class Tank {
private int x;//坦克的横坐标
private int y;//坦克的纵坐标
private int direct;//坦克方向 w上 d右 s下 a左
private int speed = 1;//速度 快慢(数字大小)
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public void moveUp() {
y -= speed;
}
public void moveRight() {
x += speed;
}
public void moveDown() {
y += speed;
}
public void moveLeft() {
x -= speed;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
}
这个类,我们新增了两个变量direct和speed。然后增加了四个move方法。这几个move方法(修改x和y坐标实现tank移动),在MYPanel中利用这几个方法会更加方便
import javax.swing.*;
public class YzjTankGame02 extends JFrame {
//定义MyPanel
MyPanel mp = null;
public static void main(String[] args) {
YzjTankGame02 yzjTankGame01 = new YzjTankGame02();
}
public YzjTankGame02() {
mp = new MyPanel();
this.add(mp);//把面板(就是游戏的绘图区域)
this.setSize(1000, 750);
this.addKeyListener(mp);//让JFrame 监听mp的键盘事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
修改只有一点:is.addKeyListener(mp);//让JFrame 监听mp的键盘事件
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;
//2. 为了监听键盘事件,实现KeyListener
public class MyPanel extends JPanel implements KeyListener {
//定义我的坦克
Hero hero = null;
//4. 定义敌人坦克,放入Vector中
Vector<EnemyTank> enemyTanks = new Vector<>();
int enemyTankSize = 3;
public MyPanel() {
hero = new Hero(100, 100);//初始化自己坦克
// hero.setSpeed(5); 可以在构造器中修改速度
//4.1 初始化敌人的坦克,方向朝下
for (int i = 0; i < enemyTankSize; i++) {
//创建一个敌人的坦克
EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);
//设置方法
enemyTank.setDirect(2);
//加入Vector
enemyTanks.add(enemyTank);
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色
//画出自己的坦克-封装方法
drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
//4.2 画出敌人的坦克, 遍历Vector
for (int i = 0; i < enemyTankSize; i++) {
//4.3 取出坦克
EnemyTank enemyTank = enemyTanks.get(i);
drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
}
}
//编写方法,画出坦克
/**
*
* @param x 坦克的左上角x坐标
* @param y 坦克的左上角y坐标
* @param g 画笔
* @param direct 坦克方向,上下左右
* @param type 坦克类型
*/
public void drawTank(int x, int y, Graphics g, int direct,int type) {
switch (type) {
case 0: //敌人坦克
g.setColor(Color.cyan);
break;
case 1: //我们坦克
g.setColor(Color.yellow);
break;
}
//1. 根据坦克的方向来绘制对应形状的坦克
//1.1 direct 表示方向(0:向上,1:向右,2:向下,3:向左)
switch (direct) {
case 0: //表示向上
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克主体
g.fillOval(x + 10, y + 20, 20,20);//画出坦克盖子
g.drawLine(x + 20, y + 30, x + 20, y);
break;
case 1: //表示向右
g.fill3DRect(x, y, 60, 10, false);//画出坦克左边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克主体
g.fillOval(x + 20, y + 10, 20,20);//画出坦克盖子
g.drawLine(x + 30, y + 20, x + 60 , y + 20);//炮筒
break;
case 2: //表示向下
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边的轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克主体
g.fillOval(x + 10, y + 20, 20,20);//画出坦克盖子
g.drawLine(x + 20, y + 30, x + 20, y + 60);
break;
case 3: //表示向左
g.fill3DRect(x, y, 60, 10, false);//画出坦克左边的轮子
g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边的轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克主体
g.fillOval(x + 20, y + 10, 20,20);//画出坦克盖子
g.drawLine(x + 30, y + 20, x , y + 20);//炮筒
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
//2.1 处理 wdsa 键按下的情况
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) { //按下w键
//2.2 改变坦克方向
hero.setDirect(0);
//3 修改坦克的坐标,让坦克动起来
//在此处修改坦克的坐标会使问题变得麻烦
//我们可以采用封装的方式,在Tank类中编写一个move方法,在此处调用来实现坦克的移动
hero.moveUp();
} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键
hero.setDirect(1);
hero.moveRight();
} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键
hero.setDirect(2);
hero.moveDown();
} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键
hero.setDirect(3);
hero.moveLeft();
}
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
}
主要添加的内容是:注释为4的所有
public class EnemyTank extends Tank{
public EnemyTank(int x, int y) {
super(x, y);
}
}