JAVA绘图坐标系
坐标体系-介绍:
下图说明了java
坐标系。坐标原点位于左上角,以像素为单位。在java
坐标系中,第一个不足x
坐标,表示当前位置为水平方向,距离坐标原点x
个像素,第二个是y
坐标,表示当前位置为垂直方向,距离坐标原点y
个像素。
坐标体系-像素:
绘图还必须要搞清一个非常重要的概念-像素,一个像素等于多少厘米?这是不同的概念两者不能比较。
像素介绍 :
计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的,例如,计算机显示器的分辨是800*600,表示是计算机屏幕上每一行由800个点组成,共有600行,整个计算机屏幕共有 480000个像素,像素是一个密度单位,而厘米是长度单位,两者无法比较。
快速入门
先画一个小圆,讲解java
绘图技术原理
第一步:先定义一个绘图类继承extends
于JPanel
类【相当于一面板】
第二步:调用paint
方法,并调用super(g)
完成对父类初始化,并调用drawOval
方法画出一个圆】
第三步:一个类继承Frame
【框架】,相当于将画板放在框架中,在父类构造器中,对面板的初始化,再设置窗口大小,再设置当调用窗口小叉时,程序完成退出,设置
框架可以显示
package paint_;
import javax.swing.*;
import java.awt.*;
/**
* @author: 海康
* @version: 1.0
*/
public class DrawCircle extends Frame{//JFrame
// 声明一个面板
MyJPanel myJPanel = null;
public static void main(String[] args) {
new DrawCircle();
}
// 调用构造器完成对属性的初始化
public DrawCircle(){
myJPanel = new MyJPanel();
this.add(myJPanel);//将面板添加到框架中
this.setVisible(true);//设置框架可以显示
this.setSize(400,400);
// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);表示点击小叉程序退出
}
}
// 第一步:定义画板类
class MyJPanel extends JPanel {
// 调用Paint【画画方法】
@Override
public void paint(Graphics g) {
super.paint(g);//调用super完成对父类的初始化
g.drawOval(10,20,100,100);//表示画出一个图的半径为100
}
}
绘图原理
Component
类提供了两个和绘图相关最重要方法:
paint(Graphics g)
绘制组件的外观
repaint()
刷新组件的外观
下面调用paint()
方法的四种情况
当组件第一次在屏幕显示的时候,程序会自动的调用paint()
方法来绘制组件
窗口最小化,再最大化
窗口的大小发生变化
repain
方法被调用时
Graphics
类常用方法
1.画直线
drawLine(int x1,int y1,int x2,inty y2)
2.画矩形边框
drawRect(int x,int y,int width,int height)
3.画椭圆边框【如果宽度和高度相等时就是一个圆】
drawOval(int x,int y,int width,int height)
4.填充椭圆【填充椭圆必须先设置颜色】
setColor(COlor.red)
fillOVal(int x,int y,int width,int heigth)
5.填充矩形【填充矩形必须先设置颜色】
setColor(COlor.red)
fillRect(int x,int y,int width,int heigth)
6.画图片【画图片必须获取到图片】
drawImage(Image img,int x,int y)
7.画字符串【画字符串必须先设置字体及大小,精细 也设置字体颜色】
drawString(String str,int x,int y)
8.设置画笔字体
setFont(Font font)
9.设置画笔颜色
setColor(Color color)
package paint_;
import javax.swing.*;
import java.awt.*;
/**
* @author: 海康
* @version: 1.0
*/
public class DrawType extends Frame{
myPanel1 mp = null;//声明一个画板
public static void main(String[] args) {
new DrawType();
}
// 使用构造器对属性的初始化
public DrawType (){
mp = new myPanel1();
this.add(mp);//将画板添加到框架
setSize(400,400);
setVisible(true);
}
}
// 定义一个画板类
class myPanel1 extends JPanel {
// 调用Paint方法
@Override
public void paint(Graphics g) {
super.paint(g);//调用super完成对父类的初始化
this.setDebugGraphicsOptions(JFrame.EXIT_ON_CLOSE);
// 画直线
g.drawLine(10,10,300,300);
// 画矩形边框
g.drawRect(20,20,430,430);
// 画椭圆边框
g.drawOval(10,10,200,200);
//填充矩形【先设置填充背景颜色】
g.setColor(Color.red);
g.fillRect(20,20,200,290);
// 填充椭圆【也必须先设置填充背景颜色】
g.setColor(Color.blue);
g.fillOval(10,10,200, 100);
// 画图片【必须先获取图片】
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("/rose.jpg");
g.drawImage(image,100,100,this);
//画字符串 drawString【先设置字体】
g.setFont(new Font("宋体",Font.BOLD,50));
g.setColor(Color.red);
g.drawString("海康",50,50);
}
}
绘画坦克
坦克大战游戏中,我们会用到坦克,现在我们就利用java
绘图技术来画出一个小坦克,完成我们坦克大战游戏1.0版本
package paint_;
import javax.swing.*;
import java.awt.*;
/**
* @author: 海康
* @version: 1.0
*/
public class TankGame01 extends Frame{
public static void main(String[] args) {
new TankGame01();
}
HspTankGame01 ht = null;
public TankGame01(){
ht = new HspTankGame01();
this.add(ht);
this.setSize(400,400);
this.setVisible(true);
}
}
class HspTankGame01 extends JPanel {
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.red);
g.fillRect(20,20,10,50);
g.fillRect(50,20,10,50);
g.fillRect(25,35,30,25);
g.setColor(Color.blue);
g.fillOval(35,43,12,12);
g.drawLine(40,43,40,20);
}
}
第一步:画出游戏区域
第二步:在paint
方法中调用画出坦克方法
在画出坦克方法中,需要传入坦克的X轴坐标,Y轴坐标,坦克类型,坦克方向,及画笔
java
事件处理机制
基本说明:
java
事件处理是采取“委派事件模型”。当事件发生时,产生事件的对象,会把此“信息”传递给“事件的监听者”,处理,这里所说的“信息”实际上就是java.awt.event
事件类库里某个类所创建的对象,把它称为“事件的对象”
示意图:
事件处理机制深入理解 :
对几个重要概念 事件源,事件,事件监听器介绍:
事件源:事件是一个产生事件的对象,比如:按键,窗口等。】
事件:事件就是承载事件源状态改变时的对象,比如是当键盘事件,鼠标事件,窗口事件等等,会生成一个事件对象,该对象保存着当前事件很多信息,比如KeyEvent
对象有含义被按下键的Code
值。java.awt.event
t和javax.swing.event
包中定义了各种的事件类型
事件监听器接口:
事件处理机制步骤是:
第一步:在自定义面板类中实现KeyListener
类【键盘监听事件或其它监听事件】,重写方法在重写方法中进行相关业务处理
第二步:在继承JFrame
中添加键盘监听事件
第三步:调用repaint
重新绘图【小球才能动】
使用事件处理机制使坦克动起来
通过按键控制上右下左(wdsa表示)
的移动
关键点是:在实现KeyListener
接口后的pressed
中修改坦克的方向和坐标,再调用repaint
方法重新绘图即可
使用前面学习的知识画出三辆敌人的坦克,如下图所示:
线程-应用到坦克大战
基本介绍:
在坦克大战游戏基础上添加如下功能:当玩家按一下j
键时,就发射一颗子弹
新增加功能
- 让敌人的坦克也能够发射子弹【可以有多颗子弹】
- 当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸更好
- 让敌人的坦克可以自由随机的上下左右衔移动
- 控制我方的坦克和敌人的坦克在规定的范围移动
让敌人的坦克也能够发射子弹【可以有多颗子弹】
当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸更好
1.当我坦克发出子弹与敌方坦克身体有交叉时,就可以将其从集合中删除,达到敌方坦克消失的目的
编写一个判断方法
2.由于不知道什么时候击中敌方坦克需要放在一个循环中不停的判断
由于不断的需要进行判断,所以可以将判断放在该类的run方法【在run方法中调用判断方法】
3.爆炸效果:需要编写一个爆炸类,由于爆炸的效果是用图片不断的切换显示的所以需要在面板中创建一个Vector集合存放爆炸类,并在我子弹打中敌人坦克时创建爆炸类存放在Vector集合中,并在paint将画出效果
让敌人的坦克可以自由随机的上下左右衔的移动
让敌人坦克也可以自由随机的上下左右移动
1.因为要求敌人的坦克,可以自由移动,因此需要将敌人坦克当做线程使用
2.我们需要将敌人坦克类实现Runnable接口
3.在run方法中编写我们的业务代码
4.在创建敌人坦克时,启动线程
控制我方的坦克和敌人的坦克在规定的范围移动
以坦克的左上角为参考点,使得坦克指定位置移动,不能超出指定范围
在移动中判断
增加新功能2
- 我方坦克在发射的子弹消亡后,才能发射新的子弹 ===》【发多颗子弹如何实现】
- 让敌人坦克发射的子弹消亡后,可以再发射子弹
- 当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果
我方坦克在发射的子弹消亡后,才能发射新的子弹 ===》【发多颗子弹如何实现】
1.在按下 J 键时,我们判断当前 hero 对象的子弹,是否已经销毁
2.如果没有销毁,就不去触发 shotEnemyTank 方法
3.如果已经销毁,才去触发 shotEnemyTank 方法
4.如果要发射多颗子弹,就使用Vector保存
5.在绘制我方子弹时,需要遍历Vector集合,画出所有子弹
注意是:
如果我们的坦克可以发射多个子弹时,在判断我方子弹是否击中敌人坦克时,就需要把我们的子弹集合中所有的子弹,都取出来和敌人的所有坦克进行判断
让敌人坦克发射的子弹消亡后,可以再发射子弹
在敌人的坦克类中编写一个方法,当敌人坦克子弹消失后,再创建一个
当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果
编写一个方法判断敌人坦克发射的子弹与我方坦克相交时,则将我方坦克isLive赋为 false
增加功能3
- 防止敌人坦克重叠运动
- 记录玩家的成绩,存盘再退出
- 记录当时的敌人坦克坐标,存盘再退出
- 玩游戏时,可以选择是开启新的游戏还是继续上局游戏
防止敌人坦克重叠运动
在敌人坦克中 添加敌人坦克集合,编写一个 isTouchEnemyTank 用于判断坦克之间是否发生碰撞,在myPanel类中,在每创建一个敌人坦克时,就给其赋一个敌人坦克集合
记录玩家的成绩,存盘再退出和记录当时 的敌人坦克坐标,存盘再退出
编写一个Recorder类,记录我方击毁敌方坦克数量 当游戏结束后,将数据写入到文件(IO)当点击游戏退出后,保存坦克的坐标和方向信息
玩游戏时可以选择是开启新的游戏还是继续上局游戏
编写一个NOde类将每个敌人信息,并且在Recorder类中定义一个Vector集合用于存放NOde对象,恢复成Node对象通过NOde的Vector支恢复敌人坦克的位置和方向
增加新功能4
游戏开始时,播放坦克大战音乐,使用一个播放音乐的类处理文件相关异常,提高代码
代码实现
package tank;
import javax.swing.*;
/**
* @author: 海康
* @version: 1.0
*/
public class TankGame extends JFrame {
myPanel mp = null;
public static void main(String[] args) {
TankGame tankGame = new TankGame();
}
public TankGame(){
mp = new myPanel();
this.add(mp);
this.setVisible(true);// 设置可显示可见
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 表示打X退出程序
this.setSize(1300,750);
this.addKeyListener(mp);
new Thread(mp).start();
}
}
package tank;
/**
* @author: 海康
* @version: 1.0
*/
public class Tank {
private int x;// 坦克X轴坐标
private int y;// 坦克Y轴坐标
private int direction;// 坦克的方向
private boolean isLive = true;
private int speed = 3;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Tank(int x, int y, int direction) {
this.x = x;
this.y = y;
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 getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
public void moveUp(){
// 判断坦克移动的范围
if (y>=0)
y=y-speed;
}
public void moveRight(){
if (x<=1000)
x=x+speed;
}
public void moveDown(){
if (y<=750)
y=y+speed;
}
public void moveLeft(){
if (x>=0)
x=x-speed;
}
}
package tank;
import javax.management.relation.RelationNotFoundException;
/**
* @author: 海康
* @version: 1.0
*/
public class Shot implements Runnable {
int x; // 坐标X
int y; // 坐标Y
int direction;// 子弹方向
int speed = 5;
boolean isLive = true;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Shot(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
public void BulletMode(){
switch (direction){
case 0:
if (y>=0){
y-=speed;
}else {
isLive = false;
}
break;
case 1:
if (x<=1000){
x+=speed;
}else {
isLive = false;
}
break;
case 2:
if (y<=750){
y+=speed;
}else {
isLive = false;
}
break;
case 3:
if (x>=0){
x-=speed;
}else {
isLive = false;
}
break;
}
}
@Override
public void run() {
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
BulletMode();
}
}
}
package tank;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author: 海康
* @version: 1.0
* 记录我方坦克击毁敌人坦克
*/
public class Record {
public static int countEnemyTank = 0;
public static BufferedWriter bw = null;
public int getCountEnemyTank() {
return countEnemyTank;
}
public static void setCountEnemyTank(int countEnemyTank) {
Record.countEnemyTank = countEnemyTank;
}
public static void addEnemyTankNumber(){
++ countEnemyTank;
}
// 写入击毁敌人坦克数的文件 src\\myRecordTank.txt
public static void record(){
try {
bw = new BufferedWriter(new FileWriter("src\\myRecordTank.txt"));
bw.write(countEnemyTank);
bw.newLine();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package tank;
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 ,Runnable{
// 初始化爆炸图片
Image image1 = null;
Image image2 = null;
Image image3 = null;
Vector<Bomb> bombs = new Vector<>();
Hero hero = null;
int enemyTanksNum = 3;
Vector<EnemyTank> enemyTanks = new Vector<>();
public myPanel(){
hero = new Hero(300,430,0);
hero.setSpeed(3);
// 初始化敌方坦克
initEnemyTank();
// 加载爆炸图片
// Image image = toolkit.getImage("src\\jpg1.jpg");
image1 = Toolkit.getDefaultToolkit().getImage("src\\bomb_1.gif");
image2 = Toolkit.getDefaultToolkit().getImage("src\\bomb_2.gif");
image3 = Toolkit.getDefaultToolkit().getImage("src\\bomb_3.gif");
}
public void countEnemyTank(Graphics g){
//画出玩家的总成绩
g.setColor(Color.red);
Font font = new Font("宋体", Font.BOLD, 32);
g.setFont(font);
g.drawString(" 海康军累积 ", 1020, 50);
g.drawString("击毁敌方坦克", 1020, 98);
drawTank(g,1020, 123, 0, 1);//画出一个敌方坦克
g.setColor(Color.BLACK);
g.drawString(Record.countEnemyTank+"",1120,160);// 显示击毁敌人坦克
}
public void initEnemyTank(){
enemyTanksNum += 2;
for (int i = 0; i < enemyTanksNum; i++) {
int enemyTankX = 100;
EnemyTank enemyTank = new EnemyTank((i + 1) * enemyTankX, 20, 2);
Vector<Shot> enemyShot = enemyTank.getEnemyShot();
Shot shot = new Shot(enemyTank.getX() , enemyTank.getY(), enemyTank.getDirection());
shot.setSpeed(5);
enemyShot.add(shot);
enemyTanks.add(enemyTank);
new Thread(enemyTank).start();
new Thread(shot).start();
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
// 画出游戏区域
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("src\\jpg1.jpg");
g.drawImage(image,0,0,1000,750,this);
// g.setColor(Color.BLACK);
// g.fillRect(0,0,1000,750);
// 画出我方坦克
if (hero.isLive()){
drawTank(g,hero.getX(),hero.getY(),hero.getDirection(),0);
}else {
drawBomb(g);
}
// 画出子弹
drawBullet(g);
// 当打掉所有敌人坦克时,再次初始化
if (enemyTanks.size() == 0){
initEnemyTank();
}
// 画出敌人坦克
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (enemyTank.isLive()){
drawTank(g,enemyTank.getX(),enemyTank.getY(),enemyTank.getDirection(),1);
Vector<Shot> enemyShot = enemyTank.enemyShot;
for (int j = 0; j < enemyShot.size(); j++) {
Shot shot = enemyShot.get(j);
if (shot.isLive){
switch (shot.direction){
case 0:
g.fillOval(shot.x,shot.y,5,5);
break;
case 1:
g.fillOval(shot.x+60,shot.y+20,5,5);
break;
case 2:
g.fillOval(shot.x+20,shot.y+60,5,5);
break;
case 3:
g.fillOval(shot.x,shot.y+20,5,5);
break;
}
}else {
enemyShot.remove(shot);// 如何坦克打出子弹 isLive 为 false 将其从集合中删除
}
}
}else {
enemyTanks.remove(enemyTank);// 如何敌人坦克 isLive为 false 将其从集合中删除
}
}
// 画出爆炸效果
drawBomb(g);
// 画出击毁敌人坦克
countEnemyTank(g);
}
public void drawBomb(Graphics g){
for (int i = 0; i < bombs.size(); i++) {
Bomb bomb = bombs.get(i);
int liveValue = bomb.liveValue;
for (int j = 0; j < 9; j++) {
if (liveValue>6){
g.drawImage(image1,bomb.x,bomb.y,60,60,this);
}else if (liveValue>3){
g.drawImage(image2,bomb.x,bomb.y,60,60,this);
}else{
g.drawImage(image3,bomb.x,bomb.y,60,60,this);
}
bomb.liveValueDown();
if (bomb.liveValue == 0){
// 如果 生命值为 0 时 从集合中删除
bombs.remove(bomb);
}
}
}
}
// 我方坦克打掉敌人坦克
public void hitEnemyTank(){
for (int i = 0; i < hero.shots.size(); i++) {
Shot shot = hero.shots.get(i);
if (shot.isLive && shot!=null)
// 取出每颗子弹与所有敌人坦克进行判断
for (int j = 0; j < enemyTanks.size(); j++) {
EnemyTank enemyTank = enemyTanks.get(j);
hitTank(shot,enemyTank);
}
}
}
// 敌人坦克打爆我方坦克
public void hitHero(){
for (int i = 0; i < enemyTanks.size(); i++) {
// 获取 所有的坦克 和 坦克中的所有子弹
EnemyTank enemyTank = enemyTanks.get(i);
if (enemyTank.isLive()&&enemyTank!=null)
for (int j = 0; j < enemyTank.enemyShot.size(); j++) {
Shot shot = enemyTank.enemyShot.get(j);
if (shot.isLive&&shot!=null)
hitTank(shot,hero);
}
}
}
// 打出多颗子弹打爆坦克
public void hitTank(Shot shot,Tank tank){
switch (tank.getDirection()){
case 0: // 坦克向上
case 2: // 坦克向下
if (shot.x >= tank.getX() && shot.x <=tank.getX()+40 &&
shot.y >= tank.getY() && shot.y <= tank.getY()+60){
shot.isLive = false;
tank.setLive(false);
Bomb bomb = new Bomb(tank.getX(), tank.getY());
bombs.add(bomb);
if (tank instanceof EnemyTank){
Record.addEnemyTankNumber();
}
enemyTanks.remove(tank);
}
break;
case 1:
case 3:
if (shot.x >= tank.getX() && shot.x <= tank.getX()+60 &&
shot.y >= tank.getY() && shot.y <= tank.getY()+40){
shot.isLive = false;
tank.setLive(false);
Bomb bomb = new Bomb(tank.getX(), tank.getY());
bombs.add(bomb);
if (tank instanceof EnemyTank){
Record.addEnemyTankNumber();
}
enemyTanks.remove(tank);
}
break;
}
}
/**
* 该方法表示是画坦克方法
* @param g 表示 画笔
* @param x 表示 坦克X坐标
* @param y 表示 坦克Y坐标
* @param direction 表示 坦克方向
* @param type 表示 坦克的类型 1 为我方坦克 0 为敌人坦克
*/
public void drawTank(Graphics g, int x, int y, int direction, int type){
switch (type){
case 0:
g.setColor(Color.cyan);
break;
case 1:
g.setColor(Color.ORANGE);
break;
}
// 画坦克方法
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);
g.fill3DRect(x+10,y+10,20,40,false);
g.fill3DRect(x+30,y,10,60,false);
g.fillOval(x+10,y+20,20,20);
g.drawLine(x+20,y,x+20,y+40);
break;
case 1:
g.fill3DRect(x,y,60,10,false);
g.fill3DRect(x+10,y+10,40,20,false);
g.fill3DRect(x,y+30,60,10,false);
g.fillOval(x+20,y+10,20,20);
g.drawLine(x+20,y+20,x+60,y+20);
break;
case 2:
g.fill3DRect(x,y,10,60,false);
g.fill3DRect(x+10,y+10,20,40,false);
g.fill3DRect(x+30,y,10,60,false);
g.fillOval(x+10,y+20,20,20);
g.drawLine(x+20,y+40,x+20,y+60);
break;
case 3:
g.fill3DRect(x,y,60,10,false);
g.fill3DRect(x+10,y+10,40,20,false);
g.fill3DRect(x,y+30,60,10,false);
g.fillOval(x+20,y+10,20,20);
g.drawLine(x,y+20,x+30,y+20);
break;
}
}
// 画出我方子弹方法
public void drawBullet(Graphics g){
Vector<Shot> shots = hero.getShots();
System.out.println(shots.size());
for (int i = 0; i < shots.size(); i++) {
Shot shot = shots.get(i);
if (shot.isLive==false){
shots.remove(shot);
}
switch (shot.direction){
case 0:
g.fillOval(shot.x+20,shot.y,5,5);
break;
case 1:
g.fillOval(shot.x+60,shot.y+20,5,5);
break;
case 2:
g.fillOval(shot.x+20,shot.y+60,5,5);
break;
case 3:
g.fillOval(shot.x,shot.y+20,5,5);
break;
}
}
}
@Override
public void keyTyped(KeyEvent e) {
}
// 按下某个键时产生事件
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyCode());
// 用wdsa 分别为上下左右
if (e.getKeyCode() == KeyEvent.VK_W){
hero.setDirection(0);
hero.moveUp();
}
if (e.getKeyCode()==KeyEvent.VK_D){
hero.setDirection(1);
hero.moveRight();
}
if (e.getKeyCode()==KeyEvent.VK_S){
hero.setDirection(2);
hero.moveDown();
}
if (e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.moveLeft();
}
if (e.getKeyCode()==KeyEvent.VK_J){
Vector<Shot> shots = hero.getShots();
Shot shot = new Shot(hero.getX(), hero.getY(), hero.getDirection());
shots.add(shot);
new Thread(shot).start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run() {
while (true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
hitEnemyTank();
hitHero();
this.repaint();
}
}
}
package tank;
import java.util.Vector;
/**
* @author: 海康
* @version: 1.0
*/
public class Hero extends Tank{
// 集合用于存储子弹
Vector<Shot> shots = new Vector<>();
public Hero(int x, int y, int direction) {
super(x, y, direction);
}
public Vector<Shot> getShots() {
return shots;
}
public void setShots(Vector<Shot> shots) {
this.shots = shots;
}
}
package tank;
import java.util.Vector;
/**
* @author: 海康
* @version: 1.0
*/
public class EnemyTank extends Tank implements Runnable{
// 定义一个Vector集合用于存放敌人坦克
Vector<Shot> enemyShot = new Vector<>();
public EnemyTank(int x, int y, int direction) {
super(x, y, direction);
}
public void setEnemyShot(Vector<Shot> enemyShot) {
this.enemyShot = enemyShot;
}
public Vector<Shot> getEnemyShot() {
return enemyShot;
}
public void enemyTankMove(){
if (enemyShot.size() == 0){
Shot shot = new Shot(getX(), getY(), getDirection());
enemyShot.add(shot);
new Thread(shot).start();
}
switch (getDirection()){
case 0:
for (int i = 0; i < 32; i++) {
moveUp();
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1:
for (int i = 0; i < 28; i++) {
moveRight();
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 2:
for (int i = 0; i < 30; i++) {
moveDown();
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 3:
for (int i = 0; i < 30; i++) {
moveLeft();
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
setDirection((int) (Math.random()*4));
}
@Override
public void run() {
while (true){
if (isLive()==false){
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
enemyTankMove();
}
}
}
package tank;
/**
* @author: 海康
* @version: 1.0
*/
public class Bomb {
int x;// 爆炸X坐标
int y;// 爆炸Y坐标
int liveValue = 9;
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 getLiveValue() {
return liveValue;
}
public void setLiveValue(int liveValue) {
this.liveValue = liveValue;
}
public Bomb(int x, int y) {
this.x = x;
this.y = y;
}
public void liveValueDown(){
liveValue --;
}
}