射击游戏分析:
射击游戏需求:
1.所参与的角色:英雄机、子弹、小敌机、大敌机、小蜜蜂、天空
2.角色间的关系:
1)英雄机发射子弹(单倍火力、双倍火力)
2)子弹打敌人(小敌机、大敌机、小蜜蜂),若打上了:
2.1)子弹消失、敌人先爆破再消失
2.2)若打的是小敌机,则玩家得1分
若打的是大敌机,则玩家得3分
若打的是小蜜蜂,则英雄机得奖励(1条命或40火力值)
3)敌人(小敌机、大敌机、小蜜蜂)撞英雄机,若撞上了:
3.1)敌人先爆破再消失
3.2)英雄机减1条命,同时,清空火力值
当英雄机命数为0时,则游戏结束
4)英雄机、子弹、小敌机、大敌机、小蜜蜂在天空上飞
1.设计小敌机数组、大敌机数组、小蜜蜂数组、子弹数组,并测试
2.设计FlyingObject超类,6个对象类继承超类
3.给FlyingObject设计两个构造方法,6个对象类分别调用
1.将小敌机数组、大敌机数组、小蜜蜂数组组合为FlyingObject数组,并测试
2.在6个对象类中重写step()移动
3.画窗口:----在World类中
1)import JFrame+JPanel
2)设计World类继承JPanel
3)将main中的代码Ctrl C+V
4)main中: frame.setSize()的参数修改为400,700
1.给类中成员添加访问控制修饰符
2.设计Images图片工具类
1.设计窗口的宽和高为常量,适当地方做修改
2.画对象:
1)想画对象需要获取对象的图片,每个对象都能获取图片,
意味着获取图片行为为共有行为,所以设计在超类FlyingObject中,
每个对象获取图片的行为都是不一样的,所以设计抽象方法
----在FlyingObject中设计抽象方法getImage()获取对象的图片
2)获取图片时需要考虑对象的状态,那是因为在不同状态下获取的图片是不同的,
因为每个对象都有状态,意味着状态为共有属性,所以设计在超类FlyingObject中
状态一般都设计为常量,同时再设计变量state来表示当前状态
----在FlyingObject中设计LIVE、DEAD、REMOVE常量,state变量
获取图片时需在去判断对象的状态,每个对象都得状态判断,
意味着判断状态为共有行为,所以设计在超类FlyingObject中,
每个对象判断状态的行为都是一样的,所以设计为普通方法
----在FlyingObject中设计isLive()、isDead()、isRemove()判断状态
3)重写getImage()获取对象的图片:
3.1)天空Sky,直接返回sky图片即可
3.2)英雄机Hero,直接返回heros[0]和heros[1]来回切换
3.3)子弹Bullet:
3.3.1)若活着的,直接返回bullet图片即可
3.3.2)若死了的,直接删除(不返回图片)
3.4)小敌机Airplane:
3.4.1)若活着的,直接返回airs[0]图片即可
3.4.2)若死了的,依次返回airs[1]到airs[4]图片,4后删除(不返回图片)
3.5)大敌机BigAirplane:
3.5.1)若活着的,直接返回bairs[0]图片即可
3.5.2)若死了的,依次返回bairs[1]到bairs[4]图片,4后删除(不返回图片)
3.6)小蜜蜂Bee:
3.6.1)若活着的,直接返回bees[0]图片即可
3.6.2)若死了的,依次返回bees[1]到bees[4]图片,4后删除(不返回图片)
4)图片有了,则可以开画了
----在World类中重写paint()方法
if(isLive()){ 活着呢 }else{ 死了的+删除的 }
分支结构使用几路结构:
----不是看要干几件事,而是看有几种情况
若不考虑爆破,状态有两种:
1)活着的
2)删除的
若考虑爆破,状态有三种:
1)活着的
2)死了的(半死不活,需爆破)
3)删除的
1.敌人入场:
1)敌人是由窗口产生的,所以在World类中设计nextOne()生成敌人对象
2)敌人入场为定时发生的,所以在run()中调用enterAction()实现敌人入场
在enterAction()中:
每400毫秒,获取敌人对象obj,enemies扩容,将obj装到enemies最后一个元素上
注意:在run()中调用enterAction()后,还得再调用repaint()方法来重画
2.子弹入场:
1)子弹是由英雄机发射出来的,所以在Hero类中设计shoot()生成子弹对象
2)子弹入场为定时发生的,所以在run()中调用shootAction()实现子弹入场
在shootAction()中:
每300毫秒,获取子弹数组对象bs,bullets扩容,将bs追加到bullets的末尾
1.飞行物移动:
1)飞行物移动为对象共有的行为,所以在FlyingObject中设计抽象方法step(),派生类中重写
2)飞行物移动为定时发生的,所以在run()中调用stepAction()实现飞行物移动
在stepAction()中:
天空动,遍历敌人敌人动,遍历子弹子弹动
2.英雄机随着鼠标移动:
1)英雄机随着鼠标动为英雄机的行为,所以在Hero中设计moveTo()实现英雄机随着鼠标移动
2)英雄机随着鼠标移动为事件触发的,所以在侦听器中重写mouseMoved()鼠标移动事件
在mouseMoved()中:
获取鼠标的x坐标和y坐标,调用moveTo()方法
3.删除越界的敌人和子弹:
1)在FlyingObject中设计isOutOfBounds()判断敌人是否越界
在Bullet中重写isOutOfBounds()判断子弹是否越界
2)删除越界敌人和子弹为定时发生的,所以在run()中调用outOfBoundsAction()删除越界的敌人和子弹
在outOfBoundsAction()中:
遍历所有敌人,判断若越界了,则最后一个敌人替换越界的敌人,缩容
遍历所有子弹,判断若越界了,则最后一个子弹替换越界的子弹,缩容
4.设计EnemyScore得分接口,小敌机和大敌机实现EnemyScore
设计EnemyAward奖励接口,小蜜蜂实现EnemyAward
1.子弹与敌人的碰撞:
1)在FlyingObject中设计isHit()检测碰撞、goDead()飞行物去死
在Hero中设计addLife()增命、addFire()增火力
2)子弹与敌人的碰撞为定时发生的,所以在run()中调用bulletBangAction()实现子弹与敌人的碰撞
在bulletBangAction()中:
遍历子弹得子弹,遍历敌人得敌人,判断若都活着并且还撞上了:
子弹去死、敌人去死
判断若为EnemyScore,则将被撞对象强转为EnemyScore,玩家得分
判断若为EnemyAward,则将被撞对象强转为EnemyAward,获取奖励类型,得奖励
2.画分和画命:
1)在Hero中设计getLife()获取英雄机的命数
2)在World类的paint()中: 画分和画命
3.英雄机与敌人的碰撞:
1)借用FlyingObject中的isHit()检测碰撞、goDead()飞行物去死
在Hero中设计subtractLife()减命、clearFire()清空火力值
2)英雄机与敌人的碰撞为定时发生的,所以在run()中调用heroBangAction()实现英雄机与敌人的碰撞
在heroBangAction()中:
遍历所有敌人得敌人,判断若都活着并且还撞上了:
敌人去死、英雄机减命、英雄机清空火力值
1.检测游戏结束:
1)借用Hero的getLife()获取英雄机的命数
2)检测游戏结束为定时发生的,所以在run()中设计checkGameOverAction()实现检测游戏结束
在checkGameOverAction()中:
判断若英雄机的命数<=0,表示游戏结束了,则…
2.画状态:
1)在World类中设计START、RUNNING、PAUSE、GAME_OVER常量,同时设计state变量表示当前状态
在Images类中设计start,pause,gameover状态图片,并赋值
在World类的paint()中: 设计在不同的状态下画不同的图片
2)设计那一堆action,为仅在运行状态下执行
设计英雄机随着鼠标移动,为仅在运行状态下执行
3)重写mouseClicked()鼠标点击事件:
启动变运行,游戏结束先清理现场再变启动
重写mouseExited()鼠标移出事件:
运行变暂停
重写mouseEntered()鼠标移入事件:
暂停变运行
小敌机:Airplane
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class Airplane extends FlyingObject implements EnemyScore{
private int speed; //移动速度
public Airplane(){ //构造方法
super(48,50); //小敌机的宽高
speed = 2; //移动速度
}
/*重写step()移动*/
public void step() {
y+=speed; //y+向下
}
private int index = 1; //爆破图的下标
/*重写getImage()获取图片*/
public BufferedImage getImage() { //每十毫秒走一次
if(isLive()) {
return Images.airs[0];
}else if(isDead()) {
BufferedImage img = Images.airs[index++]; //获取爆破图
if(index==Images.airs.length) { //到最后一张了
state = REMOVE; //将当前状态修改为REMOVE删除状态
}
return img; //返回爆破图
}
return null; //删除状态不返回图片
/*
* index=1
* 10M img=airs[1] index=2 airs[1]
* 20M img=airs[2] index=3 airs[2]
* 30M img=airs[3] index=4 airs[3]
* 40M img=airs[4] index=5 airs[4]
* (REMOVE)
* 50M 不返回图片
*/
}
public int getScore() {
return 1; //打掉小敌机玩家得1 分
}
}
大敌机:BigAirplane
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class BigAirplane extends FlyingObject implements EnemyScore{
private int speed;
public BigAirplane(){
super(66,89);
speed = 2;
}
public void step() {
y+=speed; //y+向下
}
private int index = 1; //爆破图的下标
/*重写getImage()获取图片*/
public BufferedImage getImage() { //每十毫秒走一次
if(isLive()) {
return Images.bairs[0];
}else if(isDead()) {
BufferedImage img = Images.bairs[index++]; //获取爆破图
if(index==Images.bairs.length) { //到最后一张了
state = REMOVE; //将当前状态修改为REMOVE删除状态
}
return img; //返回爆破图
}
return null; //删除状态不返回图片
}
/*重写getScore()*/
public int getScore() {
return 3; //打掉大敌机,玩家得3分
}
}
小蜜蜂:Bee
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Bee extends FlyingObject implements EnemyAward{
private int xSpeed;
private int ySpeed;
private int awardType;
public Bee(){
super(60,51);
Random rand = new Random();
xSpeed = 1;
ySpeed = 2;
awardType = rand.nextInt(2); //0到1之间
}
public void step() {
x+=xSpeed; //x向左向右
y+=ySpeed; //y+向下
if(x<=0 || x>=World.WIDTH-width){ //若x<=0或X>=(窗口宽-蜜蜂宽),表示到头了
xSpeed*=-1; //切换方向(正便=变负、负变正)
}
}
private int index = 1; //爆破图的下标
/*重写getImage()获取图片*/
public BufferedImage getImage() { //每十毫秒走一次
if(isLive()) {
return Images.bees[0];
}else if(isDead()) {
BufferedImage img = Images.bees[index++]; //获取爆破图
if(index==Images.bees.length) { //到最后一张了
state = REMOVE; //将当前状态修改为REMOVE删除状态
}
return img; //返回爆破图
}
return null; //删除状态不返回图片
}
public int getAwardType() {
return awardType; //返回奖励类型
}
}
英雄机:Hero
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class Hero extends FlyingObject{
private int life;
private int fire;
public Hero(){
super(97,139,140,400);
life = 3;
fire = 0;
}
public void step() {
}
int index = 0; //下标
/*重写getImage()获取图片*/
public BufferedImage getImage() { //每十个毫毛走一次
return Images.heros[index++%Images.heros.length]; //在0到1之间来回切换
/* index=0;
10M 返 回hero[0] index=1;
20M 返 回hero[1] index=2;
30M 返 回hero[0] index=3;
40M 返 回hero[1] index=4;
*/
}
/*英雄机发射子弹(生成子弹对象)*/
public Bullet[] shoot() {
int xStep = this.width/4; //1/4英雄机的宽
int yStep = 2;
if(fire>0) { //双倍火力
Bullet[] bs = new Bullet[2]; //2发子弹
bs[0] = new Bullet(this.x+1*xStep,this.y-yStep); //x:英雄机的x+1/4英雄机的宽 y:英雄机的y-固定的20
bs[1] = new Bullet(this.x+3*xStep,this.y-yStep); //x:英雄机的x+3/4英雄机的宽 y:英雄机的y-固定的20
fire-=2; //发射一次双倍火力,则火力值减2
return bs;
}else { //单倍
Bullet[] bs = new Bullet[1]; //1发子弹
bs[0] = new Bullet(this.x+2*xStep,this.y-yStep); //x:英雄机的x+2/4英雄机的宽 y:英雄机的y-固定的20
return bs;
}
}
/*英雄机随着鼠标移动*/
public void moveTo(int x,int y) {
this.x = x-this.width/2; //英雄机的x=鼠标的x-1/2英雄机的宽
this.y = y-this.height/2; //英雄机的y=鼠标的y-1/2英雄机的高
}
/*英雄机增命*/
public void addLife() {
life++; //命数加1
}
/*获取英雄机的命*/
public int getLife() {
return life; //返回命数
}
/*英雄机减命*/
public void subtractLife() {
life--;
}
/*清空火力值*/
public void clearFire() {
fire=0; //火力值为零
}
/*英雄机增火力*/
public void addFire() {
fire+=40; //火力值增40
}
}
天空:Sky
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject{
private int speed;
private int y1; //第二张图的y坐标
/*构造方法*/
public Sky(){
super(World.WIDTH,World.HEIGHT,0,0);
speed = 1;
y1 = -World.HEIGHT;
}
public void step() {
y += speed; //y+(向下)
y1+= speed; //y+(向下)
if(y>=World.HEIGHT) { //若y>=窗口的高,意味着y移出去了
y=-World.HEIGHT; //则修改y的值为负的窗口的高(挪到最上面去了)
}
if(y1>World.HEIGHT) { //若y1>=窗口的高,意味着y1一出去了
y1=-World.HEIGHT; //则修改y1的值为负的窗口的高(挪到最上面去了)
}
}
/*重写getImage()获取图片*/
public BufferedImage getImage() {
return Images.sky; //直接返回sky图片即可
}
public int getY1() {
return y1;
}
}
子弹:Bullet
package cn.tedu.shoot;
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; //y+向上
}
/*重写getImage()获取图片*/
public BufferedImage getImage() {
if(isLive()) {
return Images.bullet; //直接返回图片
}else if(isDead()){ //若死了的
state = REMOVE; //将状态修改为REMOVE删除状态
}
return null; //死了的和删除的,都不反图片
/*
//若活着的,返回bullet 图片
//若死了的,状态改为删除,同时不返回图片
//若删除的不返回图片
*/
}
/*重写isOutOfBounds()判断子弹是否越界*/
public boolean isOutOfBounds() {
return y<=-height; //敌人的y>=窗口的高,即为越界了
}
}
超类:FlyingObject
package cn.tedu.shoot;
import java.util.Random;
import java.awt.image.BufferedImage;
/*飞行物*/
public abstract class FlyingObject {
public static final int LIVE = 0; //活着的
public static final int DEAD = 1; //死了的
public static final int REMOVE = 2; //删除的
protected int state = LIVE; //当前状态默认为活着的
protected int width; //宽
protected int height; //高
protected int x; //x坐标
protected int y; //y坐标
//专门给小敌机,大敌机,小蜜蜂提供的
//因为三种敌人的宽高不同,所以数据得写活,自然传参
//因为三种敌人的x和y坐标相同,所以直接写死,不需要传参
public FlyingObject(int width,int height){
this.width=width;
this.height=height;
Random rand = new Random(); //随机数对象
x = rand.nextInt(World.WIDTH-width); //0到(窗口宽-小敌机宽)之间是随机数
y = -height; //y:负的敌人的高
}
/*专门给英雄机、天空、子弹提供的*/
//因为英雄机,天空,子弹的宽高xy都不同,所以数据都得写活,都得传参过来
public FlyingObject(int width,int height,int x,int y){
this.width=width;
this.height=height;
this.x=x;
this.y=y;
}
public abstract void step();
/*获取对象的图片*/
public abstract BufferedImage getImage();
/*判断是否活着的*/
public boolean isLive() {
return state==LIVE; //当前状态为LIVE则表示为活着的,返回true,否则返回flase
}
/*判断是死了着的*/
public boolean isDead() { //当前状态为DEAD则表示为活着的,返回true,否则返回flase
return state==DEAD;
}
/*判断是否删除的*/
public boolean isRemove() { //当前状态为REMOVE则表示为活着的,返回true,否则返回flase
return state==REMOVE;
}
/*判断敌人是否越界*/
public boolean isOutOfBounds() {
return y>=World.HEIGHT; //敌人的y>=窗口的高,即为越界了
}
/*检测敌人与子弹/英雄机的碰撞 this:敌人 other:子弹/英雄机*/
public boolean isHit(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<=x2 && y>=y1 && y<=y2;
}
/*飞行物去死*/
public void goDead() {
state = DEAD; //将当前状态修改为DEAD死了的
}
}
图片工具类:Images
package cn.tedu.shoot;
//图片工具类
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;
public static BufferedImage start;
public static BufferedImage pause;
public static BufferedImage gameover;
static {
start = readImage("start.png");
pause = readImage("pause.png");
gameover = readImage("gameover.png");
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];
airs[0] = readImage("airplane.png");
bairs = new BufferedImage[5];
bairs[0] = readImage("bigairplane.png");
bees = new BufferedImage[5];
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();
}
}
}
得分奖励接口:EnemyScore
package cn.tedu.shoot;
/*得分接口*/
public interface EnemyScore {
public int getScore(); //得分
}
得命或火力值奖励接口:EnemyAward
package cn.tedu.shoot;
/*奖励接口*/
public interface EnemyAward {
public int FIRE = 0; //火力
public int LIFE = 1; //命
/*获取奖励类型*/
public int getAwardType();
}
测试类:World
package cn.tedu.shoot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class World extends JPanel {
public static final int WIDTH = 400; // 窗口的宽
public static final int HEIGHT = 700; // 窗口的高
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; //游戏结束状态
private int state = START; //当前状态(默认为启动状态)
private Sky sky = new Sky(); // 天空对象
private Hero hero = new Hero(); // 英雄机
private FlyingObject[] enemies = {}; // 敌人组
private Bullet[] bullets = {}; // 子弹数组
/* 敌人生成(小敌机,大敌机,小蜜蜂)对象 */
public FlyingObject nextOne() {
Random rand = new Random();
int type = rand.nextInt(20); // 0到19之间的随机数
if (type < 5) { // 0到4返回小蜜蜂对象
return new Bee();
} else if (type < 13) { // 5到12返回小蜜蜂对象
return new Airplane();
} else { // 13到19返回大敌机对象
return new BigAirplane();
}
}
private int enterIndex = 0;
/* 敌人(小敌机,大敌机,小蜜蜂)入场 */
public void enterAction() { // 每10毫秒做一次
enterIndex++; // 每10毫秒增1
if (enterIndex % 40 == 0) { // 每400毫秒走一次
FlyingObject obj = nextOne(); // 获取敌人对象
enemies = Arrays.copyOf(enemies, enemies.length + 1); // 扩容
enemies[enemies.length - 1] = obj; // 将obj添加到最后一个元素上
}
}
private int shootIndex = 0; // 子弹入场计数
/* 子弹入场 */
public void shootAction() { // 每10毫秒走一次
shootIndex++; // 每10毫秒走一次
if (shootIndex % 30 == 0) { // 每300毫秒走一次
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(); //子弹动
}
}
/*删除越界的敌人和子弹*/
public void outOfBoundsAction() { //每10毫秒走一次
for(int i=0;i<enemies.length;i++) { //遍历所有敌人
if(enemies[i].isOutOfBounds() || enemies[i].isRemove()) { //判断是否出界或爆破
enemies[i] = enemies[enemies.length-1]; //把最后一个敌人放在出界敌人的位置
enemies = Arrays.copyOf(enemies,enemies.length-1); //缩容
}
}
for(int i=0;i<bullets.length;i++) { //遍历所有子弹
if(bullets[i].isOutOfBounds() || bullets[i].isRemove()) { //判断是否出界或爆破
bullets[i] = bullets[bullets.length-1]; //把最后一个子弹放在出界子弹的位置
bullets = Arrays.copyOf(bullets,bullets.length-1); //缩容
}
}
}
private int score = 0; //玩家得分
/*子弹与敌人的碰撞*/
public void bulletBangAction() {
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.isLive() && f.isLive() && f.isHit(b)) { //若都活着并且还撞上了
b.goDead(); //子弹去死
f.goDead(); //敌人去死
if(f instanceof EnemyScore) { //若被撞敌人为分
EnemyScore es = (EnemyScore)f; //将被撞敌人强转为得分接口
score += es.getScore(); //玩家得分
}
if(f instanceof EnemyAward) { //若被撞敌人为奖励
EnemyAward ea = (EnemyAward)f; //将被撞敌人强转为奖励接口
int type = ea.getAwardType(); //获取奖励类型
switch(type) { //根据奖励类型来获取不同的奖励
case EnemyAward.FIRE: //若奖励类型为火力
hero.addFire(); //则英雄机增火力
break;
case EnemyAward.LIFE: //若奖励类型为名
hero.addLife(); //则英雄机增命
break;
}
}
}
}
}
}
/*英雄机与敌人撞*/
public void heroBangAction() { //每10毫秒走一次
for(int i=0;i<enemies.length;i++) { //遍历所有敌人
FlyingObject f = enemies[i]; //获取每个敌人
if(hero.isLive() && f.isLive() && f.isHit(hero)) {
f.goDead(); //敌人去死
hero.subtractLife(); //英雄机减命
hero.clearFire(); //英雄机清空火力
}
}
}
public void checkGameOverAction() {
if(hero.getLife()<=0) { //表示游戏结束了
state = GAME_OVER; //将当前状态修改为游戏结束状态
}
}
/* 启动程序的执行 */
public void action() {
MouseAdapter m = new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
if(state==RUNNING) {
int x = e.getX(); //获取鼠标的x坐标
int y = e.getY(); //获取鼠标的y坐标
hero.moveTo(x,y); //英雄机随着鼠标移动
}
}
public void mouseClicked(MouseEvent e) {
switch(state) { //根据当前状态做不同的处理
case START: //启动状态时修改为运行状态
state = RUNNING;
break;
case GAME_OVER: //游戏结束状态时修改为启动状态
score = 0; //先清理现场,在修改为启动状态
sky = new Sky();
hero = new Hero();
enemies = new FlyingObject[0];
bullets = new Bullet[0];
state = START;
break;
}
}
/*重写mouseExited()鼠标移出事件*/
public void mouseExited(MouseEvent e) {
if(state==RUNNING) { //运行状态时修改为暂停状态
state = PAUSE;
}
}
/* 重写mouseEntered()鼠标移入事件*/
public void mouseEntered(MouseEvent e) {
if(state==PAUSE) { //暂停状态时修改为运行状态
state = RUNNING;
}
}
};
this.addMouseListener(m);
this.addMouseMotionListener(m);
Timer timer = new Timer(); // 定时器对象
int intervel = 10; // 定时间隔(以毫秒为单位)
timer.schedule(new TimerTask() {
public void run() { // 定时器干的事(每十毫秒走一次)
// 敌人入场 子弹入场 飞行物移动 子弹与敌人碰撞 英雄机与敌人碰撞
if(state==RUNNING) { //仅在运行状态下执行
enterAction(); //敌人(小敌机,大敌机,小蜜蜂)入场
shootAction(); //子弹入场
stepAction(); //飞行物移动
outOfBoundsAction(); //删除越界敌人
bulletBangAction(); //子弹与敌人碰撞
heroBangAction(); //英雄机与敌人的碰撞
checkGameOverAction(); //检测游戏结束
}
repaint(); // 重画 调用repaint() 画笔
}
}, intervel, intervel); //定时计划表
}
/* 重写paint()画 */
public void paint(Graphics g) { // 每10毫秒走一次
g.drawImage(sky.getImage(), sky.x, sky.y, null); // 画天空1
g.drawImage(sky.getImage(), sky.x, sky.getY1(), null); // 画天空2
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); // 画子弹
}
g.drawString("SCORE:"+score,10,25); //画分
g.drawString("LIVE:"+hero.getLife(),10,45); //画命
/*画启动图,暂停图,结束图*/
switch(state) {
case START:
g.drawImage(Images.start,0,0,null);
break;
case PAUSE:
g.drawImage(Images.pause,0,0,null);
break;
case GAME_OVER:
g.drawImage(Images.gameover,0,0,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();
}
}