图片是类与类之间的包位置关系,与代码的导包操作相关
[点击并拖拽以移动]
图片是类之间的关系,以及工具类的包位置
package com.tank.app;
import com.tank.game.GameFrame;
public class GameMain {
public static void main(String[] args) {
new GameFrame();
//注意在这种项目中尽量使用fori去遍历而不使用forEach去遍历,因为forEach的底层是迭代器,迭代器在
//删除过程中会产生异常,并且难以排查
}
}
package com.tank.game;
import com.tank.Map.GameMap;
import com.tank.Map.MapTile;
import com.tank.tank.EnemyTank;
import com.tank.tank.MyTank;
import com.tank.tank.Tank;
import com.tank.util.MyUtil;
import com.tank.util.TankPool;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.tank.util.constant.*;//这里就将该资源下的所有常量等导入
public class GameFrame extends Frame implements Runnable{
private Image over=null;
private BufferedImage image=new BufferedImage(FRAME_WIDTH,FRAME_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);
public static int gameState;//用来记录状态
public static int menuIndex;//用来记录选中的菜单选项
private Tank myTank;
//标题栏的高度
public static int titleBarH;
public static ArrayList enemies=new ArrayList<>();
public static GameMap map;
//游戏的主窗口类
//所有的游戏的展示内容都在该类中进行实现
public GameFrame(){
initEventListener();
initFrame();//所有方法都在这里进行初始化
new Thread(this).start();//启动线程
}
public void initGame(){
gameState=STATE_MENU;
}
public static int getGameState() {
return gameState;
}
public static void setGameState(int gameState) {
GameFrame.gameState = gameState;
}
private void initFrame(){
setTitle(GAME_TITLE);//设置窗口主题
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setLocation(FRAME_X,FRAME_Y);
setResizable(false);//设置不可拉伸
setVisible(true);
titleBarH=getInsets().top;
//创建坦克
}
private void drawMenu(Graphics g){
//绘制
g.setColor(Color.black);
//g.fillRect(0,0,FRAME_WIDTH,FRAME_HEIGHT);//背景黑色
setBackground(Color.black);
final int STR_WIDTH=76;
int x= FRAME_WIDTH-STR_WIDTH>>1;
int y=FRAME_HEIGHT/3;
final int DIS=50;
g.setColor(Color.white);
for (int i = 0; i < MENUS.length; i++) {
if(i==menuIndex){
//说明是我们选中的那一个
g.setColor(Color.red);
}else{
g.setColor(Color.white);
}
g.drawString(MENUS[i],x,y+DIS*i );
}
}
private void drawOver(Graphics g) {
//游戏结束时候的draw
if(over==null){
over= MyUtil.createImage("res/theEnd.png");
}
int imgW=over.getWidth(null);
int imgH=over.getHeight(null);
g.drawImage(over,FRAME_WIDTH-imgW>>1,FRAME_HEIGHT-imgH>>1,null);
g.setColor(Color.white);
g.drawString(OVER_STR0,10,FRAME_HEIGHT-20);
g.drawString(OVER_STR1,FRAME_WIDTH-200,FRAME_HEIGHT-20);
}
private void drawEnemy(Graphics g){
for(int i=0;iMENUS.length-1){
menuIndex=0;
}
//repaint();//窗口重新绘制
break;
case KeyEvent.VK_ENTER:
//TODO
newGame();
break;
}
}
private void newGame() {
//开始新游戏的方法
gameState=STATE_RUN;
//在游戏开始的时候重新启动一个线程用来控制敌人坦克的控制
myTank=new MyTank(100,100,Tank.DIR_DOWN);
map=new GameMap();
new Thread() {
@Override
//内部类也要重写run方法才能实现
public void run(){
while(true){
if(enemies.size() bullets=new ArrayList<>();//类似于弹夹,用来管理所有的子弹类
private List explodes=new ArrayList<>();//存储爆炸的容器
public Tank(int x, int y, int dir) {
this.x = x;
this.y = y;
this.dir=dir;
initTank();
}
public Tank() {
initTank();
}
private void initTank(){
hp=DEFAULT_HP;
color= MyUtil.getRandomColor();
name=MyUtil.getRandomName();//拿到随机名字
}
//坦克的逻辑处理
private void logic(){
switch(state){
case STATE_STAND:
break;
case STATE_MOVE:
move();
break;
case STATE_DIE:
break;
}
}
private void move() {
//根据方向处理坐标
oldX=x;
oldY=y;
switch(dir){
case DIR_UP:
y-=speed;
if(yFRAME_HEIGHT-RADIUS){
y=FRAME_HEIGHT-RADIUS;
}
break;
case DIR_LEFT:
x-=speed;
if(xFRAME_WIDTH-RADIUS){
x=FRAME_WIDTH-RADIUS;
}
break;
}
}
//坦克的绘制,将其自动线程控制
public void draw(Graphics g){
//这里是每一个帧数都在调用,坦克要每一帧都要知道
logic();
drawTankImage(g);//用图片绘制
drawBullets(g);//绘画子弹
drawName(g);
bloodBar.draw(g);//绘画血条
}
public abstract void drawTankImage(Graphics g);
private void drawTank(Graphics g){
g.setColor(color);
//绘制坦克的⚪
g.fillOval(x-RADIUS,y-RADIUS,RADIUS<<1,RADIUS<<1);
int endX=x;
int endY=y;
switch(dir){
case DIR_UP:
endY=y-RADIUS;
break;
case DIR_DOWN:
endY=y+RADIUS;
break;
case DIR_LEFT:
endX=x-RADIUS;
break;
case DIR_RIGHT:
endX=x+RADIUS;
break;
}
g.drawLine(x,y,endX,endY);
}
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 int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDir() {
return dir;
}
public void setDir(int dir) {
this.dir = dir;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public List getBullets() {
return bullets;
}
public void setBullets(List bullets) {
this.bullets = bullets;
}
private long fireTime;
public void fire(){
//开火的方法
if(System.currentTimeMillis()-fireTime> FIRE_INTERVAL) {
int bulletX = x;
int bulletY = y;
switch (dir) {
case DIR_UP:
bulletY -= RADIUS;
break;
case DIR_DOWN:
bulletY += RADIUS;
break;
case DIR_LEFT:
bulletX -= RADIUS;
break;
case DIR_RIGHT:
bulletX += RADIUS;
break;
}
//这里子弹就可以直接从对象池中拿了
Bullet bullet = BulletPool.get();
bullet.setX(bulletX);
bullet.setY(bulletY);
bullet.setDir(dir);
bullet.setAtk(atk);
bullet.setColor(color);
bullet.setVisible(true);
bullets.add(bullet);//要进行反复创建销毁,否则就会一直增加
fireTime=System.currentTimeMillis();//不断去更新时间
}
}
private void drawBullets(Graphics g){
//在进行绘画的同时判断是否有已经需要销毁的子弹,进行回收
for(Bullet b: bullets){
b.draw(g);
}
for(int i=0;i bullets){
for(Bullet bullet: bullets){
if(MyUtil.isCollide(x,y,RADIUS,bullet.getX(),bullet.getY())){
//碰撞到了
//子弹消失
bullet.setVisible(false);
//坦克受到伤害,用一个方法来写
hurt(bullet);
//添加爆炸特效
// explodes.add(new Explode(x-RADIUS,y+RADIUS));
addExplode(x-RADIUS,y+RADIUS-10);
}
}
}
private void addExplode(int x,int y){
Explode explode= ExplodePool.get();
explode.setX(x);
explode.setY(y);
explode.setVisible(true);
explodes.add(explode);//注意还要添加到本身的容器中
}
private void hurt(Bullet bullet){
//坦克受到伤害的方法完成
int atk=bullet.getAtk();
hp-=atk;
//这里还要有坦克死亡的方法
if(isDie()) {
die();
}
}
private void die(){
if(isEnemy){
//敌人死了
TankPool.theReturn(this);//死亡后归还
}else{
//玩家死了
//切换游戏状态
delaySecondToOver(3000);
}
}
public boolean isDie(){
return hp<=0;
}
//添加爆炸效果
public void drawExplode(Graphics g){
for(Explode explode:explodes){
explode.draw(g);
}
for (int i = 0; i < explodes.size(); i++) {
if(!explodes.get(i).isVisible()){
Explode remove=explodes.remove(i);
ExplodePool.theReturn(remove);//返回对象池
i--;
}
}
}
//画出名字
public void drawName(Graphics g){
g.setColor(color);
g.setFont(constant.TANK_NAME);
g.drawString(name,x-RADIUS,y-40);
}
//这里用一个内部类来表示坦克的血量对象
class BloodBar{
//血量对象
public static final int BAR_LENGTH=50;
public static final int BAR_HEIGHT=4;
public void draw(Graphics g){
//绘画血条,底色为黄色
g.setColor(Color.yellow);
g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);
//红色的当前血量
g.setColor(Color.RED);
g.fillRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,hp*BAR_LENGTH/DEFAULT_HP,BAR_HEIGHT);
//蓝色的边框
g.setColor(Color.BLUE);
g.drawRect(x-RADIUS,y-RADIUS-BAR_HEIGHT*2,BAR_LENGTH,BAR_HEIGHT);
}
}
public void resetBullet(){
for(Bullet b:bullets){
//在游戏重置的时候调用此方法
BulletPool.theReturn(b);
}
bullets.clear();//清空
}
//坦克的子弹与所有砖块的碰撞逻辑
public void BulletCollide(List tiles){
for(MapTile m:tiles){
if(m.getType()== MapTile.TYPE_COVER)
continue;
if(m.isCollideBullet(bullets)){
//发生碰撞,爆炸效果
if(m.getType()==MapTile.TYPE_HARD)
continue;
addExplode(m.getX()+MapTile.radius-20,m.getY()+MapTile.radius-20);
//设置地图块销毁
m.setVisible(false);
if(m.isHouse()) {
delaySecondToOver(3000);
}
}
}
}
private void delaySecondToOver(int seconds){
new Thread(){
public void run(){
try {
Thread.sleep(seconds);
GameFrame.gameState= STATE_OVER;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
//地图块和坦克的碰撞
public boolean isCollideTile(List tiles){
for(MapTile tile:tiles){
if(tile.getType()==MapTile.TYPE_COVER)
continue;
int tileX=tile.getX();
int tileY=tile.getY();
//这里是取点判断是否和坦克碰撞上
boolean Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileX+=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileX+=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileY+=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileY+=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileX-=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileX-=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
tileY-=RADIUS*2-10;
Collide=MyUtil.isCollide(x,y,RADIUS,tileX,tileY);
if(Collide)
return true;
}
return false;
}
public void back(){
x=oldX;
y=oldY;
}
}
public class MyTank extends Tank {
//将坦克图片替换为自己做的
private static Image[] tankImg;
//还有敌人的坦克
static{
//静态代码块中初始化坦克
tankImg=new Image[4];
tankImg[0]= MyUtil.createImage("res/tank.png");//这个方法来将图片加载进去
tankImg[1]=MyUtil.createImage("res/tank2.png");
tankImg[2]= MyUtil.createImage("res/tank3.png");
tankImg[3]=MyUtil.createImage("res/tank4.png");
}
public MyTank(int x, int y, int dir) {
super(x, y, dir);
}
public void drawTankImage(Graphics g){
g.drawImage(tankImg[getDir()], getX()- RADIUS, getY() - RADIUS, null);
}
}
package com.tank.tank;
import com.tank.game.GameFrame;
import com.tank.util.MyUtil;
import com.tank.util.TankPool;
import java.awt.*;
import static com.tank.util.constant.*;
public class EnemyTank extends Tank{
private double aiTime;//记录时间
private static Image[] enemyImg;
static {
enemyImg = new Image[4];
enemyImg[0] = MyUtil.createImage("res/tank.png");//这个方法来将图片加载进去
enemyImg[1] = MyUtil.createImage("res/tank2.png");
enemyImg[2] = MyUtil.createImage("res/tank3.png");
enemyImg[3] = MyUtil.createImage("res/tank4.png");
}
public EnemyTank(int x, int y, int dir) {
super(x, y, dir);
aiTime=System.currentTimeMillis();
}
public EnemyTank() {
aiTime=System.currentTimeMillis();
}
public static Tank createEnemy(){
//创建敌人坦克类
int x= MyUtil.getRandomNumber(0,2)==0?RADIUS: FRAME_WIDTH-2*RADIUS;
int y= GameFrame.titleBarH+RADIUS;
int dir=DIR_DOWN;
Tank enemy= TankPool.get();
enemy.setX(x);
enemy.setY(y);
enemy.setDir(dir);
enemy.setHp(DEFAULT_HP);//每次创建的时候要给其赋值,不然就会拿到血条已经空的坦克
enemy.isEnemy = true;//标识为敌人
//TODO
enemy.setState(STATE_MOVE);
return enemy;
}
public void drawTankImage(Graphics g){
ai();
g.drawImage(enemyImg[getDir()], getX() - RADIUS, getY() - RADIUS, null);
}
private void ai(){
//简单ai控制敌人
if(System.currentTimeMillis()-aiTime>=ENEMY_AI_INTERVAL){
//当超过五秒
this.setState(MyUtil.getRandomNumber(0,2)==0?STATE_STAND:STATE_MOVE);
//还要记得重置时间,还要改变方向
setDir(MyUtil.getRandomNumber(DIR_UP,DIR_RIGHT+1));
aiTime=System.currentTimeMillis();
}
if(Math.random()>1;
public static final int FRAME_Y=768-FRAME_HEIGHT>>1;
//游戏的状态也作为常量
//1:游戏菜单
public static final int STATE_MENU=0;
public static final int STATE_HELP=1;
public static final int STATE_ABOUT=2;
public static final int STATE_RUN=3;
public static final int STATE_OVER=4;
public static final String[] MENUS ={
"开始游戏",
"继续游戏",
"游戏帮助",
"游戏关于",
"退出游戏"
};
public static final Font font=new Font("宋体",Font.BOLD,24);
public static final Font TANK_NAME=new Font("宋体",Font.BOLD,12);
public static final int REPAINT_INTERVAL=20;//
public static final int ENEMY_MAX_COUNT=10;//敌人最大数量
public static final int ENEMY_BORN_TIME=5000;
public static final int ENEMY_AI_INTERVAL=5000;//这么长时间就换一次方向和状态
public static final double ENEMY_FIRE_INTERVAL= 0.03;//这是发射子弹的概率
public static final int TANK_ATK=80;
public static final String OVER_STR0="ESC键退出游戏";
public static final String OVER_STR1="ENTER键回到主菜单";
public static int FIRE_INTERVAL=500;//子弹发射间隔时间
public static String HOUSE_NAME="家";
}
package com.tank.util;
import com.tank.tank.EnemyTank;
import com.tank.tank.Tank;
import java.util.ArrayList;
public class TankPool {
//敌人坦克对象池,自己的坦克只有一辆,不需要对象池
private static int ENEMY_COUNT=10;
private static ArrayList enemies=new ArrayList<>();
static{
for (int i = 0; i < ENEMY_COUNT; i++) {
enemies.add(new EnemyTank());
}
}
public static Tank get(){
if(enemies.size()!=0){
return enemies.remove(0);
}else{
return new EnemyTank();
}
}
public static void theReturn(Tank enemyTank){
if(enemies.size()==ENEMY_COUNT){
return;
}
enemies.add(enemyTank);
}
}
package com.tank.game;
import com.tank.tank.Tank;
import com.tank.util.BulletPool;
import java.awt.*;
import static com.tank.util.constant.*;
public class Bullet {
private boolean isVisible=true;
public static final int DEFAULT_SPEED= Tank.DEFAULT_SPEED*2;
public static final int RADIUS=4;
//子弹类
private int x,y;
private int speed=DEFAULT_SPEED;
private int atk;
private int dir;//方向
private Color color;
public Bullet(int x, int y, int atk, int dir,Color color) {
//isVisible=true;
this.x = x;
this.y = y;
this.atk = atk;
this.dir = dir;
this.color=color;
}
public Bullet() {
//对象池的专用,所有属性值全部都是默认
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
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 int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDir() {
return dir;
}
public void setDir(int dir) {
this.dir = dir;
}
//绘画
public void draw(Graphics g){
if(!isVisible){
//已经不可见
return;
}
logic();
g.setColor(color);
g.fillOval(x-RADIUS,y-RADIUS,RADIUS<<1,RADIUS<<1);
}
private void logic(){
//子弹运动的逻辑
move();
}
private void move(){
switch (dir){
case Tank.DIR_UP:
y-=speed;
if(y<=0) {
isVisible = false;
}
break;
case Tank.DIR_DOWN:
y+=speed;
if(y>FRAME_HEIGHT) {
isVisible = false;
}
break;
case Tank.DIR_LEFT:
x-=speed;
if(x<=0) {
isVisible = false;
}
break;
case Tank.DIR_RIGHT:
x+=speed;
if(x>FRAME_WIDTH) {
isVisible = false;
}
break;
}
}
public void setVisible(boolean visible) {
this.isVisible=visible;
}
public boolean Visible(){
return isVisible;
}
}
package com.tank.util;
import com.tank.game.Bullet;
import java.util.ArrayList;
import java.util.List;
public class BulletPool {
private static final int DEFAULT_POOL_SIZE=200;//定义池子大小
//子弹池类
private static List pool=new ArrayList<>();
static{
for (int i = 0; i < DEFAULT_POOL_SIZE; i++) {
pool.add(new Bullet());
}
}
public static Bullet get(){
Bullet bullet=null;
if(pool.size()==0){
bullet=new Bullet();
}else {
bullet = pool.remove(0);
}
return bullet;
}
//在销毁之后还要还回来
public static void theReturn(Bullet b){
if(pool.size()==DEFAULT_POOL_SIZE){
return;
}
pool.add(b);
}
}
package com.tank.game;
import com.tank.util.MyUtil;
import java.awt.*;
public class Explode {
//控制爆炸效果的类
private static final int EXPLODE_COUNT=9;//没三帧显示一次
private static Image []images=new Image[3];
private static int imageWidth;
private static int imageHeight;
static{
for (int i = 0; i < 3; i++) {
images[i]= MyUtil.createImage("res/boom_"+i+".png");//拿到图片资源
}
imageWidth=images[0].getWidth(null)/2;
imageHeight=images[0].getHeight(null);
}
private int x,y;
private int index;//记录现在的帧数
public boolean visible=true;//刚创建时候为true
public Explode(int x, int y) {
this.x = x;
this.y = y;
index=0;//初始化为0
}
public Explode() {
index=0;
}
public void draw(Graphics g){
if(!visible)return;
g.drawImage(images[index/3],x-imageWidth,y-imageHeight,null);
index++;
if(index>EXPLODE_COUNT-1){
visible=false;//当帧数大于设置的值,就设置为不可见即可
}
}
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 int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
package com.tank.util;
import com.tank.game.Explode;
import java.util.ArrayList;
public class ExplodePool {
//将爆炸对象封装为对象池进行销毁和创建
private static final int EXPLODE_COUNT=200;//默认为最大为200个
private static final ArrayList explodes=new ArrayList<>();
static{
for (int i = 0; i < EXPLODE_COUNT; i++) {
explodes.add(new Explode());
}
//创建
}
public static Explode get(){
if(explodes.size()!=0){
return explodes.remove(0);
}else{
return new Explode();
}
}
//销毁之后还要还回来
public static void theReturn(Explode e){
if(explodes.size()==EXPLODE_COUNT){
return;
}
explodes.add(e);
}
}
package com.tank.Map;
import com.tank.game.Bullet;
import com.tank.game.GameFrame;
import com.tank.tank.Tank;
import com.tank.util.MyUtil;
import com.tank.util.constant;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class MapTile {
//砖块类
private int type=TYPE_NORMAL;
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 Image []tileImg=new Image[4];
public static int tileW=50;
public static int radius = tileW >> 1;
private boolean Visible=true;
public String name;
static{
tileImg[0]= MyUtil.createImage("res/wall.png");
tileImg[1]=MyUtil.createImage("res/house.png");
tileImg[2]=MyUtil.createImage("res/cover.png");
tileImg[3]=MyUtil.createImage("res/hard.png");
if(tileW<=0){
tileW=tileImg[3].getWidth(null);
}
}
private int x,y;//左上角坐标
public MapTile(int x, int y) {
this.x = x;
this.y = y;
if(tileW<=0){
tileW=tileImg[3].getWidth(null);
}
}
public MapTile() {
if(tileW<=0){
tileW=tileImg[3].getWidth(null);
}
}
public boolean isVisible() {
return Visible;
}
public void setVisible(boolean visible) {
Visible = visible;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 void draw(Graphics g){
if(!Visible){
return;
}
if(tileW<=0){
tileW=tileImg[0].getWidth(null);
}
g.drawImage(tileImg[type],x,y,null);
if(name!=null){
g.setColor(Color.blue);
g.drawString(name,x+radius/2,y+radius*3/2);
}
}
public boolean isCollideBullet(List bullets){
if(!Visible){
return false;
}
for(Bullet b:bullets){
int bulletX=b.getX();
int bulletY=b.getY();
boolean collide=MyUtil.isCollide(x+ radius,y+radius,radius,bulletX,bulletY);
if(collide){
//发生碰撞之后子弹消失
b.setVisible(false);
return true;
}
}
return false;
}
public boolean isHouse(){
return type==TYPE_HOUSE;
}
}
package com.tank.Map;
import com.tank.game.GameFrame;
import com.tank.tank.Tank;
import com.tank.util.MapPool;
import com.tank.util.MyUtil;
import com.tank.util.constant;
import java.awt.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.List;
public class GameMap {
//游戏地图类
private static ArrayList tiles=new ArrayList<>();
private static final int MAP_X= Tank.RADIUS*3;
private static final int MAP_Y=Tank.RADIUS*3;
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 TankHouse house=new TankHouse();//
public GameMap() {
init(1);
}
public ArrayList getTiles() {
return tiles;
}
public void setTiles(ArrayList tiles) {
GameMap.tiles = tiles;
}
private void init(int level){
//通过解析文件的方式来获取方法参数,从而绘制出地图,需要传进来是第几关
try {
loadLevel(level);
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadLevel(int level) throws IOException {
Properties prop=new Properties();//通过文件加载进来
prop.load(new FileInputStream("level/lv_"+level+".txt"));
//然后将文件中的信息加载进来
int enemyCount=Integer.parseInt(prop.getProperty("enemyCount"));
int enemyType=Integer.parseInt(prop.getProperty("enemyType"));
String method=prop.getProperty("method");
int invokeCount=Integer.parseInt(prop.getProperty("invokeCount"));
String []paras=new String[invokeCount];
for (int i = 0; i < invokeCount; i++) {
paras[i]=prop.getProperty("parma"+(i+1));
}
invokeMethod(method,paras);
addTile();
}
private void invokeMethod(String name,String []params){
for(String param:params){
String []split=param.split(",");
int []arr = new int[split.length];
for(int i=0;i tiles,int x,int y){
//判断砖块与砖块是否发生重叠
int tileX;
int tileY;
for(MapTile tile:tiles){
tileX=tile.getX();
tileY=tile.getY();
if (Math.abs(tileX - x) < MapTile.tileW && Math.abs(tileY - y) < MapTile.tileW) {
return true;
}
}
return false;
}
public void clearDestoryTile(){
for (int i = 0; i < tiles.size(); i++) {
if(!tiles.get(i).isVisible()){
//不可见就删除并且返回对象池
MapTile tile=tiles.remove(i);
MapPool.theReturn(tile);
}
}
}
//生成一行的块
public void addRow(int startX,int startY,int endX,int type,int DIS){
int count = (endX-startX)/(MapTile.tileW+DIS);
for (int i = 0; i < count; i++) {
MapTile tile =MapPool.get();
tile.setType(type);
tile.setX(startX+i*(MapTile.tileW+DIS));
tile.setY(startY);
tiles.add(tile);
}
}
public void addCol(int startX,int startY,int endY,int type,int DIS) {
int count = (endY - startY) / (MapTile.tileW + DIS);
for (int i = 0; i < count; i++) {
MapTile tile = MapPool.get();
tile.setType(type);
tile.setY(startY + i * (MapTile.tileW + DIS));
tile.setX(startX);
tiles.add(tile);
}
}
public void addRec(int startX,int startY,int endX,int endY,int type,int DIS){
int rows=(endY-startY)/(MapTile.tileW+DIS);
for(int i=0;i>1;
public static final int HOUSE_Y=constant.FRAME_HEIGHT-2*MapTile.tileW;
public ArrayList 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+2*MapTile.tileW,HOUSE_Y));
tiles.add(new MapTile(HOUSE_X+2*MapTile.tileW,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 ArrayList getTiles() {
return tiles;
}
public void setTiles(ArrayList tiles) {
this.tiles = tiles;
}
}
#第一关的关卡信息,注意文件中不能有空格
#敌人数量
enemyCount=50
#敌人坦克类型
enemyType=0
#地图生成的方式通过调用哪一种方法来实现
method=addRow
#该方法调用的次数来绘制
invokeCount=5
#注意方法调用时应该传入的参数
#int startX,int startY,int endX,int type,int DIS
parma1=0,0,0,0,0
parma2=0,2,0,3,2
parma3=0,4,0,3,0
parma4=0,6,0,0,2
parma5=0,8,0,2,0
这里给出的是第一个关卡,后续的可以自己设置难度以及通关等界面,只需要在文件中定义,然后代码解析文件即可



