js打地鼠

文章目录

  • 1实现效果
  • 2代码实现

1实现效果

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

游戏难度:简单,一般,困难,噩梦(控制setInterval的time参数)
按钮功能:结束(可以通过修改gameScore的值来修改判定结束的分数),开始,重开
游戏得分

2代码实现

注意路径:
在这里插入图片描述
我的img和html文件是并列关系,引入的相对路径

url(./img/xxx.jpg)

资源图片:

mouse.jpg
在这里插入图片描述

bg.jpg
在这里插入图片描述

hit.jpg
在这里插入图片描述

hummer.png
在这里插入图片描述

注意:注意计时器,何时打开了,何时需要关闭它,创建的timeId从1开始,之前的不关闭,在创建新的时,timeId是2 ,依次类推,不及时关闭定时器,可能会造成逻辑混乱。
比如:在本例中,在游戏执行过程中,直接修改下拉框后,不执行clearInterval(timeId),而是直接调用startGame(),就会创建另一个定时器,此时如果达到了判输的条件,执行gameOver(),虽然执行了clearInterval(timeId),但是关闭的定时器是新开的那个,此时的timeId值是2,原来的1还存活着。但是这个结束条件依然成立(score<=gameScore),在第一个定时器中每次执行到gameOver()都会被触发,这就是bug,所以要在改变下拉框时,要及时关闭第一个定时器(timeId=1的)。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>打地鼠</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            background-color: lightblue;
        }

        .div1 {
            text-align: center;
            background-color: lightgreen;
            width: 100%;
            line-height: 50px;

        }

        .div2 {
            margin: 0 auto;
            width: 600px;
            height: 610px;
        }

        td {
            width: 200px;
            height: 200px;
            border-radius: 100px;
            background-image: url(./img/bg.jpg);
            background-size: 100% 100%;
            background-repeat: no-repeat;
            border: 1px solid #000;
            cursor: url("./img/hummer.png"), auto;
        }
        select{
            text-align: center;
            width: 70px;
            height: 30px;
            font-family: 'Courier New', Courier, monospace;
            border-radius: 5px;
        }
        button{
            width: 100px;
            height: 30px;
            font-family: 'Courier New', Courier, monospace;
            border-radius: 5px;
            background-color: lightgray;
            margin-right: 30px;
            margin-left: 30px;
        }
        button:hover{
            background-color: orange;
            color: #fff;
        }
        span{
            color: red;
            width: 40px;
            height: 30px;
            padding-left: 10px;
            font-size: 20px;
            font-family: 'Courier New', Courier, monospace;
            display: inline-block;
            box-sizing: border-box;
        }
       
    </style>
</head>

<body>
    <audio src="./audio/bg.mp3" class="bgMusic"></audio>
    <audio src="./audio/hit.wav" class="hitMusic"></audio>
    <div class="div1">
        游戏难度:
        <select id="select">
            <option>简单</option>
            <option>一般</option>
            <option>困难</option>
            <option>噩梦</option>
        </select>
        <button id="start">开始游戏</button>
        游戏得分:
        <span id="score">0</span>
    </div>
    <div class="div2">
        <table>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </table>
    </div>
    <script>
        //是否开始游戏
        let isPlay = false;
        let score = 0;
        // 是否捶打
        let flag = true;
        let lastIndex = 0;
        var timeId = 0;
        let Tid=0;
        // 捶了是否锤中
        let isRight=false;
        let isHit=false;
        // 定时器时间
        let time = 2000;
        let index = 0;
        let gameScore = -20;
        // 获取元素
        let select = document.querySelector("#select");
        let start = document.querySelector("#start");
        let scoreSpan = document.querySelector("#score");
        let tds = document.querySelectorAll("td");
        let bgMusic = document.querySelector(".bgMusic");
        let hitMusic = document.querySelector(".hitMusic");
        // 给开始按钮添加点击事件
        start.onclick = function () {
            isPlay = !isPlay;
            if (isPlay) {
                // 获取游戏难度
                let level = select.value;
                clearTimeout(Tid);
                score = 0;
                scoreSpan.innerHTML = score;
                tds[lastIndex].style.backgroundImage = 'url(./img/bg.jpg)';
                // 设置游戏难度
                bgMusic.play();
                startGame(level);
                start.innerHTML = "结束游戏";

            } else {
                // 结束游戏
                bgMusic.pause();
                clearInterval(timeId); // 清除定时器
                start.innerHTML = "开始游戏";
            }
        }
        // 给td添加点击事件
        tds.forEach((td, i) => {
            td.onclick = hit.bind(null, i);
        })
        // 给下拉框添加change事件
        select.onchange = function () {
            if (isPlay) {
                let level = select.value;
                flag = true;
                score = 0;
                scoreSpan.innerHTML = score;
                tds[lastIndex].style.backgroundImage = 'url(./img/bg.jpg)';
                // 清除之前开启的定时器,直接切换选项,之前开启的定时器还在运行,所以要关闭
                clearInterval(timeId); 
                startGame(level);
            }
        }

        function startGame(level) {
            if (level == '简单') {
                time = 2000;
            } else if (level == '一般') {
                time = 1500;
            } else if (level == '困难') {
                time = 1000;
            } else {
                time = 800;
            }
            timeId = setInterval(function () {
                // 在还原之前,检查flag的值,为false,代表上一次没有落捶
                if (flag == false) {
                    score -= 5;
                    scoreSpan.innerHTML = score;
                }
                // 开始新的出现位置,锤击状态置为未锤击
                flag = false;
                isRight=false;
                isHit=false;
                gameOver(score);
                // 将上一次的改回原背景
                tds[lastIndex].style.backgroundImage = 'url(./img/bg.jpg)';
                // 随机获取一个索引
                if (isPlay) {
                    index = Math.floor(Math.random() * tds.length);;
                }
                // 给当前的索引添加样式
                tds[index].style.backgroundImage = 'url(./img/mouse.jpg)';
                lastIndex = index;
            }, time);
        }
        // TODO: 游戏是否击中的判断逻辑需要完善
        function hit(i) {
            // 游戏开始时,锤击才有效
            if (isPlay) {
                hitMusic.play();
                // 锤击的td和随机产生的td索引一致,只第一次捶中有效(锤击地鼠出现位置)
                if (i == lastIndex&&!isRight) {
                    isRight=true;
                    score += 3;
                    // 改变背景
                    tds[i].style.backgroundImage = 'url(./img/hit.jpg)'
                } else if(!isHit){
                    // 捶错地方,只第一次捶错有效
                    score -= 5;
                    gameOver(score);
                }
                scoreSpan.innerHTML = score;
                flag = true;
                isHit=true;
            }
        }
        // 游戏结束
        function gameOver(score) {
            if (score <= gameScore) {
                // 清楚当前的计时器id
                clearInterval(timeId);
                scoreSpan.innerHTML = score;
                isPlay = false;
                flag = true;
                start.innerHTML = "重新开始";
                Tid = setTimeout(() => {
                    alert('游戏结束,得分:' + score);
                }, 300);
            }
        }
    </script>
</body>

</html>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL十部曲之四:MySQL中的数据类型

文章目录 前言概述数字类型数字类型语法数字类型字面量十六进制字面量位字面量布尔字面量 数字类型的属性超出范围和溢出处理 时间和日期类型时间和日期类型语法DATE、DATETIME和TIMESTAMP的异同TIMESTAMP和DATETIME的自动初始化和更新时间和日期字面量 字符串类型字符串类型语…

知识圣殿,智慧熔炉

知识圣殿&#xff0c;智慧熔炉 知识殿堂&#xff0c;巍然屹立 一座灵魂熔炉&#xff0c;号称图书馆 万卷书香盈架&#xff0c;智慧如星河汇聚 每一册书页&#xff0c;流淌着人类文明的血脉 钢笔与墨水交织诗篇 思想发芽&#xff0c;真理绽放光焰 浩瀚知识海洋&#xff0c;波涛…

tensorboard+seaborn 画RL论文图片

概要 tensorboard记录数据&#xff0c;并保存为fie_name.csv 文件加载file_name.csv文件, 处理加载得到数据,然后通过seaborn 显示出来。 1. tensorboard 通常来说&#xff0c;我们一般会用 tensorboard 去记录一些数据。 所以我们先介绍一下 tensorboard 一些注意事项 seti…

mybatis-plus常用使用方法

** mybaits-plus常用使用方法 ** 常用三层分别继承方法 1.1mapper层&#xff08;接口定义层&#xff09;可以用BaseMapper<> 例如&#xff1a; 1.2.里面常用的封装方法有 1.3常用方法介绍 【添加数据&#xff1a;&#xff08;增&#xff09;】int insert(T entity);…

css不规则的文本环绕

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>不规则的文本环绕</title><style>.b…

性能测试混合业务场景

已知从生产环境中统计出的接口比例如下所示&#xff1a; 接口接口比例接口140%接口220%接口330%接口410% 场景一&#xff1a;以上接口无上下依赖关系&#xff0c;设计出容量场景 接口1比例如下&#xff1a; 接口2比例如下&#xff1a; 接口3比例如下&#xff1a; 接口4比例如…

HFSS实战(三)——过孔via TDR仿真

文章目录 一、模型的处理二、TDR仿真2.1 修改求解模式2.2增加求解设置 三、查看仿真结果3.1 查看TDR结果3.2 查看S参数结果 四、结果分析4.1上升时间tr对仿真的影响 附&#xff1a;工程链接 在上一讲中&#xff0c;主要是通过观察S参数确定via的优化是否达到目标。但S参数只能看…

AI嵌入式K210项目(21)-AI模型文件导入至TF卡

文章目录 前言一、模型文件二、方法1三、方法2总结 前言 上一章节介绍了使用MicroPython进行开发&#xff0c;IDE中有很多的示例教程&#xff0c;相信大家已经迫不及待的想试试了&#xff0c;里面人目标检测的例程需要调用训练好的模型文件&#xff0c;这一章介绍如何将AI模型…

关于MySQL的基本查询(多表查询等)

1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) ); 创建score表。SQL代码如下&#xff1a; CREATE…

25考研政治备考计划

各位小伙伴大家好&#xff0c;今天给大家分享的是25考研政治复习备考计划。 政治没有基础阶段&#xff0c;直接就是强化&#xff0c;强化的内容也就是听课&#xff0c;刷题。 【时间安排】 *7-9月中 徐涛老师或腿姐强化课&#xff0c;推荐刷肖1000 *9月中-10月中 背腿姐的背…

BLIP-2: 基于冻结图像编码器和大型语言模型的语言-图像预训练引导

BLIP-2: 基于冻结图像编码器和大型语言模型的语言-图像预训练引导 项目地址BLIP-2的背景与意义BLIP-2的安装与演示BLIP-2模型库图像到文本生成示例特征提取示例图像-文本匹配示例性能评估与训练引用BLIP-2Hugging Face集成 在语言-图像预训练领域&#xff0c;BLIP-2的出现标志着…

Mac M1 Parallels CentOS7.9 Deploy 禅道

禅道官网下载地址: https://www.zentao.net/download/max4.10-83276.html 一、官网下载 二、解压安装 将下载好的包传至CentOS7.9虚拟机 zhinian192 ~ % scp Downloads/ZenTaoPMS-max4.10-zbox_arm64.tar.gz root10.211.55.36:~ ZenTaoPMS-max4.10-zbox_arm64.tar.gz …

LabVIEW振动信号分析

LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换&#xff08;Hilbert-Huang Transform, HHT&#xff09;&#xff0c;并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具&#xff0c;特别适用于旋转机械等复杂系统的振动分析。开发了…

VR漫游:赋予用户720度身临其境的沉浸式体验

如今&#xff0c;VR全景技术已经成为了千行百业中不可或缺的一部分&#xff0c;随着用户对交互式、沉浸式体验的需求不断加强&#xff0c;VR漫游逐渐取代了传统图片&#xff0c;为人们带来了流畅且完整的VR宣传观看体验。 VR实景漫游真实的展示了现场环境&#xff0c;不仅增加了…

【yaml 文件使用】pytest+request 框架中 yaml 配置文件使用

又来进步一点点~~ 背景&#xff1a;最近在学习pytestrequest框架写接口测试自动化&#xff0c;使用yaml文件配置更方便管理用例中的数据&#xff0c;这样更方便 yaml 介绍&#xff1a; 什么是 yaml 文件&#xff1a;YAML 是 “YAML Ain’t a Markup Language”&#xff08;Y…

Sublime的安装及汉化

sublime安装 官网sublime 点击Windows 下载参考&#xff1a;傻瓜式下载 sublime汉化 1&#xff09;安装 Sublime Text 4 成功后&#xff0c;点击菜单 【Tools】 -> 【Install Package Control】&#xff1b; 注意&#xff1a;安装包控件需要等待一会&#xff0c;点击可…

【mongoDB】文档 CRUD

目录 1.插入文档 批量插入&#xff1a; 2.查询文档 3.更新文档 4.删除文档 deleteOne() deleteMany() findOneAndDelete() 1.插入文档 可以使用 insert () 方法或者 save() 方法向集合中插入文档 语法如下&#xff1a; db.collection_name.insert(document) collectio…

springboot+vue的大学生就业招聘系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

【GitHub项目推荐--不错的Flutter项目】【转载】

01 可定制的图表库 FL Chart是一个高度可定制的 Flutter 图表库&#xff0c;支持折线图、条形图、饼图、散点图和雷达图 。 项目地址&#xff1a;https://github.com/imaNNeoFighT/fl_chart LineChart BarChart PieChart Sample1 Sample2 Sample3 …

存储硬盘不要贪便宜了,守护数据最宝贵-3

第四个避坑点&#xff1a;SSD接口不要选错了 你如果直接购买新电脑&#xff0c;电脑里面的形态基本就不用关心了&#xff0c;你主要关注其他方面。这个主要针对&#xff0c;如果想对自己旧电脑进行硬盘升级的场景。 首先&#xff0c;你需要先了解你电脑上现有存储硬盘的接口&…