经典游戏,用java实现的坦克大战小游戏

今天给大家分享一个使用java编写的坦克大战小游戏,整体还是挺好玩的,通过对这款游戏的简单实现,加深对java基础的深刻理解。

一、设计思路

1.坦克大战小游戏通过java实现,其第一步需要先绘制每一关对应的地图,地图包括河流、草地、砖块、铁块等。

2.需要绘制玩家坦克、敌方坦克、以及坦克移动过程中使用到的碰撞算法,子弹与坦克之间的碰撞,

包括击中敌方坦克后的爆炸效果,通过重绘实现坦克的移动,以及各种道具的随机生成算法。

实际运行效果如下:

二、代码实现

1.首先需要将游戏中涉及到的各种对象梳理清楚,由于Java面向对象的特征,可以将一些对象公共特性抽象出来,比如将坦克抽象出一个超类,代码如下:

public abstract class Tank{
	
	int x=0;
	int y=0;
	int tempX=0;
	int tempY=0;
	int size=32;
	int direct=Constant.UP;
	int speed=1;
	int lives=1;
	int frame=0;//控制敌方坦克切换方向的时间
	boolean isAI=false;//是否自动
	boolean hit;
	boolean isShooting=false;
	boolean isDestroyed=false;
	boolean isProtected=false;
	Map map;
	GameMain gameMain;
	Collision collision;
	Bullet bullet;
	int starNum=0; //星星数
	public Tank(int size,int speed,Collision collision,Map map,GameMain gameMain) {
		this.size=size;
		this.collision=collision;
		this.map=map;
		this.gameMain=gameMain;
		this.speed=speed;	
	}
	public void move() {
		//如果是AI坦克,在一定时间或碰撞后切换方法
		if(this.isAI && gameMain.enemyStopTime>0) {
			return;
		}
		this.tempX=this.x;
		this.tempY=this.y;
		if(this.isAI) {
			this.frame++;
			if(this.frame%100==0 || this.hit) {
				this.direct=(int)(Math.random()*4);
				this.hit=false;
				this.frame=0;
			}
		}
		if(this.direct==Constant.UP) {
			this.tempY-=this.speed;
		}else if(this.direct==Constant.DOWN) {
			this.tempY+=this.speed;
		}else if(this.direct==Constant.LEFT) {
			this.tempX-=this.speed;
		}else if(this.direct==Constant.RIGHT) {
			this.tempX+=this.speed;
		}
		isHit();
		if(!this.hit) {
			this.x=this.tempX;
			this.y=this.tempY;
		}
	}
	public void isHit() {
		if(this.direct==Constant.LEFT) {
			if(this.x<=map.offsetX) {
				this.x=map.offsetX;
				this.hit=true;
			}
		}else if(this.direct==Constant.RIGHT) {
			if(this.x>=map.offsetX+map.mapWidth-this.size) {
				this.x=map.offsetX+map.mapWidth-this.size;
				this.hit=true;
			}
		}else if(this.direct==Constant.UP) {
			if(this.y<=map.offsetY) {
				this.y=map.offsetY;
				this.hit=true;
			}
		}else if(this.direct==Constant.DOWN) {
			if(this.y>=map.offsetY+map.mapHeight-this.size) {
				this.y=map.offsetY+map.mapHeight-this.size;
				this.hit=true;
			}
		}
		if(!this.hit) {
			if(collision.tankMapCollision(this, map)) {
				this.hit=true;
			}
		}
	}
	public abstract void drawTank(Graphics2D ctx2);
	
	public void shoot(int type,Graphics2D ctx2) {
		if(this.isAI && gameMain.enemyStopTime>0) {
			return;
		}
		if(this.isShooting) {
			return;
		}
		int tempX=this.x;
		int tempY=this.y;
		this.bullet=new Bullet(tempX, tempY, this.direct, gameMain, type, map, this, collision);
		if(!this.isAI) {
			if(this.starNum==0) {
				this.bullet.speed=3;
				this.bullet.fireNum=1;
			}
			if(this.starNum>0 && this.starNum<=3) {
				this.bullet.speed+=this.starNum;
				this.bullet.fireNum+=(this.starNum-1);
			}
			if(this.starNum>3) {
				this.bullet.speed+=3;
				this.bullet.fireNum+=3;
			}
		}
		if(this.direct==Constant.UP) {
			tempX = this.x + this.size/2 - this.bullet.size/2;
			tempY=this.y-this.bullet.size;
		}else if(this.direct==Constant.DOWN) {
			tempX = this.x + this.size/2 - this.bullet.size/2;
			tempY=this.y+this.bullet.size;
		}else if(this.direct==Constant.LEFT) {
			tempX=this.x-this.bullet.size;
			tempY=this.y + this.size/2 - this.bullet.size/2;
		}else if(this.direct==Constant.RIGHT) {
			tempX=this.x+this.bullet.size;
			tempY=this.y + this.size/2 - this.bullet.size/2;
		}
		this.bullet.x=tempX;
		this.bullet.y=tempY;
		if(!this.isAI) {
			//音乐
			Constant.executor.execute(new Runnable() {
				
				@Override
				public void run() {
					Constant.ATTACK_AUDIO.play();
					
				}
			});
		}
		this.bullet.drawBullet(ctx2);
		gameMain.bulletArr.add(this.bullet);
		this.isShooting=true;
	}
	
	public void distroy() {
		this.isDestroyed=true;
		gameMain.crackArr.add(new CrackAnimation(gameMain, Constant.CRACK_TYPE_TANK, this));
		if(this.isAI) {
			Constant.executor.execute(new Runnable() {
				
				@Override
				public void run() {
					Constant.TANK_DESTROY_AUDIO.play();
					
				}
			});
			gameMain.appearEnemy--;
		}else {
			Constant.executor.execute(new Runnable() {
				
				@Override
				public void run() {
					Constant.PLAYER_DESTROY_AUDIO.play();
					
				}
			});
			this.starNum=0;
		}
		
	}
}

2.坦克子类实现

public class PlayTank extends Tank{
	int protectedTime = 0;//保护时间
	int offsetX=0; //坦克2与坦克1的距离
	int type; //玩家类型
	public PlayTank(int type,Collision collision, Map map, GameMain gameMain) {
		super(32, 2, collision, map, gameMain);
		this.lives = 3;//生命值
		this.isProtected = true;//是否受保护
		this.protectedTime = 500;//保护时间
		this.type=type;
	}

	@Override
	public void drawTank(Graphics2D ctx2) {
		this.hit = false;
		if(this.type==1) {
			ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,
					Constant.POS.get("player").x+this.offsetX+this.direct*this.size, Constant.POS.get("player").y,
					Constant.POS.get("player").x+this.offsetX+this.direct*this.size+this.size, Constant.POS.get("player").y+this.size, null);
		}else {
			ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,
					Constant.POS.get("player").x+128+this.offsetX+this.direct*this.size, Constant.POS.get("player").y,
					Constant.POS.get("player").x+128+this.offsetX+this.direct*this.size+this.size, Constant.POS.get("player").y+this.size, null);
		}
		
		
		if(this.isProtected) {
			int temp=((500-protectedTime)/5)%2;
			ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,
					Constant.POS.get("protected").x, Constant.POS.get("protected").y+32*temp,
					Constant.POS.get("protected").x+this.size, Constant.POS.get("protected").y+this.size, null);
			this.protectedTime--;
			if(this.protectedTime==0) {
				this.isProtected=false;
			}
			
		}
	}
	/**
	 * 玩家坦克复活
	 * @param player
	 */
	public void renascenc(int playerType) {
		this.lives--;
		this.direct=Constant.UP;
		this.isProtected=true;
		this.protectedTime=500;
		this.isDestroyed = false;
		int temp=0;
		if(playerType==1) {
			temp=129;
		}else {
			temp=256;
		}
		this.x = temp + map.offsetX;
		this.y = 385 + map.offsetY;
	}
	
}

3.通过子类继承父类实现玩家坦克和敌方坦克的创建,创建完后,接下来就可让坦克动起来,如下:

public void addEnemyTank(Graphics2D ctx2) {
    	if(enemyArr == null || enemyArr.size() >= maxAppearEnemy || maxEnemy == 0){
    		return;
    	}
    	appearEnemy++;
    	Tank objTank=null;
    	int rand=(int) (Math.random()*4);
    	if(rand==0) {
    		objTank=new TankEnemy0(collision, map, this);
    	}else if(rand==1) {
    		objTank=new TankEnemy1(collision, map, this);
    	}else if(rand==2) {
    		objTank=new TankEnemy2(collision, map, this);
    	}else if(rand==3) {
    		objTank=new TankEnemy3(collision, map, this);
    	}
    	enemyArr.add(objTank);
    	this.maxEnemy--;
    	map.clearEnemyNum(maxEnemy, appearEnemy,ctx2);
    }

4.在移动过程中,涉及到坦克与子弹,坦克与地图之间的碰撞问题,实现如下:

/**
* 坦克与地图间的碰撞
**/
public boolean tankMapCollision(Tank tank,Map map) {
		//移动检测,记录最后一次的移动方向,根据方向判断+-overlap;
		int tileNum=0;
		int rowIndex=0;
		int colIndex=0;
		int overlap=3; //允许重叠的大小
		
		//根据tank的x、y计算map的row和col
		if(tank.direct==Constant.UP) {
			rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;
			colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;
		}else if(tank.direct==Constant.DOWN) {
			rowIndex=(tank.tempY-overlap-map.offsetY+tank.size)/map.tileSize;
			colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;
		}else if(tank.direct==Constant.LEFT) {
			rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;
			colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;
		}else if(tank.direct==Constant.RIGHT){
			rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;
			colIndex=(tank.tempX-overlap-map.offsetX+tank.size)/map.tileSize;
		}
		if(rowIndex>=map.hTileCount || rowIndex<0 || colIndex>=map.wTileCount || colIndex<0) {
			return true;
		}
		if(tank.direct==Constant.UP || tank.direct==Constant.DOWN) {
			int tempWidth=tank.tempX-map.offsetX-colIndex*map.tileSize+tank.size-overlap;
			if(tempWidth%map.tileSize==0) {
				tileNum=tempWidth/map.tileSize;
			}else {
				tileNum=tempWidth/map.tileSize+1;
			}
			for(int i=0;i<tileNum && colIndex+i<map.wTileCount;i++) {
				int mapContent=map.mapLevel[rowIndex][colIndex+i];
				if(mapContent==Constant.WALL || mapContent==Constant.GRID || mapContent==Constant.WATER || mapContent==Constant.HOME || mapContent==Constant.ANOTHER_HOME) {
					if(tank.direct==Constant.UP) {
						tank.y=map.offsetY+rowIndex*map.tileSize+map.tileSize-overlap;
					}else {
						tank.y=map.offsetY+rowIndex*map.tileSize-tank.size+overlap;
					}
					return true;
				}
			}
		}else {
			int tempHeight=tank.tempY-map.offsetY-rowIndex*map.tileSize+tank.size-overlap;
			if(tempHeight%map.tileSize==0) {
				tileNum=tempHeight/map.tileSize;
			}else {
				tileNum=tempHeight/map.tileSize+1;
			}
			for(int i=0;i<tileNum && rowIndex+i<map.hTileCount;i++) {
				int mapContent=map.mapLevel[rowIndex+i][colIndex];
				if(mapContent==Constant.WALL || mapContent==Constant.GRID || mapContent==Constant.WATER || mapContent==Constant.HOME || mapContent==Constant.ANOTHER_HOME) {
					if(tank.direct==Constant.LEFT) {
						tank.x=map.offsetX+colIndex*map.tileSize+map.tileSize-overlap;
					}else {
						tank.x=map.offsetX+colIndex*map.tileSize-tank.size+overlap;
					}
					return true;
				}
			}
		}
		return false;
	}

5.绘制界面,通过定时重绘实现,具体代码如下:

public class GameMain extends JPanel{
	
	//int enemyNum=12;
	Map map;
	Num num;
	int level=1;
	Level tankLevel;
	int gameState=Constant.GAME_STATE_MENU;
	private boolean isGameOver=false;
	int maxEnemy = 12;//敌方坦克总数
	int maxAppearEnemy = 5;//屏幕上一起出现的最大数
	int appearEnemy = 0; //已出现的敌方坦克
	int enemyStopTime=0;
	List<Bullet> bulletArr;
	List<Tank> enemyArr;
	List<CrackAnimation> crackArr;
	List<Integer> keys;
	Tank player1 = null;//玩家1
	Tank player2 = null;//玩家2
	Collision collision;
	int mainframe = 0;
	Image offScreenImage;
	Menu menu;
	Stage stage;
	Prop prop;
	Graphics2D ctx2;
	int overX = 176;
	int overY = 384;
	int propTime = 300; //道具出现频次
	int homeProtectedTime = -1;
	int winWaitTime=80;
	public void initGame(GameMain gameMain) {
		this.num=new Num(gameMain);
		this.tankLevel=new Level();
		this.collision=new Collision(gameMain);
	}
	
	public void initObject() {
		this.map=new Map(this, num, tankLevel, level);
		player1=new PlayTank(1,collision, map, this);
		player1.x = 129 + map.offsetX;
		player1.y = 385 + map.offsetY;
		player2 = new PlayTank(2,collision, map, this);
		player2.x = 256 + map.offsetX;
		player2.y = 385 + map.offsetY;
		bulletArr=new ArrayList<>();
		enemyArr=new ArrayList<>();
		crackArr=new ArrayList<>();
		keys=new ArrayList<>();
		menu=new Menu();
		stage=new Stage(level, this,this.num);
		this.isGameOver=false;
		this.propTime=400;
		this.homeProtectedTime = -1;
		this.maxEnemy=12;
		this.winWaitTime=50;
		this.appearEnemy=0;
		this.overY=384;
	}
	public void goGameOver() {
		this.isGameOver=true;
	}
   
	@Override
	public void paint(Graphics g) {
		//创建和容器一样大小的Image图片
		if(offScreenImage==null) {
			offScreenImage=this.createImage(Constant.SCREEN_WIDTH,Constant.SCREEN_HEIGHT);
		}
		//获得该图片的画布
		Graphics gImage=offScreenImage.getGraphics();
		//填充整个画布
		gImage.fillRect(0,0,Constant.SCREEN_WIDTH,Constant.SCREEN_HEIGHT);
		if(ctx2==null) {
			ctx2=(Graphics2D)gImage;
		}
		if(gameState==Constant.GAME_STATE_MENU) {
			menu.drawMenu(ctx2);
		}
		if(gameState==Constant.GAME_STATE_INIT) {
			stage.setNum(ctx2);
			stage.drawStage(ctx2);
		}
		if(gameState==Constant.GAME_STATE_START || gameState==Constant.GAME_STATE_OVER) {
			drawAll(ctx2);
		}
		if(gameState==Constant.GAME_STATE_OVER) {
			gameOver();
		}
		if(gameState==Constant.GAME_STATE_WIN) {
			this.winWaitTime--;
			drawAll(ctx2);
			if(this.winWaitTime==0) {
				nextLevel();
			}
		}
		//将缓冲区绘制好的图形整个绘制到容器的画布中
		g.drawImage(offScreenImage,0,0,null);
		
	}
	public void initMap(Graphics2D ctx2) {
		map.setNum(ctx2);
    	map.drawMap(ctx2);
	}
    public void drawAll(Graphics2D ctx2) {
    	map.setNum(ctx2);
    	map.drawMap(ctx2);
    	if(player1.lives>0) {
    		player1.drawTank(ctx2);
    	}
    	if(player2.lives>0) {
    		player2.drawTank(ctx2);
    	}
    	if(appearEnemy<maxEnemy){
    		if(mainframe % 100 == 0){
    			addEnemyTank(ctx2);
    			mainframe = 0;
    		}
    		mainframe++;
    	}
    	drawLives(ctx2);
		drawEnemyTanks(ctx2);
		map.drawGrassMap(ctx2);
    	drawBullet(ctx2);
    	drawCrack(ctx2);
    	keyEvent();
    	if(propTime<=0){
    		drawProp(ctx2);
    	}else{
    		propTime --;
    	}
    	if(homeProtectedTime > 0){
    		homeProtectedTime --;
    	}else if(homeProtectedTime == 0){
    		homeProtectedTime = -1;
    		homeNoProtected(ctx2);
    	}
    }
    public void addEnemyTank(Graphics2D ctx2) {
    	if(enemyArr == null || enemyArr.size() >= maxAppearEnemy || maxEnemy == 0){
    		return;
    	}
    	appearEnemy++;
    	Tank objTank=null;
    	int rand=(int) (Math.random()*4);
    	if(rand==0) {
    		objTank=new TankEnemy0(collision, map, this);
    	}else if(rand==1) {
    		objTank=new TankEnemy1(collision, map, this);
    	}else if(rand==2) {
    		objTank=new TankEnemy2(collision, map, this);
    	}else if(rand==3) {
    		objTank=new TankEnemy3(collision, map, this);
    	}
    	enemyArr.add(objTank);
    	this.maxEnemy--;
    	map.clearEnemyNum(maxEnemy, appearEnemy,ctx2);
    }
    public void drawEnemyTanks(Graphics2D ctx2) {
    	if(enemyArr!=null && enemyArr.size()>0) {
    		Iterator<Tank> it=enemyArr.iterator();
    		while(it.hasNext()) {
    			Tank enemyTank=it.next();
    			if(enemyTank.isDestroyed) {
    				it.remove();
    			}else {
    				enemyTank.drawTank(ctx2);
    				
    			}
    		}
    	}
    	if(enemyStopTime > 0){
    		enemyStopTime --;
    	}
    }
    /**
     * 绘制玩家生命数
     */
    public void drawLives(Graphics2D ctx2) {
    	map.drawLives(player1.lives, 1,ctx2);
    	map.drawLives(player2.lives, 2,ctx2);
    }
    /**
     * 绘制子弹
     * @param ctx2
     */
    public void drawBullet(Graphics2D ctx2) {
    	if(bulletArr != null && bulletArr.size() > 0){
    		Iterator<Bullet> it=bulletArr.iterator();
    		while(it.hasNext()) {
    			Bullet bullet=it.next();
    			if(bullet.isDestroyed) {
    				it.remove();
    				bullet.owner.isShooting=false;
    			}else {
    				//绘制子弹
    				bullet.drawBullet(ctx2);
    			}
    		}
    	}
    }
    public void drawCrack(Graphics2D ctx2) {
    	if(crackArr != null && crackArr.size() > 0){
    		Iterator<CrackAnimation> it=crackArr.iterator();
    		while(it.hasNext()) {
    			CrackAnimation crackAnimation=it.next();
    			if(crackAnimation.isOver) {
    				it.remove();
    				if(crackAnimation.crackObj instanceof Tank) {
    					Tank tank=(Tank)crackAnimation.crackObj;
    					if(tank==player1) {
    						PlayTank playerTank1=(PlayTank)player1;
    						playerTank1.renascenc(1);
    					}else if(tank==player2) {
    						PlayTank playerTank2=(PlayTank)player2;
    						playerTank2.renascenc(2);
    					}
    				}
    			}else {
    				//绘制爆炸效果
    				crackAnimation.draw(ctx2);
    			}
    		}
    	}
    }
    public void drawProp(Graphics2D ctx2) {
    	double rand=Math.random();
    	if(rand<=0.4 && prop==null) {
    		prop=new Prop(this, map, collision);
    		prop.initProp();
    	}
    	if(prop!=null) {
    		prop.drawProp(ctx2);
    		if(prop.isDestroyed) {
    			prop=null;
    			propTime=600;
    		}
    	}
    }
    public void nextLevel() {
    	level++;
    	if(level==17) {
    		level=1;
    	}
    	int oldPlayerNum=menu.playNum;
    	initObject();
    	menu.playNum = oldPlayerNum;
    	//只有一个玩家
    	if(menu.playNum == 1){
    		player2.lives = 0;
    	}
    	map.first=0;
    	stage.init(level);
    	gameState = Constant.GAME_STATE_INIT;
    }
    public void preLevel() {
    	level--;
    	if(level == 0){
    		level = 16;
    	}
    	//保存玩家数
    	int oldPlayerNum = menu.playNum;
    	initObject();
    	menu.playNum = oldPlayerNum;

    	//只有一个玩家
    	if(menu.playNum == 1){
    		player2.lives = 0;
    	}
    	stage.init(level);
    	gameState = Constant.GAME_STATE_INIT;
    }
    public void gameLoop() {
    	switch (gameState) {
    	case Constant.GAME_STATE_MENU:
    		repaint();
    		break;
    	case Constant.GAME_STATE_INIT:
    		//stage.draw();
    		if(stage.isReady == true){
    			gameState = Constant.GAME_STATE_START;
    		}
    		repaint();
    		break;
    	case Constant.GAME_STATE_START:
    		//drawAll();
    		if(isGameOver ||(player1.lives <=0 && player2.lives <= 0)){
    			gameState = Constant.GAME_STATE_OVER;
    			map.homeHit(ctx2);
    			Constant.executor.execute(new Runnable() {
					
					@Override
					public void run() {
						Constant.PLAYER_DESTROY_AUDIO.play();
						
					}
				});
    		}
    		if(appearEnemy == maxEnemy && enemyArr.size() == 0){
    			gameState  = Constant.GAME_STATE_WIN;
    		}
    		repaint();
    		break;
    	case Constant.GAME_STATE_WIN:
    		repaint();
    		break;
    	case Constant.GAME_STATE_OVER:
    		repaint();
    		
    		break;
    	}
    }
    public void gameOver() {
    	//.clearRect(0, 0, Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);
    	ctx2.drawImage(Constant.RESOURCE_IMAGE, overX+map.offsetX, overY+map.offsetY,overX+map.offsetX+64,overY+map.offsetY+32,
				Constant.POS.get("over").x, Constant.POS.get("over").y,
				Constant.POS.get("over").x+64, Constant.POS.get("over").y+32, null);
    	overY-=2;
    	if(overY<=map.mapHeight/2) {
    		initObject();
    		//if(menu.playNum==1) {
    		//	player2.lives=0;
    		//}
    		gameState = Constant.GAME_STATE_MENU;
    		
    	}
    }
    public void action() {
    	KeyAdapter l=new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				switch (gameState) {
				case Constant.GAME_STATE_MENU:
					if(e.getKeyCode()==KeyEvent.VK_ENTER){
						gameState = Constant.GAME_STATE_INIT;
						//只有一个玩家
						if(menu.playNum==1) {
							player2.lives=0;
						}
					}else {
						int n=0;
						if(e.getKeyCode()==KeyEvent.VK_DOWN) {
							n=1;
						}else if(e.getKeyCode()==KeyEvent.VK_UP) {
							n=-1;
						}
						menu.next(n);
					}
					break;
				case Constant.GAME_STATE_START:
					
					if(!keys.contains(e.getKeyCode())){
						keys.add(e.getKeyCode());
					}
					//射击
					if(e.getKeyCode()==KeyEvent.VK_SPACE && player1.lives > 0){
						player1.shoot(Constant.BULLET_TYPE_PLAYER, ctx2);
					}else if(e.getKeyCode()==KeyEvent.VK_ENTER && player2.lives > 0) {
						player2.shoot(Constant.BULLET_TYPE_PLAYER, ctx2);
					}else if(e.getKeyCode()==KeyEvent.VK_N) { //下一关
						nextLevel();
					}else if(e.getKeyCode() == KeyEvent.VK_P) {
						preLevel();
					}
					break;
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
				// TODO Auto-generated method stub
				//super.keyReleased(e);
				if(keys != null && keys.size() > 0){
		    		Iterator<Integer> it=keys.iterator();
		    		while(it.hasNext()) {
		    			Integer key=it.next();
		    			if(key.intValue()==e.getKeyCode()) {
		    				it.remove();
		    				break;
		    			}
		    			
		    		}
				}
			}

			@Override
			public void keyTyped(KeyEvent e) {
				//super.keyTyped(e);
			}
		};
		this.addKeyListener(l);
		this.setFocusable(true);
		
    	Timer timer=new Timer();
    	int interval=20;
    	timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				gameLoop();	
			}
		}, interval, interval);
    }
    public void keyEvent() {
    	if(keys.contains(KeyEvent.VK_W)){
    		player1.direct = Constant.UP;
    		player1.hit = false;
    		player1.move();
    	}else if(keys.contains(KeyEvent.VK_S)){
    		player1.direct = Constant.DOWN;
    		player1.hit = false;
    		player1.move();
    	}else if(keys.contains(KeyEvent.VK_A)){
    		player1.direct = Constant.LEFT;
    		player1.hit = false;
    		player1.move();
    	}else if(keys.contains(KeyEvent.VK_D)){
    		player1.direct = Constant.RIGHT;
    		player1.hit = false;
    		player1.move();
    	}
    	
    	if(keys.contains(KeyEvent.VK_UP)){
    		player2.direct = Constant.UP;
    		player2.hit = false;
    		player2.move();
    	}else if(keys.contains(KeyEvent.VK_DOWN)){
    		player2.direct = Constant.DOWN;
    		player2.hit = false;
    		player2.move();
    	}else if(keys.contains(KeyEvent.VK_LEFT)){
    		player2.direct = Constant.LEFT;
    		player2.hit = false;
    		player2.move();
    	}else if(keys.contains(KeyEvent.VK_RIGHT)){
    		player2.direct = Constant.RIGHT;
    		player2.hit = false;
    		player2.move();
    	}
    }
    public void homeNoProtected(Graphics2D ctx2) {
    	List<Integer[]> mapChangeIndexList=new ArrayList<Integer[]>();
		mapChangeIndexList.add(new Integer[] {23,11});
		mapChangeIndexList.add(new Integer[] {23,12});
		mapChangeIndexList.add(new Integer[] {23,13});
		mapChangeIndexList.add(new Integer[] {23,14});
		mapChangeIndexList.add(new Integer[] {24,11});
		mapChangeIndexList.add(new Integer[] {24,14});
		mapChangeIndexList.add(new Integer[] {25,11});
		mapChangeIndexList.add(new Integer[] {25,14});
		map.updateMap(mapChangeIndexList,Constant.WALL,ctx2);
    }
	public static void main(String[] args) {
		
		JFrame jf=new JFrame();
		jf.setTitle("坦克大战");
		jf.setSize(Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);
		GameMain gameMain=new GameMain();
		jf.add(gameMain);
		jf.setLocationRelativeTo(null);
		jf.setResizable(false);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
		
		jf.setVisible(true);
		
		gameMain.initGame(gameMain);
		gameMain.initObject();
		gameMain.action();
		
	}
}

接下来就可运行了。

其中,切换到下一关,按键盘N,上一个按P,空格键射击。

有兴趣的可以试一试。

下载地址:
坦克大战小游戏完整源码

相关推荐
天天扭码15 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶16 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺20 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序28 分钟前
vue3 封装request请求
java·前端·typescript·vue
陈王卜1 小时前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、1 小时前
Spring Boot 注解
java·spring boot
java亮小白19971 小时前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF1 小时前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql