IO 流-应用到坦克大战
坦克大战0.5版
增加功能
- 防止敌人坦克重叠运动
- 记录玩家的总成绩(累积击毁敌方坦克数),存盘退出【io流】
- 记泉退出游戏时敌人坦克坐标/方向,存盘退出【io流】
- 玩游戏时,可以选择是开新游戏还是继续上局游戏
package com.hspedu.tankgame5;
/**
* 炸弹
*/
public class Bomb {
int x, y; //炸弹的坐标
int life = 9; //炸弹的生命周期
boolean isLive = true; //是否还存活
public Bomb(int x, int y) {
this.x = x;
this.y = y;
}
//减少生命值
public void lifeDown() { //配合出现图片的爆炸效果
if(life > 0) {
life--;
} else {
isLive = false;
}
}
}
package com.hspedu.tankgame5;
import java.util.Vector;
/**
* 敌人的坦克
*/
@SuppressWarnings({"all"})
public class EnemyTank extends Tank implements Runnable {
//在敌人坦克类,使用Vector 保存多个Shot
Vector shots = new Vector();
//增加成员,EnemyTank 可以得到敌人坦克的Vector
//分析
//1. Vector 在
Vector enemyTanks = new Vector();
boolean isLive = true;
public EnemyTank(int x, int y) {
super(x, y);
}
//这里提供一个方法,可以将MyPanel 的成员 Vector enemyTanks = new Vector();
//设置到 EnemyTank 的成员 enemyTanks
public void setEnemyTanks(Vector enemyTanks) {
this.enemyTanks = enemyTanks;
}
//编写方法,判断当前的这个敌人坦克,是否和 enemyTanks 中的其他坦克发生的重叠或者碰撞
public boolean isTouchEnemyTank() {
//判断当前敌人坦克(this) 方向
switch (this.getDirect()) {
case 0: //上
//让当前敌人坦克和其它所有的敌人坦克比较
for (int i = 0; i = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 40 0 && !isTouchEnemyTank()) {
moveUp();
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1: //向右
for (int i = 0; i 0 && !isTouchEnemyTank()) {
moveLeft();
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
//然后随机的改变坦克方向 0-3
setDirect((int) (Math.random() * 4));
//写并发程序,一定要考虑清楚,该线程什么时候结束
if (!isLive) {
break; //退出线程.
}
}
}
}
package com.hspedu.tankgame5;
import java.util.Vector;
/**
* 自己的坦克
*/
public class Hero extends Tank {
//定义一个Shot对象, 表示一个射击(线程)
Shot shot = null;
//可以发射多颗子弹
//Vector shots = new Vector();
public Hero(int x, int y) {
super(x, y);
}
//射击
public void shotEnemyTank() {
//发多颗子弹怎么办, 控制在我们的面板上,最多只有5颗
// if(shots.size() == 5) {
// return;
// }
//创建 Shot 对象, 根据当前Hero对象的位置和方向来创建Shot
switch (getDirect()) {//得到Hero对象方向
case 0: //向上
shot = new Shot(getX() + 20, getY(), 0);
break;
case 1: //向右
shot = new Shot(getX() + 60, getY() + 20, 1);
break;
case 2: //向下
shot = new Shot(getX() + 20, getY() + 60, 2);
break;
case 3: //向左
shot = new Shot(getX(), getY() + 20, 3);
break;
}
//把新创建的shot放入到shots
//shots.add(shot);
//启动我们的Shot线程
new Thread(shot).start();
}
}
package com.hspedu.tankgame5;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;
public class HspTankGame05 extends JFrame {
// 定义MyPanel
MyPanel mp = null;
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
HspTankGame05 hspTankGame01 = new HspTankGame05();
}
public HspTankGame05() {
System.out.println("请输入选择 1: 新游戏 2: 继续上局");
String key = scanner.next();
mp = new MyPanel(key);
//将mp 放入到Thread ,并启动
Thread thread = new Thread(mp);
thread.start();
this.add(mp);//把面板(就是游戏的绘图区域)
this.setSize(1300, 950);
this.addKeyListener(mp);//让JFrame 监听mp的键盘事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
//在JFrame 中增加相应关闭窗口的处理
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Recorder.keepRecord();
System.exit(0);
}
});
}
}
package com.hspedu.tankgame5;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileInputStream;
import java.util.Vector;
/**
* 坦克大战的绘图区域
*/
//为了监听 键盘事件, 实现KeyListener
//为了让Panel 不停的重绘子弹,需要将 MyPanel 实现Runnable ,当做一个线程使用
@SuppressWarnings({"all"})
public class MyPanel extends JPanel implements KeyListener, Runnable {
//定义我的坦克
Hero hero = null;
//定义敌人坦克,放入到Vector
Vector enemyTanks = new Vector();
//定义一个存放Node 对象的Vector, 用于恢复敌人坦克的坐标和方向
Vector nodes = new Vector();
//定义一个Vector ,用于存放炸弹
//说明,当子弹击中坦克时,加入一个Bomb对象到bombs
Vector bombs = new Vector();
int enemyTankSize = 3;
//定义三张炸弹图片,用于显示爆炸效果
Image image1 = null;
Image image2 = null;
Image image3 = null;
public MyPanel(String key) {
nodes = Recorder.getNodesAndEnemyTankRec();
//将MyPanel对象的 enemyTanks 设置给 Recorder 的 enemyTanks
Recorder.setEnemyTanks(enemyTanks);
hero = new Hero(500, 100);//初始化自己坦克
switch (key) {
case "1":
//初始化敌人坦克
for (int i = 0; i 6) {
g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
} else if (bomb.life > 3) {
g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
} else {
g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
}
//让这个炸弹的生命值减少
bomb.lifeDown();
//如果bomb life 为0, 就从bombs 的集合中删除
if (bomb.life == 0) {
bombs.remove(bomb);
}
}
//画出敌人的坦克, 遍历Vector
for (int i = 0; i enemyTank.getX() && s.x enemyTank.getY() && s.y enemyTank.getX() && s.x enemyTank.getY() && s.y 0) {
hero.moveUp();
}
} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键, 向右
hero.setDirect(1);
if (hero.getX() + 60 0) {
hero.moveLeft();
}
}
//如果用户按下的是J,就发射
if (e.getKeyCode() == KeyEvent.VK_J) {
//判断hero的子弹是否销毁,发射一颗子弹
if (hero.shot == null || !hero.shot.isLive) {
hero.shotEnemyTank();
}
//发射多颗子弹
//hero.shotEnemyTank();
}
//让面板重绘
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run() { //每隔 100毫秒,重绘区域, 刷新绘图区域, 子弹就移动
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是我们子弹否击中了敌人坦克
hitEnemyTank();
//判断敌人坦克是否击中我们
hitHero();
this.repaint();
}
}
}
package com.hspedu.tankgame5;
/**
* 一个Node 对象,表示一个敌人坦克的信息
*/
public class Node {
private int x;
private int y;
private int direct;
public Node(int x, int y, int direct) {
this.x = x;
this.y = y;
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 int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
}
package com.hspedu.tankgame5;
import java.io.*;
import java.nio.Buffer;
import java.util.Vector;
/**
* 该类用于记录相关信息的.和文件交互
*/
@SuppressWarnings({"all"})
public class Recorder {
//定义变量,记录我方击毁敌人坦克数
private static int allEnemyTankNum = 0;
//定义IO对象, 准备写数据到文件中
private static BufferedWriter bw = null;
private static BufferedReader br = null;
private static String recordFile = "e:myRecord.txt";
//定义Vector ,指向 MyPanel 对象的 敌人坦克Vector
private static Vector enemyTanks = null;
//定义一个Node 的Vector ,用于保存敌人的信息node
private static Vector nodes = new Vector();
public static void setEnemyTanks(Vector enemyTanks) {
Recorder.enemyTanks = enemyTanks;
}
public static String getRecordFile() {
return recordFile;
}
//增加一个方法,用于读取recordFile, 恢复相关信息
//该方法,在继续上局的时候调用即可
public static Vector getNodesAndEnemyTankRec() {
try {
br = new BufferedReader(new FileReader(recordFile));
allEnemyTankNum = Integer.parseInt(br.readLine());
//循环读取文件,生成nodes 集合
String line = "";//255 40 0
while ((line = br.readLine()) != null) {
String[] xyd = line.split(" ");
Node node = new Node(Integer.parseInt(xyd[0]), Integer.parseInt(xyd[1]),
Integer.parseInt(xyd[2]));
nodes.add(node); //放入nodes Vector
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return nodes;
}
//增加一个方法,当游戏退出时,我们将allEnemyTankNum 保存到 recordFile
//对keepRecord 进行升级, 保存敌人坦克的坐标和方向
public static void keepRecord() {
try {
bw = new BufferedWriter(new FileWriter(recordFile));
bw.write(allEnemyTankNum + "rn");
//遍历敌人坦克的Vector ,然后根据情况保存即可.
//OOP, 定义一个属性 ,然后通过setXxx得到 敌人坦克的Vector
for (int i = 0; i
package com.hspedu.tankgame5;
/**
* 射击子弹
*/
public class Shot implements Runnable {
int x; //子弹x坐标
int y; //子弹y坐标
int direct = 0; //子弹方向
int speed = 2; //子弹的速度
boolean isLive = true; //子弹是否还存活
//构造器
public Shot(int x, int y, int direct) {
this.x = x;
this.y = y;
this.direct = direct;
}
@Override
public void run() {//射击
while (true) {
//休眠 50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//根据方向来改变x,y坐标
switch (direct) {
case 0://上
y -= speed;
break;
case 1://右
x += speed;
break;
case 2://下
y += speed;
break;
case 3://左
x -= speed;
break;
}
//老师测试,这里我们输出x,y的坐标
System.out.println("子弹 x=" + x + " y=" + y);
//当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)
//当子弹碰到敌人坦克时,也应该结束线程
if (!(x >= 0 && x = 0 && y
package com.hspedu.tankgame5;
public class Tank {
private int x;//坦克的横坐标
private int y;//坦克的纵坐标
private int direct = 0;//坦克方向 0 上1 右 2下 3左
private int speed = 1;
boolean isLive = true;
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 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;
}
}
坦克大战0.6版
增加功能
- 游戏开始时,播放经典的坦克大战音乐,[思路, 使用一个播放音乐的类,即可]
- 修正下文件存储位置
- 处理文件相关异常 =》提示代码的健壮性
package com.hspedu.tankgame6;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class AePlayWave extends Thread {
private String filename;
public AePlayWave(String wavfile) { //构造器 , 指定文件
filename = wavfile;
}
public void run() {
File soundFile = new File(filename);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (Exception e) {
e.printStackTrace();
return;
}
auline.start();
int nBytesRead = 0;
//这是缓冲
byte[] abData = new byte[512];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
package com.hspedu.tankgame6;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;
/**
* 坦克大战的绘图区域
*/
//为了监听 键盘事件, 实现KeyListener
//为了让Panel 不停的重绘子弹,需要将 MyPanel 实现Runnable ,当做一个线程使用
@SuppressWarnings({"all"})
public class MyPanel extends JPanel implements KeyListener, Runnable {
//定义我的坦克
Hero hero = null;
//定义敌人坦克,放入到Vector
Vector enemyTanks = new Vector();
//定义一个存放Node 对象的Vector, 用于恢复敌人坦克的坐标和方向
Vector nodes = new Vector();
//定义一个Vector ,用于存放炸弹
//说明,当子弹击中坦克时,加入一个Bomb对象到bombs
Vector bombs = new Vector();
int enemyTankSize = 3;
//定义三张炸弹图片,用于显示爆炸效果
Image image1 = null;
Image image2 = null;
Image image3 = null;
public MyPanel(String key) {
//先判断记录的文件是否存在
//如果存在,就正常执行,如果文件不存在,提示,只能开启新游戏,key = "1"
File file = new File(Recorder.getRecordFile());
if (file.exists()) {
nodes = Recorder.getNodesAndEnemyTankRec();
} else {
System.out.println("文件不存在,只能开启新的游戏");
key = "1";
}
//将MyPanel对象的 enemyTanks 设置给 Recorder 的 enemyTanks
Recorder.setEnemyTanks(enemyTanks);
hero = new Hero(500, 100);//初始化自己坦克
switch (key) {
case "1":
//初始化敌人坦克
for (int i = 0; i 6) {
g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
} else if (bomb.life > 3) {
g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
} else {
g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
}
//让这个炸弹的生命值减少
bomb.lifeDown();
//如果bomb life 为0, 就从bombs 的集合中删除
if (bomb.life == 0) {
bombs.remove(bomb);
}
}
//画出敌人的坦克, 遍历Vector
for (int i = 0; i enemyTank.getX() && s.x enemyTank.getY() && s.y enemyTank.getX() && s.x enemyTank.getY() && s.y 0) {
hero.moveUp();
}
} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键, 向右
hero.setDirect(1);
if (hero.getX() + 60 0) {
hero.moveLeft();
}
}
//如果用户按下的是J,就发射
if (e.getKeyCode() == KeyEvent.VK_J) {
//判断hero的子弹是否销毁,发射一颗子弹
if (hero.shot == null || !hero.shot.isLive) {
hero.shotEnemyTank();
}
//发射多颗子弹
//hero.shotEnemyTank();
}
//让面板重绘
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run() { //每隔 100毫秒,重绘区域, 刷新绘图区域, 子弹就移动
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是我们子弹否击中了敌人坦克
hitEnemyTank();
//判断敌人坦克是否击中我们
hitHero();
this.repaint();
}
}
}
package com.hspedu.tankgame5;
import java.io.*;
import java.nio.Buffer;
import java.util.Vector;
/**
* 该类用于记录相关信息的.和文件交互
*/
@SuppressWarnings({"all"})
public class Recorder {
//定义变量,记录我方击毁敌人坦克数
private static int allEnemyTankNum = 0;
//定义IO对象, 准备写数据到文件中
private static BufferedWriter bw = null;
private static BufferedReader br = null;
private static String recordFile = "e:myRecord.txt";
//定义Vector ,指向 MyPanel 对象的 敌人坦克Vector
private static Vector enemyTanks = null;
//定义一个Node 的Vector ,用于保存敌人的信息node
private static Vector nodes = new Vector();
public static void setEnemyTanks(Vector enemyTanks) {
Recorder.enemyTanks = enemyTanks;
}
public static String getRecordFile() {
return recordFile;
}
//增加一个方法,用于读取recordFile, 恢复相关信息
//该方法,在继续上局的时候调用即可
public static Vector getNodesAndEnemyTankRec() {
try {
br = new BufferedReader(new FileReader(recordFile));
allEnemyTankNum = Integer.parseInt(br.readLine());
//循环读取文件,生成nodes 集合
String line = "";//255 40 0
while ((line = br.readLine()) != null) {
String[] xyd = line.split(" ");
Node node = new Node(Integer.parseInt(xyd[0]), Integer.parseInt(xyd[1]),
Integer.parseInt(xyd[2]));
nodes.add(node); //放入nodes Vector
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return nodes;
}
//增加一个方法,当游戏退出时,我们将allEnemyTankNum 保存到 recordFile
//对keepRecord 进行升级, 保存敌人坦克的坐标和方向
public static void keepRecord() {
try {
bw = new BufferedWriter(new FileWriter(recordFile));
bw.write(allEnemyTankNum + "rn");
//遍历敌人坦克的Vector ,然后根据情况保存即可.
//OOP, 定义一个属性 ,然后通过setXxx得到 敌人坦克的Vector
for (int i = 0; i
package com.hspedu.tankgame6;
/**
* 炸弹
*/
public class Bomb {
int x, y; //炸弹的坐标
int life = 9; //炸弹的生命周期
boolean isLive = true; //是否还存活
public Bomb(int x, int y) {
this.x = x;
this.y = y;
}
//减少生命值
public void lifeDown() { //配合出现图片的爆炸效果
if(life > 0) {
life--;
} else {
isLive = false;
}
}
}
package com.hspedu.tankgame6;
import java.util.Vector;
/**
* 敌人的坦克
*/
@SuppressWarnings({"all"})
public class EnemyTank extends Tank implements Runnable {
//在敌人坦克类,使用Vector 保存多个Shot
Vector shots = new Vector();
//增加成员,EnemyTank 可以得到敌人坦克的Vector
//分析
//1. Vector 在
Vector enemyTanks = new Vector();
boolean isLive = true;
public EnemyTank(int x, int y) {
super(x, y);
}
//这里提供一个方法,可以将MyPanel 的成员 Vector enemyTanks = new Vector();
//设置到 EnemyTank 的成员 enemyTanks
public void setEnemyTanks(Vector enemyTanks) {
this.enemyTanks = enemyTanks;
}
//编写方法,判断当前的这个敌人坦克,是否和 enemyTanks 中的其他坦克发生的重叠或者碰撞
public boolean isTouchEnemyTank() {
//判断当前敌人坦克(this) 方向
switch (this.getDirect()) {
case 0: //上
//让当前敌人坦克和其它所有的敌人坦克比较
for (int i = 0; i = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() + 60 = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() + 40 = enemyTank.getY()
&& this.getY() + 60 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 40 = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() = enemyTank.getX()
&& this.getX() = enemyTank.getY()
&& this.getY() + 40 0 && !isTouchEnemyTank()) {
moveUp();
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1: //向右
for (int i = 0; i 0 && !isTouchEnemyTank()) {
moveLeft();
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
//然后随机的改变坦克方向 0-3
setDirect((int) (Math.random() * 4));
//听老韩说,写并发程序,一定要考虑清楚,该线程什么时候结束
if (!isLive) {
break; //退出线程.
}
}
}
}
package com.hspedu.tankgame6;
/**
* 自己的坦克
*/
public class Hero extends Tank {
//定义一个Shot对象, 表示一个射击(线程)
Shot shot = null;
//可以发射多颗子弹
//Vector shots = new Vector();
public Hero(int x, int y) {
super(x, y);
}
//射击
public void shotEnemyTank() {
//发多颗子弹怎么办, 控制在我们的面板上,最多只有5颗
// if(shots.size() == 5) {
// return;
// }
//创建 Shot 对象, 根据当前Hero对象的位置和方向来创建Shot
switch (getDirect()) {//得到Hero对象方向
case 0: //向上
shot = new Shot(getX() + 20, getY(), 0);
break;
case 1: //向右
shot = new Shot(getX() + 60, getY() + 20, 1);
break;
case 2: //向下
shot = new Shot(getX() + 20, getY() + 60, 2);
break;
case 3: //向左
shot = new Shot(getX(), getY() + 20, 3);
break;
}
//把新创建的shot放入到shots
//shots.add(shot);
//启动我们的Shot线程
new Thread(shot).start();
}
}
package com.hspedu.tankgame6;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;
public class HspTankGame06 extends JFrame {
//定义MyPanel
MyPanel mp = null;
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
HspTankGame06 hspTankGame01 = new HspTankGame06();
}
public HspTankGame06() {
System.out.println("请输入选择 1: 新游戏 2: 继续上局");
String key = scanner.next();
mp = new MyPanel(key);
//将mp 放入到Thread ,并启动
Thread thread = new Thread(mp);
thread.start();
this.add(mp);//把面板(就是游戏的绘图区域)
this.setSize(1300, 950);
this.addKeyListener(mp);//让JFrame 监听mp的键盘事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
//在JFrame 中增加相应关闭窗口的处理
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Recorder.keepRecord();
System.exit(0);
}
});
}
}
package com.hspedu.tankgame6;
/**
* 一个Node 对象,表示一个敌人坦克的信息
*/
public class Node {
private int x;
private int y;
private int direct;
public Node(int x, int y, int direct) {
this.x = x;
this.y = y;
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 int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
}
package com.hspedu.tankgame6;
/**
* 射击子弹
*/
public class Shot implements Runnable {
int x; //子弹x坐标
int y; //子弹y坐标
int direct = 0; //子弹方向
int speed = 2; //子弹的速度
boolean isLive = true; //子弹是否还存活
//构造器
public Shot(int x, int y, int direct) {
this.x = x;
this.y = y;
this.direct = direct;
}
@Override
public void run() {//射击
while (true) {
//休眠 50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//根据方向来改变x,y坐标
switch (direct) {
case 0://上
y -= speed;
break;
case 1://右
x += speed;
break;
case 2://下
y += speed;
break;
case 3://左
x -= speed;
break;
}
//老师测试,这里我们输出x,y的坐标
//System.out.println("子弹 x=" + x + " y=" + y);
//当子弹移动到面板的边界时,就应该销毁(把启动的子弹的线程销毁)
//当子弹碰到敌人坦克时,也应该结束线程
if (!(x >= 0 && x = 0 && y
package com.hspedu.tankgame6;
public class Tank {
private int x;//坦克的横坐标
private int y;//坦克的纵坐标
private int direct = 0;//坦克方向 0 上1 右 2下 3左
private int speed = 1;
boolean isLive = true;
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 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;
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
文 / 高扬(微信公众号:量子论) 今天在和大伙一起基于飞书,将《ChatGPT实用指南》改造成在线文档,给大家汇报下成果。 整体的排版工作仍由谷雨负责,看得出她在职场上没少写文档,排版很精美。 我们特别设计了一个个性化的目录,你看: 这份在线文档预计4月26…