TankWar單機版雛形

TankClient.java

package tungkee.javase.project.tankwar;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

/**
 * 這個類是坦克遊戲的主窗口,2011-07-10
 * @author tungkee
 * 
 */

public class TankClient extends Frame {
	/**
	 * 定義我方坦克的變量
	 */
	private Tank myTank = null;
	/**
	 * 定義虛擬的屏幕圖片,用雙緩衝解決屏幕閃爍問題
	 */
	private Image offScreenImage = null;
	/**
	 * 定義三個集合List,裝敵方坦克,子彈,爆炸等
	 */
	private List<Tank> tanks = new ArrayList<Tank>();
	private List<Missile> missiles = new ArrayList<Missile>();
	private List<Explode> explodes = new ArrayList<Explode>();
	/**
	 * 定義四堵牆,分別置於遊戲主窗口的左、右、上、下四個位置
	 */
	private Wall leftWall = new Wall(200, 200, 50, 400, this);
	private Wall rightWall = new Wall(800, 200, 50, 400, this);
	
	private Wall upWall = new Wall(300, 200, 400, 50, this);
	private Wall downWall = new Wall(300, 600, 400, 50, this);
	/**
	 * 定義血塊,血塊按照自身的不規則軌跡進行運動
	 */
	private Blood b = new Blood(this);
	/**
	 * 定義控制遊戲主窗口刷新的線程停止或運行的變量
	 */
	private boolean threadFlag = true;
	/**
	 * 定義主窗口刷新的線程變量
	 */
	private Thread thread = null;
	
	/**
	 * 整個遊戲的高度的靜態常量
	 */
	public static final int GAME_WIDTH = 1024;
	/**
	 * 整個遊戲的寬度的靜態常量
	 */
	public static final int GAME_HEIGHT = 768;
	/**
	 * 遊戲的背景顏色和遊戲的標題欄的文字
	 */
	public static final Color GAME_BACKGROUND = new Color(0, 100, 0);
	public static final String GAME_TITLE = "TankWar坦克大戰單機版";
	/**
	 * 定義坦克在遊戲界面中的最大x 和最大y 值
	 */
	public static final int Tank_MaxX = GAME_WIDTH - Tank.WIDTH;
	public static final int Tank_MaxY = GAME_HEIGHT - Tank.HEIGHT;
	
	/**
	 * 添加子彈對象到List中的方法,沒有返回值。
	 * @param missile 需要添加的子彈對象引用
	 */
	public void addMissile(Missile missile) {
		missiles.add(missile);
	}
	/**
	 * 從List中移除子彈對象的方法,沒有返回值
	 * @param missile 需要移除的子彈對象引用
	 */
	public void removeMissile(Missile missile) {
		missiles.remove(missile);
	}
	/**
	 * 添加爆炸對象到List中的方法,沒有返回值
	 * @param explode 需要添加爆炸的對象引用
	 */
	public void addExplode(Explode explode) {
		explodes.add(explode);
	}
	/**
	 * 從List中移除爆炸對象的方法,沒有返回值
	 * @param explode 需要移除爆炸的對象引用
	 */
	public void removeExplode(Explode explode) {
		explodes.remove(explode);
	}
		
	/**
	 * main方法,創建一個TankClient對象,調用其launchFrame方法
	 * @param args 命令行參數
	 */
	public static void main(String[] args) {
		TankClient tc = new TankClient();
		tc.launchFrame();
		
	}
	/**
	 * 從List中移除一個坦克的方法,沒有返回值
	 * @param tank 需要移除的坦克的對象的引用
	 */
	public void removeTank(Tank tank) {
		tanks.remove(tank);
	}
	/**
	 * 創建敵方坦克的方法,沒有返回值
	 * @param tankCount 創建敵方坦克的數量
	 */
	private void createTanks(int tankCount) {

		Tank tank = null;
		for(int i=0; i<tankCount; i++) {
			do {
				tank = createTank(false, Tank.Direction.D);
			} while(tank == null);
			tanks.add(tank);
		}
		
	}	
	/**
	 * 創建一輛坦克的方法
	 * @param good 設置爲我方坦克還是敵方坦克,true爲我方,false爲敵方
	 * @param dir 設置坦克初始的方向
	 * @return 返回一輛坦克對象的引用
	 */
	public Tank createTank(boolean good, Tank.Direction dir) {
		int x = 0;
		int y = 0;
		Tank tank = null;
		
		x = (int)(Math.random() * Tank_MaxX);
		y = (int)(Math.random() * Tank_MaxY);
		
		tank = new Tank(x, y, good, dir, this);
		//當前創建的坦克與四堵牆進行碰撞檢測,並且與坦克集合中的每一輛坦克進行
		//碰撞檢測,沒有重疊則返回坦克的對象的引用,否則返回null。
		if(!tank.collidesWithWall(leftWall) 
				&& !tank.collidesWithWall(rightWall) 
				&& !tank.collidesWithWall(upWall) 
				&& !tank.collidesWithWall(downWall)
				&& !tank.collidesWithTanks(tanks)) {
			return tank;
		}
		return null;
	}
	
	/**
	 * TankClient的launchFrame方法,用於啓動遊戲主窗體 
	 */
	
	public void launchFrame() {
		
		this.setTitle(GAME_TITLE);
		this.setBackground(GAME_BACKGROUND);
		this.setSize(GAME_WIDTH, GAME_HEIGHT);
		this.setLocation(50, 50);
		this.setResizable(false);
				
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				if(myTank != null) {
					myTank = null;
				}
				
				tanks = null;
				missiles = null;
				explodes = null;
				
				threadFlag = false;
				try {
					thread.join();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				
				System.exit(0);
			}
		});
		
		this.addKeyListener(new KeyMonitor());
		
		this.setVisible(true);
		
		//創建出我方坦克以後添加到List中,這樣方便增加敵方坦克時
		//可以和我方坦克進行碰撞檢測,以免坦克疊加在一起
		myTank = createTank(true, Tank.Direction.STOP);
		tanks.add(myTank);
		//創建敵方坦克
		createTanks(10);
		//碰撞檢測完成以後從List中移除我方坦克
		tanks.remove(myTank);
		//設置主線程睡眠1秒以後再啓動刷新遊戲界面的線程
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		//創建並啓動刷新遊戲界面的線程
		thread = new Thread(new PaintThread());
		thread.start();
	}
	
	/**
	 * 複寫了父類的paint方法,以便畫出遊戲元素
	 */
		
	@Override
	public void paint(Graphics g) {
		/*
		 * 指明子彈的數量、爆炸的數量、敵方坦克的數量、我方坦克的生命值
		 */
		
		Color c = g.getColor();
		g.setColor(Color.BLACK);
		g.drawString("ArrayList<Tank>:" + tanks.size(), 10, 40);
		g.drawString("ArrayList<Missile>:" + missiles.size(), 10, 60);
		g.drawString("ArrayList<Explode>:" + explodes.size(), 10, 80);
		g.drawString("myTank.getLife():" + myTank.getLife(), 10, 100);
		g.setColor(c);
		
		if(leftWall  != null) leftWall.draw(g);
		if(rightWall  != null) rightWall.draw(g);
		
		if(upWall  != null) upWall.draw(g);
		if(downWall  != null) downWall.draw(g);
		
		if(myTank != null) {
			if(myTank.isLive()) {
				myTank.draw(g);
				//我方坦克與四堵牆進行碰撞檢測,以避免坦克穿越牆
				myTank.collidesWithWall(leftWall);
				myTank.collidesWithWall(rightWall);
				myTank.collidesWithWall(upWall);
				myTank.collidesWithWall(downWall);
				//我方坦克與坦克集合中的每輛坦克進行碰撞檢測,以避免穿越其他坦克
				myTank.collidesWithTanks(tanks);
				//我方坦克吃血塊
				if(b != null) {
					if(myTank.eat(b)) {
						b = null;
					}
				}
			} else {
				myTank = null;
			}
		}
		
		
		
		Tank tank = null;
		for(int i=0; i<tanks.size(); i++) {
			tank = tanks.get(i);
			tank.draw(g);
			tank.collidesWithWall(leftWall);
			tank.collidesWithWall(rightWall);
			tank.collidesWithWall(upWall);
			tank.collidesWithWall(downWall);
			
			tank.collidesWithTanks(tanks);
			tank.collidesWithTank(myTank);
		}
		
		Missile missile = null;
		for(int i=0; i<missiles.size(); i++) {
			missile = missiles.get(i);
			missile.draw(g);
			missile.hitTanks(tanks);
			missile.hitTank(myTank);
			missile.hitWall(leftWall);
			missile.hitWall(rightWall);
			missile.hitWall(upWall);
			missile.hitWall(downWall);

		}	
		
		for(int i=0; i<explodes.size(); i++) {
			explodes.get(i).draw(g);
		}
		
		if(b != null) b.draw(g);
	}
	
	/**
	 * 複寫了父類的update方法,以便解決遊戲閃爍問題
	 */
	@Override
	public void update(Graphics g) {
		//使用雙緩衝解決遊戲界面閃爍的問題
		//解決方式是先將所有的元素畫在虛擬的屏幕圖片上,然後再一次性的貼在屏幕上
		if(offScreenImage == null) {
			offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
		}
		Graphics gOffScreen = offScreenImage.getGraphics();
		
		Color c = gOffScreen.getColor();
		gOffScreen.setColor(GAME_BACKGROUND);
		gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
		gOffScreen.setColor(c);
		
		paint(gOffScreen);
		g.drawImage(offScreenImage, 0, 0, null);
		
	}
	
	/**
	 * 定義了內部類PaintThread,用於每隔50毫秒對遊戲畫面進行刷新重畫
	 * @author tungkee
	 *
	 */
	private class PaintThread implements Runnable {
		@Override
		public void run() {
			try {
				while(threadFlag) {
					repaint();
					Thread.sleep(50);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
	}
	/**
	 * 定義鍵盤響應的監聽器類
	 * @author tungkee
	 *
	 */
	private class KeyMonitor extends KeyAdapter {
		@Override
		public void keyReleased(KeyEvent e) {
			switch(e.getKeyCode()) {
				case KeyEvent.VK_F2:
					if(tanks.size() == 0) createTanks(10);
					break;
				case KeyEvent.VK_F3:
					if(myTank == null) {
						myTank = createTank(true, Tank.Direction.STOP); 
					}
					break;
				default:
					myTank.keyReleased(e);
					break;
			}
			
		}

		@Override
		public void keyPressed(KeyEvent e) {
			myTank.keyPressed(e);
		}
	}
	
}

Tank.java

package tungkee.javase.project.tankwar;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

public class Tank {
	/**
	 * 定義坦克的x方向移動速度、y方向移動速度、坦克的寬度以及坦克的高度
	 */
	public static final int XSPEED = 5;
	public static final int YSPEED = 5;
	public static final int WIDTH = 30;
	public static final int HEIGHT = 30;
	//定義坦克主窗體的對象的引用以及x、y的座標
	private TankClient tc = null;
	private int x = 0;
	private int y = 0;
	//記錄坦克上一個位置的x、y座標
	private int oldX = 0, oldY = 0;
	//定義槍口的點以及發子彈的點
	private Point barrel = null;
	private Point gun = null;
	//記錄用戶按鍵,用來確定用戶需要坦克改變爲哪個方向
	private boolean bL = false, bU = false, bR = false, bD = false;
	//定義坦克是否處於活着的狀態
	private boolean live = true;
	//定義坦克的方向的枚舉類型
	enum Direction {L, LU, U, RU, R, RD, D, LD, STOP};
	//定義坦克的方向
	private Direction dir = Direction.STOP;
	//定義炮筒的方向
	private Direction barrelDir = Direction.D;
	//定義坦克是我方坦克還是敵方坦克
	private boolean good = false;
	//定義隨機數,引用了隨機數的類
	private static Random r = new Random();
	//定義坦克隨機行走的步數,在10-20之間產生
	private int step = r.nextInt(20) + 10;
	//定義坦克的生命值
	private int life = 100;
	//定義坦克的血條
	private BloodBar bb = null;
	
	public boolean isGood() {
		return good;
	}

	public Tank(int x, int y, boolean good) {
		this.x = x;
		this.y = y;
		this.oldX = x;
		this.oldY = y;
		this.good = good;
	}
	
	public Tank(int x, int y, boolean good, Direction dir, TankClient tc) {
		this(x, y, good);
		this.dir = dir;
		this.tc = tc;
	}
	
	public void draw(Graphics g) {
		//如果坦克已經處於未活着的狀態,則不對該坦克進行重畫
		if(live == false) {
			if(! good) {
				//如果該坦克對象good爲false,則從List中移除它
				tc.removeTank(this);
			}	
			return;
		}
		
		Color color = g.getColor();
		if(good) {
			//畫血條
			bb = new BloodBar();
			bb.draw(g);
			//設置我方坦克顏色爲白色
			g.setColor(Color.WHITE);
		} else {
			//設置敵方坦克顏色爲紅色
			g.setColor(Color.RED);
		}
		//畫坦克的機身,用一個圓來模擬		
		g.fillOval(x, y, WIDTH, HEIGHT);
		g.setColor(Color.BLACK);
		g.setColor(color);
		//計算確定坦克的槍口的點的位置以及發子彈的點的位置
		sureBarrelGun();
		//從坦克的機身的圓的中心點到槍口點的位置,畫一條直線模擬坦克的槍管
		g.drawLine(x + WIDTH / 2, y + HEIGHT / 2, barrel.x, barrel.y);
		//坦克的移動方法
		move();
	}
	/**
	 * 確定槍口的點以及發子彈的點的位置
	 * 因爲需要讓子彈從槍口的正中發出
	 */
	private void sureBarrelGun() {

		if(dir != Direction.STOP) {
			barrelDir = dir;
		}
		
		switch(barrelDir) {
		case L:
			barrel = new Point(x, y + HEIGHT / 2);		
			gun = new Point(barrel.x - Missile.WIDTH, barrel.y - Missile.HEIGHT / 2);
			break;
		case LU:
			barrel = new Point(x, y);
			gun = new Point(barrel.x - Missile.WIDTH, barrel.y - Missile.HEIGHT);
			break;
		case U:
			barrel = new Point(x + WIDTH / 2, y);
			gun = new Point(barrel.x - Missile.WIDTH / 2, barrel.y);
			break;
		case RU:
			barrel = new Point(x + WIDTH, y);
			gun = new Point(barrel.x, barrel.y - Missile.HEIGHT);
			break;
		case R:
			barrel = new Point(x + WIDTH, y + HEIGHT / 2);
			gun = new Point(barrel.x, barrel.y - Missile.HEIGHT / 2);
			break;
		case RD:
			barrel = new Point(x + WIDTH, y + HEIGHT);
			gun = new Point(barrel.x, barrel.y);
			break;
		case D:
			barrel = new Point(x + WIDTH / 2, y + HEIGHT);
			gun = new Point(barrel.x - Missile.WIDTH / 2, barrel.y);
			break;
		case LD:
			barrel = new Point(x, y + HEIGHT);
			gun = new Point(barrel.x - Missile.WIDTH, barrel.y);
			break;
		}
	}
	/**
	 * 坦克移動的方法
	 */
	private void move() {
		//記錄移動之前坦克的點的x、y的值
		//以便坦克移動到牆邊以後能夠回到上一次的位置
		//因爲坦克與牆的碰撞檢測中設定,當坦克與牆碰撞、
		//成功以後,坦克就停止移動,如果不記錄坦克的上一次位置
		//坦克就無法回到上一次位置,就一直處於與牆碰撞成功
		//的死循環中
		//同時也用與坦克與坦克之間的碰撞後停止並返回到上一次移動的位置
		this.oldX = x;
		this.oldY = y;
		
		switch(dir) {
		case L:
			x -= XSPEED;
			break;
		case LU:
			x -= XSPEED;
			y -= YSPEED;
			break;
		case U:
			y -= YSPEED;
			break;
		case RU:
			x += XSPEED;
			y -= YSPEED;
			break;
		case R:
			x += XSPEED;
			break;
		case RD:
			x += XSPEED;
			y += YSPEED;
			break;
		case D:
			y += YSPEED;
			break;
		case LD:
			x -= XSPEED;
			y += YSPEED;
			break;
		case STOP:
			break;
			
		}
		/*
		 * 判斷坦克當前的x值是否大於遊戲主窗體中設定的坦克的最大x值
		 * 大於則將坦克的x值設置爲最大的x值
		 */
		if(x > TankClient.Tank_MaxX) {
			x = TankClient.Tank_MaxX;
		}
		/*
		 * 判斷坦克的x值是否小於0,如果小於0則將其值設置爲0
		 */
		if(x < 0) {
			x = 0;
		}
		/*
		 * 判斷坦克當前的y值是否大於遊戲主窗體中設定的坦克的最大y值
		 * 如果大於則將坦克的y值設置爲最大的y值
		 */
		if(y > TankClient.Tank_MaxY) {
			y = TankClient.Tank_MaxY;
		}
		/*
		 * 判斷坦克的y值是否小於0,如果小於0則將其值設置爲0
		 */
		if(y < 20) {
			y = 20;
		}
		/*
		 * 如果當前坦克的good爲false
		 * 判斷當前的移動步數是否等於0,如果等於0重新獲得隨機獲得坦克移動的方向
		 * 同時隨機獲得坦克移動的步數
		 * 最後坦克移動的步數自減1
		 * 然後隨機產生一個0-50之間的數,如果這個數大於47則坦克開火		
		 */
		if(!good) {
			Direction[] dirs = Direction.values();
			if(step == 0) {
				step = r.nextInt(20) + 10;
				int rn = r.nextInt(dirs.length);
				dir = dirs[rn];
			}
			step --;
			
			if(r.nextInt(50) > 47) this.fire();
		}
		
	}
	/**
	 * 讓坦克移動到上一次的位置的方法
	 */
	public void stay() {
		this.x = oldX;
		this.y = oldY;
	}
	/**
	 * 處理按鍵事件以便確定坦克當前應該改變的方向,keyPressed
	 * @param e
	 */
	public void keyPressed(KeyEvent e) {
		switch(e.getKeyCode()) {
		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;
		}
		
		locateDirection();
	}
	/**
	 * 坦克開火的方法
	 */
	public void fire() {
		Missile m = new Missile(gun.x, gun.y, barrelDir, good, tc);
		tc.addMissile(m);
	}
	/**
	 * 指定一個方向,讓坦克朝指定的方向開火的方法
	 * @param dir 指定坦克開火的方向
	 */
	public void fire(Direction dir) {
		Missile m = new Missile(gun.x, gun.y, dir, good, tc);
		tc.addMissile(m);
	}
	/**
	 * 坦克朝八個方向開火的方法
	 */
	
	public void superFire(){
		Direction[] dirs = Direction.values();
		for(int i=0; i<dirs.length; i++) {
			if(dirs[i] != Direction.STOP) fire(dirs[i]);
		}
	}
	/**
	 * 定位坦克的方法的方法
	 */
	private void locateDirection() {
		if(bL && !bU && !bR && !bD) dir = Direction.L;
		else if(bL && bU && !bR && !bD) dir = Direction.LU;
		else if(!bL && bU && !bR && !bD) dir = Direction.U;
		else if(!bL && bU && bR && !bD) dir = Direction.RU;
		else if(!bL && !bU && bR && !bD) dir = Direction.R;
		else if(!bL && !bU && bR && bD) dir = Direction.RD;
		else if(!bL && !bU && !bR && bD) dir = Direction.D;
		else if(bL && !bU && !bR && bD) dir = Direction.LD;
		else if(!bL && !bU && !bR && !bD) dir = Direction.STOP;
		
	}
	/**
	 * 處理keyReleased事件
	 * @param e
	 */
	public void keyReleased(KeyEvent e) {
		switch(e.getKeyCode()) {
		case KeyEvent.VK_CONTROL:
			fire();
			break;
		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;
		case KeyEvent.VK_A:
			superFire();
			break;
		}
		
		locateDirection();
	}
	/**
	 * 獲得坦克自身的矩形的方法,以便進行碰撞檢測
	 * @return
	 */
	public Rectangle getRect() {
		return new Rectangle(x, y, WIDTH, HEIGHT);
	}
	
	public void setLive(boolean live) {
		this.live = live;
	}

	public boolean isLive() {
		return live;
	}
	
	/**
	 * 
	 * @param wall 被撞的牆
	 * @return 被撞後返回true,未被撞返回false
	 */
	public boolean collidesWithWall(Wall wall) {
		if(this.live && this.getRect().intersects(wall.getRect())) {
			this.stay();
			return true;
		}
		return false;
	}
	/**
	 * 與其他一輛坦克進行碰撞檢測
	 * @param tank 需要進行碰撞檢測的坦克對象引用
	 * @return 碰撞成功返回true,否則返回false
	 */
	public boolean collidesWithTank(Tank tank) {
		if(this != tank) {
			if(this.live && tank.isLive() && this.getRect().intersects(tank.getRect())) {
				this.stay();
				tank.stay();
				return true;
			}
		}
		return false;
	}
	/**
	 * 與一個List集合中的坦克進行碰撞檢測
	 * @param tanks 需要進行碰撞檢測的坦克集合
	 * @return 碰撞成功返回true,否則返回false
	 */
	public boolean collidesWithTanks(List<Tank> tanks) {
		for(int i =0; i<tanks.size(); i++) {
			if(this.collidesWithTank(tanks.get(i))) {
				return true;
			}
		}
		return false;		
	}

	public void setLife(int life) {
		this.life = life;
	}

	public int getLife() {
		return life;
	}
	/**
	 * 定義血條的內部類
	 * @author tungkee
	 *
	 */
	private class BloodBar {
		private int width = Tank.WIDTH;
		private int height = 10;
		
		public void draw(Graphics g) {
			Color c = g.getColor();
			g.setColor(Color.RED);
			g.drawRect(x, y - height, width, height);
			g.fillRect(x, y - height, width * life / 100, height);
			g.setColor(c);
		}
	}
	/**
	 * 定義坦克吃血條的方法,同樣採用矩形碰撞檢測的技術
	 * @param b 被吃的血條
	 * @return 被吃後返回true,否則返回false
	 */
	public boolean eat(Blood b) {
		if(this.live && b.isLive() && this.getRect().intersects(b.getRect())) {
			this.life = 100;
			b.setLive(false);
			return true;
		}
		return false;
	}
	
}

Missile.java

package tungkee.javase.project.tankwar;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;

import tungkee.javase.project.tankwar.Tank.Direction;

public class Missile {
	public static final int XSPEED = 10;
	public static final int YSPEED = 10;
	public static final int WIDTH = 10;
	public static final int HEIGHT = 10;
	
	private Direction dir = Direction.STOP;
	private TankClient tc = null;
	private int x = 0;
	private int y = 0;
	private boolean live = true;
	private boolean good = true;
	
	public Missile(int x, int y, Direction dir) {
		this.x = x;
		this.y = y;
		this.dir = dir;
	}
	
	public Missile(int x, int y, Direction dir, boolean good, TankClient tc) {
		this(x, y, dir);
		this.good = good;
		this.tc = tc;
	}
	
	public void draw(Graphics g) {
		if(live == false) {
			tc.removeMissile(this);
			return;
		}
		
		Color color = g.getColor();
		
		if(!good) {
			g.setColor(Color.RED);
		} else {
			g.setColor(Color.WHITE);
		}
		
		g.fillOval(x, y, WIDTH, HEIGHT);
		g.setColor(color);
		
		move();
	}

	private void move() {
		switch(dir) {
		case L:
			x -= XSPEED;
			break;
		case LU:
			x -= XSPEED;
			y -= YSPEED;
			break;
		case U:
			y -= YSPEED;
			break;
		case RU:
			x += XSPEED;
			y -= YSPEED;
			break;
		case R:
			x += XSPEED;
			break;
		case RD:
			x += XSPEED;
			y += YSPEED;
			break;
		case D:
			y += YSPEED;
			break;
		case LD:
			x -= XSPEED;
			y += YSPEED;
			break;
		}
		
		if(x < 0 || x > TankClient.GAME_WIDTH || y < 0 || y > TankClient.GAME_HEIGHT) {
			this.live = false;
		}
	}

	public boolean isLive() {
		return live;
	}
	
	public Rectangle getRect() {
		return new Rectangle(x, y, WIDTH, HEIGHT);
	}
	
	public boolean hitTank(Tank tank) {
		if(this.live && tank.isLive() && this.good != tank.isGood() && this.getRect().intersects(tank.getRect())) {
			if(tank.isGood()) {
				tank.setLife(tank.getLife() - 20);
				if(tank.getLife() == 0) tank.setLive(false);
			} else {
				tank.setLive(false);
			}
			tc.addExplode(new Explode(x, y, tc));
			this.live = false;
			return true;
		}
		return false;
	}
	
	public boolean hitTanks(List<Tank> tanks) {
		for(int i=0; i<tanks.size(); i++) {
			if(this.hitTank(tanks.get(i))) {
				return true;
			}
		}
		return false;
	}
	
	public boolean hitWall(Wall wall) {
		if(this.live && this.getRect().intersects(wall.getRect())) {

			this.live = false;
			return true;
		}
		return false;
	}
		
}
Blood.java

package tungkee.javase.project.tankwar;
import java.awt.*;

public class Blood {
	private int x, y, w, h;
	private boolean live = true;
	private TankClient tc = null;
	//指明血塊運動的軌跡,由pos中各個點構成
	private int[][] pos = {
			{200,100},{210,200},{220,230},{300,400},{100,300},{50,250},{100,200},{150,150}
	};
	private int step = 0;
	
	public Blood(TankClient tc) {
		x = pos[0][0];
		y = pos[0][1];
		w = h = 15;
		this.tc = tc;
	}
	
	public void draw(Graphics g) {
		Color c = g.getColor();
		g.setColor(Color.MAGENTA);
		g.fillRect(x, y, w, h);
		g.setColor(c);
		
		move();
	}

	private void move() {
		step ++;
		if(step == pos.length) {
			step = 0;
		}
		
		x = pos[step][0];
		y = pos[step][1];
	}
	
	
	public boolean isLive() {
		return live;
	}

	public void setLive(boolean live) {
		this.live = live;
	}

	public Rectangle getRect() {
		return new Rectangle(x, y, w, h);
	}
	
}

Explode.java

package tungkee.javase.project.tankwar;

import java.awt.*;

public class Explode {
	private int x = 0, y = 0;
	private TankClient tc = null;
	private int[] diameter = {4, 7, 12, 16, 32, 40, 49, 30, 16, 10, 6};
	private int step = 0;
	private boolean live = true;
	
	public Explode(int x, int y, TankClient tc) {
		this.x = x;
		this.y = y;
		this.tc = tc;
	}
	
	public void draw(Graphics g) {
		if(! live) {
			tc.removeExplode(this);
			return;
		}
		
		if(step == diameter.length) {
			live = false;
			step = 0;
		}
		
		Color color = g.getColor();
		g.setColor(Color.ORANGE);
		g.fillOval(x - diameter[step] / 2, y - diameter[step] / 2, diameter[step], diameter[step]);
		g.setColor(color);
		
		step ++;
	}
	
}

Wall.java

package tungkee.javase.project.tankwar;

import java.awt.*;

public class Wall {
	private int x, y;
	private int width, height;
	private TankClient tc;
	
	public Wall(int x, int y, int width, int height, TankClient tc) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.tc = tc;
	}
	
	public void draw(Graphics g) {
		Color c = g.getColor();
		g.setColor(Color.BLACK);
		g.fillRect(x, y, width, height);
		g.setColor(c);
	}
	
	public Rectangle getRect() {
		return new Rectangle(x, y, width, height);
	}
}




發佈了26 篇原創文章 · 獲贊 3 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章