java单机版坦克游戏(尚学堂)

界面客户端 TankClient.java

package com.rs;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

import javax.swing.*;



public class TankClient extends JFrame{
	public static final int GAME_WIDTH=800;//常量名字母大写
	public static final int GAME_HEIGHT=600;
	

	Tank myTank=new Tank(50,50,true,Tank.Direction.STOP, this);
	
	Wall w1=new Wall(200,200,20,150,this),w2=new Wall(300,100,300,20,this);
	
	List<Explode> explodes=new ArrayList<Explode>();
	List<Missile> missiles=new ArrayList<Missile>();
	List<Tank> tanks=new ArrayList<Tank>();
	
	Image offScreenImage=null;
	
	public void paint(Graphics g) {//面向对象方法
		g.drawString("Missiles-count:"+missiles.size(),10,45);
		g.drawString("Explodes-count:"+explodes.size(),10,60);
		g.drawString("Tanks-count:"+tanks.size(),10,75);
		g.drawString("Tanks-lift:"+myTank.getLife(),10,90);

		for(int i=0;i<missiles.size();i++){
			Missile m=missiles.get(i);
			m.hitTanks(tanks);
			m.hitTank(myTank);
			m.hitWall(w1);
			m.hitWall(w2);
		    m.draw(g);
		}	
		
		for(int j=0;j<explodes.size();j++){
			Explode e=explodes.get(j);
			e.draw(g);
		}
		
		for(int k=0;k<tanks.size();k++){
			Tank t=tanks.get(k);
			t.collidesWithWall(w1);
			t.collidesWithWall(w2);
			t.collidesWithTank(tanks);
			t.draw(g);
		}
			
		
		myTank.draw(g);
		w1.draw(g);
		w2.draw(g);
	}
	
	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(Color.GRAY);
		goffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);
		goffScreen.setColor(c);
		paint(goffScreen);
		g.drawImage(offScreenImage,0,0,null);
	}
	
	public void lauchFrame(){
		for(int i=0; i<10; i++){
			tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D, this));
		}
		
		this.setTitle("<MyTankWar>");
		this.setBounds(320,150,GAME_WIDTH,GAME_HEIGHT);		
		setResizable(false);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		setBackground(Color.gray);
		setVisible(true);
		
		this.addKeyListener(new KeyMonitor());
		new Thread(new TankThread()).start();
	}

	private static final long serialVersionUID = 1L;

	public static void main(String[] args) {
		TankClient tc=new TankClient();
		tc.lauchFrame();
	}
	
	private class TankThread implements Runnable{

		public void run() {
			while(true){
				repaint();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
	}

	private class KeyMonitor extends KeyAdapter{

		public void keyReleased(KeyEvent e) {
			myTank.keyReleased(e);
		}

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

坦克类 Tank.java:

package com.rs;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Tank {
	public static final int XSPEED = 5;
	public static final int YSPEED = 5;
	public static final int WIDTH = 30;
	public static final int HEIGHT = 30;

	private int x, y,oldX,oldY;

	TankClient tc;
	
	private BloodBar bb=new BloodBar();

	private boolean live=true;
	private boolean good;
	
	private static Random random=new Random();//一个就够了,所以设为static
	
	private int step = random.nextInt(12)+3;
	
	private int life = 100;

	private boolean bL = false, bU = false, bR = false, bD = false;

	enum Direction {
		L, LU, U, RU, R, RD, D, LD, STOP
	};// 枚举类型使用

	private Direction dir = Direction.STOP;// 坦克默认方向
	private Direction ptDir = Direction.D;// 炮筒默认方向

	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) {
			if(!good){
				tc.tanks.remove(this);
			}
			return;
		}
		Color c = g.getColor();
		if (good) {
			g.setColor(Color.CYAN);
		} else {
			g.setColor(Color.blue);
		}
		g.fillOval(x, y, WIDTH, HEIGHT);
		g.setColor(c);
		if(good) bb.draw(g);

		switch (ptDir) {
		case L:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y
					+ Tank.HEIGHT / 2);
			break;
		case LU:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y);
			break;
		case U:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH
					/ 2, y);
			break;
		case RU:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,
					y);
			break;
		case R:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,
					y + Tank.HEIGHT / 2);
			break;
		case RD:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,
					y + Tank.HEIGHT);
			break;
		case D:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH
					/ 2, y + Tank.HEIGHT);
			break;
		case LD:
			g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y
					+ Tank.HEIGHT);
			break;
		}
		move();
	}

	private void move() {
		
		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;
		}

		if (this.dir != Direction.STOP) {
			this.ptDir = this.dir;
		}

		if (x < 0)
			x = 0;
		if (y < 25)
			y = 25;
		if (x+Tank.WIDTH>TankClient.GAME_WIDTH) 
			x =TankClient.GAME_WIDTH-Tank.WIDTH;
		if (y+Tank.HEIGHT>TankClient.GAME_HEIGHT)
			y=TankClient.GAME_HEIGHT-Tank.HEIGHT;
		
		if(!good){
			Direction[] dirs=Direction.values();
			if(step == 0){
				step = random.nextInt(12)+3;
				int rn=random.nextInt(dirs.length);
				dir=dirs[rn];
			}	
			step--;
			
			if(random.nextInt(40)>38) this.fire();
		}		
		
	}
	
	public void stay(){
		x=oldX;
		y=oldY;
	}

	public void KeyPressed(KeyEvent e) {// 键盘按下
		int key = e.getKeyCode();
		switch (key) {

		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();
	}

	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;
	}

	public void keyReleased(KeyEvent e) {// 键盘松开
		int key = e.getKeyCode();
		switch (key) {
		case KeyEvent.VK_F:
			fire();
			break;
		case KeyEvent.VK_A:
			superFire();
			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;
		}
		locateDirection();
	}

	public Missile fire() {
		if(!live) return null;
		int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2;
		int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2;
		Missile m = new Missile(x, y, good, ptDir, this.tc);
		tc.missiles.add(m);
		return m;

	}
	
	public Missile fire(Direction dir) {
		if(!live) return null;
		int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2;
		int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2;
		Missile m = new Missile(x, y, good, dir,  this.tc);
		tc.missiles.add(m);
		return m;
	}

	public Rectangle getRect() {
		return new Rectangle(x,y,WIDTH,HEIGHT);
	}

	public boolean isLive() {
		return live;
	}

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

	public boolean isGood() {
		return good;
	}
	
	public boolean collidesWithWall(Wall w){
		if(this.live && this.getRect().intersects(w.getRect())){
			this.stay();
			return true;
		}
		return false;
	
	}
	
	public boolean collidesWithTank(java.util.List<Tank> tanks){
		for(int i=0;i<tanks.size();i++){
			Tank t=tanks.get(i);
			if(this!=t) {
				if(this.live && t.isLive() && this.getRect().intersects(t.getRect())){
					this.stay();
					t.stay();
					return true;
				}
			}
		}
		return false;
		
	}
	
	private void superFire() {
		Direction[] dirs=Direction.values();
		for(int i=0;i<8;i++) {
			fire(dirs[i]);
		}
	}

	public int getLife() {
		return life;
	}

	public void setLife(int life) {
		this.life = life;
	}
	
	private class BloodBar {
		public void draw(Graphics g){
			Color color=g.getColor();
			g.setColor(Color.red);
			g.drawRect(x, y+13, WIDTH, 5);
			int w=WIDTH*life/100;
			g.fillRect(x, y+13, w, 5);
			g.setColor(color);
		}
	}

}

子弹类 Missile.java:

package com.rs;

import java.awt.*;
import java.util.List;


public class Missile {//Tank子弹类
	private static final int XSPEED = 10;
	private static final int YSPEED = 10;
	public static final int WIDTH=10;
	public static final int HEIGHT=10;
	
	int x,y;
	Tank.Direction dir;
	
	private boolean live=true;
	private boolean good;
	
	private TankClient tc;
	
	public Missile(int x, int y, Tank.Direction dir) {//自动生成构造方法
		this.x = x;
		this.y = y;
		this.dir = dir;
	}
	
	public Missile(int x, int y,boolean good, Tank.Direction dir,TankClient tc) {//自动生成构造方法
		this(x, y, dir);
		this.good=good;
		this.tc=tc;
	}
	
	public void draw(Graphics g){
		if(!live) {
			tc.missiles.remove(this);
			return;
		}
		
		Color c=g.getColor();
		
		if(!good){
			g.setColor(Color.blue);
		} else{
			g.setColor(Color.BLACK);
		}		
		
		g.fillOval(x,y,WIDTH,HEIGHT);
		g.setColor(c);	
		
		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;
		case STOP:
			break;
		}
		
		if(x<0||y<0||x>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGHT){//出界
			live=false;
		}
	}

	
	public boolean isLive() {
		return live;
	}
	
	public Rectangle getRect(){//四边形
		return new Rectangle(x,y,WIDTH,HEIGHT);
	}
	
	public boolean hitTank(Tank t){
		if(this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good != t.isGood()) {
			if(t.isGood()) {
				t.setLife(t.getLife()-20);
				if(t.getLife()<=0) t.setLive(false);
			} else{
				t.setLive(false);
			}
			this.live=false;
			Explode e=new Explode(x,y,tc);
			tc.explodes.add(e);
			return true;
		}
		return false;
		
	}
	
	public boolean hitTanks(List<Tank> tanks){
		for(int i=0; i<tanks.size(); i++){
			if(hitTank(tanks.get(i))){
				return true;
			}
		}
		return false;
		
	}

	public boolean hitWall(Wall w){
		if(this.live && this.getRect().intersects(w.getRect())){
			this.live=false;
			return true;
		}
		return false;
	}
	
	 
}

爆炸效果 Explode.java:

package com.rs;

import java.awt.*;

public class Explode {// 爆炸(多幅图重碟在一起)
	int x, y;
	private boolean live = true;

	private TankClient tc;
	
	int[] diameter = { 5,  12,  26,  49,  20, 3 };
	int step = 0;

	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.explodes.remove(this);
			return;
		}
		
		if(step == diameter.length){
			live=false;
			step=0;
			return;
		}
		
		Color c=g.getColor();
		g.setColor(Color.orange);
		g.fillOval(x, y, diameter[step], diameter[step]);
		g.setColor(c);
		
		step ++;
	}
}

障碍物 Wall.java:

package com.rs;

import java.awt.Graphics;
import java.awt.Rectangle;

public class Wall {
	int x,y,w,h;
	TankClient tc;
	
	public Wall(int x, int y, int w, int h, TankClient tc) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.tc = tc;
	}
	
	public void draw(Graphics g){
		g.fillRect(x, y, w, h);
	}
	
	public Rectangle getRect(){
		return new Rectangle(x,y,w,h);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值