FlyBird(飞翔的小鸟)Java小游戏

45 篇文章 10 订阅
订阅专栏

FlyBird(飞翔的小鸟)Java小游戏

游戏简介

《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品,游戏于2013年5月24日上线,并在2014年2月突然暴红。2014年2月,《Flappy Bird》被开发者本人从苹果及谷歌应用商店(Google Play)撤下。2014年8月份正式回归App Store,正式加入Flappy迷们期待已久的多人对战模式。游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍。

在《FlappyBird》这款游戏中,玩家只需要用一根手指来操控,点击触摸屏幕,小鸟就会往上飞,不断的点击就会不断的往高处飞。放松手指,则会快速下降。所以玩家要控制小鸟一直向前飞行,然后注意躲避途中高低不平的管子。
1、在游戏开始后,点击屏幕,要记住是有间歇的点击屏幕,不要让小鸟掉下来。
2、尽量保持平和的心情,点的时候不要下手太重,尽量注视着小鸟。
3、游戏的得分是,小鸟安全穿过一个柱子且不撞上就是1分。当然撞上就直接挂掉,只有一条命。

上面简介是这款游戏的原始版本的简介,本文主要是根据这款游戏,进行逆向工程把这款游戏复刻一遍。

游戏展示

在这里插入图片描述
按键盘的上下键来控制小鸟上下移动,碰到管道会大量扣血,但是没有的时候会缓慢回血。
在这里插入图片描述

当生命值不是正数的时候,就结束游戏,按下空格可以重新开始。
在这里插入图片描述
我的代码如下
在这里插入图片描述

我的gitee地址:https://gitee.com/geek-li-hua/small-game

代码讲解

文件结构
在这里插入图片描述

首先是util包,这个包中放置的就是一些工具类,这里面存放的就是整个项目需要用到的各种常数,希望修改游戏的各种初始大小的话,那么可以通过修改这个类中的各个常数。

Constant类

package com.bird.util;

import java.awt.*;

public class Constant {
    // 窗口的大小
    public static final int FRAM_WIDTH=600;
    public static final int FRAM_HEIGHT=500;

    // 窗口的标题
    public static final String FRAM_TITLE="Fly Bird";


    // 窗口的初始化位置
    public static final int FRAM_X=200;
    public static final int FRAM_Y=200;

    // 图片路径
    public static final String BK_IMG_PATH = "img/bird_bk.png";

    // 游戏背景颜色
    public static final Color BK_COLOR = new Color(0x4B4CF); // 浅蓝色的背景

    // 小鸟的图片资源
    public static final String[] BIRD_IMG={"img/bird_normal.png", "img/bird_up.png","img/bird_down.png"};

    // 障碍物图片资源
    public static final String [] BARRIER_IMG_PATH={
            "img/barrier.png","img/barrier_up.png","img/barrier_down.png"};
}

GameUtil

一个游戏的工具类。

package com.bird.util;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;

public class GameUtil {
    public static BufferedImage loadBufferedImage(String imgPath){
        try{
            return ImageIO.read(new FileInputStream(imgPath));
        } catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }
}

GameApp

项目的启动类,这个类通过创建GameApp对象,来启动游戏。

package com.bird.app;

import com.bird.main.GameFrame;

public class GameApp {
    public static void main(String[] args) {
        new GameFrame();
    }
}

Barrier

在Barrier类中,是创造游戏中的各种障碍物的,里面拥有着详细的注释,通过注释的内容,用户可以自定义里面的某些内容。

package com.bird.main;

import com.bird.util.Constant;
import com.bird.util.GameUtil;

import java.awt.*;
import java.awt.image.BufferedImage;

/*
* 障碍物类
* */
public class Barrier {
    // 矩形参数
    private Rectangle rect;

    // 障碍物是否可以移动
    private boolean mob = true;
    // 障碍物的移动速度
    private  int speed = 3;
    // 障碍物需要的三个图片
    private  static BufferedImage[] imgs;

    // 障碍物状态
    private boolean visible;

    // 静态代码块初始化成员
    static {
        final int COUNT = 3;
        // 类加载的时候将三个图片初始化
        imgs = new BufferedImage[COUNT];
        for (int i = 0; i < COUNT; i++) {
            imgs[i] = GameUtil.loadBufferedImage(Constant.BARRIER_IMG_PATH[i]);
        }
    }

    // 位置
    private int x, y;

    // 宽度和高度
    private  int width, height;

    // 障碍物的类型
    private int type;
    public static final int TYPE_TOP_NORMAL = 0;
    public static final int TYPE_BOTTOM_NORMAL = 2;
    // 障碍物悬空
    public static final int TYPE_HOVER_NORMAL = 4;

    // 障碍物可以移动的状态
    public static final int TYPE_MOBILE = 6;

    // 获取障碍物的宽度和高度
    public static final int BARRIER_WIDTH = imgs[0].getWidth();
    public static final int BARRIER_HEIGHT = imgs[0].getHeight();
    public static final int BARRIER_HEAD_WIDTH = imgs[1].getWidth();
    public static final int BARRIER_HEAD_HEIGHT = imgs[1].getHeight();

    // 构造器
    public Barrier() {
        // 初始化矩形参数
        rect = new Rectangle();
    }

    // 宽度都是固定的,只需要控制障碍物的高度就可以了
    public Barrier(int x, int y, int height, int type) {
        this.x = x;
        this.y = y;
        this.width = BARRIER_WIDTH;
        this.height = height;
        this.type = type;
    }

    // 根据不同的类型绘制障碍物
    public void draw(Graphics g){
        switch ((type)){
            case TYPE_TOP_NORMAL:
                drawTopMormal(g);
                break;
            case TYPE_BOTTOM_NORMAL:
                drawNormalTop(g);
                break;
            case TYPE_HOVER_NORMAL: // 中间的悬空障碍物
                drawHoverNormal(g);
                break;
            case TYPE_MOBILE: // 障碍物可移动
                drawMobile(g);
                break;

        }
    }

    // 绘制从上到下的障碍物
    public void drawTopMormal(Graphics g){
        // 求出所需要的障碍物的块数
        // 公式:(当前障碍物的高度-障碍物的头部)/每一块的高度 然后 + 1
        int count = (height - BARRIER_HEAD_HEIGHT)/BARRIER_HEIGHT + 1;
        // for循环绘制障碍物
        for (int i = 0; i < count; i++) {
            g.drawImage(imgs[0], x, y + i * BARRIER_HEIGHT, null);
        }

        // 绘制头
        int y = height - BARRIER_HEAD_HEIGHT;
        g.drawImage(imgs[2], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH) / 2, y, null);
        // 给障碍物添加向左的速度
        x -= speed;
        if (x < -50){ // 当障碍物越界了
            visible = false;  // 状态为false
        }
        // 调用矩形
        rect(g);
    }

    /*
    * 绘制障碍物碰撞矩形
    * */
    public void rect(Graphics g){
        int x1 = this.x;
        int y1 = this.y;
        int w1 = imgs[0].getWidth();
//        g.setColor(Color.blue);
//        g.drawRect(x1, y1, w1, height);
        // 设置矩形参数
        setRectangle(x1, y1, w1, height);
    }

    /*
    * 障碍物的碰撞矩形参数
    * */
    public void setRectangle(int x, int y, int width, int height){
        rect.x = x;
        rect.y = y;
        rect.width = width;
        rect.height = height;
    }

    // 获取矩形
    public Rectangle getRect() {
        return rect;
    }

    //绘制从下向上的障碍物
    private void drawNormalTop(Graphics g) {
        //求出所需要障碍物的块数
        int count = height/BARRIER_HEIGHT+1;
        //for循环绘制障碍物
        for (int i = 0; i < count; i++) {
            g.drawImage(imgs[0], x, Constant.FRAM_HEIGHT-i*BARRIER_HEIGHT,  null);
        }

        //绘制头
        int y = Constant.FRAM_HEIGHT-height;
        g.drawImage(imgs[1], x - (BARRIER_HEAD_WIDTH - BARRIER_WIDTH) / 2, y, null);
        x -= speed;
        if (x < -50){ // 当障碍物越界了
            visible = false;  // 状态为false
        }
        // 调用矩形
        rect(g);
    }

    //绘制中间的障碍物
    private void drawHoverNormal(Graphics g) {
        //求出所需要障碍物的块数
        int count = (height - BARRIER_HEAD_HEIGHT)/BARRIER_HEIGHT;

        // 绘制上头
        g.drawImage(imgs[1], x, y, null);

        //for循环绘制障碍物
        for (int i = 0; i < count; i++) {
            g.drawImage(imgs[0], x, y+BARRIER_HEAD_HEIGHT + i * BARRIER_HEIGHT,  null);
        }
        // 给障碍物绘制矩形外边
        rect(g);

        //绘制下头
        int yll = y + height - BARRIER_HEAD_HEIGHT;
        g.drawImage(imgs[2], x, yll, null);
        x -= speed;
        if (x < -50){ // 当障碍物越界了
            visible = false;  // 状态为false
        }
    }

    // 绘制可以移动的障碍物
    private void drawMobile(Graphics g) {
        //求出所需要障碍物的块数
        int count = (height - BARRIER_HEAD_HEIGHT)/BARRIER_HEIGHT;

        // 绘制上头
        g.drawImage(imgs[1], x, y, null);

        //for循环绘制障碍物
        for (int i = 0; i < count; i++) {
            g.drawImage(imgs[0], x, y+BARRIER_HEAD_HEIGHT + i * BARRIER_HEIGHT,  null);
        }
        // 给障碍物绘制矩形外边
        rect(g);

        //绘制下头
        int yll = y + height - BARRIER_HEAD_HEIGHT;
        g.drawImage(imgs[2], x, yll, null);
        x -= speed;
        if (x < -50){ // 当障碍物越界了
            visible = false;  // 状态为false
        }

        // 让物体移动
        if (mob){  // 让障碍物向上移动
            y += 5;
            if (y >= 250){
                mob = false;
            }
        }
        else{ // 让障碍物向下移动
            y -= 5;
            if (y <= 100){
                mob = true;
            }
        }
    }

    // 判断什么时候绘制下一组障碍物
    public boolean isInFrame(){
        return 600 - x > 150;
    }

    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 getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }
}

Barrierpool

在真实的游戏中,我们不仅仅是需要考虑,游戏的可以运行,对于游戏的设计者我们还需要考虑内存大小问题,是否会发生内存泄露或者内存溢出等等问题,我们在创造障碍物对象的时候,会不断的new对象,每一次new的过程就是一次新的内存申请,虽然最开始的时候这个占用的内存没有什么明显的感觉,但是当玩的时间久了,这个运行内存会越来越大,直到游戏崩溃,我见过很多非科班出身的游戏开发者,在内存及时处理这块往往都没有做,导致了,游戏玩着玩着就崩溃了。

package com.bird.main;

import java.util.ArrayList;
import java.util.List;

/*
* 为了避免反复的创建和销毁对象, 使用对象池来提前创建好一些对象
* 使用的时候从池中获得,使用完毕后,归还
* */
public class Barrierpool {
    // 用于管理池中所有对象的容器
    private  static List<Barrier> pool = new ArrayList<>();
    // 池中初始的对象个数
    public static final int initCount = 16;
    // 对象池中的最大个数
    public static final int maxCount = 20;
    static {
        // 初始化池中的对象
        for (int i = 0; i < initCount; i++) {
            pool.add(new Barrier());
        }
    }

    /*
    * 从池中获取一个对象
    *
    * */
    public static Barrier getPool(){
        int size = pool.size();
        // 如果池子中有对象才可以拿
        if(size > 0){
            // 移除并返回对象
            System.out.println("拿走一个");
            return pool.remove(size - 1);
        }
        else {
            // 池中没有对象了 只能new
            System.out.println("新的对象");
            return new Barrier();
        }
    }

    /*
    * 将对象归还容器中
    * */
    public static void setPool(Barrier barrier){
        if (pool.size() < maxCount){
            pool.add(barrier);
            System.out.println("容器归还了");
        }
    }
}

Bird

这个是鸟对象的类,如何创建一只小鸟,和这个小鸟的个性属性值怎么设置,这个在这个类里面我都通过了详细的注释进行了说明。

package com.bird.main;

import com.bird.util.Constant;
import com.bird.util.GameUtil;

import java.awt.*;
import java.awt.image.BufferedImage;

/*
* 小鸟类
* */
public class Bird {
    // 小鸟矩形对象
    private Rectangle rect;

    // 小鸟加速度
    private int acceleration;

    // 小鸟的命数
    private int bird_energe; // 默认1000滴血
    private int bird_default = 1000; // 初始值

    public int getBird_default() {
        return bird_default;
    }

    public void setBird_default(int bird_default) {
        this.bird_default = bird_default;
    }

    public int getBird_energe() {
        return bird_energe;
    }

    public void setBird_energe(int bird_energe) {
        this.bird_energe = bird_energe;
    }

    // 小鸟的生命 默认是存活
    public boolean life = true;

    // 存放小鸟图片
    private BufferedImage[] images;

    // 鸟的图片数量
    public static final int BIRD_IMG_COUNT = 3;

    // 鸟的状态
    private int state;
    public static final int STATE_NORMAR = 0; // 正常飞
    public static final int STATE_UP = 1; // 向上飞
    public static final int STATE_DOWN = 2; // 向下飞

    // 小鸟位置
    private int x = 200, y = 200;

    // 小鸟移动方向 上下
    public boolean up = false, down = false; // 默认不上不下

    // 小鸟移动速度
    private int speed = 4;

    // 构造方法中初始化资源
    public Bird(){
        // 创建小鸟图片数组
        images = new BufferedImage[BIRD_IMG_COUNT];
        for (int i = 0; i < BIRD_IMG_COUNT; i++) {
            // 加载每一张图片
            images[i] =GameUtil.loadBufferedImage(Constant.BIRD_IMG[i]);
        }

        int w = images[0].getWidth();
        int h = images[0].getWidth();
        rect = new Rectangle(w, h);
        bird_energe = getBird_default();
    }

    // 绘制小鸟
    public void draw(Graphics g){
        // 导入小鸟飞翔组件
        flyLogic();
        // 时刻绘制小鸟的图片
        g.drawImage(images[state], x, y, null);

        // 绘制小鸟的矩形
//        g.drawRect(x, y, (int)rect.getWidth(), rect.height);
        rect.x = this.x;
        rect.y = this.y;
    }

    // 控制小鸟移动方向
    public void flyLogic(){
        if (up){ // 判断鸟垂直方向怎么运动
            acceleration --;
            y += acceleration;
            if (acceleration < -10){ // 越往上扑腾越慢
                acceleration = -10;
            }
            if (y < 20){ // 到达底部边界了
                y = 20;
                acceleration = 0; // 加速度设置为0防止越界
            }
        }
        if (!up){ // 往下走
            acceleration ++; // 越落地越快
            y += acceleration;
            if (acceleration > 10){ // 最高10
                acceleration = 10;
            }

            if (y > 475){ // 到达顶部边界了
                y = 475;
                acceleration = 0; // 加速度设置为0防止越界
            }

        }
    }

    // 通过传入参数来判断小鸟垂直飞翔的方向
    public void fly(int fly){
        switch (fly){
            case 1: // 如果是1的话那么就是往上飞
                state=STATE_UP;
                up = true;
                break;
            case 5: // 如果是5的话往下飞
                state=STATE_DOWN;
                up = false;
                break;
        }
    }
    // 获取矩形参数

    public Rectangle getRect() {
        return rect;
    }

    /*
    * 重新绘制小鸟位置
    * */

    public void restartDraw(){
        life = true;
        x = 200;
        y = 200;
    }
}

Cloud

Cloud类云彩类,云彩会有哪些属性,在这个类中都会体现出来,至于云彩的移动效果是怎么做出来的,原理为给云彩一个向后的速度,这样就可以制作出云彩在动的效果了,想要给游戏更多的可扩展性,不如给游戏加上导弹或者什么道具,本质上和做云彩是一个道理的。

package com.bird.main;

import java.awt.*;
import java.awt.image.BufferedImage;

/*
* 云彩类
* */
public class Cloud {
    // 云彩图片
    private BufferedImage img;

    // 云彩速度
    private int speed;

    // 云彩位置
    private  int x, y;

    // 有参和无参构造方法

    public Cloud() {
    }

    public Cloud(BufferedImage img, int speed, int x, int y) {
        this.img = img;
        this.speed = speed;
        this.x = x;
        this.y = y;
    }

    // 绘制方法
    public void draw(Graphics g){
        // 给云一个向后的速度
        x-= speed;
        g.drawImage(img, x, y, null);
    }

    /*
    * 用于判断云彩是否飞出屏幕以外
    * */
    public boolean isOutFrame(){
        if (x < -100){
            return true;
        }
        return false;
    }

}

GameBackGround

背景类,在这个类中会初始化很多游戏的背景相关的图片等等属性。

package com.bird.main;

import com.bird.util.Constant;
import com.bird.util.GameUtil;

import java.awt.*;
import java.awt.image.BufferedImage;

/*
* 游戏背景类
* */
public class GameBackGround {
    //背景需要的资源图片
    private BufferedImage bkimg;

    // 构造器初始化资源
    public GameBackGround(){
            bkimg = GameUtil.loadBufferedImage(Constant.BK_IMG_PATH);
    }

    // 绘制图片
    public void draw(Graphics g){
        // 填充背景颜色
        g.setColor(Constant.BK_COLOR);

        // 画在窗口
        g.fillRect(0, 0, Constant.FRAM_WIDTH, Constant.FRAM_HEIGHT);

        // 设置背景为黑色
        g.setColor(Color.black);

        // 获取图片的高度和宽度
        int height = bkimg.getHeight();
        int width = bkimg.getWidth();

        // 循环次数
        int count = Constant.FRAM_WIDTH/width + 1;

        for (int i = 0; i < count; i++) {
            g.drawImage(bkimg, width * i, Constant.FRAM_HEIGHT-height, null);
        }
    }
}

GameBarrierLayer

这个类就是如何布置游戏中产生的障碍物。

package com.bird.main;

import com.bird.util.Constant;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/*
* 游戏中障碍物层类
* */
public class GameBarrierLayer {
    // 游戏时间
    private GameTime gameTime;

    // 最高成绩的文本
    private int txt;

    // 随机种子
    private Random random = new Random();

    // 障碍物的集合
    private List<Barrier> barriers;

    public GameBarrierLayer(){
        // 初始化障碍物
        barriers = new ArrayList<>();
        // 初始化时间
        gameTime = new GameTime();
    }

    // 绘制障碍物
    public void draw(Graphics g, Bird bird) throws IOException {
//        Barrier barrier = new Barrier(200, 0, 200, 0);
//        barriers.add(barrier);
//        barriers.get(0).draw(g);
//
//        Barrier barrier1 = new Barrier(300, 0, 200, 2);
//        barriers.add(barrier1);
//        barriers.get(1).draw(g);
        // 画障碍物
        for (int i = 0; i < barriers.size(); i++) {
            Barrier barrier = barriers.get(i);
            if (barrier.isVisible()){ // 如果对象存在
                barrier.draw(g);     // 画出对象
            }
            else {
                // 如果不存在
                Barrier remove = barriers.remove(i);
                // 设置对象
                Barrierpool.setPool(remove);
                i --;
            }
        }
        // 判断障碍物和小鸟是否撞上了
        collideBird(bird);
        // 加入逻辑控制组件
        logic(g, bird);
    }

    // 逻辑组件
    public void logic(Graphics g, Bird bird) throws IOException {

        // 小鸟当前生命值
        g.setColor(Color.red);
        g.setFont(new Font("微软雅黑", 1, 20));
        g.drawString("生命值:" + bird.getBird_energe(),370, 50);
        if (barriers.size() == 0){
            ran();
            // 游戏刚开始的时候
            gameTime.begin(); // 时间开始
//            Barrier top = new Barrier(600, 0, numberTop, 0);
//            barriers.add(top);
//            Barrier down = new Barrier(600, 500-numberDown, numberDown, 2);
//            barriers.add(down);
            insert(600, 0, numberTop, 0);
            insert(600, Constant.FRAM_HEIGHT -numberDown, numberDown, 2);
        }
        else
        {
            // 计算时间差
            long differ = gameTime.differ();
            // 设置时间样式
            g.setColor(Color.white);
            g.setFont(new Font("微软雅黑", 1, 20));
            g.drawString("坚持了"+ differ + "秒", 30, 50);

            // 显示最高成绩记录
            txt = getText();
            if (differ <= txt)
            {
                g.drawString("最高成绩:" + txt, 200, 50);
            }
            else
            {
                setText(String.valueOf(differ));
                g.drawString("最高成绩:" + getText(), 200, 50);
            }

            // 判断最后一个障碍物是否完全进入屏幕内
            Barrier last = barriers.get(barriers.size() - 1);
            if (last.isInFrame()){
                ran();

//                Barrier top = new Barrier(600, 0, numberTop, 0);
//                barriers.add(top);
//                Barrier down = new Barrier(600, 500-numberDown, numberDown, 2);
//                barriers.add(down);
                if (number < 50){
                    insert(600, 32, 440, 4);
                }
                else if (number > 250) // 绘制可以移动的障碍物
                {
                    insert(600, 125, 200, 6);
                }
                else
                {
                    insert(600, 0, numberTop, 0);
                    insert(600, Constant.FRAM_HEIGHT -numberDown, numberDown, 2);
                }

            }
        }

    }

    /*
    * 用于从池中获取对象,并把参数封装成barrier,存入barriers数组中
    *
    * */
    public void insert(int x, int y, int height, int type){
        // 获取一个新的障碍物
        Barrier top = Barrierpool.getPool();
        // 设置参数并加入到障碍物数组里面
        top.setX(x);
        top.setY(y);
        top.setHeight(height);
        top.setType(type);
        // 初始设置对象状态为true
        top.setVisible(true);
        barriers.add(top);
    }

    // 上方障碍物的高度
    private int numberTop;

    // 下方障碍物的高度
    private int numberDown;
    // 障碍物的种类数量
    private int number;

    // 产生两个100~500之间的随机高度
    public void ran(){
        numberTop = random.nextInt(400) + 100;
        numberDown = random.nextInt(400) + 100;
        number = random.nextInt(500);
        if (numberTop + numberDown > 450){
            ran(); // 如果两个管道的高度相加大于450 就代表两个管道重合了
            // 然后重新生成
        }
    }

    /*
    * 判断障碍物和小鸟是否发生碰撞
    * */
    public boolean collideBird(Bird bird){
        for (int i = 0; i < barriers.size(); i++) {
            Barrier barrier = barriers.get(i);
            // 判断矩形是否相交
            if (barrier.getRect().intersects(bird.getRect())){
                System.out.println("撞上了");
                bird.setBird_energe(bird.getBird_energe() - random.nextInt(60)); // 随机扣除0~100点血
                if (bird.getBird_energe() <= 0){
                    bird.life = false; // 小鸟装上之后就g了
                }
                return true;
            }
            else
            {
                if (bird.getBird_energe() == bird.getBird_default()){

                }
                else {
                    // 回血功能
                    bird.setBird_energe(bird.getBird_energe() + 1);
                }
            }
        }

        return false;
    }

    /*
    * 用于清空障碍物的池子
    * */
    public void restart(){
        barriers.clear();
    }

    File file = new File("record/game.txt");


    /*
    * 用于得到文件中的数据
    * */
    public int getText() throws IOException {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        int read = Integer.parseInt(in.readLine()); // 把获取的字符串转换为int
        in.close();
        return read;
    }

    /*
    * 用于存储数据
    * */
    public void setText(String str) throws IOException {
        FileWriter fileWriter = null;
        fileWriter = new FileWriter(file);
        // 向文件中写数据
        fileWriter.write(str);
        fileWriter.close();
    }

}

GameFrame

游戏框架类,在这个类中就把所有创建好了的类,Bird,GameBackGroud对象等等拼接组装到了一个框架中了。

public class GameFrame extends Frame { // 继承框架类

    // 实例化gamebackGround类
    private GameBackGround gameBackGround;

    // 实例化Bird类
    private Bird bird;

    // 实例化GameFrontGround类
    private GameFrontGround gameFrontGround;

    // 实例化GameBarrierLayer类
    private GameBarrierLayer gameBarrierLayer;
    // 存放图片的集合
    private BufferedImage buffimg = new BufferedImage(Constant.FRAM_WIDTH, Constant.FRAM_WIDTH, BufferedImage.TYPE_4BYTE_ABGR);
    // 构造方法中初始化一些参数
    public GameFrame(){
        // 窗口是否可见
        setVisible(true); // 设置窗口可见

        // 窗口的大小
        setSize(Constant.FRAM_WIDTH, Constant.FRAM_HEIGHT);

        // 窗口的标题
        setTitle(Constant.FRAM_TITLE);

        // 窗口的初始化位置
        setLocation(Constant.FRAM_X, Constant.FRAM_Y);

        // 窗口的大小不可改变
        setResizable(false);

        // 窗口的关闭事件
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0); // 结束程序 返回0
            }
        });

        // 初始化背景
        initGamg();

        // 启动线程
        new run().start();

        // 添加按键监听
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                // 按下向上键的话 然后向上飞
                add(e);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // 松开向上键的话 就是往下飞
                minu(e);
            }
        });
    }

    // 初始化对象
    public void initGamg(){
        // 加载背景图片
        gameBackGround = new GameBackGround();
        // 加载小鸟图片
        bird = new Bird();
        // 加载前景
        gameFrontGround = new GameFrontGround();
        // 加载障碍物
        gameBarrierLayer = new GameBarrierLayer();
    }

    // 创建线程
    class run extends Thread{
        @Override
        public void run(){
            // 弄一个循环 持续的调用下面的方法
            while(true){
                repaint();
                try {
                    // 设置每33毫秒刷新一次
                    Thread.sleep(33);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    // 重写update方法时刻更新背景
    @Override
    public void update(Graphics g) {

        if (bird.life){
            // 得到图片画笔
            Graphics graphics = buffimg.getGraphics();

            // 把画笔存入到背景和小鸟对象中
            gameBackGround.draw(graphics);
            bird.draw(graphics);

            // 绘制前景
            gameFrontGround.draw(graphics);

            // 绘制障碍物
            try {
                gameBarrierLayer.draw(graphics, bird);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            // 一次性的将图片绘制到屏幕
            // 通过这个方法可以解决屏幕闪烁问题
            g.drawImage(buffimg, 0, 0, null);
        }
        else {
            String over = "游戏结束";
            g.setColor(Color.red);
            // 设置字体属性
            g.setFont(new Font("微软雅黑", 1, 60));
            g.drawString(over, 120, 250);

            // 重开提示词
            String reset = "Space Reset Game";
            g.drawString(reset, 25, 350);
        }
    }

    // 按键 让小鸟往上飞
    public void add(KeyEvent e){
        // 通过按键事件e来获取按键的值
        // 判断按键的值
        switch (e.getKeyCode()){
            // 如果是向上的按键的话 那么就传值1
            case KeyEvent.VK_UP:
                bird.fly(1);
                break;
            case KeyEvent.VK_SPACE:
                if (bird.life == false){ // 当小鸟死了的时候按下空格键重开
                    restart();
                }
                break;
        }
    }


    // 抬键 让小鸟往下飞
    public void minu(KeyEvent e){
        // 通过按键事件e来获取按键的值
        // 判断按键的值
        switch (e.getKeyCode()){
            // 这里是还是up因为是松开向上键的事件
            case KeyEvent.VK_UP:
                bird.fly(5);
                break;
        }
    }
    /*
    * 重置游戏
    * */
    public void restart(){
        gameBarrierLayer.restart(); // 清空障碍物
        bird.restartDraw(); // 重绘小鸟
        bird.setBird_energe(bird.getBird_default());
    }
}

GameFrontGround

游戏前景类,这个类就是用于制作游戏的一些前景,比如就是我们最开始的Cloud类,云类这些东西就是游戏的前景。

import com.bird.util.GameUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/*
* 游戏的前景类
* */
public class GameFrontGround {
    // 云彩的个数
    public static final int CLOUND_COUNT = 2;

    // 存放云彩的容器
    private List<Cloud> clouds;

    // 云彩的飞行速度
    public static final int CLOUND_SPEED = 9;

    // 使用得到的图片资源
    private BufferedImage[] img;

    // 用于产生随机数
    private Random random;


    // 构造器初始化数据
    public GameFrontGround() {
        clouds = new ArrayList<>();
        img = new BufferedImage[CLOUND_COUNT];

        // 容器中添加云彩图片
        for (int i = 0; i < CLOUND_COUNT; i++) {
            img[i] = GameUtil.loadBufferedImage("img/cloud" + i + ".png");
        }
        // 用于产生随机的云彩
        random = new Random();
    }

    // 绘制云彩
    public void draw(Graphics g){
        logic(); // 载入逻辑组件
        // 绘制云彩
        for (int i = 0; i < clouds.size(); i++) {
            clouds.get(i).draw(g);
        }
    }

    /*
    * 用于控制云彩的个数
    * */
    private void logic(){
        if ((int)(500 * Math.random()) < 20){ // 这里就是控制云彩产生的频率的判断 可以自定设置 通过修改if中的表达式
            // 创建云对象
            // 我们有两张云朵的图片 随机产生,然后再试速度 位置的话 就是 从最右边开始生成 上下的话位置随机
            Cloud cloud = new Cloud(img[random.nextInt(CLOUND_COUNT)], CLOUND_SPEED, 600, random.nextInt(150));
            // 向容器中添加云彩
            clouds.add(cloud);
        }
        for (int i = 0; i < clouds.size(); i++) {
            Cloud cloud = clouds.get(i);
            if (cloud.isOutFrame()){ // 如果云出界了
                clouds.remove(i);
                i -- ;
                System.out.println("云被移除" + cloud);
            }
        }
    }
}

GameTime

游戏的时间类,这类的目的是记录游戏的时间,开始时间,结束时间,时间差,这个的可以用来记录每次小鸟的游戏记录。

package com.bird.main;

/*
* 游戏计时器
* */
public class GameTime {
    // 开始时间
    private long beginTime;
    // 结束时间
    private  long endTime;
    // 时间差
    public long differ;

    public GameTime(){}

    public void begin(){
        beginTime = System.currentTimeMillis(); // 系统当前时间
    }
    // 开始与结束相差的时间
    public long differ(){
        endTime =  System.currentTimeMillis(); // 系统当前时间
        return differ = (endTime - beginTime) / 1000;
    }
}

如果大家觉得有用的话,可以关注我下面的微信公众号,极客李华,我会在里面更新更多行业资讯,企业面试内容,编程资源,如何写出可以让大厂面试官眼前一亮的简历等内容,让大家更好学习编程,我的抖音,B站也叫极客李华。

java fly bird小游戏_JavaScript实现Fly Bird小游戏
weixin_28940217的博客
02-26 532
1.分析页面结构,理清需求和功能游戏有三个界面,分别是开始界面,游戏界面和游戏结束界面。1.1 开始界面start.gif游戏的大背景上下移动的游戏标题和翅膀摆动的小鸟start 按钮,点击进入游戏界面一直移动的地面1.2 游戏界面play.gif显示越过障碍数量的计分器移动的障碍物,分别是上管道和下管道点击游戏界面,小鸟向上飞起,然后在重力作用下下坠,当小鸟和管道碰撞后,结束界面弹出,同时小鸟落...
飞翔小鸟java_java 飞翔小鸟 小游戏源码
weixin_39611765的博客
02-13 1079
【实例简介】小鸟躲避障碍物,以及计分。游戏规则:只要鼠标 不断点击,小鸟就向上飞,不要小鸟碰到障碍物 为赢【实例截图】【核心代码】package day06;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.event.Mous...
FlyBird游戏
08-08
这是一款FlyBird游戏的源代码,希望我的分享能够帮助到大家,我还有跳一跳、星图等源代码可完整运行的,后期将发出,希望支持,要的请留言。
Java桌面程序实现飞机大战,FlyBird游戏,JavaFx
最新发布
qq_40173146的博客
08-13 1785
JAVA飞机大战游戏 简介:本人在本学期,通过JAVA实训,做了一款Java桌面程序游戏(飞机大战),设计思想和自己之前的C语言一样。还是通过多线程技术为核心。因为是学校实训内容,主要目的是巩固JAVA的学习,利用到了Java中面向对象的思想(继承,封装,多态),文件的读取,数组,集合(List), 线程同步,JAVAFx图形界面,鼠标事件监听等。 游戏规则设计 主要是英雄机和敌机对战,英雄机和敌机都可以发射...
飞行的小鸟(Flybird)C语言小游戏&&C++简单小程序超简单
AGNING的博客
05-26 3587
一款简单易做的小游戏 ???? 最终效果可查看点击我查看 ???? 代码以及素材点击我
JavaScript实现Fly Bird小游戏
努力,可能成功!放弃,注定失败!
12-15 2588
1.分析页面结构,理清需求和功能 游戏有三个界面,分别是开始界面,游戏界面和游戏结束界面。 1.1 开始界面 start.gif 游戏的大背景上下移动的游戏标题和翅膀摆动的小鸟start 按钮,点击进入游戏界面一直移动的地面 1.2 游戏界面 play.gif 显示越过障碍数量的计分器移动的障碍物,分别是上管道和下管道点击游戏界面,小鸟向上飞起,然后在重力
飞翔小鸟游戏(Flying bird)(含素材)
12-09
C#小项目飞翔小鸟游戏详细教程(Flying bird),基于Winform框架(含素材)实现效果: 1.空格,鼠标左键控制小鸟跳 2.管道随机大小 3.小鸟与管道碰撞,小鸟碰到地面 4.小鸟煽动翅膀动画 5.开始暂停游戏 6.过一个管道得分增加
Java 飞翔小鸟小游戏开发 完全源码 + 论文文档
mxy2404830的博客
12-16 2945
这款游戏的起源是越南独立开发开发的手机游戏,短时间内占据了全球各大手机软件商店免费排行榜的第一位。游戏中玩家控制一只小鸟飞过一个个柱子的间隙。飞的越远分数越高,看玩家能使小鸟在空中坚持飞多久。初始界面如图1所示。 完整源码+文档+视频 : 源码+论文 下载 玩家在上图所示界面任意位置,按下鼠标左键,开始游戏。 游戏开始以后,玩家需要不断控制点击屏幕的频率来调节小鸟的飞行高度和降落速度,让小鸟顺利的通过画面右端的柱子间隙。如果玩家不小心碰到了柱子或者落到了地面上,则结束游戏。如图2所示。 如
飞翔小鸟--Java小游戏实战(代码完整)
热门推荐
Lyndsey的博客
04-05 1万+
一、写在前面: 《飞扬的小鸟》是一款曾经比较火热的小游戏,本文可以带你你从零开始,一步一步的开发出这款小游戏语言 Java 工具 IntelliJ IDEA,JDK 16 准备工作 创建好项目后,在正式开始编写代码前,先下载游戏素材放入正确的目录下。开发过程中使用的一些参数,如坐标、尺寸、速度等,你可以直接使用这些参数值,也可以尝试自定义这些参数值。 二、知识要点 Java的基本语法 Java面向对象的三大特征(封装、继承、多态) Java Swing中常见API的使用 (Swing
javaflybird源码及素材资源
09-07
在这个项目中,你将有机会深入理解如何利用Java语言构建一个简单但有趣的小游戏——飞翔小鸟Fly Bird),这是一个基于经典Flappy Bird游戏的简化版本。 首先,Java Swing是Java AWT(抽象窗口工具包)的扩展,...
fly_bird.zip
08-15
"fly_bird.zip" 文件包含了一个使用Java Applet技术实现的飞翔小鸟游戏,这是一份典型的早期网页游戏,它通过简单的交互和声音效果,为用户提供了趣味盎然的娱乐体验。下面我们将深入探讨这个小游戏的结构和关键...
飞翔小鸟游戏
12-28
用unity3d开发飞翔小鸟游戏,可运行,里面有项目图片资源,还有源码
FlyBird游戏模仿(OC版)
03-13
通过苹果2D游戏开发引擎Spritekit使用OC语言实现的一个模仿FlyBird游戏的demo。
微信小程序游戏飞翔小鸟
07-17
小程序完整demo:飞翔小鸟:canvas实现,java后端(适用1221)
java fly bird小游戏_Flappy Bird 小游戏
weixin_33109551的博客
02-26 440
各位读者老爷大家好,由于最近一直比较忙没什么空,导致好久没有更新文章了,明天有一天假期,就利用今晚时间和大家聊聊最近刚写的一个小游戏,由于自己的时间比较少,所以没有在细节上做过多的处理,程序还有很多不足的地方,也欢迎大家多多指出或者提出自己的观点,游戏代码仍然会在文章结尾处下载,废话不多说,进入正题。Flappy Bird当年红极一时的小游戏,想必大家应该都玩过,先上一张效果图效果动图我写游戏仍然...
C语言开发FlyBird小游戏飞翔小鸟小游戏,可以直接运行!
NGUP_LEE的博客
12-18 2173
前几天的实训我做了一个飞翔小鸟的游戏项目,技术性不高,但是我利用了图像处理函数在游戏里添加了声音和画面,看起来就好多了。 我不算是原创,我是根据河海大学童老师的网课给出的框架,然后又加上了自己的东西,算是改变吧,这里主要聊一下我对于我写的这个东西的理解,以及如何写出一个小游戏的理解。 对于一个小游戏可以使用一个固定的框架 int main() { HideCursor(); ...
Python基础教程——用做一个童年经典flybird游戏!【完整教程】
2301_78217634的博客
01-12 827
免费。
C语言小游戏飞翔小鸟(完整版)
致力于C语言C++知识分享!
01-31 3389
本程序设计了三种不同颜色的小鸟(可以实现三人对战)另外也有白天模式和夜晚模式,不同模式和不同小鸟是在每次死亡后随机刷新,避免产生视觉疲劳。
java fly bird小游戏_java swing实现的小游戏flybird源码附带视频配置修改教程
weixin_39784195的博客
02-26 447
大家好,今天给大家演示一下由Java swing实现的一款小游戏flybird,该游戏操作比较简单,点击鼠标确保小鸟不要触碰到柱子即可,该游戏可运行在Java环境下,jdk版本不限,下面我们来看看如何运行以及简单的修改游戏源码。(这是视频教程的笔记,项目包括源码和视频教程)1.将项目导入到eclipse(myeclipse也可以)。2.导入后我们做一些简单的配置,因为每个人Java环境不一样,...
1451
原创
5029
点赞
1万+
收藏
9万+
粉丝
关注
私信
写文章

热门文章

  • IDEA配置Maven 71403
  • HTML登录页面 42913
  • SSH配置免密登录 38199
  • java: 无法访问org.springframework.boot.SpringApplication解决办法 37242
  • html轮播图 33777

分类专栏

  • 找工作记录 33篇
  • AI 20篇
  • 开发者开发小技巧 2篇
  • Java一百道面试题 55篇
  • Linux 22篇
  • 个人隐私内容
  • 英文文章练习 1篇
  • redis 37篇
  • 数据库面试题 8篇
  • 网络安全 10篇
  • MQ 11篇
  • Andriod开发 4篇
  • 嵌入式开发 1篇
  • 高并发 15篇
  • golang 19篇
  • Django 6篇
  • C++一百道面试题 21篇
  • Flask 8篇
  • 100道Java后端大厂面试题详解 17篇
  • 程序员科普栏目
  • PTA天梯赛
  • 一百道计算机网络面试题 39篇
  • Koa 10篇
  • Spark 9篇
  • Hive 10篇
  • Scala 9篇
  • docker 12篇
  • 课程设计 1篇
  • 寒假打卡31道大厂算法题 1篇
  • 有意思的python小程序 4篇
  • matlab 9篇
  • python授课 34篇
  • SpringCloud 13篇
  • mybaits-plus 12篇
  • HTML面试与笔试题 6篇
  • shiro 2篇
  • vant 10篇
  • Hadoop 10篇
  • MapReduce 10篇
  • JS学习之旅 55篇
  • go语言一百道练习题 11篇
  • electron 1篇
  • 我的架构师 3篇
  • element-ui 4篇
  • python数据分析 3篇
  • mybatis 11篇
  • python小游戏 10篇
  • 蓝桥杯考前每日一题 18篇
  • 一百道数据结构算法面试题 21篇
  • JVM 3篇
  • 机器学习 1篇
  • 个人资源 2篇
  • 图计算 9篇
  • 秒杀系统 27篇
  • springsecurity 4篇
  • Java基础 6篇
  • 日常生活中的算法问题 6篇
  • 人力资源管理 1篇
  • sql注入 1篇
  • 考研记录分享 1篇
  • Nginx 2篇
  • 流计算 9篇
  • Chatgpt小技巧 1篇
  • 交付工程师 2篇
  • 大数据 26篇
  • HDFS 11篇
  • Zoopkeeper 2篇
  • MongDB 1篇
  • 计算机网络 11篇
  • Oracle 6篇
  • jsp 1篇
  • MinIO 8篇
  • Fink 10篇
  • 云数据库 10篇
  • NoSQL 10篇
  • HBase 15篇
  • node.js 1篇
  • python量化 5篇
  • 软件测试面试题 1篇
  • 前端一百道面试题 5篇
  • C# 5篇
  • python爬虫 2篇
  • 有趣的github项目 1篇
  • TS 1篇
  • LINGO 1篇
  • Java底层设计原理 11篇
  • 系统架构师
  • 软件测试 3篇
  • Spss学习
  • 数学问题 1篇
  • JS笔试与面试题 3篇
  • CSS面试笔试题 1篇
  • JSOUP爬虫 1篇
  • Thymeleaf 1篇
  • PHP基础
  • python处理Excel
  • 操作系统的学习与提升 18篇
  • SpringBoot的故事 36篇
  • git学习 7篇
  • axios 3篇
  • Ajax 2篇
  • Postman 1篇
  • Java每一题 33篇
  • Leetcode算法问题讲解 24篇
  • 蓝桥杯web版
  • 团队天梯赛 9篇
  • 网络安全基础入门算法 3篇
  • Java基础实验 45篇
  • Java开发小问题 11篇
  • 微信小程序开发
  • JavaWeb 10篇
  • 人工智能 2篇
  • 设计模式 7篇
  • C++开发问题 8篇
  • CSS常见小案例 22篇
  • 数据库学习与提升 24篇
  • 计算机组成原理 11篇
  • 软件工程 11篇
  • Java算法基础 11篇
  • Leetcode学习之旅 104篇
  • C语言学习 16篇
  • C++学习内容 26篇
  • 网页设计 3篇
  • 程序员也要陶冶情操 4篇
  • C++写数据结构 4篇
  • Excel使用技巧 7篇
  • python学习之旅 13篇
  • 用编程学高数 1篇
  • uni-app学习之旅 19篇
  • 蓝桥杯提高题 18篇
  • 蓝桥杯基础练习 33篇
  • 软件设计师 1篇
  • C++的STL 7篇
  • 数据结构 4篇
  • window小问题 1篇
  • 蓝桥杯学习计划 7篇
  • Vue小案例 4篇
  • Vue的学习之旅 30篇
  • 通过项目学习C++特征语法 1篇
  • web开发小问题 1篇

最新评论

  • 如何快速创建一个Django项目

    午夜心碎修勾w: 条理清晰,脉络明了,推荐所有初学者来学,一遍就会!

  • Python爬虫代理池

    北风之神c: 总结的很全面的爬虫,写得赞,博主用心了。 此国产分布式函数调度框架 funboost python万能通用函数加速器 https://funboost.readthedocs.io/zh-cn/latest/articles/c8.html 加到爬虫更强更自由更简单 。 funboost 分布式函数调度框架,定位于调度用户的任何函数,只要用户在函数里面写爬虫代码,就可以分布式调度爬虫,并且对爬虫函数施加30种控制功能, 例如 qps恒定 任何时候随意关机重启代码消息万无一失确认消费 非常简单的开启多进程叠加线程/协程,这些强大的功能绝大部分爬虫框架还做不到。 此框架如果用于爬虫,不管从任何方面比较可以领先scrapy 20年,也比任意写的爬虫框架领先10年。 主要是设计思维问题,普通爬虫框架一般就设计为url请求调度框架,url怎么请求都是被框内置架束缚死了, 所以有些奇葩独特的想法在那种框架里面难以实现,用户需要非常之精通框架本身然后改造框架才能达到随心所欲的驾驭的目的。 而此框架是函数调度框架,函数里面可以实现一切任意自由想法,天生不会有任何束缚,国内一般人设计的爬虫框架都是仿scrapy api,天生不自由受束缚。 使用funboost爬虫,与用户使用别的爬虫框架或者无框架用户手写多线程爬虫相比, funboost都代码更少更强更简单更自由。 pip install funboost 或者是直接使用 pip install boost_spider (powerd by funboost ,boost_spider比funboost增加了更加专门的针对爬虫请求和解析和存储) https://github.com/ydf0509/boost_spider

  • 什么是乐观锁、在哪用过乐观锁

    码个码: 如果两个线程同时get到version 然后在 if 判断版本号是否相等时,此时两者都还没进行修改,版本号没有进行更新,那么不就都通过了这个if版本号判断么 之后都修改了数据和更新两次版本号么,出现脏数据了,这种怎么办

  • python制作俄罗斯方块

    Aqua_1201: 把FPS = 50后面的数字改大一点就可以了,比如225

  • IEEE754

    2401_87113906: 第一个是C0D80000H

最新文章

  • 分享一位非常厉害的学弟的文章
  • macOS下载安装mysql教程
  • postman使用小技巧:如何快速构建一个页面的测试
2024
09月 1篇
07月 2篇
06月 1篇
05月 6篇
04月 37篇
03月 40篇
02月 18篇
01月 64篇
2023年818篇
2022年465篇

目录

目录

分类专栏

目录

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客李华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家深圳厂家玻璃钢雕塑情况新泰玻璃钢雕塑火炬商场美陈福州定制玻璃钢雕塑南平玻璃钢人物雕塑价格如何哈尔滨玻璃钢古代人物雕塑大头儿子玻璃钢雕塑虹口区镜面玻璃钢雕塑优质玻璃钢马雕塑网址阳江玻璃钢雕塑批发定制校庆玻璃钢雕塑水富市玻璃钢雕塑售价漯河景观园林玻璃钢景观雕塑河南玻璃钢公园雕塑江西动物玻璃钢雕塑公司江苏定制玻璃钢雕塑免费咨询项城玻璃钢雕塑厂家临沂卡通玻璃钢雕塑价格正宗玻璃钢雕塑诚信企业南通玻璃钢广场雕塑价格专业的玻璃钢雕塑的设计制作郑州锻铜玻璃钢景观雕塑生产玻璃钢熊本熊雕塑四川通道商场美陈价钱新乡玻璃钢雕塑报价天水玻璃钢雕塑厂成都玻璃钢雕塑推荐厂家延安动物玻璃钢雕塑厂家澄迈县玻璃钢雕塑凉山玻璃钢雕塑公司香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化