IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> CSS3和es6 class实现的flappy bird -> 正文阅读

[游戏开发]CSS3和es6 class实现的flappy bird

学习class时,老师讲了个flappy bird的小游戏,自己试着写了一下。

天空和土地的移动以及小鸟的飞翔使用animation实现。
用class分别创建MoveReact(移动的长方体,小鸟和水管组的父类),Bird(小鸟),Pipe(水管),PipeGroup(水管组,上下为一组),PipeGroupFactory(水管组工厂类,生成和移除水管组),
Game(控制小鸟、水管组的移动,并且检测碰撞,判断游戏是否结束)

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1">
    <style>
        html,
        body {
            height: 100%;
            margin: 0;
        }

        table {
            width: 100%;
            height: 100%;
        }

        .main {
            width: 800px;
            height: 610px;
            margin: auto;
        }

        .game {
            position: relative;
            height: 100%;
            overflow: hidden;
        }

        .sky {
            width: 200%;
            height: 500px;
            background-image: url(./img/sky.png);
            position: relative;
            overflow: hidden;
        }

        .land {
            width: 200%;
            height: 110px;
            background-image: url(./img//land.png);
            bottom: 0;
        }

        .bird {
            position: absolute;
            width: 52px;
            height: 35px;
            background-position: 0 0;
            background: url(./img/bird.png) no-repeat;
            top: 20px;
            left: 20px;
        }

        .bird.close {
            background-position: -156px 0;
        }

        .move .bird {
            animation: fly .5s steps(3, end) infinite;
        }

        .move .sky {
            animation: skymove 7s linear infinite;
        }

        .move .land {
            animation: skymove 7s linear infinite;
        }

        .pipe-group {
            position: absolute;
            height: 100%;
            top: 0;
            left: 100%;
        }

        .pipe-group .pipe {
            width: 100%;
            position: absolute;
            overflow: hidden;
        }

        .pipe-group .pipe.up {
            top: 0;
            background-image: url(./img/pipeDown.png);
            background-position: bottom;
        }

        .pipe-group .pipe.down {
            bottom: 0;
            background-image: url(./img/pipeUp.png);
        }

        /*不能使用动画的原因,停止的时候衔接不上*/

        @keyframes fly {
            from {
                background-position: 0 0;
            }

            to {
                background-position: -156px 0;
            }
        }

        @keyframes skymove {
            from {
                background-position: 0 0;
            }

            to {
                background-position: -100% 0
            }
        }
    </style>
</head>

<body>
    <table>
        <tr>
            <td>
                <div class="main">
                    <div class="game move">
                        <div class="sky"></div>
                        <div class="land"></div>
                        <div class="bird"></div>
                    </div>
                </div>
            </td>
        </tr>

    </table>
    <script>
        class MoveReact {
            constructor(dom, left, top, speedX, speedY, maxTop) {
                this.dom = dom;
                this.left = left;
                this.top = top;
                this.speedX = speedX;
                this.speedY = speedY;
                this.maxTop = maxTop;
            }
            render() {
                this.dom.style.top = this.top + 'px'
                this.dom.style.left = this.left + 'px';
            }
            /**
             * 按照矩形的速度,和指定的时间,移动矩形
             * @param {*} duration 单位:秒
             */
            move(duration) {
                this.left += this.speedX * duration;
                // this.top +=  this.speedY * this.duration;
                this.top = Math.min(this.top + this.speedY * duration, this.maxTop)
                this.render();
            }
            resetSpeed({
                speedX,
                speedY
            }) {
                speedX && (this.speedX = speedX);
                speedY && (this.speedY = speedY);

            }
        }

        class Bird extends MoveReact {
            constructor(dom, width, height, left, top, speedX, speedY, maxTop) {
                super(dom, left, top, speedX, speedY, maxTop)
                // let a = MoveReact.getElementRect(dom)
                this.width = width;
                this.height = height;
                this.g = 0.09;
            }
            move(duration) {
                super.move(duration);
                this.speedY += this.g * duration;
            }
            jump(){
                this.speedY = -3
            }
        }
        // 水管
        class Pipe {
            constructor(height, type) {
                // super(dom, left, top, speedX, speedY, duration)
                let div = document.createElement('div')
                div.className = Pipe.className + type;
                div.style.height = height + 'px'
                this.type = type;
                this.pipedom = div;
            }
            static className = 'pipe '
        }
        // 上下水管组按组移动
        class PipeGroup extends MoveReact {
            constructor(dom, height, left, speedX, gapHeight, pipeWidth) {
                super(dom, left, 0, speedX, 0, 0)
                this.height = height;
                this.maxPipeHeight = 410;
                this.gapHeight = gapHeight;
                let upHeight = parseInt(Math.random() * this.maxPipeHeight);
                this.upHeight = upHeight;
                this.downHeight = height - upHeight - gapHeight;
                this.upPipe = new Pipe(upHeight, 'up');
                this.downPipe = new Pipe(this.downHeight, 'down');
                this.width = pipeWidth;
                dom.className = PipeGroup.className;
                dom.style.width = pipeWidth + 'px';
                dom.appendChild(this.downPipe.pipedom)
                dom.appendChild(this.upPipe.pipedom)
            }
            // render() {
            //     // super.render();
            // }
            static className = 'pipe-group '
        }
        // 水管组工厂
        class PipeGroupFactory {
            constructor(dom, width, height) {
                this.group = [];
                this.groupHeight = height;
                this.gapHeight = 140;
                this.startLeft = width;
                this.container = dom;
                this.speedX = -2;
                this.pipeWidth = 52
            }
            move(duration) {
                this.group.forEach(item => {
                    item.move(duration)
                })
                while (this.group[0] && this.group[0].left < -80) {
                    let pipe = this.group.shift();
                    pipe.dom.remove()
                }
            }
            createPipe() {
                let div = document.createElement('div'),
                    pipeGroup = new PipeGroup(div, this.groupHeight, this.startLeft, this.speedX, this.gapHeight,
                        this.pipeWidth);
                this.container.appendChild(div);
                this.add(pipeGroup)
            }
            add(pipeGroup) {
                if (pipeGroup instanceof PipeGroup) {
                    this.group.push(pipeGroup)
                }

            }

            startProduce() {
                if (this.timer) {
                    return
                }
                this.timer = setInterval(() => {
                    this.createPipe()
                }, 1500);
            }
            stopProduce() {
                clearInterval(this.timer);
                this.timer = null
            }
            // static pipeWidth = 20;
            // static duration = 20;
            // static speedX;
        }
        // 游戏
        class Game {
            constructor(gamedom, skydom, birddom) {
                let bird = Game.getElementRect(birddom),
                    game = Game.getElementRect(gamedom),
                    sky = Game.getElementRect(skydom);
                this.dom = game.dom;
                this.gameHeight = sky.height;
                this.bird = new Bird(bird.dom, bird.width, bird.height, bird.left, bird.top, 0.02, 0, sky
                    .height - bird.height);
                this.pipeFactory = new PipeGroupFactory(sky.dom, game.width, sky.height);
                this.pipeFactory.createPipe();
            }
            gaming() {
                if (this.timer) {
                    return
                }
                this.pipeFactory.startProduce();
                this.dom.classList.add('move')
                this.timer = setInterval(() => {
                    this.bird.move(4);
                    this.pipeFactory.move(2)
                    // 游戏结束
                    this.isgameOver() && this.gameOver();
                }, 30)
            }
            stopGaming() {
                clearInterval(this.timer)
                this.timer = null;
                this.dom.classList.remove('move');
                this.pipeFactory.stopProduce();
            }
            isgameOver() {
                let bird = this.bird,
                    group = this.pipeFactory.group;
                if (bird.top + bird.width >= this.gameHeight) {
                    return true;
                }
                // 检测碰撞
                for (let index = 0, length = group.length; index < length; index++) {
                    let pipe = group[index];
                    if (pipe.pass) {
                        continue
                    }
                    let obj = Game.isHit(bird, pipe)
                    pipe.pass = obj.pass;
                    // 正在通过柱子 或者还没有开始通过
                    if (obj.ispassing || !obj.pass) {
                        return obj.hit;
                    } else {
                        continue;
                    }
                }
            }
            gameOver() {
                this.stopGaming();
            }
            regEvent() {
                window.onkeydown = (e) => {
                    if (e.key === "Enter") {
                        if (this.timer) {
                            this.stopGaming();
                        } else {
                            this.gaming();
                        }
                    } else if (e.key === " ") {
                        this.bird.jump();
                    }
                }
            }
            static getElementRect(selector) {
                let dom = document.querySelector(selector),
                    style = getComputedStyle(dom);
                return {
                    dom,
                    width: parseInt(style.width),
                    height: parseInt(style.height),
                    top: parseInt(style.top),
                    left: parseInt(style.left)
                }
            }
            static isHit(rec1, rec2) {
                console.log(rec1,rec2)
                // 先判断左边距 如果方块1的右侧边没有和方块2的左侧边重合说明还没有pass,并且没有碰撞
                if (rec1.left + rec1.width  - rec2.left< 20) {
                    return {
                        hit: false,
                        pass: false,
                        ispassing: false
                    }
                }
                // 判断右边距 如果方块1过了方块2的右边距则标记为pass下次不再判断
                if (20 > rec2.left + rec2.width - rec1.left) {
                    return {
                        hit: false,
                        pass: true,
                        ispassing: false
                    }
                }
                if (rec1.top - rec2.upHeight > -20  && rec1.top + rec1.height - rec2.upHeight - rec2.gapHeight < 20) {
                    return {
                        hit: false,
                        pass: false,
                        ispassing: true
                    }
                }
                return {
                    hit: true,
                    pass: false,
                    ispassing: true
                }
            }
        }
        let game = new Game('.game', '.sky', '.bird');
        game.regEvent();
        game.gaming();
    </script>
</body>

</html>

实现图
在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 17:01:20  更:2021-08-23 17:01:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 0:20:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码