面向对象(OOP):
类和对象:
shoot射击游戏项目一
需求分析
1.运行项目看结果
A:
小敌机、大敌机、蜜蜂--------敌人
英雄机发射子弹
子弹打中敌人
B:
子弹击中小敌机------玩家得1分
子弹击中打敌机------玩家得5分
子弹击中小蜜蜂------玩家得1命或者得火力值30
C:单倍火力、双倍火力的变化
英雄机的火力值变为0的时候,就成了单倍火力
火力值大于0 的时候,变为双倍火力;依次减少2
D:碰撞
敌人可以与英雄机发生碰撞,碰撞之后,英雄机的生命值减少,变为0的时候,游戏结束。
2.技术分析
设计类:
A:找对象:(6个)
英雄机、小敌机、大敌机、小蜜蜂、子弹、天空
B:抽类:
Hero、Airplane、BigAirplane、Bee、Bullet、Sky
C:设计成员变量和方法
D:测试
shoot射击游戏项目二
1.需求分析
A:设计一个父类、超类;冰洁让6个对象继承超类,测试
B:给超类添加构造方法;让6个对象分别调用超类
C:设置对象数组,进行测试
D:在6个子类、派生类中重写
E:画窗体
2.技术分析
3.代码实现
shoot射击游戏项目三
1.需求分析
A:给类中添加修饰符
B:给6个派生类中添加图片属性
1)6个派生类中添加static属性
2)在父类中添加静态方法loadimage()加载图片
3)6个派生类中static代码块,调用loadimage()方法
2.技术实现
修饰符:
public protected default private
同一个类 √ √ √ √
同一个包中不同类 √ √ √
不同包子类 √ √
不同包中的类 √
shoot射击游戏项目四
1.需求分析
A:将窗体的大小设置为常量
B:画对象
想画对象先获取到图片,针对每一个对象都能够获取到图片,获取到图片的行为是共有的,设计到父类中;
每一个对象得到图片的行为都是不一样的,设计了一个抽象方法-----getimages();
在不同状态下,得到不同的图片:
状态:设计到父类中,设计常量:LEFT;DEAD;REMOVE;
默认状态:state =LEFT
获取图片的同时,需不需要判断当前的状态???需要
每一个对象都需要判断,设计到超类/父类中
而每一个对象判断的行为都是一样的,设计普通方法即可;
---------FlyingObject:isLife()/isDead()/isRemove()
C:在6个子类对象中重写getimages()方法
- 背景sky:直接返回即可
- 子弹bullet:如果只存活的,返回images即可
如果是over的,删除即可 - 英雄机:如果是存活的,返回images[0]/images[1]
- 小敌机、大敌机、蜜蜂:如果是存活的,返回images[0]
如果是over的,images[1]到images[4]进行切换,切换完毕,到了images[4]后进行删除;
D:得到不同状态下的图片,进行开始画出来;
画对象的行为是共有的没所以设计到超类中;
每一个对象画的方式都是一样的,所以设计为普通方法
E:测试,调用即可;
设计规则:
- 将所有子类所共有的行为和属性,可以设计到超类中;-----抽共性
- 所有子类的行为都是一样的,设计为普通方法;所有子类的行为都是不一样的,设计为抽象方法;
shoot射击游戏项目五
1.需求分析
A:敌人入场
- 产生敌人;在主函数(ShootMain)类中nextOne()
- 需要定时加载敌人—enterAction()实现敌人入场
- 每400毫秒,获取到敌人,扩容,将敌人添加到数组的最后一位
B:子弹入场
- 英雄机中发射子弹,Hero类设计一个方法用来实现子弹的发射----shoot()
- run()方法中,子弹的发射shootAction()
- 每400毫秒,获取到子弹,扩容,将子弹数组添加到数组的最后一位
C:飞行物的移动
- 敌人的移动
- 子弹的移动
- 天空的移动
D:英雄机随着鼠标进行移动
- 在hero中设计方法:movedTo()实现英雄机的移动
- 在shootMian中建立监听机制,检测鼠标的移动事件
E:删除越界的飞行物
- 在FlyingObject中涉及一个方法outOfBounds()-----检测是否越界
- 在run()方法中,写一个方法outOfBoundsAction()—删除越界的飞行物
- 遍历敌人、子弹数组,如果对象不越界,那么将存放到不越界的数组中,将不越界的数组复制到敌人、子弹数组中
F:设计接口:
- 击中小敌机+大敌机-------得1分 或3分-------Enemy
- 击中蜜蜂-----随机得生命或者火力-----Award
shoot射击游戏项目六
1.需求分析
A:子弹与敌人碰撞
-
设计到父类中,hit()方法,实现检测子弹与敌人发生碰撞
-
在父类中设计一个goDead()实现飞行物over;
-
在Hero类中设计实现addLife(),addDoubleFire()
-
通过Airplane和BigAirplane中的接口来实现玩家得分
-
通过Bee中的接口实现玩家得奖励
-
[1] Hero
package shoot; import java.awt.image.BufferedImage; /** * 英雄机: * * @author YANG * */ 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 = 6; doubleFire = 0;// 单倍火力 } public void movedTo(int x, int y) { this.x = x - this.width/2; this.y = y - this.height/2; } // 移动 public void step() { System.out.println("图片的切换"); } // 英雄机发射子弹 public Bullet[] shoot(){ int xStep= this.width/4; int yStep=15; if (doubleFire>=500) { Bullet[] bs = new Bullet[3]; bs[0]=new Bullet(this.x+xStep*1, this.y-yStep); bs[1]=new Bullet(this.x+xStep*6, this.y-yStep); bs[2]=new Bullet(this.x+xStep*9, this.y-yStep); return bs; } else if(doubleFire>100&&doubleFire<500){//双倍火力 Bullet[] bs = new Bullet[2]; bs[0]=new Bullet(this.x+xStep*1, this.y-yStep); bs[1]=new Bullet(this.x+xStep*3, this.y-yStep); return bs; }else{//单倍火力 Bullet[] bs = new Bullet[1]; bs[0]=new Bullet(this.x+xStep*2, this.y-yStep); return bs; } } public void substractLife(){ life--; } public void clearDoubleFire(){ doubleFire=0; } @Override public BufferedImage getImage() { // TODO Auto-generated method stub return images[0]; } public void addDoubleFire(){ doubleFire += 30; } public void addLife(){ life++; } public int getLife() { // TODO 自动生成的方法存根 return life; } }
-
[2] Airplane
package shoot; import java.awt.image.BufferedImage; /** * 小敌机: * @author YANG * */ public class Airplane extends FlyingObject implements Enemy{ 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); this.speed = 2; } /**移动*/ public void step(){ this.y += speed; } //TODO... //得到图片 int index =1; @Override public BufferedImage getImage() { if (isLife()){ return images[0]; }else if(isDead()){ BufferedImage img = images[index++]; if(index == images.length){ state =REMOVE; } return img; } return null; } @Override public int getScore() { // TODO 自动生成的方法存根 return 1; } }
-
[3] BigAirplane
package shoot; import java.awt.image.BufferedImage; /** * 大敌机: * @author YANG * */ public class BigAirplane extends FlyingObject implements Enemy{ private static BufferedImage[] images; //静态代码块 static { images = new BufferedImage[5]; for (int i = 0; i < images.length; i++) { images[i] = loadImage("bigplane" + i + ".png"); } } int speed;//速度 /**构造方法*/ public BigAirplane(){ super(23,33); this.speed = 4; } public void step(){ this.y += speed; } int index =1; @Override public BufferedImage getImage() { // TODO Auto-generated method stub if (isLife()) { return images[0]; }else if(isDead()){ BufferedImage img = images[index++]; if(index == images.length){ state =REMOVE; } return img; } return null; } @Override public int getScore() { // TODO 自动生成的方法存根 return 3; } }
-
[4] Bee
package shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 蜜蜂:
* @author YANG
*
*/
public class Bee extends FlyingObject implements Award{
private int xSpeed;//x坐标的速度
private int ySpeed;//y坐标的速度
private int awardType;//获取奖励的类型
private static BufferedImage[] images;
//静态代码块
static {
images = new BufferedImage[5];
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("bee" + i + ".png");
}
}
public Bee(){
super(100,400);
xSpeed = 2;
ySpeed = 4;
Random rand = new Random();
awardType = rand.nextInt(2);//0 1
}
public void step(){
x += xSpeed;
y += ySpeed;
if (x < 0 || x >= ShootMain.SCREEN_WIDTH - width) {
xSpeed *= -1;
}
}
int index =1;
@Override
public BufferedImage getImage() {
if (isLife()){
return images[0];
}else if(isDead()){
BufferedImage img = images[index++];
if(index == images.length){
state =REMOVE;
}
return img;
}
/**
* index =1;
* 10m images[1]
* */
return null;
}
@Override
public int getAwardType() {
// TODO 自动生成的方法存根
return awardType;
}
}
-
[5]Sky
package shoot; import java.awt.Graphics; import java.awt.image.BufferedImage; /** * 天空: * @author YANG * */ public class Sky extends FlyingObject{ private static BufferedImage images; //静态代码块 static { images = loadImage("background.png"); } private int speed;//速度 public int y1;//第二张图片的坐标 /**构造方法*/ public Sky(){ super(ShootMain.SCREEN_WIDTH, ShootMain.SCREEN_HEIGHT, 0, 0); speed = 1; y1 = -ShootMain.SCREEN_HEIGHT; } /**天空移动*/ public void step(){ y+= speed; y1+=speed; if (y>=ShootMain.SCREEN_HEIGHT) { y=-ShootMain.SCREEN_HEIGHT; } if (y1>=ShootMain.SCREEN_HEIGHT) { y1=-ShootMain.SCREEN_HEIGHT; } } @Override public BufferedImage getImage() { // TODO Auto-generated method stub return images; } public void paintObject(Graphics g){ g.drawImage(getImage(), x, y, null); g.drawImage(getImage(), x, y1, null); } }
-
[6] Bullet
package shoot;
import java.awt.image.BufferedImage;
/**
* 子弹
* @author YANG
*
*/
public class Bullet extends FlyingObject{
private static BufferedImage images;
//静态代码块
static {
images = loadImage("bullet.png");
}
private int speed;//速度
/**构造方法*/
public Bullet(int x, int y){
super(8, 14, x, y);
speed = 1;
}
/**子弹的移动*/
public void step(){
this.y -= speed;
}
//重写getImage()中的方法获取图片
@Override
public BufferedImage getImage() {
// TODO Auto-generated method stub
if (isLife()) {
return images;
}else if(isDead()){
state = REMOVE;
}
return null;
}
public boolean outOfBounds() {
// TODO 自动生成的方法存根
return this.y<=-this.height;
}
}
- [7] ShootMain
package shoot;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.StyledEditorKit.ForegroundAction;
/**
* 主函数的类:
*
* @author YANG
*
*/
public class ShootMain extends JPanel {
public static final int SCREEN_WIDTH = 400;
public static final int SCREEN_HEIGHT = 700;
// 起始状态START、RUNNING、PAUSE、GAME_OVER
// 默认起始状态
/**
* 鼠标点击事件:
* 启动状态:结束----启动
* 暂停状态:鼠标从屏幕里滑道外;
* 运行状态:从外到里
* 结束状态:英雄机的生命值为0
*/
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;
public int state = START;
public static BufferedImage start;
public static BufferedImage pause;
public static BufferedImage gameover;
static{
start = FlyingObject.loadImage("start.png");
pause = FlyingObject.loadImage("pause.png");
gameover = FlyingObject.loadImage("gameover.png");
}
private Sky sky = new Sky();
private Hero hero = new Hero();
private FlyingObject[] flys ={};
private Bullet[] bullets ={};
public FlyingObject nextOne(){
Random rand =new Random();
int type = rand.nextInt(20);
if(type<5){
return new Airplane();
}else if(type < 12){
return new Bee();
}else{
return new BigAirplane();
}
}
// 实现敌人入场
int enterindex=0;
public void enterAction(){
enterindex++;
if (enterindex % 40 == 0) {
// 获取到敌人
FlyingObject f = nextOne();
flys = Arrays.copyOf(flys, flys.length+1);
flys[flys.length-1]=f;
// 敌人添加到数组的最后一位
}
}
// 子弹入场
int shootIndex=0;
public void shootAction(){
shootIndex++;
if (shootIndex % 40 == 0) {
Bullet[] bs = hero.shoot();//获取子弹数组
bullets =Arrays.copyOf(bullets, bullets.length+bs.length);
// 将产生的子弹数组放到原数组中的最后
System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);
}
}
// 飞行物移动
public void stepAction(){
sky.step();
for (int i = 0; i < flys.length; i++) {
flys[i].step();
}
for (int i = 0; i < bullets.length; i++) {
bullets[i].step();
}
}
public void outOfBoundsAction(){
int index = 0; //存放不越界的数组下标
// 新建不越界的敌人数组
FlyingObject[] flysLive = new FlyingObject[flys.length];
for (int i = 0; i < flys.length; i++) {
// 获取到每一个敌人
FlyingObject f =flys[i] ;
// 判断是否不越界
if(!f.outOfBounds()){
flysLive[index] = f;
index++;
}
// 如果不越界,
// 将不越界的敌人存放到不越界的数组中
}
flys =Arrays.copyOf(flysLive, index);
index = 0;
Bullet[] bulletsLive = new Bullet[bullets.length];
for (int i = 0; i < bullets.length; i++) {
Bullet b = bullets[i];
if (!b.outOfBounds()) {
bulletsLive[index] = b;
index++;
}
}
bullets = Arrays.copyOf(bulletsLive, index);
}
int score =0;
// 子弹与敌人的碰撞
public void bulletBangAction(){
//遍历所有的子弹
for (int i = 0; i < bullets.length; i++) {
//获取每一个子弹
Bullet b = bullets[i];
// 遍历所有的敌人
for (int j = 0; j < flys.length; j++) {
FlyingObject f = flys[j];
if(f.hit(b)&&b.isLife()&&f.isLife()){
f.goDead();//敌人over
b.goDead();//子弹over
if (f instanceof Enemy) {//如果撞上的是敌人就能得分
Enemy e = (Enemy)f;
score += e.getScore();
}
// 如果撞上的是奖励
if (f instanceof Award) {
Award a =(Award)f;
int type = a.getAwardType();
switch(type){
case Award.DOUBLE_FIRE:
hero.addDoubleFire();
break;
case Award.LIFE:
hero.addLife();
break;
}
}
}
}
}
// 获取每一个敌人
// 判断碰撞
}
// 英雄机与敌人发生碰撞
public void heroBangAction(){
/**
* 思路:
* (1)借助FlyingObject中的hit()方法检测碰撞
* (2)借助FlyingObject中的goDead()方法over
* (3)在hero类中设计一个方法实现碰撞之后substractLife()减少生命,clearDoubleFire()
* (4)在run()方法中实现英雄机与敌人发生碰撞
* heroBangAction();
* 遍历敌人获取到每一个敌人
* 判断撞上了
* 敌人over,英雄机减少生命,清空火力。
*
*/
// 遍历所有的敌人
for (int i = 0; i < flys.length; i++) {
FlyingObject f = flys[i];
if (hero.isLife()&&f.isLife()&&f.hit(hero)) {
f.goDead();
hero.substractLife();
hero.clearDoubleFire();
}
}
}
// 检测游戏是否结束
public void checkGameOver(){
// 判断英雄机的生命值如果小于零的话,游戏结束,修改状态。
if (hero.getLife() <= 0) {
state =GAME_OVER;
}
}
public void action() {
// 鼠标的点击事件
// 鼠标适配器
MouseAdapter ma =new MouseAdapter() {
/**重写*/
public void mouseMoved(MouseEvent e){
int x = e.getX();
int y = e.getY();
// System.out.println(x+","+y);
hero.movedTo(x, y);
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO 自动生成的方法存根
switch (state) {
case START:
state =RUNNING;
break;
case GAME_OVER:
score =0;
sky = new Sky();
hero = new Hero();
flys = new FlyingObject[0];
bullets = new Bullet[0];
state = START;
break;
default:
break;
}
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO 自动生成的方法存根
if (state == PAUSE) {
state = RUNNING;
}
}
@Override
public void mouseExited(MouseEvent e) {
// TODO 自动生成的方法存根
if (state==RUNNING) {
state = PAUSE;
}
}
};
this.addMouseListener(ma);//处理鼠标的操作事件
this.addMouseMotionListener(ma);//处理鼠标的移动事件
// 定时器
Timer timer =new Timer();
int inters = 10;
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO 自动生成的方法存根
if (state == RUNNING) {
// 敌人入场
stepAction();
enterAction();
// 子弹入场
shootAction();
// 删除越界的飞行物
outOfBoundsAction();
bulletBangAction();
heroBangAction();
checkGameOver();
}
// 重绘
repaint();
}
}, inters, inters);//计划任务
}
public void paint(Graphics g) {
super.paint(g);
sky.paintObject(g);
hero.paintObject(g);
for (int i = 0; i < flys.length; i++) {
flys[i].paintObject(g);
}
for (int i = 0; i < bullets.length; i++) {
bullets[i].paintObject(g);
}
g.drawString("分数:"+score, 30, 60);
g.drawString("生命:"+hero.getLife(), 30, 80);
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;
default:
break;
}
}
public static void main(String[] args) {
ShootMain sm = new ShootMain();
JFrame jf = new JFrame();
jf.add(sm);// 将画布装在窗体上
jf.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);// 窗体大小
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocationRelativeTo(null);// 居中显示
jf.setVisible(true);
sm.action();
}
}
- [8] FlyingObject
package shoot;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.imageio.ImageIO;
/**
* 父类:飞行物
* @author YANG
*
*/
public abstract class FlyingObject {
// 成员变量
protected int width;// 宽
protected int height;// 高
protected int x;// x坐标
protected int y;// y坐标
public static final int LIFE = 0;//存活
public static final int DEAD = 1;//over
public static final int REMOVE = 2;//删除
public int state = LIFE;// 当前状态
public FlyingObject(int width, int height) {
this.width = width;
this.height = height;
Random rand = new Random();
this.x = rand.nextInt(ShootMain.SCREEN_WIDTH - this.width);
this.y = -this.height;
}
public FlyingObject(int width, int height, int x, int y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
public void step() {
System.out.println("飞行物移动!");
}
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 BufferedImage getImage();
public void paintObject(Graphics g) {
g.drawImage(this.getImage(),x, y, null);
}
//判断当前状态是不是存活的
public boolean isLife(){
return state ==LIFE;
}
//判断当前状态是不是存活的
public boolean isDead(){
return state ==DEAD;
}
//判断当前状态是不是存活的
public boolean isRemove(){
return state ==REMOVE;
}
// 检测是否越界
public boolean outOfBounds(){
return this.y>=ShootMain.SCREEN_HEIGHT;
}
// 检测子弹与敌人发生碰撞this:
public boolean hit(FlyingObject other){
int x1 = this.x - other.width;
int y1 = this.y - other.height;
int x2 = this.x + this.width;
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;//将对象的状态修改为DEAD;
}
}
- [9] Enemy
package shoot;
/**
* 得分接口
* @author YANG
*
*/
public interface Enemy {
// 得分接口
public int getScore();
}
- [10] Award
package shoot;
/**
* 奖励接口
* @author YANG
*
*/
public interface Award {
public int DOUBLE_FIRE =0;
public int LIFE =1;
// 获取奖励类型
public int getAwardType();
}