【简单空战】做一个Java小游戏的设计,第三部分

代码

package owo.cn;
		/*
		* 程序入口
		 * 所有游戏展示内容实现处
		 */

import owo.game.GameFrame;

public class GameMain {
	public static void main(String[] aaa) {
		new GameFrame();	//对GameFrame进行初始化
	}
}
————————————————————————————————————————————
package owo.game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import owo.plane.AirCraft;
import owo.util.Constant;

/*
 * 弹药类
 */
public class Ammo {
	public static final int DEFAULT_SPEED=7;//——————————子弹速度
	public static final int RADIUS=3;//子弹大小
	
	private static Image[] AmmoImg;//子弹绘图
	static {
		AmmoImg=new Image[4];
		AmmoImg[0]=Toolkit.getDefaultToolkit().createImage("photo/ammoup.png");
		AmmoImg[1]=Toolkit.getDefaultToolkit().createImage("photo/ammodo.png");
		AmmoImg[2]=Toolkit.getDefaultToolkit().createImage("photo/ammole.png");
		AmmoImg[3]=Toolkit.getDefaultToolkit().createImage("photo/ammori.png");
	}
	public Ammo(int x,int y,int dir) {
		this.setX(x);
		this.setY(y);
		this.setDir(dir);
		
	}

	public void  drawImgAmmo(Graphics g) {
		g.drawImage(AmmoImg[getDir()], getX(), getY(),null);
	}
	
	
	private int x,y;
	private int speed=DEFAULT_SPEED;
	private int dir;
	private int atk;
	private Color color;
	
	private boolean visible=true;//子弹可见
	
	public Ammo(int x,int y,int dir,int atk, Color color) {
		this.setX(x);
		this.setY(y);
		this.setDir(dir);
		this.setAtk(atk);
		this.color=color;
	}
	public Ammo() /*给对象池使用,均为默认值*/{
		
	}
	
	public void draw (Graphics g) /*绘制子弹*/{
		if(!visible)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 AirCraft.DIR_UP:
			y-=speed;
			if(y<=0) {visible=false;} 			
			break;
			
		case AirCraft.DIR_DOWN:
			y+=speed;
			if(y>Constant.FRAME_HEIGHT) {visible=false;}	
			break;
			
		case AirCraft.DIR_LEFT:
			x-=speed;
			if(x<0) {visible=false;} 		
			break;
			
		case AirCraft.DIR_RIGHT:
			x+=speed;
			if(x>Constant.FRAME_WIDTH) {visible=false;}	
			break;
		}
	}
	
	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 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 getAtk() {
		return atk;
	}

	public void setAtk(int atk) {
		this.atk = atk;
	}
	
	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color= color;
	}
	
	public boolean isVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible= visible;
	}
	
}

package owo.game;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

/*
 * 爆炸
 */
public class Explode {
	public static final int EXPLODE_FRAME_COUNT=9;
	//————————————————————导入图片
	private static Image[] img;
	//————————————————————爆炸效果的宽高
	public static int explodewidth;
	public static int explodeheight;
	static {
		img=new Image[EXPLODE_FRAME_COUNT/3];
		for(int i=0;i<img.length;i++) {
			img[i]=Toolkit.getDefaultToolkit().createImage("photo/boom_"+i+".png");
		}
		explodewidth =img[0].getWidth(null);
		explodeheight =img[0].getHeight(null);
	}
	
	
	//——————————————————爆炸属性
	private int x,y;
	//———————————————————当前播放帧0~9
	private int index;
	//————————————-——————设置不可见
	private boolean visible=true;
	
	public Explode() {
		index=0;
	}
	
	public Explode(int x,int y) {
		this.x=x;
		this.y=y;
		 index=0;
	}
	
	public void draw(Graphics g) {
		//————————————————————————————爆炸贴图位置、宽高调整
		if(explodeheight<=0) {
			explodewidth =img[0].getWidth(null);
			explodeheight=img[0].getHeight(null)>>1;
		}
		
		
		if(!visible)return;
		g.drawImage(img[index/3], x-explodewidth, y-explodeheight,null);
		index ++;
		//——————————————————————播放完最后一帧后,不可见
		if(index>=EXPLODE_FRAME_COUNT) {
			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 owo.game;

//————————————————————————————————————游戏主窗口类,实现展示内容

import static owo.util.Constant.*;//————引入常量名称
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.awt.color.*;
import java.util.List;
import javax.swing.*;

import owo.plane.AirCraft;
import owo.plane.EnemyPlane;
import owo.plane.MyPlane;

//==========================窗口=================================
public class GameFrame extends Frame implements Runnable{
	
	private Image overImg=null;//————————————定义游戏结束图片
	private BufferedImage bufImg=new BufferedImage(FRAME_WIDTH,FRAME_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR);//——————定义和屏幕大小一致的图,BufferedImage→在缓冲区的图片
	
	private static int gameStat;//————————游戏状态,gameStat于“菜单”取值
	
	private int menuIndex;//——————————————菜单指向(i=menuIndex表示选中那一个)

	private MyPlane myPlane;//——————————————————————————————定义一个飞机
	
	private List <AirCraft> enemies =new ArrayList<>();//敌人容器
	
	public static int titleBarH;//——————————————————————————标题栏高度
	
	/*
 * 对窗口初始化
 */
	public GameFrame() {
		initFrame();
		
		initEventListener();
		new Thread(this).start();//————————————启动用于刷新窗口的线程
}
	
	private void initGame() /*初始化游戏*/{
		gameStat=STAT_MENU;
	}
	
	private void initFrame() /*初始化属性*/{
	
	setTitle(GAME_TITLE);//————————————————————————设置标题
	setSize(FRAME_WIDTH,FRAME_HEIGHT);//————————————设置窗口大小
	setResizable(false);//————————————————————————————大小不可变
	setLocation(FRAME_X,FRAME_Y);//————————————————————设置窗口位置
	setVisible(true);//——————————————————————————————————让窗口可见
	titleBarH=getInsets().top;//求标题栏高度
	repaint();//————————————————————————回调update方法
	
}

	//============================菜单文字===========================
	
	public void update(Graphics g1)/*update 该方法调用所有绘制内容*/ {
	//这里将系统画笔设置为g1      ↑   为图片画笔传位
		
		Graphics g =bufImg.getGraphics();//得到图片的画笔
										//使用图片的画笔将所有内容放到图片上
		
		g.setFont(FONT);
		switch(gameStat) /*表现菜单文字*/{
		case STAT_MENU:
			repaint();//——————————————————回调update方法,这里没有repaint会显示不出来
			drawMenu(g);
			break;
		case STAT_HELP:
			drawHelp(g);
			break;
		case STAT_RUN:
			drawRun(g);
			break;
		case STAT_OVER:
			drawOver(g);
			break;
		}
//———因为要和屏幕大小一致,所以设为0,0,null
			  g1.drawImage(bufImg,0,0,null);//——————用系统画笔将图片绘制到frame
	}
	private Image helpImg;
	private void drawHelp(Graphics g) {
		g.setColor(Color.LIGHT_GRAY);
		g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
		if(helpImg==null) {
			helpImg=Toolkit.getDefaultToolkit().createImage("photo/help.png");
		}
		int width =helpImg.getWidth(null);
		int height =helpImg.getHeight(null);
		
		int x=FRAME_WIDTH-width>>1;
		int y=FRAME_HEIGHT-height>>1;
		g.drawImage(helpImg, x, y, null);
			g.setColor(Color.WHITE);
			g.drawString("任意键继续", 10,FRAME_HEIGHT-10);
				
				
		}
	private void drawRun(Graphics g) /*游戏运行内容*/{
		g.setColor(Color.CYAN);		//————————————进入游戏背景
		g.fillRect(0,0, FRAME_WIDTH, FRAME_HEIGHT);
		
		drawEnemies(g);
		
		myPlane.draw(g);
		
		drawExplodes(g);
		
		//——————————————————————子弹和飞机撞的方法
		ammoCollidePlane();
		
	}
	private void drawEnemies(Graphics g) /*绘制敌人*/{
		//+如果敌人死亡,则从容器移除
		for(int i=0 ; i<enemies.size();i++) {
			AirCraft enemy = enemies.get(i);//+++++++++++++++++++++++++
			if(enemy.isDie()) {
				enemies.remove(i);
				i--;
				continue;
		}
			enemy.draw(g);
		}
	}
	//————————————————————————————————————绘制游戏结束
	private void drawOver(Graphics g) {
		if(overImg==null) {
			//——————————————————保证只加载一次
			overImg=Toolkit.getDefaultToolkit().createImage("photo/game_over.png");
					
		}
			g.setColor(Color.BLACK);
			g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
		
			int imgW =overImg.getWidth(null);
			int imgH =overImg.getHeight(null);
			
			g.drawImage(overImg, FRAME_WIDTH-imgW>>1, FRAME_HEIGHT-imgH>>1, null);
	
			//——————————————————————游戏结束后按键提示
		g.setColor(Color.RED);
		g.drawString(OVER_STR0, 20, FRAME_HEIGHT-50);
		g.drawString(OVER_STR1, FRAME_WIDTH-220, FRAME_HEIGHT-50);
	
	}
	
	private void drawMenu(Graphics g) /*绘制菜单内容*/{
		
		g.setColor(Color.LIGHT_GRAY);		//————————————背景
		g.fillRect(0,0, FRAME_WIDTH, FRAME_HEIGHT);
		
	//final int STR_WHIDTH=60;//——————————————————菜单位置
		int x =100;
		int y =FRAME_HEIGHT/3;
	final int DIS =54;
		g.setColor(Color.BLACK);
		for(int i=0;i<MENUS.length;i++) /*书写菜单文字*/{
			if(i==menuIndex )		 /*选中菜单为白色*/ {
				g.setColor(Color.WHITE);
			}else {
				g.setColor(Color.BLACK);
			}
			g.drawString(MENUS[i], x, y+DIS*i);
		}
	
	}
	//=================按键监听=====================================
	private void initEventListener() /*初始化窗口事件监听*/{
	addWindowListener(new WindowAdapter() {
		@Override
		public void windowClosing(WindowEvent e) {
			System.exit(0);
		}
	});//————————————————————————————————————————点X关闭界面
	
	addKeyListener(new KeyAdapter()/*按键事件监听*/ {
		@Override//————————————————————————————————————————
		public void keyPressed(KeyEvent e) {
			int keyCode=e.getKeyCode();//————————获得按下的键值
		  switch(gameStat) {
			case STAT_MENU:
				keyEventMenu(keyCode);
				break;
			case STAT_HELP:
				keyEventHelp(keyCode);
				break;
			case STAT_RUN:
				keyEventRun(keyCode);
				break;
			case STAT_OVER:
				keyEventOver(keyCode);
				break;
		  	}
		}
		//================菜单状态下按键处理================
		private void keyEventMenu(int keyCode) {
			switch(keyCode) {
				case KeyEvent.VK_UP:
				case KeyEvent.VK_W:
					if(--menuIndex < 0) {
						menuIndex=MENUS.length - 1;
					}
					//repaint();
					break;
				case KeyEvent.VK_DOWN:
				case KeyEvent.VK_S:
					if(++menuIndex > MENUS.length - 1) {
						menuIndex = 0;
					}
					//repaint();
					break;	
				case KeyEvent.VK_ENTER://进入游戏
					//newGame(1);
					//break;
				switch(menuIndex){
					case 0:newGame(1);
						break;
					case 1:setGameStat(STAT_HELP);
						break;
					case 2:System.exit(0);
						break;
				}
					
			}
		}
		
		private void newGame(int leve) /*开始游戏*/{
			gameStat=STAT_RUN;

			myPlane =new MyPlane(500,600,AirCraft.DIR_UP);
			new Thread() /*用一个单独线程控制产生敌人*/{
				@Override
				public void run() {
					while(true) {
						if(enemies.size()<ENEMY_MAX_COUNT) {
							AirCraft enemy=EnemyPlane.createEnemy();
							enemies.add(enemy);
						}try {
							Thread.sleep(ENEMY_BORN_TIME);}
							catch(InterruptedException e) {
								e.printStackTrace();
							}
						//———————————————————只有在游戏run状态下才创建敌人
						if(gameStat != STAT_RUN) {
							break;
						}
						}
					
					}
				
			}.start();
		}
		
		private void keyEventHelp(int keyCode) {
			setGameStat(STAT_MENU);
		}
		private void keyEventRun(int keyCode) /*游戏中的按键处理*/{
				switch(keyCode) {
				case KeyEvent.VK_UP:
				case KeyEvent.VK_W:
					myPlane.setDir(AirCraft.DIR_UP);//————改变方向
					myPlane.setState(AirCraft.STATE_MOVE);//——飞机切换到移动
					break;
				case KeyEvent.VK_DOWN:
				case KeyEvent.VK_S:
					myPlane.setDir(AirCraft.DIR_DOWN);//————改变方向
					myPlane.setState(AirCraft.STATE_MOVE);//——飞机切换到移动
					break;	
				case KeyEvent.VK_LEFT:
				case KeyEvent.VK_A:
					myPlane.setDir(AirCraft.DIR_LEFT);//————改变方向
					myPlane.setState(AirCraft.STATE_MOVE);//——飞机切换到移动
					break;
				case KeyEvent.VK_RIGHT:
				case KeyEvent.VK_D:
					myPlane.setDir(AirCraft.DIR_RIGHT);//————改变方向
					myPlane.setState(AirCraft.STATE_MOVE);//——飞机切换到移动
					break;
				case KeyEvent.VK_SPACE:
					myPlane.fire();
					break;
				}
		}
		
		//——————————————————————————————————游戏结束按键处理
		private void keyEventOver(int keyCode) {
			//————————————————————————————————结束游戏
			if(keyCode==KeyEvent.VK_ESCAPE)	{
				System.exit(0);
			}else if(keyCode==KeyEvent.VK_ENTER) {
				setGameStat(STAT_MENU);
				//——————————————————重置游戏状态
				restGame();		
			}
		}
		//————————————————————————死亡后退出重置游戏
		
		private void restGame() {
			menuIndex=0;
			//————————————自己飞机的子弹还回对象池
			myPlane=null;//——————————————销毁自己
			//———————————清空敌人资源
			for(AirCraft enemy:enemies) {
				enemy.ammosReturn();
			}
			enemies.clear();
		}
		
		
		@Override//——————————————————————————————————————放开
		public void keyReleased(KeyEvent e) {
			
		}
		
	});
	
}
	//=================刷新率=====================================

	@Override
	public void run() {
		while(true) /*刷新频率,回调update*/{
			repaint();
			try {
				Thread.sleep(REPAINT_INTERVAL);
			} catch (InterruptedException e) {
					e.printStackTrace();
			}
		}
	}

	//——————————————我子弹和敌人碰撞
	private void ammoCollidePlane() {
		for(AirCraft enemy:enemies) {
			enemy.collideAmmos(myPlane.getAmmos());
		}
		//——————————————敌人子弹和我碰撞
		for(AirCraft enemy:enemies) {
			myPlane.collideAmmos(enemy.getAmmos());
		}
	
	}
	//————————————————————所有目标上爆炸效果
	private void drawExplodes(Graphics g){
		for(AirCraft enemy: enemies) {
			enemy.drawExplodes(g);
		}
		  myPlane.drawExplodes(g);
	}
	public static void setGameStat(int gameStat) {
		GameFrame.gameStat=gameStat;
	}
	
}
————————————————————————————————————————————
package owo.plane;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.List;

import owo.game.Ammo;
import owo.game.Explode;
import owo.game.GameFrame;
import owo.util.AmmoPool;
import owo.util.Constant;
import owo.util.EnemyPlanePool;
import owo.util.ExplodesPool;
import owo.util.MyUtil;

/*
 * 飞机属性
 */
public abstract class AirCraft {
	
	
	
	public static final int DIR_UP   = 0;//——————————方向
	public static final int DIR_DOWN = 1;//——————————方向
	public static final int DIR_LEFT = 2;//——————————方向
	public static final int DIR_RIGHT= 3;//——————————方向
	
	public static final int RADIUS=20;//——————————————大小
	
	public static final int DEFAULT_HP=500;//————————————初始HP
	
	public static final int DEFAULT_SPEED=4;//——————————默认速度,每帧3像素
	
	public static final int STATE_STAND=0;//————————————状态
	public static final int STATE_MOVE =1;//————————————状态
	public static final int STATE_DIE  =2;//————————————状态
		
	private int x,y;
	private int hp=DEFAULT_HP;
	private int atk;
	public static final int MAX_ATK=200;
	public static final int MIN_ATK=160;
	private int def;
	private int speed=DEFAULT_SPEED;
	private int dir;
	private int state = STATE_STAND;
	private Color color;
	
	private boolean isEnemy=false;//判别是否为敌人
	
	private HpBar bar =new HpBar();
	
	private List <Ammo> ammos=new ArrayList();//——————————弹药
	
	private List<Explode>explodes=new ArrayList<>();//—————————容器保存爆炸效果
	
	public AirCraft(int x,int y,int dir)/*自己飞机颜色,连同弹药颜色*/ {
		this.x=x;
		this.y=y;
		this.dir=dir;
		initPlane();
			}
	
	public AirCraft() {
		initPlane();
	}
	private void initPlane() {
		color =new Color(154,51,154);
		atk=MyUtil.getRandomNu(MIN_ATK, MAX_ATK);
	}
	

	public void draw(Graphics g){
		logic();
		
		drawImgAirCraft(g);
		
		drawAmmos(g);
		
		bar.draw(g);
	}
	
	public abstract void  drawImgAirCraft(Graphics g)/*图片绘制飞机*/;
	

	
	private void drawAirCraft(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*2;
			break;
		case DIR_DOWN:
			endy=y+RADIUS*2;
			break;
		case DIR_LEFT:
			endx=x-RADIUS*2;
			break;
		case DIR_RIGHT:
			endx=x+RADIUS*2;
			break;
		
		}
		
		g.drawLine(x, y, endx, endy);
	}
	
	private void logic() /*飞机逻辑处理*/{
		//System.out.println("AirCraft.logic");
		switch(state) {
		case STATE_STAND:
			break;
		case STATE_MOVE:
			//System.out.println("AirCraft.logic+");
			move();
			break;
		case STATE_DIE:
			break;

		}
	}
	private  void move() /*飞机移动*/{
		switch(dir) {
			case DIR_UP:
				y-=speed;
				if(y<RADIUS+GameFrame.titleBarH) {
					y=RADIUS+GameFrame.titleBarH;
				}
				break;
			case DIR_DOWN:
				y+=speed;
				if(y>Constant.FRAME_HEIGHT-RADIUS) {
					y=Constant.FRAME_HEIGHT-RADIUS;
				}
				break;
			case DIR_LEFT:
				x-=speed;
				if(x<RADIUS) {
					x=RADIUS;
				}
				break;
			case DIR_RIGHT:
				x+=speed;
				if(x>Constant.FRAME_WIDTH-RADIUS) {
					x=Constant.FRAME_WIDTH-RADIUS;
				}
				break;
		}
		//System.out.println(this);
		
	}
	
	
	
	public static int getDirUp() {
		return DIR_UP;
	}
	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 getHp() {
		return hp;
	}
	public void seHp(int hp) {
		this.hp=hp;
	}
	public  int getAtk() {
		return atk;
	}
	public void setAtk(int atk) {
		this.atk=atk;
	}
	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 getAmmos() {
		return ammos;
	}
	public void setAmmos(List ammos) {
		this.ammos=ammos;
	}
	public boolean isEnemy() {
		return isEnemy;
	}
	public void setEnemy(boolean enemy) {
		isEnemy=enemy;
	}
	
	
	@Override
	public String toString() {
		return "AirCraft{"+
				"x="+ x +
				",y="+ y +
				",hp="+ hp +
				",atk="+ atk +
				",dir="+ dir +
				",state="+ state +
				'}';
				
	}
	
	public void fire() /*开火的方法*/{
		int ammoX=x;
		int ammoY=y;
		switch(dir) {
		case DIR_UP:
			ammoY-=RADIUS;
			break;
		case DIR_DOWN:
			ammoY+=RADIUS;
			break;
		case DIR_LEFT:
			ammoX-=RADIUS;
			break;
		case DIR_RIGHT:
			ammoX+=RADIUS;
			break;
		}
		//从池获取子弹对象
		Ammo ammo=AmmoPool.get();
		//子弹属性设置
		ammo.setX(ammoX);
		ammo.setY(ammoY);
		ammo.setDir(dir);
		ammo.setAtk(atk);
		ammo.setColor(color);
		ammo.setVisible(true);
		
		ammos.add(ammo);
	}
	private void drawAmmos(Graphics g) /*绘制发射的子弹*/{
		for(Ammo ammo:ammos) {
			ammo.draw(g);
			
		}
		for(int i=0;i<ammos.size();i++) /*检查所有子弹,移除不可见的子弹,还给池*/{
			Ammo ammo=ammos.get(i);
			if(!ammo.isVisible()) {
				Ammo remove=ammos.remove(i);
				i--;
				AmmoPool.tRrturn(remove);
			}
		}
	}
	//——————————————————————————飞机报销时处理所有子弹
	public void ammosReturn() {
		for(Ammo ammo:ammos) {
			AmmoPool.tRrturn(ammo);
		}
		ammos.clear();
	}
	
	//————————————————————子弹与飞机互动的方法
	public void collideAmmos (List <Ammo> ammos) {
	//————————————————————检测所有子弹和飞机碰撞	
	for(Ammo ammo:ammos) {
		int ammoX=ammo.getX();
		int ammoY=ammo.getY();
		//————————————————子弹撞上目标
		if(MyUtil.isCollide(x, y, RADIUS,ammoX, ammoY)) {
	//————————————————————子弹消失
	ammo.setVisible(false);
	//————————————————————伤害
	hurt(ammo);
	//————————————————————爆炸效果
	Explode explode=ExplodesPool.get();
	explode.setX(x+20);
	explode.setY(y);
	explode.setVisible(true);
	explode.setIndex(0);
	explodes.add(explode);//——————爆炸贴图中心为子弹击中的飞机坐标,加以调整
	
			}
		}
	}
	//————————————————————————飞机受到伤害
	private void hurt(Ammo ammo) {
		int atk =ammo.getAtk();
		hp-=atk;
		if(hp<0) {
			hp=0;
			die();
		}
	}
	//————————————————————死亡
	private void die(){
		if(isEnemy) {
			//————————————————————————敌人死亡,归还对象池
			EnemyPlanePool.tRrturn(this);
		}else {
			//—————————————————————————自己死,游戏结束
			GameFrame.setGameStat(Constant.STAT_OVER);
		}
		
	}
	//————————————————————————判断当前目标死亡
	public boolean isDie() {
		return hp<=0;
	}
	
	//————————————————————与当前物体上绘制爆炸效果
	public void drawExplodes(Graphics g) {
		for(Explode explode :explodes) {
			explode.draw(g);
		}
		//消除不可见的爆炸,还给对象池
		for(int i=0;i<explodes.size();i++) {
			Explode explode=explodes.get(i);
			if(!explode.isVisible()) {
				Explode remove=explodes.remove(i);
				ExplodesPool.tRrturn(remove);
				i--;
			}
		}
		
		
	}
	//设定一个内部类设定血条
	 class HpBar{
		 public static final int BAR_LINGTH=40;
		 public static final int BAR_HEIGHT=5;
		 
		 public void draw(Graphics g) {
			 g.setColor(color.WHITE);//————————————填充底色
			 g.fillRect(x-RADIUS, y+15+RADIUS-BAR_HEIGHT*2, BAR_LINGTH, BAR_HEIGHT);
			 g.setColor(color.GREEN);//————————————绿当前血量
			 g.fillRect(x-RADIUS, y+15+RADIUS-BAR_HEIGHT*2, hp*BAR_LINGTH/DEFAULT_HP, BAR_HEIGHT);
			 g.setColor(color.WHITE);//————————————白色边框
			 g.drawRect(x-RADIUS, y+15+RADIUS-BAR_HEIGHT*2, BAR_LINGTH, BAR_HEIGHT);
		 }
	 }
	
}
package owo.plane;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import owo.game.GameFrame;
import owo.util.Constant;
import owo.util.EnemyPlanePool;
import owo.util.MyUtil;

public class EnemyPlane extends AirCraft{//————————————————敌方飞机
private static Image[] EneImg;//敌方飞机绘图
	private long aiTime;//——————————————————计时3秒开始的时间
	
	static {
		EneImg=new Image[4];
		EneImg[0]=Toolkit.getDefaultToolkit().createImage("photo/up21.png");
		EneImg[1]=Toolkit.getDefaultToolkit().createImage("photo/dow21.png");
		EneImg[2]=Toolkit.getDefaultToolkit().createImage("photo/lef21.png");
		EneImg[3]=Toolkit.getDefaultToolkit().createImage("photo/ri21.png");
	}
	
	private EnemyPlane(int x,int y,int dir) {
		super(x,y,dir);
		aiTime=System.currentTimeMillis();//一旦刷出就计时
	}
	public EnemyPlane() {
		aiTime=System.currentTimeMillis();//一旦刷出就计时
	}
	
	public static AirCraft createEnemy()/*创建敌人*/ {
		//——————————————————————————————出生点
		int x=MyUtil.getRandomNu(0,2)== 0 ? RADIUS :Constant.FRAME_WIDTH-RADIUS;
		int y=GameFrame.titleBarH+RADIUS;
		int dir=DIR_DOWN;
		AirCraft enemy=EnemyPlanePool.get();
		enemy.setX(x);
		enemy.setY(y);
		enemy.setDir(dir);
		enemy.setEnemy(true);
		enemy.setState(STATE_MOVE);//++++++++++++++
		enemy.seHp(AirCraft.DEFAULT_HP);

		return enemy;
	}
	
	
	public void drawImgAirCraft(Graphics g)/*图片绘制飞机*/{
		ai();
		
			g.drawImage(EneImg[getDir()], getX()-RADIUS, getY()-RADIUS,null);
		
	}
	private void ai() /*敌人AI*/{
		//————————行动状态————————————————————————————
		if(System.currentTimeMillis()- aiTime >Constant.ENEMY_AI_TIME) {
			setState(MyUtil.getRandomNu(0,2)==0? STATE_MOVE:STATE_MOVE);//间隔3秒随机状态
			setDir(MyUtil.getRandomNu(DIR_UP,DIR_LEFT+1));
			
		aiTime =System.currentTimeMillis();
		}
		//———————————发射状态———————————
		if(Math.random()<Constant.ENEMY_FIRE_PERCENT) {
			fire();
		}
		
	}
	
}

package owo.plane;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

public class MyPlane extends AirCraft{//————————————————己方飞机
	private static Image[] AirImg;//己方飞机绘图
	static {
		AirImg=new Image[4];
		AirImg[0]=Toolkit.getDefaultToolkit().createImage("photo/up2.png");
		AirImg[1]=Toolkit.getDefaultToolkit().createImage("photo/dow2.png");
		AirImg[2]=Toolkit.getDefaultToolkit().createImage("photo/lef2.png");
		AirImg[3]=Toolkit.getDefaultToolkit().createImage("photo/ri2.png");
	}
	
	public MyPlane(int x,int y,int dir) {
		super(x,y,dir);
	}
	@Override
	public void  drawImgAirCraft(Graphics g) {
		g.drawImage(AirImg[getDir()], getX()-RADIUS, getY()-RADIUS,null);
	}
}
————————————————————————————————————————————
package owo.util;

import java.util.ArrayList;
import java.util.List;

import owo.game.Ammo;

/*
 * 子弹对象池
 */
public class AmmoPool {
	public static final int DEFAULT_POOL_SIZE=1000;
	public static final int POOL_MAX_SIZE=1250;
	private static List<Ammo> pool=new ArrayList<>();//保存所有子弹的容器
	
	static/*创建1000个子弹对象,添加*/{
		for(int i=0;i <DEFAULT_POOL_SIZE;i++) {
			pool.add(new Ammo());
		}
	}
	
	public static Ammo get()/*池中获得子弹*/ {
		Ammo ammo=null;
		if(pool.size()==0) /*池,空了*/{
			ammo =new Ammo();//那就创建一个
		}else				 /*池,还有,拿第一个位置的子弹*/{
			ammo =pool.remove(0);
		}
		return ammo;
	}
	public static void tRrturn(Ammo ammo) /*子弹消失时,还到池中*/{
		if(pool.size()==POOL_MAX_SIZE) /*池中子弹到max,不再归还*/{
			return;
		}
		pool.add(ammo);
	}
}

package owo.util;

import java.awt.Font;
import java.awt.Toolkit;

/*
 * 游戏所有常量均于该类维护;统一使用一个常量类,方便设置语言
 */
public class Constant {
	//=====================窗口==============================
	public static final String GAME_TITLE="简单空战";
	
	public static final int FRAME_WIDTH=1100;  //窗口宽
	public static final int FRAME_HEIGHT=900;//窗口高
	
	//——————————————————————————————————————————动态获得屏幕长宽
	public static final int SC_W=Toolkit.getDefaultToolkit().getScreenSize().width;
	public static final int SC_H=Toolkit.getDefaultToolkit().getScreenSize().height;
	
	
	public static final int FRAME_X=SC_W-FRAME_WIDTH>>1;//窗口坐标
	public static final int FRAME_Y=SC_H-FRAME_HEIGHT>>1;//窗口坐标
	//======================菜单==============================
	public static final int STAT_MENU = 0;//菜单
	public static final int STAT_HELP = 1;//帮助
	public static final int STAT_RUN = 2; //进入游戏
	public static final int STAT_OVER = 3;//退出
	
	public static final String[] MENUS= {
			"| 新的游戏(w↑)|",
			"| 新手帮助     |",
			"| 退出游戏(s↓)|"
			
			
	};
	public static final String OVER_STR0="【ESC】退出游戏";
	public static final String OVER_STR1="【Ent】退回菜单";
	
	public static final Font FONT=new Font("黑体",Font.BOLD,25);//字体
	//======================刷新==============================
	public static final int REPAINT_INTERVAL=15;
	//======================敌人数量==========================
	public static final int ENEMY_MAX_COUNT=20;
	//======================敌人刷新时间(4秒)================
	public static final int ENEMY_BORN_TIME=4000;
	//======================敌人获得状态(1秒)================
	public static final int ENEMY_AI_TIME=1000;
	//======================敌人判断发射子弹(0.04%)==========
	public static final double ENEMY_FIRE_PERCENT=0.04;
	
	
}

package owo.util;

import java.util.ArrayList;
import java.util.List;

import owo.plane.AirCraft;
import owo.plane.EnemyPlane;

/*
 * 敌人池
 */

public class EnemyPlanePool {
	public static final int DEFAULT_POOL_SIZE=20;
	public static final int POOL_MAX_SIZE=20;
	private static List<AirCraft> pool=new ArrayList<>();//保存所有敌人的容器
	
	static/*创建敌人对象,添加*/{
		for(int i=0;i <DEFAULT_POOL_SIZE;i++) {
			pool.add(new EnemyPlane());
		}
	}
	
	public static AirCraft get()/*池中获得敌人*/ {
		AirCraft aircraft=null;
		if(pool.size()==0) /*池,空了*/{
			aircraft =new EnemyPlane();//那就创建一个
		}else				 /*池,还有,拿第一个位置的敌人*/{
			aircraft =pool.remove(0);
		}
		return aircraft;
	}
	public static void tRrturn(AirCraft aircraft) /*敌人消失时,还到池中*/{
		if(pool.size()==POOL_MAX_SIZE) /*池中敌人到max,不再归还*/{
			return;
		}
		pool.add(aircraft);
	}
}
package owo.util;

import java.util.ArrayList;

/*
 * 爆炸池
 */
import java.util.List;

import owo.game.Explode;

public class ExplodesPool {

	public static final int DEFAULT_POOL_SIZE=15;
	public static final int POOL_MAX_SIZE=20;
	//保存所有爆炸的容器7
	private static List<Explode> pool=new ArrayList<>();
	
	static/*创建BOMM对象,添加*/{
		for(int i=0;i <DEFAULT_POOL_SIZE;i++) {
			pool.add(new Explode());
		}
	}
	
	public static Explode get()/*池中获得爆炸*/ {
		Explode explode=null;
		if(pool.size()==0) /*池,空了*/{
			explode =new Explode();//那就创建一个
		}else				 /*池里还有,拿第一个位置的爆炸*/{
			explode =pool.remove(0);
		}
		return explode;
	}
	public static void tRrturn(Explode explode) /*爆炸消失时,还到池中*/{
		if(pool.size()==POOL_MAX_SIZE) /*池中爆炸到max,不再归还*/{
			return;
		}
		pool.add(explode);
	}
}

package owo.util;

public class MyUtil /*随机数*/{
	public static final int getRandomNu(int min,int max) {
		return (int)(Math.random()*(max-min)+min);
	}
	//碰撞
	//判断点是否在方形内部
	//rext方形中点XY坐标
	//radius边长的一半
	//point点的XY坐标
	//return,点在方形内部,返回true,else→false
	public static final boolean isCollide(int rectX,int rectY,int radius,int pointX,int pointY){
		//正方形中心点与XY轴的距离 
		int disX=Math.abs(rectX-pointX);
		int disY=Math.abs(rectY-pointY);
		if(disX<radius && disY<radius)
			return true;
		return false;
	}
	
	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值