day07
功能实现的步骤:
1.先写行为:
1)若是某个对象特有的行为,则将设计在派生类中
若是所有对象共有的行为,则将设计在超类中
1.1)所有派生类行为都一样,设计为普通方法
1.2)所有派生类行为都不一样,设计为抽象方法,而后派生类重写
2.窗口调用:
1)定时触发的,在run()中调用
2)事件触发的,在监听器中调用
3)画出来的,在paint()中调用
项目功能:
1.敌人入场 ---------- 定时发生
1)创建敌人对象
敌人对象 --------------- 是由窗口创建出来的
---创建敌人对象的行为 ----设计在窗口类World中设计nextOne()
/** 成员方法:生成敌人(小敌机、大敌机、小蜜蜂)对象 */
public FlyingObject nextOne() {
Random rand = new Random(); //随机数对象
int type = rand.nextInt(20); //0~19之间的数
if (type < 8) { //0~7返回小敌机
return new Airplane();
} else if(type < 16){ //8~15返回小敌机
return new BigAirplane();
} else { //16~19返回小敌机
return new Bee();
}
}
2)将对象添加到enemies数组中
敌人入场为定时发生的,在run()中调用enterAction()实现敌人入场,
在enterAction()中,每400毫秒调用nextOne()方法获取敌人,enemies数组扩容,装在最后一个元素上。
/** 成员方法:敌人(小敌机、大敌机、小蜜蜂)入场 */
int enterIndex = 0; //敌人入场计数
public void enterAction() { //每10个毫秒走一次
enterIndex++; //每10毫秒增1
if(enterIndex%40 == 0) { //每400(10*40)毫秒走一次
FlyingObject obj = nextOne();
enemies = Arrays.copyOf(enemies,enemies.length+1);//数组扩容
//将敌人对象填充到enemies数组的最后一个元素上
enemies[enemies.length-1] = obj;
}
}
2.子弹入场 ---------- 定时发生
1)创建子弹对象
子弹对象 --------------- 是由英雄机发射出来的
---创建子弹对象的行为 ----设计在英雄机类Hero中
/** 成员方法:英雄机发射子弹(创建子弹对象) */
public Bullet[] shoot() {
int xStep = this.width/4; //xStep:1/4英雄机的宽
int yStep = 20; //yStep:固定的20
if (doubleFire > 0) { //双
Bullet[] bs = new Bullet[2]; //2发子弹
//英雄机的x坐标加1/4英雄机的宽
bs[0] = new Bullet(this.x + 1 * xStep,y-yStep);
//英雄机的x坐标加3/4英雄机的宽
bs[1] = new Bullet(this.x + 3 * xStep, y-yStep);
doubleFire -= 2; //发射一次双倍火力,火力值减2
return bs;
} else { //单
Bullet[] bs = new Bullet[1]; //1发子弹
//英雄机的x坐标加2/4英雄机的宽
bs[0] = new Bullet(this.x + 2 * xStep, y-yStep);
return bs;
}
}
import java.awt.image.BufferedImage;
/**
* 英雄机
* @author soft01
*/
public class Hero extends FlyingObject{
/** 静态变量:英雄机图片 */
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("hero" + i + ".png");
}
}
/** 成员变量:生命、火力值 */
private int life; //生命
private int doubleFire; //火力值
/** 构造方法 */
public Hero(){
super(97,124,140,400);
life = 3;
doubleFire = 0;
}
/** 成员方法:英雄机移动 */
public void step() {}
/** 成员方法:英雄机随鼠标移动 */
void moveTo(int x,int y) { }
/** 成员方法:获取图片 */
int index = 0;
@Override
public BufferedImage getImage() {
if(isLife()) {
return images[index++%2]; //(index++%2)余数为0或1
}
return null;
}
/** 成员方法:英雄机发射子弹(创建子弹对象) */
public Bullet[] shoot() {
int xStep = this.width/4; //xStep:1/4英雄机的宽
int yStep = 20; //yStep:固定的20
if (doubleFire > 0) { //双
Bullet[] bs = new Bullet[2]; //2发子弹
//英雄机的x坐标加1/4英雄机的宽
bs[0] = new Bullet(this.x + 1 * xStep,y-yStep);
//英雄机的x坐标加3/4英雄机的宽
bs[1] = new Bullet(this.x + 3 * xStep, y-yStep);
doubleFire -= 2; //发射一次双倍火力,火力值减2
return bs;
} else { //单
Bullet[] bs = new Bullet[1]; //1发子弹
//英雄机的x坐标加2/4英雄机的宽
bs[0] = new Bullet(this.x + 2 * xStep, y-yStep);
return bs;
}
}
}
2)将对象添加到bullets数组中
子弹入场为定时发生的,在run()中调用shootAction()实现敌人入场,
在shootAction()中,每300毫秒调用shoot()方法获取子弹,bullets数组扩容,数组追加。
/** 成员方法:子弹入场,英雄机发射子弹 */
int shootIndex = 0; //子弹入场计数
public void shootAction() { //每10个毫秒走一次
shootIndex++; //每10毫秒增1
if(shootIndex%30 == 0) { //每300(10*30)毫秒走一次
//获取英雄机发射出来的子弹对象
Bullet[] bs = hero.shoot();
//扩容(bs有几个元素就扩大几个)
bullets = Arrays.copyOf(bullets,bullets.length+bs.length);
//数组的追加
System.arraycopy(bs, 0, bullets,bullets.length - bs.length, bs.length);
}
}
3.飞行物移动 ---------- 定时发生
1)移动是所有对象所共有的行为,并且每个对象移动的行为都是不一样的,
所以在超类FlyingObject中设计了抽象方法step(),
/** 抽象方法:飞行物移动 */
public abstract void step();
派生类重写step()方法
/** 成员方法:英雄机移动 */
public void step() {}
/** 成员方法:小敌机移动 */
/** 成员方法:大敌机移动 */
public void step() {
y += speed; //y+(向下)
}
import java.awt.image.BufferedImage;
/**
* 小敌机
* @author soft01
*/
public class Airplane extends FlyingObject{
/** 静态变量:小敌机图片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[5];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("airplane" + i + ".png");
}
}
/** 成员变量:移动速度 */
private int speed; //移动速度
/** 构造方法 */
public Airplane() {
super(49,36);
speed = 2;
}
/** 成员方法:小敌机移动 */
public void step() {
y += speed; //y+(向下)
}
/** 成员方法:获取图片 */
int index = 1; //轮换图片的起始位置
@Override
public BufferedImage getImage() { //每10个毫秒轮换一次
if(isLife()) { //若活着的
return images[0]; //返回第一张图
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //从第2张图片到最后一张图片轮换
if (index == images.length) { //如果是最后一张图片时
state = REMOVE; //状态改为删除
}
return img; //返回对应下标的图片
}
return null; //死了的和删除的,都返回null
}
}
/**
* 大敌机
* @author soft01
*/
public class BigAirplane extends FlyingObject{
/** 静态变量:大敌机图片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("bigplane" + i + ".png");
}
}
/** 成员变量:移动速度 */
private int speed; //移动速度
/** 构造方法 */
public BigAirplane() {
super(69,99);
speed = 2;
}
/** 成员方法:大敌机移动 */
@Override
public void step() {
y += speed; //y+(向下)
}
/** 成员方法:获取图片 */
int index = 1; //轮换图片的起始位置
@Override
public BufferedImage getImage() { //每10个毫秒轮换一次
if(isLife()) { //若活着的
return images[0]; //返回第一张图
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //从第2张图片到最后一张图片轮换
if (index == images.length) { //如果是最后一张图片时
state = REMOVE; //状态改为删除
}
return img; //返回对应下标的图片
}
return null; //死了的和删除的,都返回null
}
}
/** 成员方法:子弹移动 */
@Override
public void step() {
y -= speed; //y-(向上)
}
import java.awt.image.BufferedImage;
/**
* 子弹
* @author soft01
*/
public class Bullet extends FlyingObject{
/** 静态变量:子弹图片*/
private static BufferedImage image;
static {
image = loadImage("bullet.png");
}
/** 成员变量:移动速度 */
private int speed; //移动速度
/** 构造方法 */
public Bullet(int x,int y) {
super(8,14,x,y);
speed = 3;
}
/** 成员方法:子弹移动 */
@Override
public void step() {
y -= speed; //y-(向上)
}
/** 成员方法:获取图片 */
@Override
public BufferedImage getImage() {
if(isLife()) { //若活着的
return image; //返回image
} else if(isDead()) { //若死了的
state= REMOVE; //状态改为删除
}
return null; //死了的和删除的,都返回null
}
}
/** 成员方法:小蜜蜂移动 */
@Override
public void step() {
x += xSpeed;
y += ySpeed;
if(x <= 0 || x >= World.WIDTH-this.width) {
xSpeed *= -1;
}
}
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 小蜜蜂
* @author soft01
*/
public class Bee extends FlyingObject{
/** 静态变量:小蜜蜂图片*/
private static BufferedImage[] images;
static {
images = new BufferedImage[2];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("bee" + i + ".png");
}
}
/** 成员变量:移动速度 */
private int xSpeed; //x坐标移动速度
private int ySpeed; //y坐标移动速度
private int awardType; //奖励类型
/** 构造方法 */
public Bee() {
super(60,50);
xSpeed = 1;
ySpeed = 2;
Random rand = new Random();
awardType = rand.nextInt(2); //0~1之间的随机数
}
/** 成员方法:小蜜蜂移动 */
@Override
public void step() {
x += xSpeed;
y += ySpeed;
if(x <= 0 || x >= World.WIDTH-this.width) {
xSpeed *= -1;
}
}
/** 成员方法:获取图片 */
int index = 1; //轮换图片的起始位置
@Override
public BufferedImage getImage() { //每10个毫秒轮换一次
if(isLife()) { //若活着的
return images[0]; //返回第一张图
} else if(isDead()) { //若死了的
BufferedImage img = images[index++]; //从第2张图片到最后一张图片轮换
if (index == images.length) { //如果是最后一张图片时
state = REMOVE; //状态改为删除
}
return img; //返回对应下标的图片
}
return null; //死了的和删除的,都返回null
}
}
/** 成员方法:天空移动 */
public void step() {
y +=speed; //y+(向下)
y1+=speed; //y1+(向下)
if(y>=World.HEIGHT){ //若y>=窗口的高
y = -World.HEIGHT; //则修改y的值为负的窗口的高
}
if(y1>=World.HEIGHT){ //若y1>=窗口的高
y1 = -World.HEIGHT; //则修改y1的值为负的窗口的高
}
}
import java.awt.Graphics;
import java.awt.image.BufferedImage;
/**
* 天空
* @author soft01
*/
public class Sky extends FlyingObject{
/** 静态变量:天空图片 */
private static BufferedImage image;
static {
image = loadImage("background.png");
}
/** 成员变量:移动速度 */
private int y1; //第二张图片的y坐标
private int speed; //移动速度
/** 构造方法 */
public Sky(){
super(World.WIDTH,World.HEIGHT,0,0);
y1 = -height;
speed = 1;
}
/** 成员方法:天空移动 */
public void step() {
y +=speed; //y+(向下)
y1+=speed; //y1+(向下)
if(y>=World.HEIGHT){ //若y>=窗口的高
y = -World.HEIGHT; //则修改y的值为负的窗口的高
}
if(y1>=World.HEIGHT){ //若y1>=窗口的高
y1 = -World.HEIGHT; //则修改y1的值为负的窗口的高
}
}
/** 成员方法:获取图片 */
public BufferedImage getImage() {
return image;
}
/** 成员方法:画对象的 g:画笔 */
public void paintObject(Graphics g) {
g.drawImage(getImage(),x,y,null);
g.drawImage(getImage(),x,y1,null);
}
}
2)飞行物移动为定时发生的,在run()中调用stepAction()实现飞行物移动,
在stepAction()中,天空动,遍历敌人而后敌人动,遍历子弹而后子弹动
/** 成员方法:飞行物入场 */
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 action() {
Timer timer = new Timer(); //创建定时器对象
int interval = 10; //定时间隔(以毫秒为单位)
timer.schedule(new TimerTask() {
@Override
public void run() {//定时干的事(每10个毫秒走一次)
enterAction(); //敌人入场,子弹入场,飞行物移动
shootAction(); //子弹入场,英雄机发射子弹
stepAction(); //飞行物入场
repaint(); //重画(重新调用paint()方法)
}
},interval,interval); //定时计划
}
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
/**
* 整个世界
* @author soft01
*/
public class World extends JPanel{
/** 常量:窗口宽、窗口高 */
public static final int WIDTH = 400;
public static final int HEIGHT = 700;
/** 成员变量:天空、英雄机、飞行物敌人数组、子弹数组 */
private Sky sky = new Sky();
private Hero hero = new Hero();
private FlyingObject[] enemies = {};
private Bullet[] bullets = {};
/** 启动程序的执行 */
public void action() {
Timer timer = new Timer(); //创建定时器对象
int interval = 10; //定时间隔(以毫秒为单位)
timer.schedule(new TimerTask() {
@Override
public void run() { //定时干的事(每10个毫秒走一次)
enterAction(); //敌人入场,子弹入场,飞行物移动
shootAction(); //子弹入场,英雄机发射子弹
stepAction(); //飞行物入场
repaint(); //重画(重新调用paint()方法)
}
},interval,interval); //定时计划
}
/** 成员方法:生成敌人(小敌机、大敌机、小蜜蜂)对象 */
public FlyingObject nextOne() {
Random rand = new Random(); //随机数对象
int type = rand.nextInt(20); //0~19之间的数
if (type < 8) { //0~7返回小敌机
return new Airplane();
} else if(type < 16){ //8~15返回小敌机
return new BigAirplane();
} else { //16~19返回小敌机
return new Bee();
}
}
/** 成员方法:敌人(小敌机、大敌机、小蜜蜂)入场 */
int enterIndex = 0; //敌人入场计数
public void enterAction() { //每10个毫秒走一次
enterIndex++; //每10毫秒增1
if(enterIndex%40 == 0) { //每400(10*40)毫秒走一次
FlyingObject obj = nextOne();
enemies = Arrays.copyOf(enemies, enemies.length+1); //数组扩容
enemies[enemies.length-1] = obj; //将敌人对象填充到enemies数组的最后一个元素上
}
}
/** 成员方法:子弹入场,英雄机发射子弹 */
int shootIndex = 0; //子弹入场计数
public void shootAction() { //每10个毫秒走一次
shootIndex++; //每10毫秒增1
if(shootIndex%30 == 0) { //每300(10*30)毫秒走一次
Bullet[] bs = hero.shoot(); //获取英雄机发射出来的子弹对象
bullets = Arrays.copyOf(bullets, bullets.length+bs.length); //扩容(bs有几个元素就扩大几个)
System.arraycopy(bs, 0, bullets, bullets.length - bs.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(); //子弹移动
}
}
/** 成员方法:paint()方法 */
@Override
public void paint(Graphics g) {
sky.paintObject(g); //画天空
hero.paintObject(g); //画英雄机
for (int i = 0; i < enemies.length; i++) { //遍历所有敌人
enemies[i].paintObject(g); //画敌对飞行物
}
for (int i = 0; i < bullets.length; i++) { //遍历子弹
bullets[i].paintObject(g); //画子弹
}
}
/** main主方法 */
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); //1)设置窗口可见 2)尽快调用paint()方法
world.action(); //启动程序
}
}