第16章:坦克大战1.0
总体内容
- 1.0版本包括:绘制游戏区域,绘制坦克(敌人和我方),实现用键盘按键来操控坦克上下左右移动(且移动过程中,坦克炮筒朝向发生变化)
- 本文中的案例包括:
①用java在面板上画一个圆圈
②小球受键盘按键控制进行移动,- 本文中项目完成包括:
①绘制游戏区域
②绘制我方坦克
③控制坦克上下左右移动
④绘制敌人坦克(注意炮筒方向)
项目说明
坦克大战的演示就省略了,和小时候玩的坦克大战差不多
java绘图坐标体系
坐标体系 - 介绍
坐标体系 - 像素
java绘图技术
绘图快速入门案例
案例要求:在面板上画一个小圆
步骤:
- 写一个面板类MyPanel(继承Panel),重写paint()(绘图)方法,在方法内调用Graphics(画笔)的方法drawOval()来画园
- 写一个窗口类Excise(继承JFrame),在窗口类中定义一个面板对象,在构造器中初始化该对象,并把面板放到窗口中,设置窗口大小和是否可见
- 在主方法中创建窗口类对象。创建对象时会调用构造器,对窗口和面板进行设置,并调用paint()方法绘制圆
import javax.swing.*;
import java.awt.*;
//JFrame 相当于一个窗口
// 本例中窗口(Excise继承了JFrame)内有一画板(MyPanel),用画笔(Graphics)来绘图
public class Excise extends JFrame {//JFrame对应一个窗口
//定义一个面板
private MyPanel mp = null;
//主方法
public static void main(String[] args) {
new Excise();
}
//构造器
public Excise() {
//初始化面板
mp = new MyPanel();
//把面板放到窗口中
this.add(mp);
//设置窗口大小
this.setSize(400, 300);
//设置窗口可以显示
this.setVisible(true);
//设置 当点击窗口的X时,程序完全退出
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//定义一个MyPanel类(面板类),继承JPanel
// 画图形,就在面板上画
class MyPanel extends JPanel {
//说明:
//1. MyPanel对象 相当于一个画板
//2. Graphics g 这里g相当于画笔
//3. Graphics中提供了很多绘图的方法
@Override
public void paint(Graphics g) {//paint()是绘图方法
super.paint(g);//调用父类的方法完成初始化(不可省略)
//画出一个圆,调用Graphics的drawOval()方法
g.drawOval(10, 10, 100, 100);
}
}
输出结果:
绘图中的paint()
绘图常用方法
- 画直线:drawLine方法 - 第1,2个参数为起点,第3,4个参数为终点(如果起点和重点的x值不同,则为斜线)
- 画矩形:drawRect方法 - 第1,2个参数为起点,第3,4个参数为长和宽
- 画填充矩形:fillRect方法
①先设置画笔的颜色g.setColor(Color.blue);
②再画填充颜色后的矩形g.fillRect(10,10,100,100);
- 画图片
先把图片copy到out下的项目文件夹下面
画图片的代码(2步):
输出结果:
- 画字符串(也就是写字)–>三步
给画笔设置颜色和字体,然后再写字
项目:绘制游戏区域
游戏中有很多坦克,所以我们将坦克先抽象成一个父类,定义一些方法让子类去继承
Tank.java
package com.wpz.tankgame;
/**
* @author 王胖子
* @version 1.0
* 因为该游戏会有很多坦克
* 所以先抽象成一个父类
*/
public class Tank {
private int x;//坦克横坐标
private int y;//坦克纵坐标
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
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;
}
}
编写我的坦克->继承Tank
MyTank.java
package com.wpz.tankgame;
/**
* @author 王胖子
* @version 1.0
* 我的坦克
*/
public class MyTank extends Tank {
public MyTank(int x, int y) {
super(x, y);
}
}
编写面板类->继承Jpanel(在面板上绘制游戏区域)
MyPanel.java
package com.wpz.tankgame;
import javax.swing.*;
import java.awt.*;
/**
* @author 王胖子
* @version 1.0
* 坦克大战的绘图区域
*/
public class MyPanel extends JPanel {
MyTank myTank = null;//在绘图区域中先定义一个自己的坦克
public MyPanel() {
myTank = new MyTank(100, 100);//初始化自己的坦克
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//绘图区域:填充矩形,默认是黑色
}
}
编写窗口类->继承JFrame
TankGame.java
package com.wpz.tankgame;
import javax.swing.*;
/**
* @author 王胖子
* @version 1.0
* 窗口类
*/
public class TankGame extends JFrame {
private MyPanel mp = null;//定义面板
public static void main(String[] args) {
new TankGame();
}
public TankGame() {
this.mp = new MyPanel();//初始化面板
this.add(mp);//把面板加到窗口中
this.setSize(1000, 750);//设置窗口大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭方式:点击X则退出程序
this.setVisible(true);//设置是否可见
}
}
输出效果
项目:绘制坦克
- 根据坦克构造器传入的横纵坐标来确定坦克各个点的坐标,使得坦克变成一个整体
- 将画坦克的代码单独写在一个方法中,增强复用性和可维护性
- 不同类型和不同移动方向的坦克 要学会如何处理
package com.wpz.tankgame;
import javax.swing.*;
import java.awt.*;
/**
* @author 王胖子
* @version 1.0
* 坦克大战的绘图区域
*/
public class MyPanel extends JPanel {
MyTank myTank = null;//先定义一个自己的坦克
public MyPanel() {
myTank = new MyTank(100, 100);//初始化自己的坦克
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//绘图区域:填充矩形,默认是黑色
//画出坦克->封装到画坦克的方法中
drawTank(myTank.getX(), myTank.getY(), g, 0, 0);//画出我的坦克
}
/**
* 该项目有两种类型坦克:①我方②敌方 -> 不同类型的坦克,颜色不同
* 该项目有四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
*
* @param x 坦克左上角x坐标
* @param y 坦克左上角y坐标
* @param g 画笔
* @param direction 坦克的移动方向(上下左右)
* @param type 坦克的类型(敌方/我方)
*/
public void drawTank(int x, int y, Graphics g, int direction, int type) {
//两种类型的坦克①我方②敌方 -> 不同类型的坦克,颜色不同
switch (type) {
case 0://我方
g.setColor(Color.CYAN);
break;
case 1://敌方
g.setColor(Color.YELLOW);
break;
}
//四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
switch (direction) {
case 0://向上
g.fill3DRect(x, y, 10, 60, false);//画坦克左边轱辘(fillRect()画填充的矩形)
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, x + 20, y + 30);//画坦克的炮筒
break;
default:
System.out.println("暂时没有处理");
}
}
}
输出效果:
java事件处理机制
案例:小球移动
解决:怎样让小球受到键盘的控制,上下左右移动
- 让面板实现KeyListener接口。KeyListener是监听器,可以监听键盘事件,当面板实现了该接口后,就要实现该接口的三个方法(按下,松开,输出),所以实现了该接口,就可以在该类中编写需要监听的事件
class MyPanel extends JPanel implements KeyListener
- 需要监听的事件为:当键盘按下↑↓←→时,小球的坐标发生相应变化。此时就需要把小球左上角的横纵坐标写成变量,方便加减
public void keyPressed(KeyEvent e){//判断按下的键}
- 当小球坐标发生变化时,一定要进行重绘
this.repaint();
- 在窗口类中添加面板的键盘监听器。不写这个的话,窗口是不知道需要监听面板上发生的键盘事件的(//JFrame窗口对象 可以监听键盘事件:即监听面板上发生的键盘事件)
相当于在编码中:面板类中写需要监听的事件,窗口类中为面板添加监听器
this.addKeyListener(mp);
- 事件监听通俗来说就是:一个类实现事件监听接口成为监听器类,然后再实现接口中处理事件的方法,当事件发生时,监听器监听到该事件,就会把该事件(KeyEvent对象)作为参数传给事件处理方法
package com.wpz.event;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* @author 王胖子
* @version 1.0
* 让小球收到键盘的控制,上下左右移动 -->来讲解java的事件控制
*/
//窗口类
public class BallMove extends JFrame {
MyPanel mp = null;
public static void main(String[] args) {
BallMove ballMove = new BallMove();
}
public BallMove() {
mp = new MyPanel();
this.add(mp);
this.setSize(250, 200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
//JFrame窗口对象 可以监听键盘事件:即监听面板上发生的键盘事件
this.addKeyListener(mp);
}
}
//面板类
//KeyListener 是监听器,可以监听键盘事件
//面板类实现键盘监听器,所以在面板类中可以写需要监听的键盘事件
class MyPanel extends JPanel implements KeyListener {
//为了让小球可以移动,把他左上角的坐标(x,y)设置成变量
int x = 10;
int y = 10;
@Override
public void paint(Graphics g) {
super.paint(g);
// g.fillOval(10,10,20,20);
g.fillOval(x, y, 20, 20);//填充的小球,默认填充黑色
}
//当某个键按下,该方法被触发
@Override
public void keyPressed(KeyEvent e) {
// System.out.println((char) e.getKeyCode()+"键 被按下");
//根据用户按下不同键,来处理小球移动
//在java中会给每一个键,分配一个值(int)
if (e.getKeyCode() == KeyEvent.VK_DOWN) {//KeyEvent.VK_DOWN就是向下箭头对应的code
y++;
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
y--;
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
x--;
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
x++;
}
//让面板重绘(当坐标x/y发生变化时,需要主动调用paint()方法进行重绘,这样才能显示小球移动的效果)
this.repaint();
}
//当某个键释放(松开),该方法被触发
@Override
public void keyReleased(KeyEvent e) {
}
//有字符输出时,该方法被触发
@Override
public void keyTyped(KeyEvent e) {
}
}
静态效果图,按↑↓←→可以控制小球移动
事件处理机制
基本说明
概念说明
项目:控制坦克上下左右移动(代码改进过程)
步骤及改进代码的过程
- 画出不同方向的坦克。前面已经画过上,现在把右下左的坦克类型也画出来。在drawTank的第二个switch中添加代码。
- 写出事件处理机制的基本代码。
①面板类实现KeyListener接口,并实现接口的三个事件处理方法,本项目中只处理键盘按键的事件(keyPressed)
②判断事件(按键的类型)->WDSA。先把事件处理空下,一会再想,先写完基本流程。
③重绘。在判断结束后(事件处理结束后),用repaint()放啊主动调用paint()进行重绘。
④窗口类的构造器中,为面板类添加键盘监听器。- 写事件处理的逻辑(总体分为2步)
①改变x/y坐标
②改变坦克的方向关于上面事件处理的①,②,写一下我的想法以及改进过程
- 我先不考虑坦克的方向,先写了坐标的变化
① 最开始写的:因为坦克左上角的x和y坐标 在父类中给出了set()和get()方法,所以我直接使用了这两种方法来对坦克的x和y坐标进行修改myTank.setY(myTank.getY()-2);
② 改进1:上面的代码调用了两次方法,效率↓且复用性、维护性差,所以就想着把坐标的改变封装到方法中,因为这是所有坦克移动时都需要的调用的方法,所以干脆把这些方法写到父类中,体会面向对象的好处(封装)
public void moveUp(){//向上移动 y-=2; }
③改进2:将移动的常量换为变量,方便控制移动的速度。 先死后活的思想,开始时坐标是加减固定值,由此想到可以扩展成变化的值,所以引入变量speed(速度)–>提供get和set方法,可以在初始化坦克对象时赋值
public void moveUp(){ y-=speed; }
myTank.setSpeed(5);//修改移动速度
- 考虑如何改变坦克的方向
① 最开始想到的解决方法:将direction设置成面板类的全局变量。
首先我的需求是要在keyPressed()事件处理方法中修改坦克的方向,坦克的方向是由direction表示的,此时direction是传入drawTank()中的一个参数,我在一个方法中是访问不到另一个方法中的参数的,所以我自然想到了把direction设置成面板类中的全局变量,这样我就可以在该类中的任何方法中使用到该变量了–>可行但不好
②改进:direction是所有坦克都具有的属性,它表示坦克的方向,所以我把direction属性写到了tank父类中,并为它提供get和set方法
myTank.moveUp();//改变坦克的坐标(将改变坐标封装到父类的moveUp()方法中) myTank.setDirection(0);//改变坦克的方向(将direction作为所有坦克的属性放到父类中)
面板类MyPanel
package com.wpz.tankgame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* @author 王胖子
* @version 1.0
* 坦克大战的绘图区域
*/
public class MyPanel extends JPanel implements KeyListener {
MyTank myTank = null;//先定义一个自己的坦克
public MyPanel() {
myTank = new MyTank(100, 100);//初始化自己的坦克
myTank.setSpeed(5);//设置坦克移动的速度
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//绘图区域:填充矩形,默认是黑色
//画出坦克->封装到画坦克的方法中
//对direction做了修改,把它放到了tank父类中(使用get()方法访问)
drawTank(myTank.getX(), myTank.getY(), g, myTank.getDirection(), 0);//画出我的坦克
}
/**
* 该项目有两种类型坦克:①我方②敌方 -> 不同类型的坦克,颜色不同
* 该项目有四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
*
* @param x 坦克左上角x坐标
* @param y 坦克左上角y坐标
* @param g 画笔
* @param direction 坦克的移动方向(上下左右)
* @param type 坦克的类型(敌方/我方)
*/
public void drawTank(int x, int y, Graphics g, int direction, int type) {
//两种类型的坦克①我方②敌方 -> 不同类型的坦克,颜色不同
switch (type) {
case 0://我方
g.setColor(Color.CYAN);
break;
case 1://敌方
g.setColor(Color.YELLOW);
break;
}
//四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
//direction:0:向上,1:向右,2:向下,3:向左
switch (direction) {
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, x + 20, y + 30);//画坦克的炮筒
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 keyPressed(KeyEvent e) {
//判断事件(当按下WDSA键时进行处理)
if (e.getKeyCode() == KeyEvent.VK_W) {//上
myTank.moveUp();//改变坦克的坐标(将改变坐标封装到父类的moveUp()方法中)
myTank.setDirection(0);//改变坦克的方向(将direction作为所有坦克的属性放到父类中)
} else if (e.getKeyCode() == KeyEvent.VK_D) {//右
myTank.moveRight();
myTank.setDirection(1);
} else if (e.getKeyCode() == KeyEvent.VK_S) {//下
myTank.moveDown();
myTank.setDirection(2);
} else if (e.getKeyCode() == KeyEvent.VK_A) {//左
myTank.moveLeft();
myTank.setDirection(3);
}
//重绘
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
实体类Tank
package com.wpz.tankgame;
/**
* @author 王胖子
* @version 1.0
* 因为该游戏会有很多坦克
* 所以先抽象成一个父类
*/
public class Tank {
private int x;//坦克横坐标
private int y;//坦克纵坐标
//将坦克的方向写到父类中 这样任意坦克在不同方法中 都可以设置移动方向
private int direction;//坦克的方向(0:上,1:右,2:下,3:左)
private int speed = 2;//移动速度
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
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 int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
//将坦克移动时的坐标改变封装到 父类的方法中
//直接改变坐标的x/y值(取代myTank.setY(myTank.getY()-2);)
//先死后活:开始时坐标是加减固定值-->可以扩展成变化的--引入变量-->speed(可以在初始化坦克对象时赋值)
public void moveUp() {
y -= speed;
}
public void moveRight() {
x += speed;
}
public void moveDown() {
y += speed;
}
public void moveLeft() {
x -= speed;
}
}
窗口类
package com.wpz.tankgame;
import javax.swing.*;
/**
* @author 王胖子
* @version 1.0
* 窗口类
*/
public class TankGame extends JFrame {
private MyPanel mp = null;//定义面板
public static void main(String[] args) {
new TankGame();
}
public TankGame() {
this.mp = new MyPanel();
this.add(mp);
this.setSize(1000, 750);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(mp);//为面板添加键盘监听器
}
}
本章作业
分析:
修改的部分:
- 新建敌人坦克类
- 面板类中:定义敌人坦克集合及坦克数量,在构造器中初始化敌人坦克(同时修改坦克方向),在paint中绘制敌人坦克
敌人坦克类
package com.wpz.tankgame;
/**
* @author 王胖子
* @version 1.0
* 敌人的坦克
*/
public class EnemyTank extends Tank {
public EnemyTank(int x, int y) {
super(x, y);
}
}
面板类
package com.wpz.tankgame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;
/**
* @author 王胖子
* @version 1.0
* 坦克大战的绘图区域
*/
public class MyPanel extends JPanel implements KeyListener {
MyTank myTank = null;//定义一个自己的坦克
Vector<EnemyTank> enemyTanks = new Vector<>();//定义敌人的坦克,放到Vector中
int enemyTankSize = 3;//敌人坦克的数量
public MyPanel() {
myTank = new MyTank(100, 100);//初始化自己的坦克
myTank.setSpeed(5);//设置坦克移动的速度
//初始化敌人的坦克(注意:使用循环来添加。因为敌人坦克数量多,不要一个一个add)
for (int i = 0; i < enemyTankSize; i++) {
//创建一个敌人的坦克
EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
//设置方向
enemyTank.setDirection(2);
//加入敌人坦克集合
enemyTanks.add(enemyTank);
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//绘图区域:填充矩形,默认是黑色
//画出自己的坦克->封装到画坦克的方法中
//对direction做了修改,把它放到了tank父类中(使用get()方法访问)
drawTank(myTank.getX(), myTank.getY(), g, myTank.getDirection(), 0);//画出我的坦克
//画敌人的坦克->遍历集合
for (int i = 0; i < enemyTanks.size(); i++) {
//取出坦克
EnemyTank enemyTank = enemyTanks.get(i);
drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirection(), 1);
}
}
/**
* 该项目有两种类型坦克:①我方②敌方 -> 不同类型的坦克,颜色不同
* 该项目有四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
*
* @param x 坦克左上角x坐标
* @param y 坦克左上角y坐标
* @param g 画笔
* @param direction 坦克的移动方向(上下左右)
* @param type 坦克的类型(敌方/我方)
*/
public void drawTank(int x, int y, Graphics g, int direction, int type) {
//两种类型的坦克①我方②敌方 -> 不同类型的坦克,颜色不同
switch (type) {
case 0://我方
g.setColor(Color.CYAN);
break;
case 1://敌方
g.setColor(Color.YELLOW);
break;
}
//四种移动方向:不同移动方向使用画笔绘制的坦克是不同的
//direction:0:向上,1:向右,2:向下,3:向左
switch (direction) {
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, x + 20, y + 30);//画坦克的炮筒
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 keyPressed(KeyEvent e) {
//判断事件(当按下WDSA键时进行处理)
if (e.getKeyCode() == KeyEvent.VK_W) {//上
myTank.moveUp();//改变坦克的坐标(将改变坐标封装到父类的moveUp()方法中)
myTank.setDirection(0);//改变坦克的方向(将direction作为所有坦克的属性放到父类中)
} else if (e.getKeyCode() == KeyEvent.VK_D) {//右
myTank.moveRight();
myTank.setDirection(1);
} else if (e.getKeyCode() == KeyEvent.VK_S) {//下
myTank.moveDown();
myTank.setDirection(2);
} else if (e.getKeyCode() == KeyEvent.VK_A) {//左
myTank.moveLeft();
myTank.setDirection(3);
}
//重绘
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
输出效果