选题目的和意义:
随着人们精神文化生活的日益丰富,为了让我们在闲暇的时间多方面发展个人的兴趣爱好,为了更好地开发个人智力,游戏成为人们生活中不可缺少的一部分。游戏产业促动高科技技术不断升级,作为经济增长的一大支撑点,已经成为经济腾飞的“第四产业”。作为休闲游戏的起源应该追溯到早期的俄罗斯方块和坦克大战,坦克大战是童年经常玩的游戏,也是一款经典游戏。《坦克大战》游戏几乎家喻户晓,对我们80后90后而言,是童年最珍贵的回忆。此款游戏是一款以红白机为平台操作射击游戏,玩家可以控制自己的坦克,以歼灭对方的坦克,其操作方式及其简单,是一款男女老少皆宜的游戏。为了满足人们的个性化需求,使玩家在游戏的过程中,更能体验游戏本身的乐趣,也为了满足更好的用户体验。
1 环境要求
操作系统:Windows 7(SP1)以上
JAVA虚拟机:JDK1.8以上
开发环境:Eclipse(4.5以上)
2 角色设定
用户在系统中扮演的角色,以及可以执行的职责。
玩 家 操纵玩家坦克,与敌方坦克作战,同时保护本基地。敌方坦克随机移动,发射子弹。
3 设定玩家(玩家一,玩家二,即一个人玩还是两个人玩),我方坦克的方向和子弹由用户控制,所有墙块都可以打碎,但是铁墙是打不碎的,草地不能阻止坦克和子弹的前进,河流能阻止坦克前进,但是不能阻止子弹前进。我方基地被毁则游戏结束,自己的坦克被毁游戏也结束,唯一赢得方式是消灭所有的敌方坦克,则可以进入下一关。一关比一关的难度大,通过地图来实现。
Wall:
Visible:
git提交截图
关键代码
Map类
1.GameMap
public class GameMap {
public static final int MAP_X = Tank.RADIUS*3;
public static final int MAP_Y = Tank.RADIUS*3 + GameFrame.titleBarH;
public static final int MAP_WIDTH = Constant.FRAME_WIDTH-Tank.RADIUS*6;
public static final int MAP_HEIGHT = Constant.FRAME_HEIGHT-Tank.RADIUS*8-GameFrame.titleBarH;
//地图元素块的容器
private List<MapTile> tiles = new ArrayList<>();
//大本营
private TankHouse house;
public GameMap() {}
/**
* 初始化地图元素块,level : 第几关
*/
public void initMap(int level){
tiles.clear();
try {
loadLevel(level);
} catch (Exception e) {
e.printStackTrace();
}
//初始化大本营
house = new TankHouse();
addHouse();
}
/**
* 加载关卡信息
* @param level
*/
private void loadLevel(int level) throws Exception{
//获得关卡信息类的唯一实例对象
LevelInof levelInof = LevelInof.getInstance();
levelInof.setLevel(level);
Properties prop = new Properties();
prop.load(new FileInputStream("level/lv_"+level));
//将所有的地图信息都加载进来
int enemyCount = Integer.parseInt(prop.getProperty("enemyCount"));
//设置敌人数量
levelInof.setEnemyCount(enemyCount);
//0,1 对敌人类型解析
String[] enemyType = prop.getProperty("enemyType").split(",");
int[] type = new int[enemyType.length];
for (int i = 0; i < type.length; i++) {
type[i] = Integer.parseInt(enemyType[i]);
}
//设置敌人类型
levelInof.setEnemyType(type);
//关卡难度
//如果没有设计游戏难度,那么就当默认的处理
String levelType = prop.getProperty("levelType");
levelInof.setLevelType(Integer.parseInt(levelType==null? "1" : levelType));
String methodName = prop.getProperty("method");
int invokeCount = Integer.parseInt(prop.getProperty("invokeCount"));
//把实参都读取到数组中来。
String[] params = new String[invokeCount];
for (int i = 1; i <=invokeCount ; i++) {
params[i-1] = prop.getProperty("param"+i);
}
//使用读取到的参数,调用对应的方法。
invokeMethod(methodName,params);
}
//根据方法的名字和参数调用对应的方法
private void invokeMethod(String name,String[] params){
for (String param : params) {
//获得每一行的方法的参数,解析。
String[] split = param.split(",");
//使用一个int 数组保存解析后的内容
int[] arr = new int[split.length];
int i;
for (i = 0; i < split.length-1; i++) {
arr[i] = Integer.parseInt(split[i]);
}
//块之间的间隔是地图块的倍数
final int DIS = MapTile.tileW ;
//解析最后一个double值
int dis = (int)(Double.parseDouble(split[i])*DIS);
switch(name){
case "addRow":
addRow(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
MAP_X+MAP_WIDTH-arr[2]*DIS,arr[3],dis);
break;
case "addCol":
addCol(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
MAP_Y+MAP_HEIGHT-arr[2]*DIS,
arr[3],dis);
break;
case "addRect":
addRect(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
MAP_X+MAP_WIDTH-arr[2]*DIS,
MAP_Y+MAP_HEIGHT-arr[3]*DIS,
arr[4],dis);
break;
}
}
}
//将老巢的所有的元素块添加到地图的容器中
private void addHouse(){
tiles.addAll(house.getTiles());
}
/**
* 某一个点确定的地图块。是否和 tiles 集合中的所有的块 有重叠的部分
* @param tiles
* @param x
* @param y
* @return 有重叠返回 true,否则 false
*/
private boolean isCollide(List<MapTile> tiles, int x ,int y){
for (MapTile tile : tiles) {
int tileX = tile.getX();
int tileY = tile.getY();
if(Math.abs(tileX-x) < MapTile.tileW && Math.abs(tileY-y) < MapTile.tileW){
return true;
}
}
return false;
}
/**
* 只对没有遮挡效果的块进行绘制
* @param g
*/
public void drawBk(Graphics g){
for (MapTile tile : tiles) {
if(tile.getType() != MapTile.TYPE_COVER)
tile.draw(g);
}
}
/**
* 只绘制有遮挡效果的块
* @param g
*/
public void drawCover(Graphics g){
for (MapTile tile : tiles) {
if(tile.getType() == MapTile.TYPE_COVER)
tile.draw(g);
}
}
public List<MapTile> getTiles() {
return tiles;
}
/**
* 将所有的不可见的地图块从容器中移除
*/
public void clearDestroyTile(){
for (int i = 0; i < tiles.size(); i++) {
MapTile tile = tiles.get(i);
if(!tile.isVisible())
tiles.remove(i);
}
}
/**
*往地图块容器中添加一行指定类型的地图块
* @param startX 添加地图块的起始的x坐标
* @param startY 添加地图块的起始的Y坐标
* @param endX 添加地图块的结束的x坐标
* @param type 地图块的类型
* @param DIS 地图块之间的中心点的间隔 如果是块的宽度 意味着是连续的,
* 如果大于块的宽度就是不连续的
*/
public void addRow(int startX,int startY, int endX, int type, final int DIS){
int count = (endX - startX +DIS )/(MapTile.tileW+DIS);
for (int i = 0; i <count ; i++) {
MapTile tile = MapTilePool.get();
tile.setType(type);
tile.setX(startX + i * (MapTile.tileW+DIS));
tile.setY(startY);
tiles.add(tile);
}
}
/**
* 往地图元素块容器中添加一列 元素。
* @param startX 该列的起始x坐标
* @param startY 该列的起始y坐标
* @param endY 改了的结束y坐标
* @param type 元素类型
* @param DIS 相邻元素中心点的间距
*/
public void addCol(int startX,int startY, int endY, int type, final int DIS){
int count = (endY - startY +DIS)/(MapTile.tileW+DIS);
for (int i = 0; i <count ; i++) {
MapTile tile = MapTilePool.get();
tile.setType(type);
tile.setX(startX );
tile.setY(startY + i * (MapTile.tileW+DIS));
tiles.add(tile);
}
}
//对指定的矩形区域添加元素块
public void addRect(int startX,int startY,int endX, int endY, int type, final int DIS){
int rows = (endY-startY+DIS)/(MapTile.tileW+DIS);
for (int i = 0; i <rows ; i++) {
addRow(startX,startY+i*(MapTile.tileW+DIS),endX,type,DIS);
}
}
}
2.TankHouse
public class TankHouse {
//老巢的xy坐标
public static final int HOUSE_X = (Constant.FRAME_WIDTH-3*MapTile.tileW >> 1)+2;
public static final int HOUSE_Y = Constant.FRAME_HEIGHT-2 *MapTile.tileW;
//一共六块地图块
private List<MapTile> tiles = new ArrayList<>();
public TankHouse() {
tiles.add(new MapTile(HOUSE_X,HOUSE_Y));
tiles.add(new MapTile(HOUSE_X,HOUSE_Y+MapTile.tileW));
tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y));
tiles.add(new MapTile(HOUSE_X+MapTile.tileW*2,HOUSE_Y));
tiles.add(new MapTile(HOUSE_X+MapTile.tileW*2,HOUSE_Y+MapTile.tileW));
//有文字的块
tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y+MapTile.tileW));
//设置老巢地图块的类型
tiles.get(tiles.size()-1).setType(MapTile.TYPE_HOUSE);
}
public void draw(Graphics g){
for (MapTile tile : tiles) {
tile.draw(g);
}
}
public List<MapTile> getTiles() {
return tiles;
}
}
3.MapTile
public class MapTile {
public static final int TYPE_NORMAL = 0;
public static final int TYPE_HOUSE = 1;
public static final int TYPE_COVER = 2;
public static final int TYPE_HARD = 3;
public static int tileW = 40;
public static int radius = tileW >> 1;
private int type = TYPE_NORMAL;
private static Image[] tileImg;
static{
tileImg = new Image[4];
tileImg[TYPE_NORMAL] = MyUtil.createImage("res/tile.png");
tileImg[TYPE_HOUSE] = MyUtil.createImage("res/house.png");
tileImg[TYPE_COVER] = MyUtil.createImage("res/cover.png");
tileImg[TYPE_HARD] = MyUtil.createImage("res/hard.png");
if(tileW <=0){
tileW = tileImg[TYPE_NORMAL].getWidth(null);
}
}
//图片资源的左上角
private int x,y;
private boolean visible = true;
public MapTile() {
}
public MapTile(int x, int y) {
this.x = x;
this.y = y;
if(tileW <=0){
tileW = tileImg[TYPE_NORMAL].getWidth(null);
}
}
public void draw(Graphics g){
if(!visible)
return;
if(tileW <=0){
tileW = tileImg[TYPE_NORMAL].getWidth(null);
}
g.drawImage(tileImg[type],x,y,null);
}
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 boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
/**
* 地图块和若干个子弹是否有碰撞
* @param bullets
* @return
*/
public boolean isCollideBullet(List<Bullet> bullets){
if(!visible || type == TYPE_COVER)
return false;
for (int i = 0; i < bullets.size(); i++) {
Bullet bullet = bullets.get(i);
// }
// for (Bullet bullet : bullets) {
int bulletX = bullet.getX();
int bulletY = bullet.getY();
boolean collide = MyUtil.isCollide(x + radius, y + radius, radius, bulletX, bulletY);
if(collide){
//子弹的销毁
bullet.setVisible(false);
BulletsPool.theReturn(bullet);
return true;
}
}
return false;
}
//判断当前的地图块是否是老巢
public boolean isHouse(){
return type == TYPE_HOUSE;
}
@Override
public String toString() {
return "MapTile{" +
"x=" + x +
", y=" + y +
", visible=" + visible +
'}';
}
}