飞机大战-java基础小程序(初学项目)08

Shoot射击游戏第八天:
1.英雄机随着鼠标移动:
  1)英雄机随着鼠标动为英雄机的行为,所以在Hero中设计moveTo()实现英雄机随着鼠标移动
  2)英雄机随着鼠标动为事件触发的,所以在侦听器中重写mouseMoved()鼠标移动事件
    在mouseMoved()中:
      获取鼠标的x/y坐标,英雄机随着动

(事件、侦听器都是swing相关的内容-------不要求掌握

1)事件:发生了一件事
2)事件处理:发生事之后所做的操作
3)侦听器:
  3.1)有一个侦听器对象
  3.2)把侦听器装到你家去)

2.删除越界的敌人和子弹:
  1)在FlyingObject中设计isOutOfBounds()判断敌人是否越界
    在Bullet中重写isOutOfBounds()判断子弹是否越界
  2)删除越界的敌人和子弹为定时发生的,所以在run中调用outOfBoundsAction()实现删除越界的敌人和子弹
    在outOfBoundsAction()中:
      遍历敌人/子弹数组,判断若越界了:
        用最后一个敌人/子弹将越界敌人/子弹替换掉,缩容
3.设计EnemyScore得分接口,Airplane和BigAirplane实现接口
  设计EnemyAward奖励接口,Bee实现接口

(删除越界的敌人和子弹:


现在的程序运行时间比较长的时候,会特别卡
----原因是: 对象太多了


1秒钟-------2个敌人+3个子弹----共5个
1分钟-------共300个
10分钟------共3000个


10毫秒------遍历30+30-----共60个
1秒钟-------共6000
1分钟-------共360000

10毫秒------遍历3000+3000-----共6000个
1秒钟-------共600000
1分钟-------共36000000)

(  事件                 事件处理
鼠标点击         启动状态变为运行状态
鼠标移动         英雄机随着动
鼠标移出         运行状态变为暂停状态
鼠标移入         暂停状态变为运行状态

窗口的状态:
1)启动状态-------------车点着火了,还没有走
2)运行状态-------------车在走着
3)暂停状态-------------碰到红灯,车暂时不走了
4)游戏结束状态---------车熄火了
)

我们昨天看到的飞机飞出了窗口但是并没有在内存中删除,所以我们用数组来删除掉越界的敌人来保证内存的不卡

3.子弹与敌人的碰撞:

1)在FlyingObject中设计isHit()检测碰撞、goDead()飞行物去死 在Hero中设计addLife()增命、addFire()增火力

2)子弹与敌人的碰撞为定时发生的,所以在run中调用bulletBangAction()实现子弹与敌人的碰撞 在bulletBangAction()中: 遍历子弹得子弹,遍历敌人得敌人,判断若都活着并且撞上了: 子弹去死、敌人去死 若被撞敌人能得分,则强转为得分接口, ----玩家增分 若被撞敌人为奖励,则强转为奖励接口, ----获取奖励类型,依据不同的类型来获取不同的奖励

4.画分和画命:

1)在Hero中设计getLife()获取命

2)在World的paint()中: 画分、画命

 

 

5.对象的多态:-----被撞的敌人就是多态的

1)作为FlyingObject形态,则能做FlyingObject里面的事

2)作为EnemyScore形态,则能做EnemyScore里面的事

 

6.为何要强转:

1)若你想访问的东西(getScore())在超类中没有时,就必须强转

2)若你想访问的东西(isLife()、goDead()..)在超类中就有,则不用强转

7.强转之前为何要判断:----不判断有可能会发生类型转换异常

int score = 0; //玩家得分
public void bulletBangAction() { //每10毫秒走一次
  for(int i=0;i<bullets.length;i++) { //遍历所有子弹
    Bullet b = bullets[i]; //获取每一个子弹
    for(int j=0;j<enemies.length;j++) { //遍历所有敌人
      FlyingObject f = enemies[j]; //获取每一个敌人
      if(b.isLife() && f.isLife() && f.isHit(b)) { //若都活着,并且还撞上了
    b.goDead(); //子弹去死
    f.goDead(); //敌人去死

 

 

知识点:

接口:
  1)是一种数据类型(引用数据类型)
  2)由interface定义
  3)只能包含常量和抽象方法
  4)接口不能被实例化
  5)接口是需在被实现/继承的,实现类/派生类:
      必须重写所有抽象方法
  6)一个类可以实现多个接口,用逗号分隔
    若又继承又实现时,应先继承后实现
  7)接口可以继承接口

接口的好处:-----代码复用 2.行为的多态:-----getScore()、getAwardType()都是多态的

1)小敌机、大敌机、大黄蜂getScore()执行的结果不同

2)小蜜蜂、大黄蜂getAwardType()执行的结果不同

多态:

1)意义:

1.1)同一类型的引用指向不同的对象时,有不同的实现 ----行为的多态:cut()、step()、getImage()...

1.2)同一个对象被造型为不同的类型时,有不同的功能 ----对象的多态:我、你、水

2)向上造型/自动类型转换:

2.1)超类型的引用指向派生类的对象

2.2)能造型成为的数据类型: 超类+所实现的接口

2.3)能点出来什么,看引用的类型

3)强制类型转换,成功的条件只有如下两种情况:

3.1)引用所指向的对象,就是该类型

3.2)引用所指向的对象,实现了该接口或继承了该类

4)强转时若不符合如上条件,则发生ClassCastException类型转换异常 建议:在强转之前先通过instanceof来判断引用指向的对象是否是该类型

 

设计规则:
1.将所有派生类所共有的属性和行为,抽到超类中-------抽共性
2.所有派生类的行为都一样,设计为普通方法
  所有派生类的行为都不一样,设计为抽象方法
3.将部分派生类所共有的属性和行为,抽到接口中
  接口是对继承的单根性的扩展---------实现多继承
我们上次讲到儿子类只能有一个爸爸类,所以我们要实现继承就要用到了接口(相当于后爸)

 

 

我们先建接口

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

我们这个不是class别看错了是Interface

 

 

 

 

 

 

 

代码:

package cn.tude;

public interface EnemyAward {
	public int FIRE =0;
	public int LIFE =1;
	public int getAwardType();
	
}

 

package cn.tude;

public interface EnemyScore {
	public int getScore();
}
package cn.tude;

import java.awt.image.BufferedImage;
import java.util.Random;

public class Airplane extends FlyingObject {
	private int speed;

	public Airplane() {
		super(48, 50);
		speed = 2;
	}

	public void step() {
		y+=speed;
	}

	private int index = 1;

	public BufferedImage getImage() {
		if (isLife()) {
			return Images.airs[0];
		} else if (isDead()) {
			BufferedImage img = Images.airs[index++];
			if (index == Images.airs.length) {
				state = REMOVE;

			}
			return img;

		}
		return null;

	}

	

	
	

}
package cn.tude;

import java.util.Random;
import java.awt.image.BufferedImage;
public class Bee extends FlyingObject{
	
	private int xspeed;//x移动速度
	private int yspeed;//y移动速度
	private int awardType;//奖励类型
	public Bee(){
		super(20,50);
		
		Random rand=new Random();
		
		
		xspeed=1;
		yspeed=2;
		awardType=rand.nextInt(2);
	}
	public void step(){
		x+=xspeed;
		y+=yspeed;
		if(x<=0||x>=World.WIDTH-width){
			xspeed*=-1;
		}
		
	}
	private int index=1;
	public BufferedImage getImage(){
		if(isLife()){
			return Images.bees[0];
		}else if (isDead()){
			BufferedImage img=Images.bees[index++];
			if(index==Images.bees.length){
				state=REMOVE;
			}
			return img;
		}
		return null;
	}
	}
package cn.tude;


import java.awt.image.BufferedImage;
public class BigAirplane extends FlyingObject {

	private int speed;// 移动速度

	public BigAirplane() {
		super(66, 89);

		speed = 2;
	}

	public void step() {
		y += speed;
	}
	private int index=1;
	public BufferedImage getImage(){
		if (isLife()){
			return Images.bairs[0];
		}else if (isDead()){
			BufferedImage img =Images.bairs[index++];
			if(index==Images.bairs.length){
				state=REMOVE;
			}
			return img;
		}
		return null;
	}

}
package cn.tude;

import java.awt.image.BufferedImage;
public class Bullet  extends FlyingObject{
	//子弹

	private int speed;//移动速度
	public Bullet(int x,int y){
		super(8,20,x,y);
		
		
		speed=3;
		
	}
	public void step(){
		y-=speed;
	}
	public BufferedImage getImage(){
		if (isLife()){
			return Images.bullet;
			
		}else if (isDead()){
			state=REMOVE;
		}
		return null;
	}
	public boolean isOutOfBounds() {
		return y<=-height;
	}
}
package cn.tude;

import java.util.Random;


import java.awt.image.BufferedImage;

public abstract class FlyingObject {
	public static final int LIFE=0;
	public static final int DEAD=1;
	public static final int REMOVE=2;
	protected int state =LIFE;
	
	
	
	protected int x;
	protected int y;
	protected int width;
	protected int height;
	public FlyingObject(int width,int height ){
		Random rand =new Random();
	//	width=rand.nextInt(400-width);
		x = rand.nextInt(World.WIDTH - width);
		y =-height;
		this.width=width;
		this.height=height;
	}
	public FlyingObject(int width,int height ,int x,int y){
		this.height=height;
		this.width=width;
		this.x=x;
		this.y=y;
		
	}
	public abstract void step();
	public abstract BufferedImage getImage();
	public boolean isLife(){
		return state==LIFE;
		
	}
	public boolean isDead(){
		return state==DEAD;
	}
		public boolean isRemove(){
			return state==REMOVE;
		}
	public boolean isOutOfBounds(){
		return y>=World.HEIGHT;
	}
public boolean isHit(FlyingObject other){
	int x1=this.x-other.width;
	int x2=this.x+this.width;
	int y1=this.y-other.height;
	int y2=this.y+this.height;
	int x=other.x;
	int y=other.y;
	return x>x1 && x<=x2 &&y>=y1 && y<=y2;
			
}public void goDead(){
	state=DEAD;
}
}
package cn.tude;

import java.awt.image.BufferedImage;

public class Hero extends FlyingObject {
	// int width;
	// int height;
	// int x;
	// int y;
	private int life;
	private int fire;

	public Hero() {
		super(97, 139, 140, 400);

		life = 3;
		fire = 0;
	}

	// 移动
	// void step(){//步
	// System.out.println("英雄机切换图片了");
	// }
	public void step() {
	}

	private int index = 0;

	public BufferedImage getImage() {

		return Images.heros[index++ % Images.heros.length];
	}

	public void moveTo(int x,int y){
		this.x=x-this.width/2;
		this.y=y-this.height/2;
		
	}
	public Bullet[] shoot(){
		int xspeed =this.width/4;
		int yspeed=20;
	if(fire>0){
	Bullet[] bs=new Bullet[2];
	bs[0]=new Bullet(this.x+1*xspeed,this.y-yspeed);
	bs[1]=new Bullet(this.x+3*xspeed,this.y-yspeed);
	fire -=2;
	return bs;
	}else  {
	Bullet[] bs=new Bullet[1];
	bs[0]=new Bullet(this.x+2*xspeed-5,this.y-yspeed);
	return bs;
}
}

}
package cn.tude;

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

public class Images {

	public static BufferedImage sky;
	public static BufferedImage bullet;
	public static BufferedImage[] heros;
	public static BufferedImage[] airs;
	public static BufferedImage[] bairs;
	public static BufferedImage[] bees;

	static {
		sky =readImage("background.png");
		bullet=readImage("bullet.png");
		heros=new BufferedImage[2];
		
		heros[0]=readImage("hero0.png");
		heros[1]=readImage("hero1.png");
		airs=new BufferedImage[5];
		bairs=new BufferedImage[5];
		bees=new BufferedImage[5];
		airs[0]=readImage("airplane.png");
		bairs[0]=readImage("bigairplane.png");
		bees[0]=readImage("bee.png");
		for (int i=1;i<airs.length;i++){
			airs[i]=readImage("bom"+i+".png");
			bairs[i]=readImage("bom"+i+".png");
			bees[i]=readImage("bom"+i+".png");
		}
	
		
		
		
		
	}

	public static BufferedImage readImage(String fileName) {
		try {
			BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));
			return img;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
}
package cn.tude;
import java.awt.image.BufferedImage;

public class Sky extends FlyingObject{
	
	private int speed;//移动速度
	private int y1;//第2张图的y坐标
	/**构造方法*/
	public Sky(){
		super(World.WIDTH,World.HEIGHT,0,0);
		
		speed=1;
		y1=-World.HEIGHT;
		
	//	System.out.println(y+","+y1);
		//测试代码
		
	}
	
		
	public void step(){
		y+=speed;
		y1+=speed;
		if(y>=World.HEIGHT){
			y=-World.HEIGHT;
		}
		if(y1>=World.HEIGHT){
			y1=-World.HEIGHT;
		}
	}
	public BufferedImage getImage(){
		return Images.sky;
		
	}public int getY1(){
		return y1;
	}
	

}
package cn.tude;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.omg.Messaging.SyncScopeHelper;


import java.awt.image.BufferedImage;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.TimerTask;
import java.util.Timer;
import java.util.Random;
import java.util.Arrays;

public class World extends JPanel {
	public static final int WIDTH = 400;
	public static final int HEIGHT = 700;

	private Hero hero = new Hero();
	private Sky sky = new Sky();
	private FlyingObject[] enemies = {};// 0
	private Bullet[] bullets = {};

	public FlyingObject nextOne() {
		Random rand = new Random();
		int type = rand.nextInt(20);
		if (type < 5) {
			return new Bee();
		} else if (type < 14) {
			return new Airplane();
      
		} else {
			return new BigAirplane();
		}

	}

	
	private int enterIndex=0;
	public void enterAction(){
		enterIndex++;
		if(enterIndex%40==0){
			FlyingObject obj =nextOne();
			enemies=Arrays.copyOf(enemies,enemies.length+1);
			enemies[enemies.length-1]=obj;
 			
		}
		
	}
	private int shootIndex=0;
	public void shootAction(){
		
		shootIndex++;
		if(shootIndex%30==0){
			Bullet[] bs=hero.shoot();
			bullets=Arrays.copyOf(bullets,bullets.length+bs.length);
		System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length);
		//System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length);
			//bullets=Arrays.copyOf(bullets,bullets.length+bs.length);
			
		}
		
	}
	public void stepAction(){
		sky.step();

		for(int i=0;i<enemies.length;i++){
			enemies[i].step();
			
		}	for(int i=0;i<bullets.length;i++){
			bullets[i].step();
			
		}
		
	}
	public void outOfBoundsAction(){
		for(int i=0;i<enemies.length;i++){
			if(enemies[i].isOutOfBounds()){
				enemies[i]=enemies[enemies.length-1];
				enemies=Arrays.copyOf(enemies, enemies.length-1);
			}
			for(int d=0;d<bullets.length;d++){
				
				if(bullets[d].isOutOfBounds()){
					bullets[d]=bullets[bullets.length-1];
					bullets=Arrays.copyOf(bullets, bullets.length-1);
				}
			}
		}
	}
	
	
	public  void bulletBangAction(){
		for(int i=0;i<bullets.length;i++){
			Bullet b=bullets[i];
			for(int j=0;j<enemies.length;j++){
				FlyingObject p=enemies[j];
				if(b.isLife()&&p.isLife()&&p.isHit(b)){
					b.goDead();
					p.goDead();
					
				}
			}
		}
	}
		public void action() {
		MouseAdapter m=new MouseAdapter(){
			public void mouseMoved(MouseEvent e){
				int x=e.getX();//获取鼠标x坐标
				int y=e.getY();
				hero.moveTo(x, y);
				
			}
		};
		
		
		this.addMouseListener(m);//处理鼠标操作事件
		this.addMouseMotionListener(m);//处理鼠标滑动事件
		
		
	
		
		
		Timer timer = new Timer();
		int intervel = 10;// 定时间隔等于(10毫秒走一次)

		timer.schedule(new TimerTask() {
			public void run() {// 定时干的事
				bulletBangAction();
				enterAction();
				shootAction();
				outOfBoundsAction();
				System.out.println(enemies.length+","+bullets.length);
                //我们用这句话来输出敌人和子弹的内存情况
				stepAction();
				repaint();
			}
		}, intervel, intervel);
	
		BufferedImage img = Images.sky;
	}
	
	public void paint(Graphics g) {
		g.drawImage(sky.getImage(), sky.x, sky.y, null);
		g.drawImage(sky.getImage(), sky.x, sky.getY1(), null);	
		g.drawImage(hero.getImage(),hero.x,hero.y,null);
		for(int i=0;i<enemies.length;i++){
			FlyingObject f= enemies[i];
			g.drawImage(f.getImage(), f.x,f.y,null);
		}for(int i=0;i<bullets.length;i++){
			Bullet b=bullets[i];
			g.drawImage(b.getImage(),b.x,b.y,null);
		}
		
	}

	public static void main(String[] args) {

		JFrame frame = new JFrame();
		World world = new World();
		frame.add(world);

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(WIDTH, HEIGHT);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		world.action();

	}

}

 

测试结果:

 

https://download.csdn.net/download/Theshy08/12740617

 

 

public abstract class FlyingObject { public static final int LIFE = 0; //活着呢 public static final int DEAD = 1; //死了的(先爆破) public static final int REMOVE = 2; //删除了(爆破后删除) protected int state = LIFE; //当前状态(默认活着) protected int width; //宽 protected int height; //高 protected int x; //x坐标 protected int y; //y坐标 /** 无参构造方法 */ public FlyingObject(){ } /**专门给小敌机、大敌机、小蜜蜂提供的构造方法 */ public FlyingObject(int width,int height){ this.width = width; this.height = height; Random rand = new Random(); x = rand.nextInt(World.WIDTH-width); //x:0到(窗口-小敌机的宽)之间的随机数 y = -height; //y:负的小敌机的高 } /** 专门给英雄机、子弹、天空提供的构造方法 */ public FlyingObject(int width,int height,int x,int y){ this.width = width; this.height = height; this.x = x; this.y = y; } /** 读取图片 */ public static BufferedImage loadImage(String fileName){ try{ BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); return img; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(); } } /** 飞行物移动了 */ public abstract void step(); public abstract BufferedImage getImage(); /** 判断是否活着 */ public boolean isLife(){ return state==LIFE; } /** 判断是否死了的 */ public boolean isDead(){ return state==DEAD; } /** 判断是否删除的 */ public boolean isRemove(){ return state==REMOVE; } /** 画对象 g:画笔 */ public void paintObject(Graphics g){ g.drawImage(getImage(), x, y, null); } /** 检测飞行物是否越界 */ public abstract boolean outOfBounds(); /** 敌人与子弹/英雄机的碰撞 this:敌人 other:子弹或英雄机 */ public boolean hit(FlyingObject other){ int x1 = this.x-other.width; //x1:敌人的x int x2 = this.x+this.width; //x2:敌人的x int y1 = this.y-other.height; //y1:敌人的y int y2 = this.y+this.height; //y2:敌人的y int x = other.x; //x:子弹的x int y = other.y; //y:子弹的y return x>=x1 && x=y1 && y<=y2; } public void goDead(){ state = DEAD; //修改当前状态为死了的 } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值