当前位置: 首页 > news >正文

CSS实现经典打字小游戏《生死时速》

在这里插入图片描述

🌻 前言

CSS 中有这样一个模块:Motion Path 运动模块,它可以使元素按照自定义的路径进行移动。本文将为你讲解这个模块属性的使用,并且利用它实现我小时候电脑课经常玩的一个打字游戏:金山打字的《生死时速》。

🪴 Motion Path 使用教程

css中有这样一个模块:Motion Path ,它可以实现元素按不规则路径移动。

Motion Path模块包含 offset 的一系列属性,包括以下几个:

  • offset-path:设置元素运动路径;
  • offset-distance:控制当前元素基于 offset-path 运动的距离;
  • offset-anchor:定义元素在路径上移动时的锚点。 简单来说就是,运动元素可能不是一个点,那么就需要指定元素中的哪个点附着在路径上进行运动
  • offset-position:指定运动的初始位置;
  • offset-rotate:定义沿 offset-path 运动路径移动时元素的朝向;

1. offset-path

offset-path 属性可以取以下几个值来设置元素的运动路径:

  • ray()函数ray([<angle> && <size> && contain?]),设置以射线状路线偏移;
  • url()函数:用id选择器绑定页面内联SVG元素中任意图形元素的路径;
  • <basic-shape>:一些css的基本形状函数,例如:circle(), ellipse(), inset(), path(), polygon(), rect()等,对于可以设置position位置的circle(), ellipse(),如果没有设置position的话,就会应用offset-position的值;
  • box-edge:设置以相对的父元素的边缘为运动路径,例如设置content-box、border-box、fill-box等,可以设置按内容区的边缘还是边框边缘等;

看下面例子就懂了:

下面代码中ray射线运动是设置元素朝70度方向运动200px;
按svg路径运动是让电车以一个五角星的svg的路线运动;
shape图形是让电车以polygon()绘制的菱形运动;
box是在其父盒子边缘运动;
jcode

2. offset-distance

设置运动的距离,可以是值,也可以是百分比,例如设置0%处于初始位置,100%就是移动到路径的终点。所以一般实现元素按不规则路径移动,就是通过animation修改offset-distance实现的。

jcode

3. offset-anchor

设置元素的哪个点沿着路径运动,例如设置offset-anchor: center bottom为元素的底部中心点沿路径移动,其他就不多说了,使用方式和background-position一样。

jcode

4. offset-position

设置运动的起始位置,只能作用于可以设置position的路线.

例如 ray() 射线运动,可以设置起点位置,或者ellipse()、circle()等这些需要设置position的图形元素。而且如果在定义路径时已经写明了position的话,offset-position是不会生效的,例如circle(50% at 25% 25%)

5. offset-rotate

offset-rotate定义元素沿偏移路径定位时的方向,默认的话是元素角度会一直和运动路径的水平角度保持一致,当然你也可以自定义固定角度,或者反向显示元素(reverse)。

看下面例子就明白了:

jcode

🎯 游戏开发

1. 游戏简介

游戏开始后,警察在3秒后开始出动,如果警察抓到小偷(位置重合)即游戏失败。
你需要根据页面底部的对话正确输入单词,即可让小偷不断运动,拉开与警察的距离,如果在输入全部对话前没有被警察逮到,即闯关成功。

整个游戏其实实现起来很简单,只需要在设置offset路径动画的基础上加一点点细节就完成了。

2. 利用offset属性实现运动路径

找个svg在线编辑网站,设计一个用来当道路等路径path,然后将两个位置重合的元素设置相同的运动路径,即可实现警察和小偷的运动路线。

tutieshi_640x347_4s.gif

3. 实现警察追小偷

  1. 如何实现警察小偷你追我赶的情景呢?很简单,警察是一直在运动的,只要小偷不要一直运动,两者错开即可。

只需要利用animation-play-state: paused属性控制小偷运动暂停即可,如果你输入正确的字符,则设置为animation-play-state: running继续运动。

  1. 如何制作打字控制小偷移动的效果呢?

很简单,监听键盘输入即可,如果输入正确,则将此字符推入答案中,并设置小偷animation-play-state: running让他继续运动,延时一小段时间再设置为paused暂停。
答案和题目重合,并且答案设置为了蓝色,在答案尾部还利用step逐帧动画,方便体现打字的进度。因为输入时,输入空格也需要光标移动,所以一定要在答案元素上设置white-space: pre以保留空白符的所有空白。另外,为了使要输入的字符永远显示出来,我在推入答案时会使光标调用scrollIntoView()方法使其滚动到可视区。

document.addEventListener('keydown', function (event) {const myinput = answer.textContentif (event.key === words[myinput.length]) {timer && clearTimeout(timer)answer.textContent = myinput + event.keythief.style.setProperty('--paused', 'running');document.querySelector('.show').scrollIntoView(true)timer = setTimeout(() => {thief.style.setProperty('--paused', 'paused');}, 400);}
});
setTimeout(() => {checkCollision()police.style['animation-play-state'] = 'running'
}, 2000);

在这里插入图片描述

4. 判断结果

如果做碰撞检测呢并显示结果呢?

碰撞检测其实很简单,只需要利用getBoundingClientRect()方法获取警察和小偷的定位,判断是否几乎重合即可。判断输赢的方式为:如果你在打完所有文字之前不被逮捕则闯关成功,否则闯关失败。

// 碰撞检测
function checkCollision() {const policeRect = police.getBoundingClientRect()const thiefRect = thief.getBoundingClientRect()if (answer.textContent.length >= words.length) {showResult(true)return}if (Math.abs(policeRect.x - thiefRect.x) < 2 && Math.abs(policeRect.y - thiefRect.y) < 2) {showResult()return}requestAnimationFrame(checkCollision)
}
// 结局判断
function showResult(flag) {if (flag) {document.querySelector('.success').style.display = 'grid'} else {document.querySelector('.fail h1').textContent =`你被逮捕了!${document.querySelector(".timing").textContent}`document.querySelector('.fail').style.display = 'grid'}
}

在这里插入图片描述

🎮 玩游戏

《生死时速》游戏地址

更多游戏

🎁最后

学如逆水行舟,不进则退~
我是喜欢归纳总结前端相关知识的前端阿彬,欢迎点赞关注

在这里插入图片描述

相关文章:

  • 【Windows】配置Flutter开发环境
  • ArrayList和LinkedList的区别!!!
  • 文献学习——PWM - PFM模式无缝转换的PFC变换器统一控制
  • LVS工作模式详解,NAT全方位剖析
  • PromptMRG: Diagnosis-Driven Prompts for Medical Report Generation
  • 还在用Flex布局?OUT了 快来看看grid布局吧!
  • 计算机二级Access选择题考点—代码篇
  • Java程序设计 第五章 循环
  • 微信小程序毕业设计-智慧消防系统项目开发实战(附源码+论文)
  • 今日成果2024-6-7 TrustZone TEE安全SDK开发指南
  • MySQL 保姆级教程(四):过滤数据
  • c语言回顾-结构体
  • redis 09 事务
  • 【Ardiuno】实验使用ESP32单片机根据光线变化控制LED小灯开关(图文)
  • SpringBoot集成Elasticsearch实例
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • java中具有继承关系的类及其对象初始化顺序
  • Map集合、散列表、红黑树介绍
  • 人脸识别最新开发经验demo
  • 如何设计一个微型分布式架构?
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 学习笔记TF060:图像语音结合,看图说话
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • $forceUpdate()函数
  • %@ page import=%的用法
  • (C语言)fread与fwrite详解
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (二)正点原子I.MX6ULL u-boot移植
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (四) 虚拟摄像头vivi体验
  • (一)appium-desktop定位元素原理
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)Linux下编译安装log4cxx
  • (转)重识new
  • (转载)Linux网络编程入门
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .htaccess 强制https 单独排除某个目录
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net FrameWork简介,数组,枚举
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • :O)修改linux硬件时间
  • @取消转义
  • [ vulhub漏洞复现篇 ] ThinkPHP 5.0.23-Rce
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [C++] cout、wcout无法正常输出中文字符问题的深入调查(1):各种编译器测试