java小游戏-java小游戏-飞机大战
- 1 窗口创建
- 2 背景图片添加
- 3 启动页面制作
- 4 启动页面点击事件
- 5 游戏物体父类的编写
- 6 背景的移动
- 7 双缓存的添加
- 8 背景图片的循环出现
- 9 添加我方飞机
- 10 添加首颗子弹
- 11 我方子弹的批量添加
- 12 敌方飞机的批量添加
- 13 我方子弹与敌人飞机碰撞检测
- 14 我方子弹与敌方飞机碰撞后处理
- 15 我方飞机与敌方飞机的碰撞检测
- 16 敌方boss的添加和移动
- 17 为敌方boss添加子弹
- 18 我方飞机与敌方的子弹碰撞检测
- 19 我方飞机与敌方boss的碰撞检测
- 20 计分面板的编写
- 21 游戏规则的改变
- 22 为boss添加生命值
- 23 游戏的暂停功能
- 24 子弹和敌机的越界消失
- 25 为敌机添加爆炸效果图
- 26 为敌方boss添加血条
1 窗口创建
创建GameWin类
public class GameWin extends JFrame {
public void launch(){
//设置窗口是否可见
this.setVisible(true);
//设置窗口大小
this.setSize(600,600);
//设置窗口位置
this.setLocationRelativeTo(null);
//设置窗口标题
this.setTitle("飞机大战");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//不可修改边框
this.setResizable(false);
}
public static void main(String[] args) {
GameWin gameWin = new GameWin();
gameWin.launch();
}
}
2 背景图片添加
先导入图片在项目下img文件下
创建GameUtils类
public class GameUtils {
//背景图片
public static Image bgImage = Toolkit.getDefaultToolkit().getImage("img/bg.jpg");
}
在GameWin类重写paint方法
@Override
public void paint(Graphics g) {
g.drawImage(GameUtils.bgImage,0,0,null);
}
3 启动页面制作
在GameUtils类添加参数
//boss图片
public static Image bossImage = Toolkit.getDefaultToolkit().getImage("img/boss.png");
//爆炸图片
public static Image explodeImage = Toolkit.getDefaultToolkit().getImage("img/explode/e6.gif");
在GameWin类添加状态
//游戏状态 0 未开始 1 游戏中 2 暂停 3 通关失败 4 通关成功
public static int state = 0;
@Override
public void paint(Graphics g) {
if(state == 0){
g.drawImage(GameUtils.bgImage,0,0,null);
g.drawImage(GameUtils.bossImage,220,120,null);
g.drawImage(GameUtils.explodeImage,270,350,null);
g.setColor(Color.yellow);
g.setFont(new Font("仿宋",Font.BOLD,40));
g.drawString("点击开始游戏",180,300);
}
}
4 启动页面点击事件
在GameWin类launch方法添加鼠标点击事件
public void launch(){
...
//鼠标点击事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(e.getButton() == 1 && state == 0){//鼠标左键点击
state = 1;
repaint();
}
}
});
}
@Override
public void paint(Graphics g) {
...
if(state == 1){
g.drawImage(GameUtils.bgImage,0,0,null);
g.drawImage(GameUtils.bossImage,220,120,null);
g.drawImage(GameUtils.explodeImage,270,350,null);
g.setColor(Color.yellow);
g.setFont(new Font("仿宋",Font.BOLD,40));
g.drawString("游戏开始了",180,300);
}
}
5 游戏物体父类的编写
创建GameObj类
public class GameObj {
Image img;
//坐标
int x,y;
//宽高
int wight,height;
//移动速度
double speed;
//窗口
GameWin frame;
public GameObj() { }
public GameObj(Image img, int x, int y, double speed) {
this.img = img;
this.x = x;
this.y = y;
this.speed = speed;
}
public GameObj(Image img, int x, int y, int wight, int height, double speed, GameWin frame) {
this.img = img;
this.x = x;
this.y = y;
this.wight = wight;
this.height = height;
this.speed = speed;
this.frame = frame;
}
//绘制自身方法
public void paintSelf(Graphics g){
g.drawImage(img,x,y,null);
}
//获取矩形对象,用于碰撞检测
public Rectangle getRec(){
return new Rectangle(x,y,wight,height);
}
public Image getImg() { return img; }
public void setImg(Image img) { this.img = img; }
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getWight() { return wight; }
public void setWight(int wight) { this.wight = wight; }
public int getHeight() { return height; }
public void setHeight(int height) { this.height = height; }
public double getSpeed() { return speed; }
public void setSpeed(double speed) { this.speed = speed; }
public GameWin getGameWin() { return frame; }
public void setGameWin(GameWin frame) { this.frame = frame; }
}
6 背景的移动
创建BgObj类
public class BgObj extends GameObj{
@Override
public Image getImg() {
return super.getImg();
}
public BgObj(){}
public BgObj(Image img, int x, int y, double speed) {
super(img, x, y, speed);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y += speed;
}
}
在GameWin类中引用
//背景图片
BgObj bgObj = new BgObj(GameUtils.bgImage,0,-2000,2);
public void launch(){
...
while (true){
repaint();
try {
Thread.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g) {
...
if(state == 1){
bgObj.paintSelf(g);
}
}
7 双缓存的添加
在GameWin类添加参数
Image offScreenImage = null;
//宽高
int width = 600;
int height = 600;
public void launch(){
//设置窗口是否可见
this.setVisible(true);
//设置窗口大小
...
}
@Override
public void paint(Graphics g) {
if(offScreenImage == null){
offScreenImage = createImage(width,height);
}
Graphics gImage = offScreenImage.getGraphics();
gImage.fillRect(0,0,width,height);
if(state == 0){
gImage.drawImage(GameUtils.bgImage,220,120,null);
gImage.drawImage(GameUtils.bossImage,220,120,null);
gImage.drawImage(GameUtils.explodeImage,270,350,null);
gImage.setColor(Color.yellow);
gImage.setFont(new Font("仿宋",Font.BOLD,40));
gImage.drawString("点击开始游戏",180,300);
}
if(state == 1){
bgObj.paintSelf(gImage);
}
g.drawImage(offScreenImage,0,0,width,height,null);
}
8 背景图片的循环出现
在BgObj类修改paintSelf方法
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y += speed;
if(y >= 0){
y = -2000;
}
}
9 添加我方飞机
在GameUtils类添加常量
//我方战斗机图片
public static Image planeImg = Toolkit.getDefaultToolkit().getImage("img/plane.png");
创建PlaneObj类
public class PlaneObj extends GameObj {
@Override
public Image getImg() {
return super.getImg();
}
public PlaneObj() {
super();
}
public PlaneObj(Image img, int x, int y, int width, int height, double speed, GameWin frame) {
super(img, x, y, width, height, speed, frame);
this.frame.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
PlaneObj.super.x = e.getX() - 11;
PlaneObj.super.y = e.getY() - 16;
}
});
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在GameWin中引用
//我方飞机对象
public PlaneObj planeObj = new PlaneObj(GameUtils.planeImg,290,550,20,30,0,this);
@Override
public void paint(Graphics g) {
...
if(state == 1){
//游戏中
bgObj.paintSelf(gImage);
planeObj.paintSelf(gImage);
}
g.drawImage(offScreenImage,0,0,width,height,null);
}
10 添加首颗子弹
在GameUtils类添加常量
//我方子弹图片
public static Image shellImg = Toolkit.getDefaultToolkit().getImage("img/shell.png");
创建ShellObj类
public class ShellObj extends GameObj{
@Override
public Image getImg() {
return super.getImg();
}
public ShellObj() {
super();
}
public ShellObj(Image img, int x, int y, int wight, int height, double speed, GameWin gameWin) {
super(img, x, y, wight, height, speed, gameWin);
}
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y -= speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在GameWin类中引用
//我方子弹
ShellObj shellObj = new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this);
@Override
public void paint(Graphics g) {
...
if(state == 1){
//游戏中
bgObj.paintSelf(gImage);
planeObj.paintSelf(gImage);
shellObj.paintSelf(gImage);
}
g.drawImage(offScreenImage,0,0,width,height,null);
}
11 我方子弹的批量添加
在GameUtils类添加参数
//所有游戏物体的集合
public static List<GameObj> gameObjList = new ArrayList<>();
//我方子弹的集合
public static List<ShellObj> shellObjList = new ArrayList<>();
在GameWin类中生成子弹
// //我方子弹
// ShellObj shellObj = new ShellObj(GameUtils.shellImg,planeObj.getX()+3,planeObj.getY()-16,14,29,5,this);
//游戏的重绘次数
int count = 1;
public void launch() {
...
//设置窗口标题
this.setTitle("飞机大战");
GameUtils.gameObjList.add(bgObj);
GameUtils.gameObjList.add(planeObj);
while (true) {
if (state == 1) {
createObj();
repaint();
}
try {
Thread.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g) {
...
if (state == 1) {
//游戏中
for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
GameUtils.gameObjList.get(i).paintSelf(gImage);
}
}
g.drawImage(offScreenImage, 0, 0, width, height, null);
count++;
}
//创建对象
void createObj() {
//我方子弹
if (count%15 == 0) {
GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg, planeObj.getX() + 3, planeObj.getY() - 16, 14, 29, 5, this));
GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size()-1));
}
}
12 敌方飞机的批量添加
在GameUtils类添加参数
//敌机图片
public static Image enemyImg = Toolkit.getDefaultToolkit().getImage("img/enemy.png");
//敌机的集合
public static List<EnemyObj> enemyObjList = new ArrayList<>();
创建EnemyObj类
public class EnemyObj extends GameObj {
public EnemyObj() {
super();
}
public EnemyObj(Image img, int x, int y, int width, int height, double speed, GameWin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在GameWin类中创建
//创建对象
void createObj() {
//我方子弹
if (count%15 == 0) {
GameUtils.shellObjList.add(new ShellObj(GameUtils.shellImg, planeObj.getX() + 3, planeObj.getY() - 16, 14, 29, 5, this));
GameUtils.gameObjList.add(GameUtils.shellObjList.get(GameUtils.shellObjList.size()-1));
}
//敌机创建
if (count%15 == 0) {
GameUtils.enemyObjList.add(new EnemyObj(GameUtils.enemyImg, (int)(Math.random()*12)*50,0,49,36,5,this));
GameUtils.gameObjList.add(GameUtils.enemyObjList.get(GameUtils.enemyObjList.size()-1));
}
}
13 我方子弹与敌人飞机碰撞检测
在EnemyObj类paintSelf方法添加判断
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
//碰撞检测
for (ShellObj shellObj : GameUtils.shellObjList) {
if(this.getRec().intersects(shellObj.getRec())){
System.out.println("碰撞了");
}
}
}
14 我方子弹与敌方飞机碰撞后处理
在GameUtils类添加参数
//要删除元素的集合
public static List<GameObj> removeList = new ArrayList<>();
在EnemyObj类修改paintSelf方法
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
//碰撞检测
for (ShellObj shellObj : GameUtils.shellObjList) {
if(this.getRec().intersects(shellObj.getRec())){
shellObj.setX(-100);
shellObj.setY(-100);
this.x = -200;
this.y = -200;
GameUtils.removeList.add(shellObj);
GameUtils.removeList.add(this);
}
}
}
在GameWin类修改paint方法
@Override
public void paint(Graphics g) {
...
if (state == 1) {
//游戏中
for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
GameUtils.gameObjList.get(i).paintSelf(gImage);
}
GameUtils.gameObjList.removeAll(GameUtils.removeList);
}
g.drawImage(offScreenImage, 0, 0, width, height, null);
count++;
}
15 我方飞机与敌方飞机的碰撞检测
在EnemyObj类修改paintSelf方法
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
//敌我飞机碰撞检测
if(this.getRec().intersects(this.frame.planeObj.getRec())){
GameWin.state = 3;
}
...
}
在GameWin类修改paint方法
@Override
public void paint(Graphics g) {
...
if (state == 3) {
//失败
gImage.drawImage(GameUtils.explodeImage, planeObj.getX()-33,planeObj.getY()-50, null);
gImage.setColor(Color.red);
gImage.setFont(new Font("仿宋", Font.BOLD, 50));
gImage.drawString("GAME OVER", 180, 300);
}
g.drawImage(offScreenImage, 0, 0, width, height, null);
count++;
}
16 敌方boss的添加和移动
创建BossObj类
public class BossObj extends GameObj {
public BossObj(Image img, int x, int y, int width, int height, double speed, GameWin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
if (x > 550 || x < -50) {
speed = -speed;
}
x += speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在GameWin类中引用
//敌方boss对象
public BossObj bossObj = new BossObj(GameUtils.bossImage,250,35,155,100,5,this);
public void launch() {
...
this.setTitle("飞机大战");
GameUtils.gameObjList.add(bgObj);
GameUtils.gameObjList.add(planeObj);
GameUtils.gameObjList.add(bossObj);
...
}
17 为敌方boss添加子弹
创建BulletObj类
public class BulletObj extends GameObj {
public BulletObj(Image img, int x, int y, int width, int height, double speed, GameWin frame) {
super(img, x, y, width, height, speed, frame);
}
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
}
@Override
public Rectangle getRec() {
return super.getRec();
}
}
在GameUtils类中添加参数
//敌机子弹图片
public static Image bulletImg = Toolkit.getDefaultToolkit().getImage("img/bullet.png");
//敌机子弹的集合
public static List<BulletObj> bulletObjList = new ArrayList<>();
在GameWin生成子弹
//创建对象
void createObj() {
...
//敌机子弹
if (count%15 == 0) {
GameUtils.bulletObjList.add(new BulletObj(GameUtils.bulletImg, bossObj.getX() + 76, bossObj.getY() + 85, 15, 25, 5, this));
GameUtils.gameObjList.add(GameUtils.bulletObjList.get(GameUtils.bulletObjList.size()-1));
}
}
18 我方飞机与敌方的子弹碰撞检测
在BulletObj类paintSelf方法添加判断
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
y += speed;
//敌方子弹与我方飞机的碰撞检测
if (this.getRec().intersects(this.frame.planeObj.getRec())){
GameWin.state = 3;
}
}
19 我方飞机与敌方boss的碰撞检测
在PlaneObj类paintSelf方法添加判断
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
//我方飞机与敌方boss的碰撞检测
if (this.frame.bossObj != null && this.getRec().intersects(this.frame.bossObj.getRec())){
GameWin.state = 3;
}
}
20 计分面板的编写
在GameUtils类添加方法
//绘制字符串的工具类
public static void drawWord(Graphics gImage,String str,Color color,int size,int x,int y){
gImage.setColor(color);
gImage.setFont(new Font("仿宋",Font.BOLD,size));
gImage.drawString(str,x,y);
}
在GameWin类添加参数
//游戏得分
public static int score = 0;
@Override
public void paint(Graphics g) {
。。。
if (state == 0) {
//未开始
gImage.drawImage(GameUtils.bgImage, 220, 120, null);
gImage.drawImage(GameUtils.bossImage, 220, 120, null);
gImage.drawImage(GameUtils.explodeImage, 270, 350, null);
gImage.setColor(Color.yellow);
GameUtils.drawWord(gImage,"点击开始游戏",Color.yellow,40,180,300);
}
if (state == 1) {
//游戏中
for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
GameUtils.gameObjList.get(i).paintSelf(gImage);
}
GameUtils.gameObjList.removeAll(GameUtils.removeList);
}
if (state == 3) {
//失败
gImage.drawImage(GameUtils.explodeImage, planeObj.getX()-33,planeObj.getY()-50, null);
GameUtils.drawWord(gImage,"GAME OVER",Color.RED,50,180,300);
}
GameUtils.drawWord(gImage,score+" 分",Color.green,40,30,100);
g.drawImage(offScreenImage, 0, 0, width, height, null);
count++;
}
在EnemyObj类paintSelf方法自增
@Override
public void paintSelf(Graphics gImage) {
...
//碰撞检测
for (ShellObj shellObj : GameUtils.shellObjList) {
if(this.getRec().intersects(shellObj.getRec())){
shellObj.setX(-100);
shellObj.setY(-100);
this.x = -200;
this.y = -200;
GameUtils.removeList.add(shellObj);
GameUtils.removeList.add(this);
GameWin.score++;
}
}
}
21 游戏规则的改变
在GameWin类添加参数
//敌方boss对象
public BossObj bossObj = null;
//敌机出现的数量
int enemyCount = 0;
public void launch() {
...
GameUtils.gameObjList.add(bgObj);
GameUtils.gameObjList.add(planeObj);
//GameUtils.gameObjList.add(bossObj);
...
}
//创建对象
void createObj() {
//敌机子弹
if (count%15 == 0 && bossObj != null) {
GameUtils.bulletObjList.add(new BulletObj(GameUtils.bulletImg, bossObj.getX() + 76, bossObj.getY() + 85, 15, 25, 5, this));
GameUtils.gameObjList.add(GameUtils.bulletObjList.get(GameUtils.bulletObjList.size()-1));
}
//敌机创建
if (count%15 == 0) {
GameUtils.enemyObjList.add(new EnemyObj(GameUtils.enemyImg, (int)(Math.random()*12)*50,0,49,36,5,this));
GameUtils.gameObjList.add(GameUtils.enemyObjList.get(GameUtils.enemyObjList.size()-1));
enemyCount++;
}
...
if(enemyCount > 100 && bossObj == null){
bossObj = new BossObj(GameUtils.bossImage,250,35,155,100,5,this);
GameUtils.gameObjList.add(bossObj);
}
}
22 为boss添加生命值
在BossObj类添加参数判断
//boos生命值
int life = 10;
@Override
public void paintSelf(Graphics gImage) {
super.paintSelf(gImage);
if (x > 550 || x < -50) {
speed = -speed;
}
x += speed;
for (ShellObj shellObj : GameUtils.shellObjList){
if (this.getRec().intersects(shellObj.getRec())){
shellObj.setX(-100);
shellObj.setY(100);
GameUtils.removeList.add(shellObj);
life--;
}
if (life <= 0){
GameWin.state = 4;
}
}
}
在GameWin类添加游戏通关绘制
@Override
public void paint(Graphics g) {
...
if (state == 4) {
//通关
gImage.drawImage(GameUtils.explodeImage, bossObj.getX() + 30,bossObj.getY(), null);
GameUtils.drawWord(gImage,"游戏通关",Color.green,50,190,300);
}
GameUtils.drawWord(gImage,score+" 分",Color.green,40,30,100);
g.drawImage(offScreenImage, 0, 0, width, height, null);
count++;
}
23 游戏的暂停功能
在GameWin类中launch方法添加键盘监听事件
public void launch() {
...
//键盘监听事件
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
switch (state){
case 1:
state = 2;
break;
case 2:
state = 1;
break;
default:
}
}
}
});
...
}
24 子弹和敌机的越界消失
在ShellObj添加判断
@Override
public void paintSelf(Graphics g) {
super.paintSelf(g);
y -= speed;
//我方子弹的越界消失 条件 y < 0 改变后的坐标 (-100,100)
if (y < 0){
this.x = -100;
this.y = 100;
GameUtils.removeList.add(this);
}
}
在EnemyObj添加判断
@Override
public void paintSelf(Graphics gImage) {
...
//敌机的越界消失 判断条件 y > 600 改变后的坐标(-200,-200)
if (y > 600){
this.x = -200;
this.y = 200;
GameUtils.removeList.add(this);
}
...
}
在BulletObj添加判断
@Override
public void paintSelf(Graphics gImage) {
...
//敌方子弹的越界消失 条件 y > 600 改变后的坐标(-300,300)
if (y > 600){
this.x = -300;
this.y = 300;
GameUtils.removeList.add(this);
}
}
在GameWin类添加测试控制台输出
@Override
public void paint(Graphics g) {
...
count++;
System.out.println(GameUtils.gameObjList.size());
}
25 为敌机添加爆炸效果图
在GameObj类添加构造器
public GameObj(int x, int y) {
this.x = x;
this.y = y;
}
创建ExplodeObj类
public class ExplodeObj extends GameObj {
static Image[] pic = new Image[16];
int explodeCount = 0;
static {
for (int i = 0; i < pic.length; i++) {
pic[i] = Toolkit.getDefaultToolkit().getImage("img/explode/e"+(i+1)+".gif");
}
}
public ExplodeObj(int x, int y) {
super(x, y);
}
@Override
public void paintSelf(Graphics gImage) {
if (explodeCount < 16){
super.img = pic[explodeCount];
super.paintSelf(gImage);
explodeCount++;
}
}
}
在GameUtils添加参数
//爆炸的集合
public static List<ExplodeObj> explodeObjList = new ArrayList<>();
在EnemyObj类添加判断
@Override
public void paintSelf(Graphics gImage) {
...
//碰撞检测
for (ShellObj shellObj : GameUtils.shellObjList) {
if(this.getRec().intersects(shellObj.getRec())){
ExplodeObj explodeObj = new ExplodeObj(x,y);
GameUtils.explodeObjList.add(explodeObj);
GameUtils.removeList.add(explodeObj);
shellObj.setX(-100);
shellObj.setY(-100);
this.x = -200;
this.y = -200;
GameUtils.removeList.add(shellObj);
GameUtils.removeList.add(this);
GameWin.score++;
}
}
}
在GameWin类添加
@Override
public void paint(Graphics g) {
...
if (state == 1) {
GameUtils.gameObjList.addAll(GameUtils.explodeObjList);
//游戏中
for (int i = 0; i < GameUtils.gameObjList.size(); i++) {
GameUtils.gameObjList.get(i).paintSelf(gImage);
}
GameUtils.gameObjList.removeAll(GameUtils.removeList);
}
...
}
26 为敌方boss添加血条
在BossObj类的paintSelf方法添加绘制
@Override
public void paintSelf(Graphics gImage) {
...
//血条的白色背景
gImage.setColor(Color.white);
gImage.fillRect(20,40,100,10);
//血条的绘制
gImage.setColor(Color.red);
gImage.fillRect(20,40,life * 100 / 10,10);
}