【HTML】【消失的花木兰】花木兰:三兔蹦迪走,安能辨我是兔子?

news2025/1/19 7:57:21

前言

(改编)
  某日,参军后的花木兰刚回到家乡,却不料遇上抓拿自己的官兵… 因此,花木兰变成兔子躲了起来,你能否找到躲起来的花木兰呢?一起来拭目以待…

一、游戏名称与游戏规则(玩法)

游戏名称

花木兰:安能辨我是兔子

游戏规则(玩法)

游戏的规则非常简单,游戏开始后,花木兰会变成兔子,会与另外两只一模一样的兔子进行交换位置。找到最后的花木兰所变的兔子的位置即可获胜!
  玩法如图所示(会有背景声音,也可进行关闭声音。):

find-rabbit.gif

二、大体设计与代码讲解

大体设计

  1. 首先,找素材(图片和音频)。弄个背景图,这里选择青青草地。(让兔子在进行跳跃起来的时候,能达到合理)
  2. 我们曾经玩过躲包包的游戏,学习了互换位置的思路。我们在这个基础上实现平行移动互换位置,并且完成小幅度的跳跃即可。(代码中有注释)

代码讲解

由于代码也比较简单,而且也有注释;这里就直接上完整的代码啦~

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="花木兰:安能辨我是兔子, 南方者">
    <meta name="keywords" content="花木兰:安能辨我是兔子, 南方者">
    <title>花木兰:安能辨我是兔子</title>
    <link rel="shortcut icon" href="./img/rabbit.png" size="32x32">
</head>

<body>
    <div class="head">
        <h1>花木兰:安能辨我是兔子</h1>
        <h1 style="color: red; cursor: pointer;" onclick="gameStart()">开始游戏</h1>
        <h3 onclick="changeBGM()">声音状态:<span id="bgmStatus">开启</span>(点击这里可关闭)</h3>
        <div style="font-size: medium; color: #919191;">(注意:背景声音会有些大。)</div>
    </div>
    <div class="game">
        <div class="rabbit" onclick="gameOver(0)">
            <div style="display: none;" class="v-talk">
                <img src="./img/talk.png" alt="">
            </div>
            <img class="i-rabbit" src="./img/rabbit.png" alt="" style="opacity: 1;">
        </div>
        <div class="rabbit" onclick="gameOver(1)">
            <div style="display: none;" class="v-talk">
                <img src="./img/talk.png" alt="">
            </div>
            <img class="i-rabbit" src="./img/rabbit.png" alt="" style="opacity: 1;">
        </div>
        <div class="rabbit" onclick="gameOver(2)">
            <div style="display: none;" class="v-talk">
                <img src="./img/talk.png" alt="">
            </div>
            <!-- <img src="./img/Mulan.png" alt="" id="mulan" style="opacity: 1;"> -->
            <!-- <img src="./img/rabbit.png" alt=""> -->
            <img class="i-rabbit" src="./img/rabbit.png" alt="" style="opacity: 1;">
        </div>
    </div>

    <!-- 信息弹窗框 (该初始模板来源地址:http://www.webkaka.com/tutorial/html/2021/1015185/)-->
    <div class="modal-dialog" id="modal-dialog">
        <div class="modal-header">
            <h2 id="modal-title">提示框标题</h2>
            <span class="btn-close" onclick="closeModal()">×</span>
        </div>
        <div class="modal-body">
            <p id="modal-content">内容</p>
        </div>
        <div class="modal-footer">
            <span class="btn" onclick="closeModal()">确定</span>
        </div>
    </div>
</body>

</html>
<script>
    var isPlayBgm = true;
    var talkList = document.getElementsByClassName("v-talk");
    // var mulan = document.getElementById("mulan");
    var imgList = document.getElementsByClassName('i-rabbit');
    var isStart = false;
    var isMove = false;
    var answer = getRan(); // 随机生成木兰的位置,0,1,2

    function getRan() {
        return Math.floor(Math.random() * 3);
    }
    imgList[answer].src = "./img/Mulan.png"; // 设置为木兰
    // console.log("init answer:", answer)
    // gameStart();
    function gameStart() {
        // console.log(mulan)
        // console.log("answer:", answer)
        if (isStart || isMove) {
            return;
        }
        var mulan = imgList[answer];
        isStart = true;
        isMove = true;
        var count = 1;
        talkList[answer].style.display = "";
        talkList[answer].style.opacity = 0.8;
        mulan.style.opacity = 1;
        playBGM('./mp3/change.mp3');
        // 播放木兰变身动画
        var interval = setInterval(() => {
            var opacity = mulan.style.opacity;
            // console.log(opacity);
            if (opacity <= 0) {
                window.clearInterval(interval)
                // 播放变身成兔子(“碰”的一声)
                changeBody();
                return;
            }
            opacity -= count * 0.28;
            // console.log(opacity, count);
            if (0.8 > opacity)
                talkList[answer].style.opacity = opacity;
            mulan.style.opacity = opacity;
            count++;
        }, 400);
    }

    function changeBody() {
        var mulan = imgList[answer];
        // console.log(mulan)
        setTimeout(() => {
            talkList[answer].style.display = "none";
        }, 200)
        setTimeout(() => {
            mulan.src = "./img/smoke.png";
            playBGM('./mp3/peng.mp3');
            mulan.style.opacity = 0.8;
        }, 300)
        setTimeout(() => {
            mulan.style.opacity = 1;
            mulan.src = "./img/rabbit.png";
            setTimeout(() => {
                move(5); // 移动5次
            }, 200);
        }, 800)
        changePointer(true);
    }

    // window.onload = function () { move(2); }

    function move(sum) {
        // 小兔跳动(移动)

        // moveOne(imgList[0], imgList[1]);
        var num = getRan();
        while (answer == num) {
            num = getRan();
        }
        moveOne(answer, num, sum);
    }

    function moveOne(p1, p2, sum) {
        var node1 = imgList[p1], node2 = imgList[p2];
        // console.log("p1:", p1, "p2:", p2, "answer:", answer)
        playBGM("./mp3/jump.mp3");
        var t1 = node1.offsetTop;
        var l1 = node1.offsetLeft;
        var t2 = node2.offsetTop;
        var l2 = node2.offsetLeft;
        // console.log(node1, node1.offsetLeft, node2, node2.offsetLeft)
        // console.log("l1:" + l1, "t1:" + t1, " --- ", "l2:" + l2, "t2:" + t2);
        var moveX = Math.abs(l1 - l2); // 取绝对值
        var moveY = Math.abs(t1 - t2);
        var translate1 = "-webkit-transform:";
        var translate2 = "-webkit-transform:";
        var translate1;
        var translate2;
        if (l1 >= l2) {
            translate1 += " translate(" + String(moveX) + "px,";
            translate2 += " translate(" + String(-moveX) + "px,";
        } else {
            translate1 += " translate(" + String(-moveX) + "px,";
            translate2 += " translate(" + String(moveX) + "px,";
        }
        node1.classList.add("game-trans");
        node2.classList.add("game-trans");
        // console.log(translate2, translate1)
        node1.style.cssText = translate2 + String(-100) + "px);"; // y轴进行范围性移动
        node2.style.cssText = translate1 + String(-100) + "px);";

        setTimeout(function () {
            node1.style.cssText = translate2 + String(0) + "px);";
            node2.style.cssText = translate1 + String(0) + "px);";
            sum--;
            setTimeout(function () {
                // 这里瞬间变回原来的位置,实际上是并没有变化的。
                // 主要是为了形成视觉上的切换,因此只需要记录最终位置即可。(即 anster 的最终值)
                node1.classList.remove("game-trans");
                node2.classList.remove("game-trans");
                node1.style.cssText = "translate(0px,0px)";
                node2.style.cssText = "translate(0px,0px)";
            }, 800);
            if (p1 == answer) {
                answer = p2;
            } else if (p2 == answer) {
                answer = p1;
            }
            if (sum < 0) {
                isMove = false;
                return;
            }
            var num1 = getRan();
            var num2 = getRan();
            while (num2 == num1) {
                num2 = getRan();
            }
            setTimeout(() => {
                moveOne(num1, num2, sum);
            }, 1000)
        }, 300);
    }


    function changePointer(isPointer) {
        var imgList = document.getElementsByTagName('img');
        // 图片是否变鼠标滑入变小手
        var txt = "";
        if (isPointer) {
            txt = "pointer";
        }
        for (img of imgList) {
            // console.log(img)
            img.style.cursor = txt;
        }
    }

    function playBGM(url) {
        if (!isPlayBgm) {
            // 当前不开启
            return;
        }
        //浏览器适用       
        contextClass = window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
        try {
            var context = new contextClass();
            var source = null;
            var audioBuffer = null;
            function stopSound() {
                if (source) {
                    source.stop(0); //立即停止
                }
            }
            function playSound() {
                source = context.createBufferSource();
                source.buffer = audioBuffer;
                source.loop = false;
                source.connect(context.destination);
                source.start(0); //立即播放    
            }
            function initSound(arrayBuffer) {
                context.decodeAudioData(arrayBuffer, function (buffer) { //解码成功时的回调函数
                    audioBuffer = buffer;
                    playSound();
                }, function (e) { //解码出错时的回调函数
                    console.log('404', e);
                });
            }
            function loadAudioFile(url) {
                var xhr = new XMLHttpRequest(); //通过XHR下载音频文件
                xhr.open('GET', url, true);
                xhr.responseType = 'arraybuffer';
                xhr.onload = function (e) { //下载完成
                    initSound(this.response);
                };
                xhr.send();
            }
            //这里用来存储背景音乐的路径
            loadAudioFile(url);
        } catch (e) {
            console.log('无法找到音乐!');
        }
    }

    function changeBGM() {
        var bgmStatus = document.getElementById("bgmStatus");
        // console.log(bgmStatus);
        var txt = "";
        if (isPlayBgm) {
            isPlayBgm = false;
            txt += "关闭";
        } else {
            isPlayBgm = true;
            txt += "开启";
        }
        // console.log(txt)
        bgmStatus.innerHTML = txt;
    }

    // 展开答案并且判断是否正确
    function gameOver(id) {
        if (!isStart || isMove) { // 游戏未开始 或 正在跳动
            return;
        }
        var titleValue, contentValue;
        // console.log("end answer:", answer, id)
        if (answer == id) {
            playBGM("./mp3/victory.mp3")
            titleValue = "胜利!";
            contentValue = "恭喜你成功找到了变身的兔子!<br>成功拿下花木兰!";
        } else {
            playBGM("./mp3/defeat.mp3")
            titleValue = "失败!";
            var text = "";
            switch (answer) {
                case 0:
                    text = "第一个";
                    break;
                case 1: text = "中间";
                    break;
                case 2: text = "最后一个";
                    break;
            }
            contentValue = "很抱歉,你找的并不是花木兰。<br>花木兰太狡猾了,她躲在了" + text + "!";
        }
        showModalMsg(titleValue, contentValue);
        imgList[answer].src = "./img/Mulan.png";
        changePointer(false);
        isStart = false;
    }

    // 显示弹窗框
    function showModalMsg(titleValue, contentValue) {
        var title = document.getElementById("modal-title");
        title.innerText = titleValue;
        var content = document.getElementById("modal-content");
        content.innerHTML = contentValue;
        var modal = document.getElementById("modal-dialog");
        modal.style.display = "block";
    }
    // 关闭弹窗框
    function closeModal() {
        var modal = document.getElementById("modal-dialog");
        modal.style.display = "";
    }


</script>
<style>
    .head {
        position: fixed;
        width: 100%;
        text-align: center;
    }

    .head h1 {
        font-size: -webkit-xx-large;
    }

    body {
        /* 背景图设置 */
        background: url("./img/bg.png") no-repeat center center;
        background-size: cover;
        background-attachment: fixed;
        margin: 0px;
    }

    body,
    html,
    .game {
        height: 100%;
        width: 100%;
        /* margin: 50px; */
    }

    .game {
        display: flex;
        justify-content: space-around;
    }

    .rabbit {
        display: flex;
        /* 垂直居中 */
        align-items: center;
        /* 水平居中 */
        justify-content: center;
        /* 文字居中 */
        text-align: center;
        height: 100%;
        width: 25%;
        /* background: #000; */
    }


    img {
        max-width: 100%;
        max-height: 100%;
    }

    .game-trans {
        transition: transform 0.5s linear 0s;
    }

    .modal-body {
        padding: 20px;
    }

    .modal-header,
    .modal-footer {
        padding: 10px 20px;
    }

    .modal-header {
        border-bottom: #eee solid 1px;
    }

    .modal-header h2 {
        font-size: 20px;
    }

    .modal-footer {
        border-top: #eee solid 1px;
        text-align: right;
    }

    .modal-dialog {
        display: none;
        background: #fefefe;
        border: #333 solid 1px;
        border-radius: 5px;
        margin-left: -180px;
        margin-top: -50px;
        position: fixed;
        left: 50%;
        top: 30%;
        z-index: 11;
        width: 360px;
    }

    .btn-close {
        cursor: pointer;
        color: #aaa;
        font-size: 30px;
        text-decoration: none;
        position: absolute;
        right: 5px;
        top: 0;
    }

    .btn-close:hover {
        color: #919191;
    }

    .btn {
        cursor: pointer;
        background: #428bca;
        border: #357ebd solid 1px;
        border-radius: 3px;
        color: #fff;
        display: inline-block;
        font-size: 14px;
        padding: 8px 15px;
        text-decoration: none;
        text-align: center;
        min-width: 60px;
        position: relative;
        transition: color 0.1s ease;
    }

    .btn:hover {
        background: #357ebd;
    }

    .v-talk {
        position: fixed;
        z-index: 10;
        opacity: 0.8;
    }
</style>

仓库地址与体验地址

大家可以直接来笔者的网站来体验
  在线体验(pc端):体验传送门
  仓库地址:暂无(想要的可以直接去扒笔者的网站传送门

以前的小游戏

  • 【HTML】【休闲益智】还有9块月饼并未获得!请及时出战!(解锁月饼小游戏 - 掘金 (juejin.cn)
  • 【微信小游戏】合成大灯笼 丨 2022🧭寻找暴富人🧧(首次个人小活动) - 掘金 (juejin.cn)
  • 【HTML】【休闲益智】真相?真香?只有一个!看看谁是大馋虫 or 贪吃鬼(找出真正吃了月饼的人 - 掘金 (juejin.cn)
  • 【HTML】【休闲益智】还有9块月饼并未获得!请及时出战!(解锁月饼小游戏 - 掘金 (juejin.cn)
  • 更多好玩的游戏

文章小尾巴

文章写作、模板、文章小尾巴可参考:《写作“小心思”》

  感谢你看到最后,最后再说两点~
  ①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。
  ②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~
   我是南方者,一个热爱计算机更热爱祖国的南方人。
  (文章内容仅供学习参考,如有侵权,非常抱歉,请立即联系作者删除。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

joinquant量化数据精准吗?

在股票量化投资中&#xff0c;joinquant量化数据起到很大的作用&#xff0c;因为joinquant量化平台的数据能够从众多只股票数据中&#xff0c;能够一一罗列出来&#xff0c;也就是说&#xff0c;joinquant量化数据可以在计算和分析数据模型中&#xff0c;能够帮助投资者找到他们…

【SpringBoot1】创建第一个SpringBoot项目

创建SpringBoot项目可以通过两种方式&#xff1a; 1、通过访问&#xff1a;https://start.spring.io/&#xff0c;SpringBoot的官方网站进行创建SpringBoot项目&#xff1b; 2、通过工具&#xff08;例如&#xff1a;Idea&#xff09;创建SpringBoot项目。本次使用IDEA创建第一…

数据结构进阶 红黑树

作者&#xff1a;小萌新 专栏&#xff1a;数据结构进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍高阶数据结构: 红黑树 红黑树红黑树的概念红黑树的性质红黑树节点的定义红黑树的插入情况一情况二情况三红黑树的验证红黑…

远程监控网络摄像头通用指南

一、引言 随着物联网技术的发展&#xff0c;越来越多的场景需要我们通过技术手段去感知。画面和声音相当于机器的眼睛和耳朵&#xff0c;有了这些实时数据我们可以做很多事情&#xff0c;比如车牌识别、人脸识别、体温识别等等。本文将全方位介绍网络摄像头如何接入软件的实现…

2022.12 青少年机器人技术等级考试理论综合试卷(四级)

2022年12月 青少年机器人技术等级考试理论综合试卷&#xff08;四级&#xff09; 分数&#xff1a; 100 题数&#xff1a; 30 一、 单选题(共 20 题&#xff0c; 共 80 分) 1.以下关于 Arduino C 语言的说法&#xff0c; 正确的是?&#xff08; &#xff09; A.setup() 函数和…

SpringMVC Interceptor拦截器

SpringMVC中的拦截器用于拦截控制器方法的执行&#xff0c;执行在Controller前后&#xff0c;和视图渲染完成后。如下图所示&#xff1a; 一、创建拦截器 继承HandlerInterceptor 接口&#xff0c;并实现其中的方法 public class FirstInterceptor implements HandlerInter…

儿子小伟刚刚再婚,大衣哥就河南新乡商演,这是给孙子攒奶粉钱吗

现如今的社会&#xff0c;因为人们的攀比心理&#xff0c;结一次婚能让人脱一层皮&#xff0c;尤其是农村赚钱难&#xff0c;结婚花钱就更难了。其实不只是普通老百姓&#xff0c;强如农民歌唱家大衣哥这样的人&#xff0c;也架不住儿子一而再&#xff0c;再而三的结婚。 大衣哥…

Qt基础之二十一:QtRO(Qt Remote Object)实现进程间通信

这里将QtRO单独从上一篇Qt基础之二十:进程间通信拎出来,因为它是Qt5.9以后新加入的模块,专门用于进程间通信。其使用步骤有点类似之前介绍过的RPC(Remote Procedure Call)框架:gRPC和thrift,关于这两个框架详见 Qt中调用thrift和Qt中调用gRPC QtRO基于Socket封装,不仅支…

小程序开发——模板与配置

一、WXML 模板语法 1.数据绑定的基本原则 ① 在 data 中定义数据 ② 在 WXML 中使用数据2.在 data 中定义页面的数据 在页面对应的 .js 文件中&#xff0c;把数据定义到 data 对象中即可&#xff1a;3. Mustache 语法的格式 把data中的数据绑定到页面中渲染&#xff0c;使用…

【测试】java+selenium环境搭建

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、下载安装谷歌浏览器二、下载谷歌驱动三、常见问题&解决方法1. SessionNotCreatedException2. The version of ChromeDriver only support xxxxxxxxx3. The path to the driver executable the path to普通小…

5-2输入/输出管理-I/O核心子系统

文章目录一.I/O调度二.设备保护三.SPOOLing技术&#xff08;假脱机技术&#xff09;四.设备的分配与回收1.设备分配时应该考虑的因素2.静态分配和动态分配3.设备分配管理中的数据结构&#xff08;1&#xff09;设备控制表DCT&#xff08;Device Control Table&#xff09;&…

MySQL进阶篇之Linux安装MySQL8.0.26

Linux安装MySQL 需要更多安装MySQL的教程&#xff0c;请查阅Linux学习笔记——MySQL数据库管理系统安装部署 1、MySQL下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 2、在FinalShell中输入rz&#xff0c;然后选择下载好的MySQL安装包&#xff0c;进行上…

【数据质量】一起聊聊数据质量

Garbage In, Garbage Out ​ 数据质量关注的是数据的健康&#xff0c;数据健康和人的健康很相似&#xff0c;人的健康会影响人的生活品质&#xff0c;同样数据的健康会影响数据的使用品质。为了保证我们健康&#xff0c;我们需要养成良好的生活习惯&#xff0c;膳食平衡&#x…

Open3D DBSCAN聚类(Python版本)

文章目录 一、简介二、算法步骤三、实现代码四、实现效果参考资料一、简介 DBSCAN算法,全称为“Density-Based Spatial Clustering of Applications with Node”,也就是“基于密度的聚类”。此类算法是假设聚类结构能通过样本分布的紧密程度确定,从样本密度的角度来考察样本…

亿发浅析:财务一体化功能与管理流程

在信息时代的背景下&#xff0c;企业信息化已成为中小企业降低成本、提高效率、提高竞争力的重要手段&#xff0c;也是中小企业实现长期可持续发展的有效途径。 信息化对企业管理的好处是显而易见的&#xff0c;如加快信息流&#xff0c;提高信息资源利用率&#xff0c;促进企业…

STM32使用FSMC驱动LCD

关于FSMC驱动LCD的函数LCD_WR_REG的理解首先你需要理解使用结构体LCD_BASE若有错误&#xff0c;请各位师兄师姐指点原理框图重要的函数理解关于LCD_BASE和函数LCD_WR_REG&#xff08;u16 regval&#xff09;的理解至于0X6C00 0802地址也是一样的。首先要说的是这是我个人的理解…

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 (五)位拆分与运算

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 &#xff08;五&#xff09;位拆分与运算 &#x1f508;声明&#xff1a; &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN博客 &#x1f9e8;未经作者允许&#xff0c;禁止转载 &#x1f511;系列专栏&#xff1a;牛客Veri…

Burp Suite Professional 2023.1 (macOS, Linux, Windows) - Web 应用安全、测试和扫描

Burp Suite Professional, Test, find, and exploit vulnerabilities. 请访问原文链接&#xff1a;https://sysin.org/blog/burp-suite-pro-2023&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org Burp Suite Professional&a…

《后端技术面试 38 讲》学习笔记 Day 07

《后端技术面试 38 讲》学习笔记 Day 07 21丨分布式架构&#xff1a;如何应对高并发的用户请求 原文摘抄 当同时访问系统的用户不断增加的时候&#xff0c;需要消耗的系统计算资源也不断增加&#xff0c;需要更多的 CPU 和内存去处理用户的计算请求&#xff0c;需要更多的网络…

二叉树、平衡二叉树、红黑树、B树、B+树、B*树的区别

二叉树 如下图&#xff0c;是一个二叉树的结构图片&#xff1a; 可以看到无论是对象“9”、还是“5”、“13”、“2”、“7”、“11”、“15”它们的下面分别都叉了两个其他的对象。而且这两个对象都是左边的数值要小一些&#xff0c;右边的数值要大一些。 所以这就是二叉树的…