项目代码下载: CSDN_java小游戏-坦克大战1.0
项目代码下载:百度云盘链接
VSCode直接选择打开文件夹即可(打开项目名的文件夹,该文件夹下一层便是bin/src等子文件夹)
来源:该游戏来自尚学堂~,大家有兴趣可以去关注一下(^_^)
游戏界面样式
游戏需求分析
- 模式选择:单人模式、双人模式
- 坦克上下左右移动,可以发射子弹,击中敌方坦克发生爆炸、击中围墙,围墙消失、被子弹击中消失。
- 胜负逻辑判断:
胜利:游戏开始后,敌方坦克数量被清空;
失败:游戏开始后,我方坦克数量被清空或者基地被摧毁。 - 页面设计
设计类
GameObject:抽象类,定义抽象方法
GamePanel:主页面,游戏开始控制
Base:基地类
Blast:爆炸类,对于爆炸的图片进行滚动播放
Bot:敌方坦克
Bullet:子弹类
Direction:方向枚举
EnemBullet:敌人子弹
PlayerOne:玩家1-坦克1:WASD – 控制上下左右的方向,空格发射炮弹.
PlayerTwo:玩家2-坦克2:方向键 – 控制上下左右的方向,k键发射炮弹.
Tank:坦克类
Wall:围墙类
过程1:初始化界面
目标:熟悉UI页面布局,调用图片
过程2:用面向对象思想设置功能
目标:理解面向对象的思想,为类添加对应的功能
过程3:调用类实例化对象
目标:使用ArrayList存放对象信息
- GamePanel .java
package game;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class GamePanel extends JFrame {
int width = 800; // 页面的宽度
int height = 610;// 页面的高度
Image offScreemImage = null; // 双缓存图片,用于解决闪烁问题
Image select = Toolkit.getDefaultToolkit().getImage("images/selecttank.gif");// 初始页面的选择坦克
int y = 150;// 初始页面的y坐标
int state = 0; // 游戏状态
int a = 1;// 临时信息
int count = 0;
int enemyCount = 0;// 控制敌方坦克数量
ArrayList<Bot> botList = new ArrayList<Bot>(); // 敌方坦克
ArrayList<Wall> wallList = new ArrayList<Wall>();// 围墙
ArrayList<Bullet> bulletList = new ArrayList<Bullet>();// 子弹
ArrayList<Bullet> removeList = new ArrayList<Bullet>();// 移除子弹
ArrayList<Tank> playerList = new ArrayList<Tank>();// 玩家坦克
ArrayList<Base> baseList = new ArrayList<Base>();// 基地
ArrayList<Blast> blastList = new ArrayList<Blast>();// 爆炸
// 玩家1
PlayerOne playerOne = new PlayerOne("images/player/p1tankU.gif", 240, 550, this, "images/player/p1tankU.gif",
"images/player/p1tankL.gif", "images/player/p1tankR.gif", "images/player/p1tankD.gif");
// 玩家2
PlayerTwo playerTwo = new PlayerTwo("images/player/p2tankU.gif", 625, 550, this, "images/player/p2tankU.gif",
"images/player/p2tankL.gif", "images/player/p2tankR.gif", "images/player/p2tankD.gif");
// 敌方
Bot bot = new Bot("images/enemy/enemy1U.gif", 500, 110, this, "images/enemy/enemy1U.gif",
"images/enemy/enemy1L.gif", "images/enemy/enemy1R.gif", "images/enemy/enemy1D.gif");
// 基地
Base base = new Base("images/star.gif", 370, 560, this);
// 游戏开始
private void start() {
// 设置页面布局
setTitle("坦克大战");
setSize(width, height);
setLocationRelativeTo(null);
setDefaultCloseOperation(3);
setResizable(false);
setVisible(true);
this.addKeyListener(new KeyMonitor());// 添加监听器
// 添加围墙
for (int i = 0; i < 14; i++) {
wallList.add(new Wall("images/walls.gif", 50 + i * 50, 170, this));
}
wallList.add(new Wall("images/walls.gif", 305, 560, this));
wallList.add(new Wall("images/walls.gif", 305, 500, this));
wallList.add(new Wall("images/walls.gif", 365, 500, this));
wallList.add(new Wall("images/walls.gif", 425, 500, this));
wallList.add(new Wall("images/walls.gif", 425, 560, this));
baseList.add(base); // 添加基地
while (true) {
// 游戏失败判定
if ((playerList.size() == 0 && (state == 1 || state == 2)) || baseList.size() == 0) {
state = 4;
}
// 游戏胜利判定
if (botList.size() == 0 && enemyCount == 10) {
state = 5;
}
// 添加敌方坦克
if (count % 100 == 0 && enemyCount < 10 && (state == 1 || state == 2)) {
int rnum = new Random().nextInt(400);
System.out.println(rnum + "---");
botList.add(new Bot("images/enemy/enemy1U.gif", rnum, 110, this, "images/enemy/enemy1U.gif",
"images/enemy/enemy1L.gif", "images/enemy/enemy1R.gif", "images/enemy/enemy1D.gif"));
enemyCount++;
}
repaint(); // 重新绘制
try {
Thread.sleep(25);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
/**
* paint(Graphics g) : 绘图,g是画笔
*/
@Override
public void paint(Graphics g) {
if (offScreemImage == null) {
offScreemImage = this.createImage(width, height);
}
Graphics gImage = offScreemImage.getGraphics();
gImage.setColor(Color.gray);
gImage.fillRect(0, 0, width, height);
gImage.setColor(Color.blue);
gImage.setFont(new Font("仿宋", Font.BOLD, 50));
if (state == 0) {
gImage.drawString("选择游戏模式", 220, 100);
gImage.drawString("1. 单人模式", 220, 200);
gImage.drawString("2. 双人模式", 220, 300);
gImage.setFont(new Font("仿宋", Font.BOLD, 20));
gImage.drawString("输入1,2切换模式,Enter 确认", 220, 400);
gImage.drawImage(select, 160, y, null);
} else if (state == 1 || state == 2) {
// gImage.drawString("游戏开始", 200, 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(), 20, 100);
// 绘制游戏元素
// playerOne.paintSelf(gImage);
for (Tank player : playerList) {
player.paintSelf(gImage);
}
for (Wall wall : wallList) {
wall.paintSelf(gImage);
}
for (Bullet bullet : bulletList) {
bullet.paintSelf(gImage);
}
bulletList.remove(removeList);
// 敌方坦克
// bot.paintSelf(gImage);
for (Bot bot : botList) {
bot.paintSelf(gImage);
}
for (Base base : baseList) {
base.paintSelf(gImage);
}
for (Blast blast : blastList) {
blast.paintSelf(gImage);
}
count++;
} else if (state == 3) {
gImage.drawString("游戏暂停", 220, 200);
} else if (state == 4) {
gImage.drawString("游戏失败", 220, 200);
} else if (state == 5) {
gImage.drawString("游戏胜利", 220, 200);
}
g.drawImage(offScreemImage, 0, 0, null);
}
public static void main(String[] args) {
GamePanel gp = new GamePanel();
gp.start();
}
/**
* 通过继承适配器,实现事件的处理
*/
class KeyMonitor extends KeyAdapter {
// 按下键盘
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_1:
a = 1;
y = 150;
break;
case KeyEvent.VK_2:
a = 2;
y = 250;
break;
case KeyEvent.VK_ENTER:
state = a;
playerList.add(playerOne);
if (state == 2) {
playerList.add(playerTwo);
}
playerOne.alive = true;
playerTwo.alive = true;
break;
case KeyEvent.VK_P:
if (state != 3) {
a = state;
state = 3;
} else {
state = a;
if (a == 0)
a = 1;
}
default:
playerOne.KeyPressed(e);
playerTwo.KeyPressed(e);
}
}
// 松开键盘
@Override
public void keyReleased(KeyEvent e) {
playerOne.KeyReleased(e);
playerTwo.KeyReleased(e);
}
}
}
过程4:联合调试
目标:完成基础功能