Java编写的坦克大战【适合小白】
看了很多大佬编辑的项目发现都是一部分,并且没有详细的解读对于小白会相对难理解;这里将把所有代码及开发且的基础发布出供大家参考:
首先我们要有该项目的架构和基础变量
如下是坦克大战的架构基础
最后展示整个编写完后的运行结果:
Panel类
package com.learn.exercise.tanke;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;
/*
* 游戏备注:
* 1/2选择单双人游戏
* 回车进入游戏
* wasd控制坦克移动
* 按空格进行射击
*P按键游戏暂停
* */
/**
* 游戏页面与执行类
*/
public class Panel extends JFrame{
/**双缓冲技术解决图片闪动的问题*/
//(大致思路就是讲图片和游戏页面都在Java后台绘制一个页面然后将这个页面放到画布上)
Image offScreemImage = null;
private int width=800;
private int height=610;
//定义指针图片(通过移动该图片来选择游戏模式)
private Image select=Toolkit.getDefaultToolkit().getImage("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankR.gif");
//指针初始纵坐标
private int y =150;
//游戏模式0游戏开始1、单人模式;2、双人模式 5游戏控制成功,4失败;3暂停
public int state=0;
//添加键盘事件;key作为按下按键的键值重新定义的变量a
private int a = 1;
//重绘次数(为了控制敌方坦克添加的速度;count表示画布重绘的次数)
int count = 0 ;
//已生成敌人的数量
int enenyCount = 0;
//游戏元素列表
ArrayList<Bullet> bulletList = new ArrayList<Bullet>();
ArrayList<Bot> botList = new ArrayList<Bot>();
//子弹与敌方坦克碰撞
ArrayList<Bullet> removeList = new ArrayList<Bullet>();
//子弹与我方坦克碰撞
ArrayList<Tank> playerList = new ArrayList<Tank>();
//围墙
ArrayList<Wall>wallList = new ArrayList<Wall>();
//基地
ArrayList<Base>baseList = new ArrayList<Base>();
//添加爆炸元素的列表
ArrayList<Blast>blastList= new ArrayList<Blast>();
//PlayerOne变量玩家一,默认向上
PlayerOne playerOne = new PlayerOne("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankU.gif",125,510,
this,"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankU.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankL.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankR.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankD.gif");
//PlayerTwo变量玩家二默认向上
PlayerTwo playerTwo = new PlayerTwo("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankU.gif",625,510,
this,"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankU.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankL.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankR.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\p1tankD.gif");
//Bot 敌方图片
Bot bot = new Bot("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1U.gif",500,110,
this,"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1U.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1L.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1R.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1D.gif");
//添加一个基地
Base base = new Base("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\base.png",365,560,this);
/**
* lauch()方法
*/
//窗口的启动
public void lauch(){
setTitle("坦克大战");
setSize(width,height);
setLocationRelativeTo(null);
setDefaultCloseOperation(3);
setResizable(false);
setVisible(true);
/**添加键盘监视器;调取KeyMonitor中的数据(将KeyMonitor类实例化)*/
this.addKeyListener(new Panel.KeyMonitor());
/**添加围墙*/
for (int i=0;i<14;i++){
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg",
i*60,220,this));
}
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg", 305,560,this));
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg", 305,500,this));
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg", 365,500,this));
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg", 425,500,this));
wallList.add(new Wall("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\rsteels.jpg", 425,560,this));
/**添加基地*/
baseList.add(base);
/**重绘*/
// 在画直线的时候,我们应该把数据保存起来,在刷新窗体时顺便把直线也一并画出来。
//目的:在挪动窗口的时候依旧会重新绘制线条而不是挪动导致消失不见
while (true){
//游戏控制开关(胜利判断)
if (botList.size()==0&&enenyCount == 10){
state = 5;
}
//(失败判断)
if ((playerList.size() == 0 && (state==1||state ==2)) || baseList.size() == 0){
state = 4;
}
// 批量添加电脑坦克Bot
if (count % 100 ==1 && enenyCount < 6 && (state == 1|| state == 2)){//state游戏状态限制
//随机生成敌方坦克
Random random = new Random();
int rnum = random.nextInt(800);
botList.add(new Bot("E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1U.gif",rnum,110,
this,"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1U.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1L.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1R.gif",
"E:\\Program Files\\GYJ\\IntelliJ IDEA 2020.1.2\\classOne\\src\\com\\learn\\exercise\\tanke\\img\\enemy1D.gif"));
enenyCount++;
}
repaint();
try{
Thread.sleep(25);
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* paint()方法
* @param g
*/
@Override
public void paint(Graphics g){
/**双缓冲技术解决图片闪动的问题部分代码*/
//创建和容量一样大小的Image图片
if (offScreemImage == null){
offScreemImage = this.createImage(width,height);
}
/**获得该图片的画笔*/
Graphics gImage = offScreemImage.getGraphics();
//为窗口背景进行上色
//g.setColor(Color.gray);原本的g都更换为双缓存后的变量
gImage.setColor(Color.gray);
gImage.fillRect(0,0,width,height);
gImage.setColor(Color.blue);
//为窗口添加启动文字及样式
gImage.setFont(new Font("仿宋",Font.BOLD,50));
//state=0游戏未开始
if(state==0){
gImage.drawString("选择游戏模式",220,100);
gImage.drawString("单人模式",220,200);
gImage.drawString("双人模式",220,300);
//绘制指针
gImage.drawImage(select,160,y,null);
}else if (state==1||state==2){//state=1/2时,游戏开始
gImage.drawString("游戏开始",220,100);
if (state==1){
gImage.drawString("单人模式",220,200);
}else{
gImage.drawString("双人模式",220,200);
}
//显示敌方坦克数
gImage.setFont(new Font("仿宋",Font.BOLD,30));
gImage.setColor(Color.red);
gImage.drawString("剩余敌人:"+botList.size(),0,60);
//添加游戏元素;出现玩家小坦克
//没有添加碰撞前的状态playerOne.paintSelf(gImage);
for (Tank player:playerList){
player.paintSelf(gImage);
}
for (Bullet bullet:bulletList){
bullet.paintSelf(gImage);
}
//敌方小坦克
for (Bot bot:botList){
bot.paintSelf(gImage);
}
//删除子弹removeAll();
bulletList.removeAll(removeList);
//绘制游戏中绘制出来围墙
for (Wall wall:wallList){
wall.paintSelf(gImage);
}
//绘制游戏中绘制出来基地
for (Base base:baseList){
base.paintSelf(gImage);
}
//绘制爆炸元素
for (Blast blast:blastList){
blast.paintSelf(gImage);
}
//重绘一次
count++;
}//游戏胜利控制
else if (state ==5){
gImage.drawString("游戏胜利",220,200);
}//游戏失败控制
else if (state ==4){
gImage.drawString("游戏失败",220,200);
}//添加暂停情况
else if (state == 3){
gImage.drawString("游戏暂停",220,200);
}
/**将缓冲区图片绘制好后的图形整个绘制到容器的画布中*/
g.drawImage(offScreemImage,0,0,null);
}
/**
* 键盘监视器继承KeyAdapter类
*/
class KeyMonitor extends KeyAdapter{
//按下键盘
@Override
public void keyPressed(KeyEvent e){
//返回键值
//System.out.println(e.getKeyChar());
//添加键盘事件;key作为按下按键的键值
int key = e.getKeyCode();
//用Switch来判断key的值
switch (key){
//VK_1:按键1的键值
case KeyEvent.VK_1:
//这里不能直接添加state=1(state只能按回车赋值)否则会直接跳转为单人模式
//这里需要重新定义一个a进行该部分赋值操作
a = 1;
y = 150;
break;
case KeyEvent.VK_2:
a = 2;
y = 250;
break;
case KeyEvent.VK_ENTER:
//按回车键赋值state=1
state = a;
//玩家一坦克
playerList.add(playerOne);
//玩家二坦克:platerOne
if (state==2){
playerList.add(playerTwo);
//定义坦克玩家二初始化为存在,当被击中后生命值为false
playerTwo.alive = true;
}
//定义坦克初始化为存在,当被击中后生命值为false
playerOne.alive = true;
break;
//暂停P
case KeyEvent.VK_P:
if (state != 3){
a =state;
state = 3;
}else {
state = a;
if (a == 0){
a=1;
}
}
break;
//键盘按下wasd时
default:
playerOne.keyPressed(e);
playerTwo.keyPressed(e);
}
}
//松开键盘的时候
@Override
public void keyReleased(KeyEvent e){
playerOne.keyReleased(e);
//玩家二的键盘事件
playerTwo.keyReleased(e);
}
}
/**
* main()方法
* @param args
*/
public static void main(String[] args) {
Panel gp= new Panel();
gp.lauch();
}
}