Java最全纯Java实现坦克大战游戏,源码公开,阿里出品

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 10、当我的坦克被敌人子弹击中,我的坦克爆炸

  • 11、防止敌人坦克重叠运动

  • 12、可以分关–做一个开始的Panel,它是空的主要是提示关卡

  • 13、游戏可以暂停、继续–暂停时将子弹、坦克速度设为0,坦克方向不变

  • 14、可以记录玩家的成绩

  • 15、java如何操作声音文件

一、源码


package com.haiding.tank_7;

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.io.File;

import javax.imageio.ImageIO;

import javax.swing.*;

import java.util.*;

import javax.sound.sampled.*;

public class MyTank07 extends JFrame implements ActionListener{

//定义组件

MyPanel mp=null;

//定义一个开始面板

MyStartPanel msp=null;

//做出菜单

JMenuBar jmb=null;

//开始游戏

JMenu jm1=null;

JMenuItem jmi1=null;

//退出游戏

JMenuItem jmi2=null;

//存盘退出

JMenuItem jmi3=null;

//接上局

JMenuItem jmi4=null;

public static void main(String[] args) {

MyTank07 mt=new MyTank07();

}

//构造函数

public MyTank07(){

//创建菜单及菜单选项

jmb=new JMenuBar();

jm1=new JMenu(“游戏(G)”);

//设置快捷方式

jm1.setMnemonic(‘G’);

jmi1=new JMenuItem(“开始新游戏(N)”);

jmi1.setMnemonic(‘N’);

//对jmi1相应

jmi1.addActionListener(this);

jmi1.setActionCommand(“newgame”);

jmi2=new JMenuItem(“退出游戏(E)”);

jmi2.setMnemonic(‘E’);

jmi2.addActionListener(this);

jmi2.setActionCommand(“exit”);

jmi3=new JMenuItem(“存盘退出(S)”);

jmi3.setMnemonic(‘S’);

jmi3.addActionListener(this);

jmi3.setActionCommand(“save”);

jmi4=new JMenuItem(“继续游戏©”);

jmi4.setMnemonic(‘C’);

jmi4.addActionListener(this);

jmi4.setActionCommand(“congame”);

jm1.add(jmi1);

jm1.add(jmi2);

jm1.add(jmi3);

jm1.add(jmi4);

jmb.add(jm1);

this.setJMenuBar(jmb);

//构建组件

msp=new MyStartPanel();

Thread t=new Thread(msp);

t.start();

this.add(msp);

//设置JFrame窗体

this.setTitle(“坦克大战”);//JFrame标题

this.setSize(600, 500);//JFrame窗体大小

this.setLocationRelativeTo(null);//在屏幕中心显示

this.setVisible(true);//显示

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出并关闭JFrame

}

public void actionPerformed(ActionEvent e) {

//对用户不同的点击,做出不同的处理

if(e.getActionCommand().equals(“newgame”)){

//创建战场面板

mp=new MyPanel(“newgame”);

//启动mp线程

Thread ta=new Thread(mp);

ta.start();

//先删除旧的开始面板

this.remove(msp);

//加入组件

this.add(mp);

//监听

this.addKeyListener(mp);

//显示,刷新JFrame

this.setVisible(true);

}else if(e.getActionCommand().equals(“exit”)){

//用户点击了退出菜单

//保存用户游戏记录数据

Recorder.keepRecording();

System.exit(0);

}else if(e.getActionCommand().equals(“save”)){

//用户点击保存菜单

//保存击毁敌人的数量和敌人的坐标

Recorder.setEts(mp.ets);

Recorder.keepRecAndEnemyTank();

System.exit(0);

}else if(e.getActionCommand().equals(“congame”)){

//继续上次游戏

//创建战场面板

mp=new MyPanel(“congame”);

//启动mp线程

Thread ta=new Thread(mp);

ta.start();

//先删除旧的开始面板

this.remove(msp);

//加入组件

this.add(mp);

//监听

this.addKeyListener(mp);

//显示,刷新JFrame

this.setVisible(true);

}

}

}

//开始面板–起提示作用

class MyStartPanel extends JPanel implements Runnable{

int times=0;

public void paint(Graphics g){

super.paint(g);

g.setColor(Color.black);

g.fillRect(0, 0, 400, 300);

//提示信息

if(times%2==0){

g.setColor(Color.yellow);

//开关信息的字体

Font myFont=new Font(“华文新魏”, Font.BOLD, 30);

g.setFont(myFont);

g.drawString(“Stage: 1”, 150, 150);

}

}

public void run() {

while(true){

//休眠

try {

Thread.sleep(500);

} catch (Exception e) {

e.printStackTrace();

}

times++;

//重画

this.repaint();

}

}

}

//我的面板Panel

class MyPanel extends JPanel implements KeyListener,Runnable{//MyPanel继承Jpanel面板,创建KeyListener键盘接口和Runnable线程接口

//定义一个我的坦克

Hero hero=null;

//定义声音播放

AePlayWave apw=null;

//定义敌人的坦克组

Vector ets=new Vector();

Vector nodes=new Vector();

//定义炸弹集合

Vector bombs=new Vector();

int enSize=3;//初始敌人坦克数量

//定义爆炸图片

Image image1=null;

Image image2=null;

Image image3=null;

//构造函数

public MyPanel(String flag){

hero=new Hero(200, 270);//我的坦克初始位置

//恢复游戏记录

Recorder.getRecoring();

if(flag.equals(“newgame”)){

//播放开战声音

apw=new AePlayWave(“e:\tankgame\tankmusic.wav”);

apw.start();

//初始化敌人的坦克

for(int i=0;i<enSize;i++){

//创建一辆敌人的坦克对象

EnemyTank et=new EnemyTank((i+1)*50, 0);

//初始敌人坦克颜色

et.setColor(2);

//初始敌人坦克的方向

et.setDirect(1);

//将MyPanel的敌人向量交给该敌人坦克

et.setEts(ets);

//启动敌人坦克进程

Thread t=new Thread(et);

t.start();

//给敌人坦克添加一颗子弹

Shot s=new Shot(et.x+10, et.y+30, 1);

//把子弹加入给敌人

et.ss.add(s);

Thread t2=new Thread(s);

t2.start();

//加入敌人坦克

ets.add(et);

}

}else if(flag.equals(“congame”)){

nodes=new Recorder().getNodesAndEnNums();

//初始化敌人的坦克

for(int i=0;i<nodes.size();i++){

Node node=nodes.get(i);

//创建一辆敌人的坦克对象

EnemyTank et=new EnemyTank(node.x, node.y);

//初始敌人坦克颜色

et.setColor(2);

//初始敌人坦克的方向

et.setDirect(node.direct);

//将MyPanel的敌人向量交给该敌人坦克

et.setEts(ets);

//启动敌人坦克进程

Thread t=new Thread(et);

t.start();

//给敌人坦克添加一颗子弹

Shot s=new Shot(et.x+10, et.y+30, 1);

//把子弹加入给敌人

et.ss.add(s);

Thread t2=new Thread(s);

t2.start();

//加入敌人坦克

ets.add(et);

}

}

//初始化爆炸图片

try {

image1=ImageIO.read(new File(“bomb1.gif”));

image2=ImageIO.read(new File(“bomb2.gif”));

image3=ImageIO.read(new File(“bomb3.gif”));

} catch (Exception e) {

e.printStackTrace();

}

}

//画出提示信息

public void showInfo(Graphics g){

//画出提示信息坦克(该坦克不参与战斗,只是用于显示提示信息)

this.drawTank(80, 330, g, 1, 0);

g.setColor(Color.BLACK);

g.setFont(new Font(“宋体”,Font.BOLD,20));

g.drawString(Recorder.getEnNum()+“”, 110, 350);//显示敌人坦克数量

this.drawTank(140, 330, g, 0, 0);

g.setColor(Color.BLACK);

g.setFont(new Font(“宋体”,Font.BOLD,20));

g.drawString(Recorder.getMyLife()+“”, 170, 350);//显示我的坦克数量

//画出玩家的总成绩

g.setColor(Color.black);

g.setFont(new Font(“宋体”,Font.BOLD,20));

g.drawString(“您的总成绩”, 420, 30);

this.drawTank(420, 60, g, 1, 0);

g.setColor(Color.black);

g.setFont(new Font(“宋体”,Font.BOLD,20));

g.drawString(Recorder.getAllEnNum()+“”, 460, 80);

}

//重写paint函数

public void paint(Graphics g){

super.paint(g);//调用父类paint方法

//画出提示信息

this.showInfo(g);

//设置Panel底色

g.setColor(Color.black);

g.fillRect(0, 0, 400, 300);//fillRect(0,0,X?,Y?)中X?/Y?为活动区域

//画出自己的坦克

if(hero.isLive==true){

this.drawTank(hero.getX(), hero.getY(), g, 0, this.hero.direct);

}

//从ss向量中取出每一颗子弹并画出

for(int i=0;i<this.hero.ss.size();i++){

Shot myShot=hero.ss.get(i);

//画出一颗子弹,判断子弹是否为空

if(myShot!=null&&myShot.isLive==true){

g.draw3DRect(myShot.x, myShot.y, 1, 1, false);

}

//判断子弹是否死亡

if(myShot.isLive==false){

//从向量ss中删除该子弹

hero.ss.remove(myShot);

}

}

//画出炸弹

for(int i=0;i<bombs.size();i++){

//取出炸弹

Bomb b=bombs.get(i);

if(b.life>6){

g.drawImage(image1, b.x, b.y, 30, 30, this);

}else if(b.life>3){

g.drawImage(image2, b.x, b.y, 30, 30, this);

}else {

g.drawImage(image3, b.x, b.y, 30, 30, this);

}

//让b的生命值减少

b.lifeDown();

//如果炸弹生命值为0,就把该炸弹从bombs向量中去掉

if(b.life==0){

bombs.remove(b);

}

}

//画出敌人的坦克

for(int i=0;i<ets.size();i++){

EnemyTank et=ets.get(i);

if(et.isLive){

this.drawTank(et.getX(), et.getY() , g, 1, et.getDirect());

//再画出敌人坦克的子弹

for(int j=0;j<et.ss.size();j++){

//取出子弹

Shot enemyShot=et.ss.get(j);

if(enemyShot.isLive){

g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false);

}else{

//如果敌人的坦克死亡了就从向量Vector中去掉

et.ss.remove(enemyShot);

}

}

}

}

}

//判断我的子弹是否击中敌人的坦克

public void hitEnemyTank(){

//遍历Vector集合类

for(int i=0;i<hero.ss.size();i++){

//先取子弹

Shot myShot=hero.ss.get(i);

//判断子弹是否有效

if(myShot.isLive){

//取出每一个敌人坦克与子弹进行判断

for(int j=0;j<ets.size();j++){

//取出坦克

EnemyTank et=ets.get(j);

//判断敌人坦克是否还活着

if(et.isLive){

if(this.hitTank(myShot, et)){

apw=new AePlayWave(“e:\tankgame\tank_explosion.wav”);

apw.start();

//调用reduceEnNum()减少敌人坦克统计数

Recorder.reduceEnNum();

//调用addEnNumRec()增加消灭敌人坦克统计数

Recorder.addEnNumRec();

}

}

}

}

}

}

//判断敌人的子弹是否击中我的坦克

public void hitMe(){

//取出每一个敌人的坦克

for(int i=0;i<this.ets.size();i++){

//取出敌人的坦克

EnemyTank et=ets.get(i);

//取出每一颗敌人的子弹

for(int j=0;j<et.ss.size();j++){

//取出子弹

Shot enemyShot=et.ss.get(j);

if(hero.isLive){

if(this.hitTank(enemyShot, hero)){

}

}

}

}

}

//写一个函数专门判断子弹是否击中敌人坦克

public boolean hitTank(Shot s,Tank et){

boolean b=false;

//判断该敌人坦克的方向

switch(et.direct){

case 0://敌人坦克向上或向下

case 1:

if(s.x>et.x&&s.x<et.x+20&&s.y>et.y&&s.y<et.y+29){

//击中方向为上或下的敌人坦克

//子弹死亡

s.isLive=false;

//敌人坦克死亡

et.isLive=false;

b=true;

//创建一颗炸弹

Bomb bomb=new Bomb(et.x, et.y);

//放入Vector向量中管理

bombs.add(bomb);

}

break;

case 2://敌人坦克向左或向右

case 3:

if(s.x>et.x&&s.x<et.x+29&&s.y>et.y&&s.y<et.y+20){

//击中方向为左或右的敌人坦克

//子弹死亡

s.isLive=false;

//敌人坦克死亡

et.isLive=false;

b=true;

//创建一颗炸弹

Bomb bomb=new Bomb(et.x, et.y);

//放入Vector向量中管理

bombs.add(bomb);

}

break;

}

return b;

}

//画出坦克的函数

public void drawTank(int x,int y,Graphics g,int type,int direct){

//判断是什么类型的坦克

switch(type){

case 0:

g.setColor(Color.cyan);//我的坦克颜色

break;

case 1:

g.setColor(Color.yellow);//敌人坦克颜色

break;

case 2:

g.setColor(Color.red);

break;

}

//判断坦克的方向

switch(direct){

//向上走的坦克

case 0:

//画出我的坦克(到时再封装成一个函数)

//1、画出左边的矩形

g.fill3DRect(x, y, 5, 30, false);

//2、画出右边的矩形

g.fill3DRect(x+15, y, 5, 30, false);

//3、画出中间矩形

g.fill3DRect(x+5, y+5, 10, 20, false);

//4、画出中间圆形

g.fillOval(x+5, y+10, 10, 10);

//5、画出线(炮筒)

g.drawLine(x+10, y+15, x+10, y);

break;

//向下走的坦克

case 1:

g.fill3DRect(x, y, 5, 30, false);

g.fill3DRect(x+15, y, 5, 30, false);

g.fill3DRect(x+5, y+5, 10, 20, false);

g.fillOval(x+5, y+10, 10, 10);

g.drawLine(x+10, y+15, x+10, y+29);

break;

//向左走的坦克

case 2:

g.fill3DRect(x, y, 30, 5, false);

g.fill3DRect(x, y+15, 30, 5, false);

g.fill3DRect(x+5, y+5, 20, 10, false);

g.fillOval(x+10, y+5, 10, 10);

g.drawLine(x+15, y+10, x, y+10);

break;

//向右走的坦克

case 3:

g.fill3DRect(x, y, 30, 5, false);

g.fill3DRect(x, y+15, 30, 5, false);

g.fill3DRect(x+5, y+5, 20, 10, false);

g.fillOval(x+10, y+5, 10, 10);

g.drawLine(x+15, y+10, x+29, y+10);

break;

}

}

public void keyPressed(KeyEvent e) {//按下键事件a向左s向下d向右w向上

if(e.getKeyCode()==KeyEvent.VK_W||e.getKeyCode()==KeyEvent.VK_UP){

//向上

this.hero.setDirect(0);

this.hero.moveUp();

}else if(e.getKeyCode()==KeyEvent.VK_S||e.getKeyCode()==KeyEvent.VK_DOWN){

//设置我的坦克的方向,向下

this.hero.setDirect(1);

this.hero.moveDown();

}else if(e.getKeyCode()==KeyEvent.VK_A||e.getKeyCode()==KeyEvent.VK_LEFT){

//向左

this.hero.setDirect(2);

this.hero.moveLeft();

}else if(e.getKeyCode()==KeyEvent.VK_D||e.getKeyCode()==KeyEvent.VK_RIGHT){

//向右

this.hero.setDirect(3);

this.hero.moveRight();

}

//判断玩家是否按下空格键,不可接上面else if。不然不能同时按方向键和空格(space)键

if(e.getKeyCode()==KeyEvent.VK_SPACE){

apw=new AePlayWave(“e:\tankgame\tank_Shelling_sound.wav”);

apw.start();

//控制子弹连发

if(this.hero.ss.size()<=4){

//按下空格后开火

this.hero.shotEnemy();

}

}

//调用repaint()函数,来重绘界面

this.repaint();

}

public void keyReleased(KeyEvent e) {//弹起键事件

}

public void keyTyped(KeyEvent e) {//按键输出值

}

//重写run函数

public void run() {

while(true){

try {

Thread.sleep(100);//休息100毫秒后重绘MyPanel面板

} catch (Exception e) {

e.printStackTrace();

}

this.hitEnemyTank();

//判断敌人的子弹是否击中我的坦克

this.hitMe();

//重绘MyPanel面板

this.repaint();

}

}

}

二、成员类


package com.haiding.tank_7;

import java.util.Vector;

import java.io.*;

import javax.sound.sampled.*;

//播放声音的类

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[2048];

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();

}

}

}

//记录恢复点

class Node{

int x,y,direct;

public Node(int x,int y,int direct){

this.x=x;

this.y=y;

this.direct=direct;

}

}

//记录类,同时也可以保存玩家的设置

class Recorder{

//记录每关有多少敌人

private static int enNum=20;

//设置我有多少可用的人

private static int myLife=3;

//记录总共消灭了多少敌人的坦克

private static int allEnNum=0;

//从文件中恢复记录点

private static Vector nodes=new Vector();

private static FileWriter fw=null;

private static BufferedWriter bw=null;

private static FileReader fr=null;

private static BufferedReader br=null;

private static Vector ets=new Vector();

//完成读取任务点任务

public static Vector getNodesAndEnNums(){

try {

fr=new FileReader(“e:\tankgame\tanksave.txt”);

br=new BufferedReader(fr);

String n=“”;

//先读一行

n=br.readLine();

allEnNum=Integer.parseInt(n);

while((n=br.readLine())!=null){

String []Recovery=n.split(" ");//split方法可以按一行字符中有多少个空间来返回数组

Node node=new Node(Integer.parseInt(Recovery[0]),Integer.parseInt(Recovery[1]),Integer.parseInt(Recovery[2]));

nodes.add(node);

}

} catch (Exception e) {

e.printStackTrace();

}finally{

try {

br.close();

fr.close();

} catch (Exception e2) {

e2.printStackTrace();

}

}

return nodes;

}

//保存击毁敌人的数量和敌人坦克坐标、方向

public static void keepRecAndEnemyTank(){

try {

//创建

fw=new FileWriter(“e:\tankgame\tanksave.txt”);

bw=new BufferedWriter(fw);

bw.write(allEnNum+“\r\n”);

//保存当前还活着的敌人坦克坐标、方向

for(int i=0;i<ets.size();i++){

//取出第一个坦克

EnemyTank et=ets.get(i);

if(et.isLive){

//活的保存

String recode=et.x+" “+et.y+” "+et.direct;//得到坐标x,y和方向direct

//写入到文件

bw.write(recode+“\r\n”);

}

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//关闭流,先开后关,后开先关

try {

bw.close();

fw.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

//从文件中读取记录

public static void getRecoring(){

try {

fr=new FileReader(“e:\tankgame\tanksave.txt”);

br=new BufferedReader(fr);

String n=br.readLine();

allEnNum=Integer.parseInt(n);

} catch (Exception e) {

1200页Java架构面试专题及答案

小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞

百度、字节、美团等大厂常见面试题

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

e.printStackTrace();

}finally{

try {

br.close();

fr.close();

} catch (Exception e2) {

e2.printStackTrace();

}

}

return nodes;

}

//保存击毁敌人的数量和敌人坦克坐标、方向

public static void keepRecAndEnemyTank(){

try {

//创建

fw=new FileWriter(“e:\tankgame\tanksave.txt”);

bw=new BufferedWriter(fw);

bw.write(allEnNum+“\r\n”);

//保存当前还活着的敌人坦克坐标、方向

for(int i=0;i<ets.size();i++){

//取出第一个坦克

EnemyTank et=ets.get(i);

if(et.isLive){

//活的保存

String recode=et.x+" “+et.y+” "+et.direct;//得到坐标x,y和方向direct

//写入到文件

bw.write(recode+“\r\n”);

}

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//关闭流,先开后关,后开先关

try {

bw.close();

fw.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

//从文件中读取记录

public static void getRecoring(){

try {

fr=new FileReader(“e:\tankgame\tanksave.txt”);

br=new BufferedReader(fr);

String n=br.readLine();

allEnNum=Integer.parseInt(n);

} catch (Exception e) {

1200页Java架构面试专题及答案

小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞

[外链图片转存中…(img-S3xISR60-1715354739233)]

[外链图片转存中…(img-hTnPakrK-1715354739234)]

百度、字节、美团等大厂常见面试题

[外链图片转存中…(img-nE5sSWta-1715354739234)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值