资源描述
Java课程设计
任 务 书
简单电子游戏坦克大战设计
1、关键内容:
设计一个简单坦克大战电子游戏,能够允很多位玩家在局域网
中同时对战
2、 系统要求:游戏含有图形游戏界面,能让用户看到游戏所给出反馈。
有些人机交互功效,使用户操作指定游戏元素,而且坦克含有生命值,能
攻击敌方,无法攻击友方,而且坦克攻击含有视觉效果!
3、 具体要求(包含技术要求等):
1.需要有图形游戏界面,让用户能看到游戏给出反馈
2.有些人机交互功效,使用户能操作指定游戏元素
3.不一样队伍坦克,须显示不一样外观,已分辨敌我
4.坦克能够开火,攻击敌方,但不能攻击队友
5需要有不可被子弹穿透墙
6.坦克有生命值,并非被击中一次就会爆炸
7游戏结束后可重新开始
学习并掌握以下技术:Java、JavaBean 等
熟练使用以下开发工具:Myeclipse 等
实现系统上述功效。
4、 进度安排:
12月28日 ~ 12月 29日:课程设计选题,查找参考资料
12月30日 ~ 1月1日: 完成系统设计和数据库设计
1月2日 ~ 1月4日: 完成程序代码编写
1月4日 ~ 1月5日:系统测试和完善
1月5日 ~ 1月6日:完成课程设计汇报,准备答辩
分工:
摘 要
伴随计算机普及和对电子游戏认识,电子游戏已被越来越多人选作放松、娱乐休闲方法;电子游戏既不需要专门购置游戏器材,也不需要宽广游戏场地,只需要一台能独立完成任务计算机即可,它能够是大家工作、学习时用计算机,并不需要另行配置,这比起传统休闲游戏即省钱又省事。局域网游戏更是能够将现实空间中零碎计算机,组织起来,使其在逻辑空间中集中起来,使游戏组织、开展变得轻松。如此轻松而又安逸休闲方法,使得越来越多人尝试,甚至已经将电子游戏作为关键休闲方法,既然有如此多人使用,那其中肯定存在巨大商机,即使大家不愿意为一个小小休闲游戏花费金钱,但在游戏中添加广告、游戏相关服务也包藏了巨大财富;当然电子游戏制作现在已是空前火爆,大大小小游戏企业横空出世,全部想在电子游戏制作这个行业里占据一席之地,而一款成功电子游戏需要精心策划、分析、设计,只有这么才能取得游戏中包藏财富,和做出一款真正能够让玩家娱乐、放松游戏,而不是骗取玩家钱财工具。
关键字:电子游戏;坦克大战;
目 录
一、 系统分析 - 1 -
可行性分析 - 1 -
需求分析 - 1 -
二、 概要设计 - 2 -
工作步骤图 - 2 -
项目计划 - 3 -
开发及运行环境 - 3 -
三、 具体设计和算法实现 - 4 -
游戏主窗口 - 4 -
游戏元素 - 8 -
四、 测试 - 10 -
测试环境 - 10 -
测试结果 - 10 -
五、 软件截图 - 11 -
六、 总结 - 14 -
七、 参考文件 - 15 -
一、 系统分析
可行性分析
技术可行性
软件使用swing、GUI、Socket、面向对象设计等技术实现,这些技术均已是很成熟技术,之前已经有相当多使用这些技术成功案例,故现使用这些技术是可行。
经济可行性
本软件为无偿软件,将无偿提供软件下载、运行和维护服务,软件暂无收入,待公布以后伴随使用者越来越多,将添加对应广告、服务,从而增加收入,若使用者寥寥无几,将再次分析是否重新策划软件或放弃开发,以降低损失。
需求分析
经过反复研究和市场调查,得悉游戏须含有以下功效:
q 需要有图形游戏界面,让用户能看到游戏给出反馈
q 不一样队伍坦克,须显示不一样外观,已分辨敌我
q 坦克能够开火,攻击敌方
q 坦克有生命值
q 游戏结束时须判定哪一队胜利
q 游戏结束后可重新开始
q 游戏操作、进度等须提供对应说明,以通知玩家
二、 概要设计
工作步骤图
程序开始
初始化游戏元素
依据游戏元素属性,对其进行操作和绘出去图形
战斗结束?
项目计划
本游戏是一个经典电子小游戏,应含有以下结构:
q 游戏主窗口
游戏一切效果、进度、消息等全部将由游戏主窗口展示
q 封装游戏元素
游戏元素包含:坦克、子弹、等游戏必需元素
开发及运行环境
开发时硬件环境
q CPU:Inter P7350
q 显卡:NVIDIA GeForce 105M
q 内存:金士顿2G/DDR2-667
q 显示器:三星液晶14寸/分辨率:1280X800
开发时软件环境
q 操作系统:Windows7
q JDK:1.5.0
q IDE:Eclipse3.4.0
运行时硬件环境
q CPU:Inter P7350
q 显卡:NVIDIA GeForce 105M
q 内存:金士顿2G/DDR2-667
运行时软件环境
q 操作系统:Windows 7
q JRE:1.6.0
q 显示器:三星液晶14寸/分辨率:1280X800
q
三、 具体设计和算法实现
游戏主窗口
游戏主窗口是人机交互窗口,对玩家而言,她们只和游戏主窗口打交道,并不关心游戏内部是怎样实现,所以游戏主窗口部分最关键便是游戏数据输入、输出。
在程序中须创建一个类TankClient,继承自Frame来创建一个窗口。
游戏数据输入
游戏中坦克需要能往上、下、左、右四个方向运动,故须设置4个按键,使其能操作坦克,另须设一个键控制坦克开火。为方便操作,本游戏设置方向键分别表示上下左右,空格表示开火。
具体实现为在TankClient类中添加内部适配器类代码以下:
/**
* 方向键被按下后标识被按下键
* @param e 键盘事件
*/
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_LEFT:
bL = true;
break;
case KeyEvent.VK_UP:
bU = true;
break;
case KeyEvent.VK_RIGHT:
bR = true;
break;
case KeyEvent.VK_DOWN:
bD = true;
break;
case KeyEvent.VK_CONTROL:
if (!this.hasMyMissile())
fire();
break;
case KeyEvent.VK_A:
superFire();
break;
case KeyEvent.VK_F2:
tc = null;
new TankClient("TankClient", 50, 10, 3);
break;
}
locateDirection();
}
/**
* 方向键被松开后标识被松开键
* @param e 键盘事件
*/
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_LEFT:
bL = false;
break;
case KeyEvent.VK_UP:
bU = false;
break;
case KeyEvent.VK_RIGHT:
bR = false;
break;
case KeyEvent.VK_DOWN:
bD = false;
break;
}
locateDirection();
}
/**
* 依据按下键定位方向
*/
public void locateDirection() {
if (bL && !bU && !bR && !bD)
dir = Direction.L;
if (bL && bU && !bR && !bD)
dir = Direction.LU;
if (!bL && bU && !bR && !bD)
dir = Direction.U;
if (!bL && bU && bR && !bD)
dir = Direction.RU;
if (!bL && !bU && bR && !bD)
dir = Direction.R;
if (!bL && !bU && bR && bD)
dir = Direction.RD;
if (!bL && !bU && !bR && bD)
dir = Direction.D;
if (bL && !bU && !bR && bD)
dir = Direction.LD;
if (!bL && !bU && !bR && !bD)
dir = Direction.STOP;
}
/**
* 依据方向移动坦克
*/
public void move() {
lastX = x;
lastY = y;
switch (dir) {
case L:
x -= SPEED;
break;
case LU:
x -= XYSPEED;
y -= XYSPEED;
break;
case U:
y -= SPEED;
break;
case RU:
x += XYSPEED;
y -= XYSPEED;
break;
case R:
x += SPEED;
break;
case RD:
x += XYSPEED;
y += XYSPEED;
break;
case D:
y += SPEED;
break;
case LD:
x -= XYSPEED;
y += XYSPEED;
break;
case STOP:
break;
}
if (dir != Direction.STOP)
ptDir = dir;
//控制坦克不出界
if (x < 0)
x = 0;
if (y < 30)
y = 30;
if (x > TankClient.WINDOW_WIDTH - this.RADIUS * 2)
x = TankClient.WINDOW_WIDTH - this.RADIUS * 2;
if (y > TankClient.WINDOW_HEIGHT - this.RADIUS * 2)
y = TankClient.WINDOW_HEIGHT - this.RADIUS * 2;
}
/**
* 依据坦克位置和炮筒方向发射炮弹
*/
public void fire() {
if (!this.live)
return;
int x = this.x + Tank.RADIUS - Missile.RADIUS;
int y = this.y + Tank.RADIUS - Missile.RADIUS;
Missile m = new Missile(x, y, this.good, ptDir, this, tc);
tc.missiles.add(m);
}
/**
* 画炮筒
* @param g Graphics对象
*/
public void drawPT(Graphics g) {
int x1 = this.x + Tank.RADIUS;
int y1 = this.y + Tank.RADIUS;
int x2 = this.x + Tank.RADIUS;
int y2 = this.y + Tank.RADIUS;
switch (ptDir) {
case L:
x2 = x1 - PT_LENGTH;
break;
case LU:
x2 = x1 - PT_XY;
y2 = y1 - PT_XY;
break;
case U:
y2 = y1 - PT_LENGTH;
break;
case RU:
x2 = x1 + PT_XY;
y2 = y1 - PT_XY;
break;
case R:
x2 = x1 + PT_LENGTH;
break;
case RD:
x2 = x1 + PT_XY;
y2 = y1 + PT_XY;
break;
case D:
y2 = y1 + PT_LENGTH;
break;
case LD:
x2 = x1 - PT_XY;
y2 = y1 + PT_XY;
break;
}
g.drawLine(x1, y1, x2, y2);
}
游戏数据输出
玩家需要从游戏输出数据中取得游戏信息,如坦克在往上行驶、坦克发了颗子弹、坦克爆炸等,这些均需要经过游戏数据输出来通知玩家。
因为TankClient继承自Frame,Frame类中方法paint,能够在窗口中绘制图形,满足了游戏需要图形界面需求
代码以下:
//主面版
public void paint(Graphics g) {
if (this == null)
return;
if (!myTank.isLive()) {
if (-- this.myTankNum > 0) {
myTank = new Tank(Tank_X, Tank_Y, true, this);
} else {
g.drawString("GameOver!", 350, 280);
g.drawString("按F2键重新开始..", 340, 300);
return;
}
}
if (tankAllNum == 0) {
g.drawString(".:恭喜过关!:.", 350, 280);
g.drawString("按F2键重新开始..", 340, 300);
return;
}
this.reinforceTank();
this.drawWalls(g);
this.drawMissiles(g);
this.drawMyTank(g);
this.drawEnemyTanks(g);
this.drawExplodes(g);
this.drawTreasure(g);
this.drawMessage(g);
}
/**
* 重写update方法,先将窗体上图形画在图片对象上,再一次性显示
*/
public void update(Graphics g) {
if (offScreenImage == null) {
offScreenImage = this.createImage(WINDOW_WIDTH, WINDOW_HEIGHT);
}
Graphics gImage = offScreenImage.getGraphics();
Color c = gImage.getColor();
gImage.setColor(Color.GREEN);
gImage.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
gImage.setColor(c);
paint(gImage);
g.drawImage(offScreenImage, 0, 0, null);
}
/**
* 用线程重画,每隔一段时间重画窗体
* @author Magci
*
*/
private class PaintThread implements Runnable {
/**
* 每隔REFRESH_RATE毫秒重画一次窗体
*/
public void run() {
while (true) {
repaint();
try {
Thread.sleep(REFRESH_RATE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 监听键盘事件,按方向键控制坦克移动
* @author Magci
*
*/
private class KeyMonitor extends KeyAdapter {
/**
* 处理按键被按下事件
*/
public void keyPressed(KeyEvent e) {
myTank.keyPressed(e);
}
/**
* 处理按键被松开事件
*/
public void keyReleased(KeyEvent e) {
myTank.keyReleased(e);
}
}
/**
* 敌方坦克支援
*/
public void reinforceTank() {
if (tankNum < tankMaxNum && tankAllNum > tankNum) {
int i = rand.nextInt(10);
Tank enemyTank = new Tank(200 + 50 * i, 100, false, this);
if (!enemyTank.collidesWithTank(myTank, true) && !enemyTank.collidesWithTanks(enemyTanks, true)) {
enemyTanks.add(enemyTank);
this.tankNum ++;
}
}
}
/**
* 加入墙
* @param g Graphics对象
*/
public void drawWalls(Graphics g) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = walls.get(i);
wall.draw(g);
}
}
/**
* 画我方坦克
* @param g Graphics对象
*/
public void drawMyTank(Graphics g) {
if (myTank != null) {
myTank.draw(g);
myTank.collidesWithWalls(walls);
if (trea != null)
myTank.eatTreasure(trea);
}
}
/**
* 画敌方坦克
* @param g Graphics对象
*/
public void drawEnemyTanks(Graphics g) {
for (int i = 0; i < enemyTanks.size(); i++) {
Tank enemyTank = enemyTanks.get(i);
enemyTank.draw(g);
enemyTank.collidesWithWalls(walls);
enemyTank.collidesWithTank(myTank, false);
enemyTank.collidesWithTanks(enemyTanks, false);
}
}
/**
* 画炮弹
* @param g Graphics对象
*/
public void drawMissiles(Graphics g) {
for (int i = 0; i < missiles.size(); i++) {
Missile m = missiles.get(i);
if (m != null) {
m.draw(g);
m.hitTanks(enemyTanks);
m.hitTank(myTank);
m.hitWalls(walls);
m.hitMissiles(missiles);
}
}
}
/**
* 加入爆炸
* @param g Graphics对象
*/
public void drawExplodes(Graphics g) {
for (int i=0; i < explodes.size(); i++) {
Explode e = explodes.get(i);
e.draw(g);
}
}
/**
* 出现宝物
* @param g Graphics对象
*/
public void drawTreasure(Graphics g) {
if (rand.nextInt(100) == 0)
trea = null;
if (rand.nextInt(300) == 0) {
int x = rand.nextInt(785);
int y = rand.nextInt(555);
trea = new Treasure(x,y + 30,15,15);
}
if (trea != null) {
trea.collidesWithWalls(walls);
trea.draw(g);
}
}
/**
* 打印信息
* @param g Graphics对象
*/
public void drawMessage(Graphics g) {
g.drawString("EnemyTanks Count: " + enemyTanks.size(), 10, 50);
g.drawString("All EnemyTanks Count: " + this.tankAllNum, 10, 70);
g.drawString("MyTank Count: " + this.myTankNum, 10, 90);
g.drawString("MyTank Life: " + myTank.getLife(), 10, 110);
}
/**
* 返回敌方坦克总数量
* @return 敌方坦克总数量
*/
public int getTankAllNum() {
return tankAllNum;
}
/**
* 设置敌方坦克总数量
* @param tankAllNum 敌方坦克总数量
*/
public void setTankAllNum(int tankAllNum) {
this.tankAllNum = tankAllNum;
}
/**
* 返回目前敌方坦克数量
* @return 返回目前敌方坦克数量
*/
public int getTankNum() {
return tankNum;
}
/**
* 设置目前敌方坦克数量
* @param tankNum 目前敌方坦克数量
*/
public void setTankNum(int tankNum) {
this.tankNum = tankNum;
}
}
class Tank {
/**
* 坦克水平垂直移动时X、Y轴上速度
*/
public static final int SPEED = 5;
/**
* 坦克45度移动时X、Y轴上速度
*/
public static final int XYSPEED = (int) (Math.sqrt(2) * SPEED / 2);
/**
* 坦克半径
*/
public static final int RADIUS = 15;
/**
* 炮筒长度
*/
public static final int PT_LENGTH = 20;
/**
* 45度炮筒X、Y坐标偏移量
*/
public static final int PT_XY = (int) (Math.sqrt(2) * PT_LENGTH) / 2;
/**
* 坦克初始生命值
*/
public static final int LIFE = 100;
// 坦克左上角位置
private int x, y;
// 标识方向键状态:true表示被按下,false表示被松开
private boolean bL = false, bU = false, bR = false, bD = false;
// 定义八个方向和停止状态
enum Direction {
L, LU, U, RU, R, RD, D, LD, STOP
};
/**
* 坦克方向
*/
public Direction dir = Direction.STOP;
/**
* 坦克炮筒方向
*/
public Direction ptDir = Direction.U;
TankClient tc = null;
//标识敌我坦克,true表示我方坦克,false表示敌方坦克
private boolean good;
//标识坦克生命状态
private boolean live = true;
private Random rand = new Random();
//地方坦克改变一次方向需要步数
private int step = rand.nextInt(10) + 3;
//坦克上一个位置
private int lastX = -1, lastY = -1;
//坦克生命值
private int life = LIFE;
//坦克生命条
LifeBar lb = new LifeBar();
/**
* 依据坦克位置和敌我状态创建一个坦克
* @param x 坦克左上角X坐标
* @param y 坦克左上角Y坐标
* @param good 坦克敌我状态
*/
public Tank(int x, int y, boolean good) {
this.x = x;
this.y = y;
this.good = good;
}
/**
* 依据坦克位置,敌我状态和目前游戏窗体创建一个坦克
* @param x 坦克左上角X坐标
* @param y 坦克左上角Y坐标
* @param good 坦克敌我状态
* @param tc 目前游戏窗体
*/
public Tank(int x, int y, boolean good, TankClient tc) {
this(x, y, good);
this.tc = tc;
}
/**
* 在窗体上画出坦克
* @param g Graphics对象
*/
展开阅读全文