java学习第51天,shootgame

1、效果


2、游戏类

package com.sukla.shoot;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**游戏主界面*/
public class ShootGame extends JPanel{
	
	public static final int WIDTH=400;		//宽
	public static final int HEIGHT=654;		//高
	
	public static BufferedImage background;
	public static BufferedImage start;
	public static BufferedImage gameover;
	public static BufferedImage pause;		//暂停
	public static BufferedImage airplane;
	public static BufferedImage bee;
	public static BufferedImage bullet;
	public static BufferedImage hero0;
	public static BufferedImage hero1;
	
	public Hero hreo=new Hero();			//英雄机器
	public Bullet[] bullets={};				//子弹数组
	public FlyingObject[] flyings={};			//敌机和小蜜蜂
	
	//总得分
	private int score=0;
	//状态
	private int state;						//状态
	public static final int START=0;
	public static final int RUNNING=1;
	public static final int PAUSE=2;
	public static final int GAME_OVER=3;
	
	static{									//加载图片资源
		try {
			background=ImageIO.read(ShootGame.class.getResource("background.png"));
			start=ImageIO.read(ShootGame.class.getResource("start.png"));
			gameover=ImageIO.read(ShootGame.class.getResource("pause.png"));
			pause=ImageIO.read(ShootGame.class.getResource("pause.png"));
			airplane=ImageIO.read(ShootGame.class.getResource("airplane.png"));
			bee=ImageIO.read(ShootGame.class.getResource("bee.png"));
			bullet=ImageIO.read(ShootGame.class.getResource("bullet.png"));
			hero0=ImageIO.read(ShootGame.class.getResource("hero0.png"));
			hero1=ImageIO.read(ShootGame.class.getResource("hero1.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//background成员 所在CLASS的名字ShootGame
	}
	
	//重写绘制方法
	public void paint(Graphics g){//g为画笔
			g.drawImage(background,0,0,null);//画图片
			paintHero(g);					//画英雄机
			paintBullet(g);					//画子弹
			paintFlyingObjects(g);			//画敌人
			paintScore(g);					//画分数画命
			paintState(g);					//画状态
		};
		
	public void paintState(Graphics g){
		switch(state){
		case START:
			g.drawImage(start, 0, 0, null);
			break;
		case PAUSE:
			g.drawImage(pause, 0, 0, null);
			break;
		case GAME_OVER:
			g.drawImage(gameover, 0, 0, null);
			break;
		}
	}	
		
	public void paintScore(Graphics g){
		g.setColor(new Color(0x22bd7a));	//设置文字颜色
		g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,25));				//设置字体
		g.drawString("score:"+score, 20, 35);
		g.drawString("LIVE:"+hreo.getLive(), 20, 65);
	}
		//画英雄机
	public void paintHero(Graphics g){
			g.drawImage(hreo.image, hreo.x, hreo.y, null);
		};
		//画子弹
	public void paintBullet(Graphics g){ 
			for(int i=0;i<bullets.length;i++){
				Bullet b=bullets[i];
				g.drawImage(b.image, b.x, b.y, null);
			};
	};
		//画敌人
	public void paintFlyingObjects(Graphics g){
			for(int i=0;i<flyings.length;i++){
				FlyingObject o=flyings[i];
				g.drawImage(o.image, o.x, o.y, null);
			};
		};
	
	public static void main(String[] args) {

		// TODO Auto-generated method stub
		JFrame frame=new JFrame("飞机大战");		//画框+标题
		ShootGame game=new ShootGame();
		frame.add(game);					//将JPanel 放到 JFrame上
		
		frame.setSize(WIDTH, HEIGHT);
		frame.setAlwaysOnTop(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	//默认关闭
		frame.setLocationRelativeTo(null);	//初始位置
		
		frame.setVisible(true);				//显示尽快调用paint画图 绘制一次
		
		game.action();						//启动执行操作
		
	}

	private Timer timer;				//定时器
	private int interval=10;			//定时时间间隔ms
	
	/**启动执行操作*/
	public void action(){
		//鼠标事件
		//swing里面的鼠标事件适配器 MouseAdapter这个适配器用空实现实现了好几个方法 我们只需要重写想要的方法即可
		MouseAdapter l=new MouseAdapter(){
			/**重写鼠标移动事件*/
			public void mouseMoved(MouseEvent e){//重写mouseMoved
				if(state==RUNNING){
					int x=e.getX();			//鼠标的x
					int y=e.getY();			//鼠标的y
					hreo.moveTo(x, y);		//英雄机移动
				}
			}
			/**重写鼠标点击事件*/
			public void mouseClicked(MouseEvent e){
				switch(state){
				case START:
					state=RUNNING;
					break;
				case GAME_OVER:
					hreo=new Hero();
					flyings=new FlyingObject[0];
					bullets=new Bullet[0];
					state=START;
					break;
				}
			}
			/**重写鼠标移出事件*/
			public void mouseExited(MouseEvent e){
				if(state!=GAME_OVER){
					state=PAUSE;
				}
			}
			/**重写鼠标移入事件*/
			public void mouseEntered(MouseEvent e){
				if(state==PAUSE){
					state=RUNNING;
				}
			}
		};
		//给当前面板添加鼠标操作的监听事件
		this.addMouseListener(l);
		//给当前面板ipanel加一个鼠标滑动监听事件
		this.addMouseMotionListener(l);
		
		timer=new Timer();
		timer.schedule(new TimerTask(){	//匿名内部类的对象
			@Override
			public void run() {			//重写run方法
				if(state==RUNNING){
					//飞行物入场 
					enterAction();
					//飞行物走步
					stepAction();
					//飞机发射子弹 子弹入场
					shootAction();
					//判断子弹是否命中敌机并处理
					bangAction(); 
					//删除越界飞行物
					outOfBoundsAction();
					//判断是否游戏结束
					checkGameOverAction();
				}
				//重绘 调用paint方法
				repaint();
			}
		}, interval,interval);			//定时触发
	}
	
	/**检查游戏是否结束*/
	public void checkGameOverAction(){
		if(isGameOver()){//判断是否结束
			state=GAME_OVER;
		}
	}
	/**判断游戏是否结束*/
	public boolean isGameOver(){
		
		for(int i=0;i<flyings.length;i++){
			int index=-1;				//撞击上的飞行物的索引
			FlyingObject obj=flyings[i];	//每个飞行物
			if(hreo.hit(obj)){
				hreo.substarctLife();	//减少,命
				hreo.setDoubleFire(0);	//减少火力
				index=i;
			}
			if(index!=-1){
				FlyingObject t=flyings[index];						//删除撞击的飞行物
				flyings[index]=flyings[flyings.length-1];
				flyings[flyings.length-1]=t;
				flyings=Arrays.copyOf(flyings, flyings.length-1);
			}
		}
		return hreo.getLive()<=0;									//返回是否有命
	}
	
	/**删除越界飞行物*/
	public void outOfBoundsAction(){
		/**删除所有越界敌人和蜜蜂*/
		int index=0;					//下标
		FlyingObject[] flyingLives=new FlyingObject[flyings.length]; //声明一个长度一样的数组
		for(int i=0;i<flyings.length;i++){
			FlyingObject f=flyings[i];
			if(!f.outOfBounds()){
				flyingLives[index++]=f;
			}
		}
		flyings=Arrays.copyOf(flyingLives, index);
		
		/**删除所有越界子弹*/
		index=0;
		Bullet[] bulletLives=new Bullet[bullets.length];
		for(int i=0;i<bullets.length;i++){
			Bullet b=bullets[i];
			if(!b.outOfBounds()){
				bulletLives[index++]=b;
			}
		}
		bullets=Arrays.copyOf(bulletLives, index);
	}
	
	/**子弹是否击中敌机的处理*/
	public void bangAction(){
		for(int i=0;i<bullets.length;i++){		//所有子弹
			Bullet b=bullets[i];
			bang(b);							//子弹和飞行物碰撞
		}
	}
	
	
	/**子弹打敌人*/
	public void bang(Bullet b){
		int index=-1;
		for(int i=0;i<flyings.length;i++){
			FlyingObject obj=flyings[i];
			if(obj.shootBy(b)){
				index=i;						//被击中的飞机的下标
				break;
			}
		}
		if(index!=-1){
			FlyingObject one=flyings[index];	
			if(one instanceof Enemy){			//判断是不是敌机是的话就加分 多态的应用
				score+=((Enemy)one).getScore();	//强转为敌机类型来使用敌机类型特有的方法
			}else if(one instanceof Award){		//判断是小蜜蜂这种奖励类型
				Award a=(Award)one;
				int type=a.getType();			//获取奖励类型
				switch(type){
				case Award.DOUBLE_FIRE:			//判断奖励类型
				hreo.addBoubleFire();			//颁发奖励
				break;
				case Award.LIFE:
					hreo.addLife();
					break;
				}
			}
			//获取奖励之后删除被击中的目标
			//交换位置 然后缩容
			FlyingObject t=flyings[index];
			flyings[index]=flyings[flyings.length-1];
			flyings[flyings.length-1]=t;
			flyings=Arrays.copyOf(flyings, flyings.length-1);
		}
	}
	int shootIndex=0;					//控制射击频率
	/**发射子弹*/
	//子弹入场
	public void shootAction(){
		shootIndex++;
		if(shootIndex%10==0){			//300ms发射一次
			Bullet[] bs=hreo.shoot();	//英雄机发射子弹
			bullets=Arrays.copyOf(bullets, bullets.length+bs.length);				//数组的扩容
			System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);	//数组的追加 a数组从b位置开始复制到c数组的d位置开始复制e个元素
		}
	}
	
	int flyingEnterdIndex=0;		//飞行物入场计数
	/**飞行物入场*/
	public void enterAction(){
		flyingEnterdIndex++;
		if(flyingEnterdIndex%40==0){
			FlyingObject obj=nextone();
			flyings=Arrays.copyOf(flyings, flyings.length+1);	//数组扩容
			flyings[flyings.length-1]=obj;						//将敌人装到数组中	
		}
	}
	
	/**随机生成?和✈*/
	//工厂方法:生产对象,一般为static的
	public static FlyingObject nextone(){
		Random rand =new Random();
		int type=rand.nextInt(20);	//[0,19)
		if(type==0){
			return new Bee();
		}else{
			return new Airplane();
		}
	}
	/**飞行物走步*/
	public void stepAction(){
		//敌人(敌机和小蜜蜂)走一步
		for(int i=0;i<flyings.length;i++){
			flyings[i].step();
		}
		//子弹走一步
		for(int i=0;i<bullets.length;i++){
			bullets[i].step();
		}
		//hero
		hreo.step();
	}
	
}














2、可获取奖励的接口

package com.sukla.shoot;
/**奖励*/
public interface Award {
int DOUBLE_FIRE=0; //双倍火力
int LIFE=1;        //一条命
int getType();     //获取奖励类型
}


3、可获取分数的接口

package com.sukla.shoot;
/**
 * 敌机都可以得分
 * 得分
 * */
public interface Enemy {
int getScore();
}


4、飞行物类

package com.sukla.shoot;
import java.awt.image.BufferedImage;
/**
 * 飞行物类
 * created by sukla.
 * 成员变量设置为私有
 * 方法设置为公有
 * 不建议使用默认访问修饰
 * 
 * */
public abstract class FlyingObject {
protected int width;        //宽
protected int height;       //高
protected int x;            //X坐标
protected int y;            //Y坐标
protected BufferedImage image; //图片 

							
public abstract void step();   //走步

/**敌人是否被子弹击中*/
public boolean shootBy(Bullet b){
	int x=b.x;				//子弹的x
	int y=b.y;				//子弹的y
	return x>this.x&&x<this.x+this.width
			&&
			y>this.y&&y<this.y+this.height;
};

/**检测是否超出游戏面板界限*/
public abstract boolean outOfBounds();

}


5、第一类敌机、继承飞行物类、实现获取分数接口

package com.sukla.shoot;

import java.util.Random;

/**敌机:是飞行物,也是敌人*/
public class Airplane extends FlyingObject implements Enemy {
	private int speed=2;        //每次移动2步
	
	/**初始化实例变量*/
	public Airplane(){
		image=ShootGame.airplane;
		width=image.getWidth();
		height=image.getHeight();
		Random rand=new Random();
		x=rand.nextInt(ShootGame.WIDTH-width);
		y=-height;
	};
	
	public int getScore(){
		return 10;
	};
	
	public void step(){
		y+=speed;
	};
	
	/**重写检测是否越界*/
	public boolean outOfBounds(){
		return y>y+ShootGame.HEIGHT;
	}
}


6、第一类奖励飞行物,继承飞行物、实现获取奖励接口

package com.sukla.shoot;

import java.util.Random;

/**小蜜蜂:飞行物+奖励*/
public class Bee extends FlyingObject implements Award{
	private int xSpeed=1; //横向移动
	private int ySpeed=2; //纵向移动
	private int awardType;//奖励的类型
	
	/**初始化实例变量*/
	public Bee(){
    	image=ShootGame.bee;
    	width=image.getTileWidth();
    	height=image.getHeight();
    	y=-height;
    	Random rand=new Random();
    	x=rand.nextInt(ShootGame.WIDTH-width);
    	awardType=rand.nextInt(2);
    };
	/**获取奖励类型*/
    public int getType(){
    	return awardType;
    };
    
    //走步
    public void step(){
    	if(x<0){
    		xSpeed=1;
    	};
    	if(x>ShootGame.WIDTH-width){
    		xSpeed=-1;
    	}
    	x+=xSpeed;
    	y+=ySpeed;
    };
    
    /**重写检测越界*/
    public boolean outOfBounds(){
    	return y>height+ShootGame.HEIGHT;
    };
    
    
}


7、子弹类、继承飞行物类

package com.sukla.shoot;
/**子弹:飞行物*/
public class Bullet extends FlyingObject {
	private int speed=30;
	
	/**初始化成员变量*/
	public Bullet(int x,int y){
		image=ShootGame.bullet;
		width=image.getWidth();
		height=image.getHeight();
		this.x=x;
		this.y=y;
	};
	
	//走步
	public void step(){
		y-=speed;
	}
	
	/**重写检测是否越界*/
	public boolean outOfBounds(){
		return y<-y;
	}
}


8、玩家操纵的战斗机、继承飞行物类

package com.sukla.shoot;
import java.awt.image.BufferedImage;
/**英雄机:飞行物*/
public class Hero extends FlyingObject {
	private BufferedImage[] images={};
	private int index;			//图片交换计数
	private int doubleFire;		//双倍火力
	private int life;			//命
	public Hero (){
		image=ShootGame.hero0;
		width=image.getWidth();
		height=image.getHeight();
		x=180;
		y=550;
		doubleFire=0;
		life=3;
		images=new BufferedImage[]{ShootGame.hero0,ShootGame.hero1};
	}
	public int getLive(){
		return life;
	}
	//走步
	public void step(){
	int num=index++/10%images.length;
		image=images[num];	
	}
	//发射子弹
	public Bullet[] shoot(){
		int xStep=this.width/4;
		int yStep=20;
		if(doubleFire>0){
			Bullet[] bullets=new Bullet[2];
			bullets[0]=new Bullet(this.x-xStep*5,this.y-yStep);
			bullets[1]=new Bullet(this.x+xStep*5,this.y-yStep);
			return bullets;
		}else{
			Bullet[] bullets=new Bullet[1];
			bullets[0]=new Bullet(this.x,this.y-yStep);
			return bullets;
		}
	}
	/**移动 x:鼠标的x y:鼠标的y*/
	public void moveTo(int x,int y){
		this.x=x-this.width/2;
		this.y=y-this.height/2;
	}
	
	//添加双倍火力
	public void addBoubleFire(){
		doubleFire+=40;
	}
	
	//添加命
	public void addLife(){
		life++;
	}
	
	/**重写检测是否越界*/
	public boolean outOfBounds(){
		return false;
	}
	
	/**碰撞算法*/
	public boolean hit(FlyingObject other){
		return !(
				(other.x+other.width<this.x)
				||(other.x>this.x+this.width)
				||(other.y+other.height<this.y)
				||(other.y>this.y+this.height)
				);
	}
	
	/**碰撞后的动作*/
	public void substarctLife(){
		life--;
	}
	
	/**设置火力*/
	public void setDoubleFire(int doubleFire){
		this.doubleFire=doubleFire;
	}
	
	
	
}


猜你喜欢

转载自blog.csdn.net/sukla/article/details/80102469