Shoot射击游戏第九天:
理论:
1.内存管理
2.面向对象三大特征 案例:
1.英雄机与敌人的碰撞:
1)借用FlyingObject的isHit()碰撞检测、goDead()飞行物去死 在Hero中设计subtractLife()减命、clearFire()清空火力值 2)英雄机与敌人的碰撞为定时发生的,所以在run()中调用heroBangAction()实现英雄机与敌人的碰撞 在heroBangAction()中: 遍历敌人得敌人,判断若都活着并且撞上了: 敌人去死、英雄机减命、英雄机清空火力值
2.检测游戏结束:
1)借用Hero的getLife()获取命数
2)检测游戏结束为定时发生的,所以在run()中调用checkGameOverAction()检测游戏的结束 在checkGameOverAction()中: 判断:若英雄机命数<=0表示游戏结束,则......
3.画状态:
1)在World中设计START、RUNNING、PAUSE、GAME_OVER状态常量,state变量表示当前状态 在Images中设计start、pause、gameover状态图片,静态块中赋值 在World类的paint()中: 设计在不同状态下画不同的图
2)设计run中那一堆action,仅在运行状态下执行 设计mouseMoved()中英雄机跟着鼠标移动,仅在运行状态下执行
3)重写mouseClicked()鼠标点击事件: 启动状态变运行状态,游戏结束状态先清理现场再变启动状态 重写mouseExited()鼠标移出事件: 运行状态变为暂停状态 重写mouseEntered()鼠标移入事件: 暂停状态变为运行状态
知识点
1.内存管理:由JVM来管理
1)堆:
1.1)存储new出来的对象(包括实例变量)
1.2)垃圾:没有任何引用所指向的对象 垃圾回收器(GC)不定时到内存堆中回收垃圾, 回收过程是透明(看不到的)的,不一定一看到垃圾就立刻回收, 通过调用System.gc()建议JVM尽快调度GC来回收
1.3)实例变量的生命周期: 创建对象时存储在堆中,对象被回收时一并被回收
1.4)内存泄漏:不再使用的内存还没有被及时的回收 建议:不再使用的对象及时将引用设置为null
2)栈:
2.1)存储正在调用的方法中的局部变量(包括方法的参数)
2.2)调用方法时,会在栈中为该方法分配一块对应的栈帧, 栈帧中存储局部变量(包括参数), 方法调用结束时,栈帧被自动清除,局部变量一并被清除
2.3)局部变量的生命周期: 调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
3)方法区:
3.1)存储.class字节码文件(包括静态变量、方法)
3.2)方法只有一份,通过this来区分具体的调用对象
面向对象三大特征:------面试题:你对面向对象的理解?
1.封装:
1)类:封装的是对象的属性和行为
2)方法:封装的是具体的业务逻辑功能实现 3)访问控制修饰符:封装的是具体的访问权限
2.继承:
1)作用:代码复用
2)超类:所有派生类所共有的属性和行为 接口:部分派生类所共有的属性和行为 派生类:派生类所特有的属性和行为
3)单一继承、多接口实现,具备传递性
3.多态:
1)行为多态:所有抽象方法都是多态的 对象多态:所有对象都是多态的
2)向上造型、强制类型转换、instanceof判断
3)多态的表现形式:
3.1)重写:表现了形为的多态
3.2)向上造型:表现了对象的多态
//-------------------复用性好、扩展性好、维护性好
//Airplane(1)--------
//BigAirplane(3)
//BigYellowBee(8)----适用于所有实现EnemyScore得分接口的类
if(f instanceof EnemyScore){
EnemyScore es = (EnemyScore)f;
score += es.getScore(); //getScore()是多态的
}
//Bee()
//BigYellowBee()-----适用于所有实现EnemyAward奖励接口的类
if(f instanceof EnemyAward){
EnemyAward ea = (EnemyAward)f;
int type = ea.getAwardType(); //getAwardType()是多态的
switch(type){
case 0:
hero.addFire();
break;
case 1:
hero.addLife();
break;
}
}
//-------------复用性差、扩展性差、维护性差
if(f instanceof Airplane){---------只能适用于Airplane
Airplane a = (Airplane)f;
score += a.getScore();
}
if(f instanceof BigAirplane){------只能适用于BigAirplane
BigAirplane ba = (BigAirplane)f;
score += ba.getScore();
}
if(f instanceof Bee){--------------只能适用于Bee
Bee bee = (Bee)f;
int type = bee.getAwardType();
switch(type){
case 0:
hero.addFire();
break;
case 1:
hero.addLife();
break;
}
}
if(f instanceof BigYellowBee){-----只能适用于BigYellowBee
BigYellowBee byb = (BigYellowBee)f;
score += byb.getScore();
int type = byb.getAwardType();
switch(type){
case 0:
hero.addFire();
break;
case 1:
hero.addLife();
break;
}
}
}
}
}
}
儿子类和爸爸类和干爹之间的关系
人 p1 = new 理发师();
人 p2 = new 外科医生();
人 p3 = new 演员();
p1.cut(); //剪发
p2.cut(); //开刀
p3.cut(); //停止表演
abstract class 人{
abstract void cut();
}
class 理发师 extends 人{
void cut(){ 剪发 }
}
class 外科医生 extends 人{
void cut(){ 开刀 }
}
class 演员 extends 人{
void cut(){ 停止表演 }
}
Object:所有类的鼻祖----所有类都直接或间接的继承了Object
垃圾回收器(GC)-----不定时到内存中清扫垃圾
代码:
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Airplane extends FlyingObject implements EnemyScore{
private int speed;// 移动速度
public Airplane() {
super(48, 50);
speed = 4;
}
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;
}
public int getScore(){
return 1;//打掉小敌机的一分
}
}
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Bee extends FlyingObject implements EnemyAward{
private int xspeed;// x移动速度
private int yspeed;// y移动速度
private int awardType;// 奖励类型
public Bee() {
super(68, 51);
//
Random rand = new Random();
// x= rand.nextInt(400-width);
// y=-height;
xspeed = 2;
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;
}public int getAwardType(){
return awardType;
}
}
package cn.tedu.shoot;
import java.awt.image.BufferedImage;
//import java.util.Random;
public class BigAirplane extends FlyingObject implements EnemyScore{
private int speed;// 移动速度
public BigAirplane() {
super(66, 89);
// Random rand=new Random();
// x= rand.nextInt(400-width);
// y=-height;
speed = 3;
}
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;
}public int getScore(){
return 3;//大掉小敌机的三分
}
}
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;
}
public BufferedImage getImage() {
if (isLife()) {
return Images.bullet;
} else if (isDead()) {
state = REMOVE;
}
return null;
/*
* 若活着的:返回子弹图片 若死了的:将状态修改为REMOVE;同时不返回图片 若删除了的:不返回图片
*
*/
}
public boolean isOutOfBounds() {
return y<=-height;
}
}
package cn.tedu.shoot;
public interface EnemyAward {
public int FIRE =0;
public int LIFE =1;
public int getAwardType();
}
package cn.tedu.shoot;
//等分接口
public interface EnemyScore {
public int getScore();
}
package cn.tedu.shoot;
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 width;
protected int height;
protected int x;
protected int y;
// 重写
public abstract void step();// {
// System.out.println("飞行物移动了");
// }
// 获取对象的图片
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;
}public FlyingObject(int width, int height) {// 专门给小蜜蜂,大敌机,小敌机提供的,以为三种飞行器的x,y都是不同的,所以要写活
this.width = width;
this.height = height;
Random rand = new Random();
x = rand.nextInt(World.WIDTH - width);
y =-World.HEIGHT;
}
public FlyingObject(int width, int height, int x, int y) {// 专门给英雄机,天空子弹提供的,以为三种飞行器的x,y都是不同的,所以要写活
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
}
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() {
}
private int index = 0;
public BufferedImage getImage() {
return Images.heros[index++ % Images.heros.length];
}
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;
}
}
public void moveTo(int x,int y){
this.x=x-this.width/2;
this.y=y-this.height/2;
}
public void addLife(){
life++;
}
public int getlife(){
return life;
}
public void subtractLife(){
life--;
}
public void addFire(){
fire+=40;
}
public void clearFire(){
fire=0;
}
}
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 {// 初始化静态资源
// sky =读取BufferedImage。png图片;
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];
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.tedu.shoot;
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;
}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.tedu.shoot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.omg.Messaging.SyncScopeHelper;
import java.awt.image.BufferedImage;
import java.awt.Graphics;
import java.util.TimerTask;
import java.util.Timer;
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 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);
}
}
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].isRemove()) {// 越界了
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);// 缩容
}
}
}
}
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.isLife() && f.isLife() && f.isHit(bullets[i])) {
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() {
for (int i = 0; i < enemies.length; i++) {
FlyingObject f = enemies[i];
if (hero.isLife() && f.isLife() && 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();
hero.moveTo(x, y);
}
}
public void mouseClicked(MouseEvent e) {
switch(state){
case START:
state=RUNNING;
break;
case GAME_OVER:
score=0;
hero=new Hero();
sky=new Sky();
enemies=new FlyingObject[0];
bullets=new Bullet[0];
state =START;
break;
}
}public void mouseExited(MouseEvent e) {
if (state==RUNNING){//运行状态时
state=PAUSE;//修改为暂停状态
}
}public void mouseEntered(MouseEvent e) {
if(state==PAUSE){
state=RUNNING;
}
}
};// 侦听器对象
this.addMouseListener(m);// 处理鼠标操作事件
this.addMouseMotionListener(m);// 处理鼠标滑动事件
Timer timer = new Timer();
int intervel = 10;// 定时间隔等于(10毫秒走一次)
timer.schedule(new TimerTask() {
public void run() {// 定时干的事
if (state ==RUNNING){
enterAction();
shootAction();
stepAction();
outOfBoundsAction();
System.out.println(enemies.length + "," + bullets.length);
bulletBangAction();
heroBangAction();
checkGameOverAction();
}
repaint();
}
}, intervel, intervel);
}
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);
}
g.drawString("SCORE:" + score, 10, 25);
g.drawString("LIFE:" + 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);
break;
}
}
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/12740633
这里飞机大战就结束了希望我的分享对你有所帮助
大家如果真的想学好的话就不要着急一点点写,要重头写一遍写到最后才真正的有收获
我第一次写写了3个多小时而且还有好多的bug希望大家不要着急
//刚开始买了个关子就是为什么这么多敌人和子弹,如果我的博客你有认真的阅读那么我相信你应该知道了原因
注:这里飞机大战是本人在某公司学习时所写,用来基础学习请不要拿来做一些违法的事情,仅供与学习交流.